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

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

基本上,这是两个问题合二为一 - 因为如果我可以列出系统中导出的所有符号及其共享库路径,那么我就可以简单地输出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_PRELOADLD_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 操作。我在谷歌上找不到任何东西。所以这是一个快速脚本:

edt11x/findinsharedlibs

相关内容