Linux – Find where is a shared library symbol defined on a live system / list all symbols exported on a system

dynamic-linkinglinux

Basically, this is two questions into one – because if I can list all symbols exported within a system, along with their shared library path, then I could simply grep that output.

For kernel symbols, I guess it is somewhat easier – because we can always cat /proc/kallsyms and get a list of all symbols of those modules loaded in memory; then sudo cat /proc/modules will give a list of loaded modules with their addresses, but not the paths where does modules have been loaded from (if they are built as separate, out-of-tree .ko objects)

For instance, I try to trace the program kst using 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
...

… and I would like to know where this _ZNK13QGraphicsItem10parentItemEv resides.

So, what to do about shared library symbols? Reading through [gcc-help] Re: finding the library in which symbol is defined.; I tried something like this:

$ 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
...

… but that gives me additional problems: I don't really know all the paths which are scanned for shared libraries on my system, so when I first tried find /lib ... it didn't find anything; I find this guessing of directories irksome, just as well as the alternative: scanning the entire root filesystem with find … And also, I seem to hit up *.so's which cannot be opened by nm (maybe because they are symlinks?), which output a quite a bit of error messages (which I don't like either).

The thing is – ldd (or ld?) probably performs some of this lookup of symbols, but I tried the respective manpages, and I cannot see a way to "find" any symbol from the command line, without providing some sort of executable file as an argument. Side question – would there a way to use these tools for that?

So, what I'm looking for a command line tool, which would behave something like (pseudocode):

$ ./findsymbol '_Zls6QDebugN13QGraphicsItem16GraphicsItemFlagE'
symbol found in:
    /usr/lib/libQtGui.so.4.7.2:00766d70 T _Zls6QDebugN13QGraphicsItem16GraphicsItemFlagE
...

… where I don't specify any directories to search – but which would also handle, e.g. LD_PRELOAD or LD_LIBRARY_PATH; say if I do:

$ LD_PRELOAD="/path/to/mylib.so" ./findsymbol '*mylib_print*'

… then I'd get the /path/to/mylib.so where the given symbol was defined (given that such a symbol wouldn't exist in the standard libraries) – and would output "not found" otherwise. And otherwise, ./findsymbol --dumpall could produce a list of all available symbols and their locations seen from a given environment (e.g. a specific bash shell).

Does a tool like this exist for Linux?

Best Answer

The paths to look for libraries in will be listed in the file /etc/ld.so.conf, the environment variable LD_LIBRARY_PATH and any RPATHs encoded into the ELF binary. The program ldd will tell you what libraries a specific application will load.

Once you have a symbol you are curious about, you can use the program nm to dump symbols of .o and .a files and readelf to dump symbols from a .so or any elf executable.

Examples:

nm -g /usr/lib/blah.a
readelf -Ws /usr/lib/blah.so

And finally, with that background aside, here is your holy grail:

Given a symbol _ZN6Kopete6Global10PropertiesC2Ev, where is this?

scanelf -l -s _ZN6Kopete6Global10PropertiesC2Ev | grep _ZN6Kopete6Global10PropertiesC2Ev

which yields:

ET_DYN _ZN6Kopete6Global10PropertiesC2Ev /usr/lib64/libkopete.so.4.11.4

The -l flag says to search dirs in /etc/ld.so.conf and the -s specifies the symbol to find.

Related Question