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


21

基本上,这是两个问题合而为一-因为如果我可以列出系统中导出的所有符号以及它们的共享库路径,那么我可以简单地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] Re:查找定义了符号的库。; 我尝试过这样的事情:

$ 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?)可能执行了一些这种符号查找,但是我尝试了各自的联机帮助页,并且在没有提供某种可执行文件作为命令的情况下,我看不到从命令行“查找”任何符号的方法。论点。附带问题-是否可以使用这些工具?

因此,我正在寻找一种命令行工具,其行为类似于(pseudocode):

$ ./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可能会产生从给定环境(例如特定bash外壳)看到的所有可用符号及其位置的列表。

Linux是否存在这样的工具?

Answers:


16

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

一旦您对符号感到好奇,就可以使用该程序nm转储.o.a文件的符号,并readelf转储a .so或任何elf可执行文件中的符号。

例子:

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指定要查找的符号。


这是不完整的:某些程序从特定于应用程序的目录加载库。
吉尔(Gilles)'所以

2
@Gilles scanelf允许您指定要搜索的特定目录并支持递归搜索,-r因此您可以调整其搜索路径或搜索整个系统而不会遇到太多麻烦。例如,scanelf -r -s SYMBOL /lib/* /usr/* /opt/*将发现图书馆隐藏的大多数地方。
casey 2013年

7

在GNU系统上(使用GNU libc动态链接器时),您可以通过以下方式运行程序:

LD_DEBUG=bindings kst2

查找符号解析到的位置。


0

我已经遇到过很多次,试图将代码从一个Linux系统移植到另一个。通常,我最终只能使用grep's所有标准目录。我找不到任何谷歌搜索。因此,这是一个快速脚本:

edt11x / findinsharedlibs

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.