查找在实时系统上定义的共享库符号的位置/列出系统上导出的所有符号

sda*_*aau 25 linux dynamic-linking

基本上,这是将两个问题合二为一——因为如果我可以列出系统内导出的所有符号,以及它们的共享库路径,那么我可以简单地grep输出。

对于内核符号,我想它更容易一些 - 因为我们总是可以cat /proc/kallsyms获取内存中加载的那些模块的所有符号的列表;thensudo 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
...
Run Code Online (Sandbox Code Playgroud)

......我想知道它在哪里_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
...
Run Code Online (Sandbox Code Playgroud)

...但这给我带来了额外的问题:我真的不知道在我的系统上扫描共享库的所有路径,所以当我第一次尝试时find /lib ...它没有找到任何东西;我发现这种对目录的猜测令人讨厌,就像替代方案一样:使用find...扫描整个根文件系统而且,我似乎遇到了无法打开的 *.so 文件nm(可能是因为它们是符号链接?),其中输出相当多的错误消息(我也不喜欢)。

问题是 - ldd(或ld?)可能会执行一些符号查找,但我尝试了相应的联机帮助页,但我看不到从命令行“查找”任何符号的方法,而无需提供某种可执行文件作为争论。附带问题 - 有没有办法为此使用这些工具?

所以,我正在寻找一个命令行工具,它的行为类似于(伪代码):

$ ./findsymbol '_Zls6QDebugN13QGraphicsItem16GraphicsItemFlagE'
symbol found in:
    /usr/lib/libQtGui.so.4.7.2:00766d70 T _Zls6QDebugN13QGraphicsItem16GraphicsItemFlagE
...
Run Code Online (Sandbox Code Playgroud)

...我没有指定任何要搜索的目录 - 但也可以处理,例如LD_PRELOADor LD_LIBRARY_PATH; 说如果我这样做:

$ LD_PRELOAD="/path/to/mylib.so" ./findsymbol '*mylib_print*'
Run Code Online (Sandbox Code Playgroud)

...然后我会得到/path/to/mylib.so给定符号的定义位置(假设标准库中不存在这样的符号) - 否则将输出“未找到”。否则,./findsymbol --dumpall可以生成从给定环境(例如特定bash外壳)看到的所有可用符号及其位置的列表。

Linux 是否存在这样的工具?

cas*_*sey 18

查找库的路径将在文件/etc/ld.so.conf、环境变量LD_LIBRARY_PATH和任何编码到 ELF 二进制文件中的RPATH 中列出。该程序ldd将告诉您特定应用程序将加载哪些库。

一旦你有一个你感兴趣的符号,你就可以使用该程序nm来转储文件的符号,.o并从一个或任何 elf 可执行.a文件readelf中转储符号.so。

例子:

nm -g /usr/lib/blah.a
readelf -Ws /usr/lib/blah.so
Run Code Online (Sandbox Code Playgroud)

最后,抛开这些背景,这是你的圣杯:

给定一个符号_ZN6Kopete6Global10PropertiesC2Ev,这是哪里?

scanelf -l -s _ZN6Kopete6Global10PropertiesC2Ev | grep _ZN6Kopete6Global10PropertiesC2Ev
Run Code Online (Sandbox Code Playgroud)

产生:

ET_DYN _ZN6Kopete6Global10PropertiesC2Ev /usr/lib64/libkopete.so.4.11.4
Run Code Online (Sandbox Code Playgroud)

该-l标志表示在其中搜索目录/etc/ld.so.conf并-s指定要查找的符号。

  • @Gilles `scanelf` 允许您指定要搜索的特定目录并使用 `-r` 支持递归搜索,因此您可以调整其搜索路径或搜索整个系统而不会遇到太多麻烦。例如`scanelf -r -s SYMBOL /lib/* /usr/* /opt/*` 将找到库隐藏的大部分位置。 (2认同)

Sté*_*las 8

在 GNU 系统上(使用 GNU libc 动态链接器时),您可以将程序运行为:

LD_DEBUG=bindings kst2
Run Code Online (Sandbox Code Playgroud)

找到符号解析到的位置。