![查找实时系统上定义的共享库符号的位置/列出系统上导出的所有符号](https://linux22.com/image/51653/%E6%9F%A5%E6%89%BE%E5%AE%9E%E6%97%B6%E7%B3%BB%E7%BB%9F%E4%B8%8A%E5%AE%9A%E4%B9%89%E7%9A%84%E5%85%B1%E4%BA%AB%E5%BA%93%E7%AC%A6%E5%8F%B7%E7%9A%84%E4%BD%8D%E7%BD%AE%2F%E5%88%97%E5%87%BA%E7%B3%BB%E7%BB%9F%E4%B8%8A%E5%AF%BC%E5%87%BA%E7%9A%84%E6%89%80%E6%9C%89%E7%AC%A6%E5%8F%B7.png)
基本上,这是两个问题合二为一 - 因为如果我可以列出系统中导出的所有符号及其共享库路径,那么我就可以简单地输出grep
该输出。
对于内核符号,我想这更容易一些 - 因为我们总是可以cat /proc/kallsyms
获取加载到内存中的那些模块的所有符号的列表;然后sudo cat /proc/modules
将给出已加载模块的列表及其地址,但不是加载模块的路径(如果它们是作为单独的树外 .ko 对象构建的)
例如,我尝试kst
使用以下命令跟踪程序ltrace
:
$ ltrace kst2
...
_ZNK13QGraphicsItem10parentItemEv(0xa1ccdb4, 0, 0xbfe631a8, 0x823652b, 0xbfe63298) = 0xa1ce854
__dynamic_cast(0xa1ce854, 0x839ff00, 0x8306b80, 84, 0xbfe63298) = 0xa1ce800
_ZNK13QGraphicsItem10parentItemEv(0xa1ccdb4, 0x839ff00, 0x8306b80, 84, 0xbfe63298) = 0xa1ce854
__dynamic_cast(0xa1ce854, 0x839ff00, 0x8306b80, 84, 0xbfe63298) = 0xa1ce800
...
...我想知道它_ZNK13QGraphicsItem10parentItemEv
位于哪里。
那么,如何处理共享库符号呢?通读[gcc-help] 回复:查找定义符号的库。;我尝试过这样的事情:
$ find /usr/lib -name '*.so*' -exec nm --print-file-name --defined-only --dynamic {} \; | grep "QGraphicsItem"
...
/usr/lib/libQtGui.so.4.7.2:00766d70 T _Zls6QDebugN13QGraphicsItem16GraphicsItemFlagE
/usr/lib/libQtGui.so.4.7.2:00766aa0 T _Zls6QDebugN13QGraphicsItem18GraphicsItemChangeE
/usr/lib/libQtGui.so.4.7.2:00767e80 T _Zls6QDebugP13QGraphicsItem
...
...但这给我带来了额外的问题:我并不真正知道在我的系统上扫描共享库的所有路径,所以当我第一次尝试时find /lib ...
它没有找到任何东西;我发现这种对目录的猜测令人厌烦,就像替代方案一样:用find
...扫描整个根文件系统而且,我似乎遇到了无法打开的*.so nm
(也许因为它们是符号链接?),其中输出相当多的错误消息(我也不喜欢)。
问题是 - ldd
(或ld
?)可能会执行一些符号查找,但我尝试了相应的联机帮助页,并且我看不到一种从命令行“查找”任何符号的方法,而不提供某种可执行文件作为争论。附带问题 - 有没有办法使用这些工具来实现这一点?
所以,我正在寻找一个命令行工具,其行为类似于(伪代码):
$ ./findsymbol '_Zls6QDebugN13QGraphicsItem16GraphicsItemFlagE'
symbol found in:
/usr/lib/libQtGui.so.4.7.2:00766d70 T _Zls6QDebugN13QGraphicsItem16GraphicsItemFlagE
...
...我没有指定任何要搜索的目录 - 但也可以处理,例如LD_PRELOAD
或LD_LIBRARY_PATH
;说如果我这样做:
$ LD_PRELOAD="/path/to/mylib.so" ./findsymbol '*mylib_print*'
...然后我会得到/path/to/mylib.so
给定符号的定义位置(假设标准库中不存在这样的符号) - 否则会输出“未找到”。否则,./findsymbol --dumpall
可以生成从给定环境(例如特定 shell)看到的所有可用符号及其位置的列表bash
。
Linux 上有这样的工具吗?
答案1
查找库的路径将在文件/etc/ld.so.conf
、环境变量LD_LIBRARY_PATH
和编码到 ELF 二进制文件中的任何 RPATH 中列出。该程序ldd
将告诉您特定应用程序将加载哪些库。
一旦你有了一个你感兴趣的符号,你就可以使用该程序nm
转储.o
和.a
文件的符号,并从一个或任何 elf 可执行文件readelf
转储符号。.so
例子:
nm -g /usr/lib/blah.a
readelf -Ws /usr/lib/blah.so
最后,抛开这些背景,这是你的圣杯:
给定一个符号_ZN6Kopete6Global10PropertiesC2Ev
,这是哪里?
scanelf -l -s _ZN6Kopete6Global10PropertiesC2Ev | grep _ZN6Kopete6Global10PropertiesC2Ev
产生:
ET_DYN _ZN6Kopete6Global10PropertiesC2Ev /usr/lib64/libkopete.so.4.11.4
该-l
标志表示要搜索目录/etc/ld.so.conf
并-s
指定要查找的符号。
答案2
在 GNU 系统上(当使用 GNU libc 动态链接器时),您可以将程序运行为:
LD_DEBUG=bindings kst2
找到符号解析到的位置。
答案3
我在尝试将代码从一个 Linux 系统移植到另一个 Linux 系统时多次遇到过这种情况。通常我只是结束所有标准目录的 grep 操作。我在谷歌上找不到任何东西。所以这是一个快速脚本: