28

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?

3 Answers 3

21

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.

3
  • 1
    This is incomplete: some programs load libraries from application-specific directories. Commented Dec 5, 2013 at 1:08
  • 4
    @Gilles scanelf allows you to specify specific directories to search in and support recursive seaching with -r so you can tweak its search paths or search your entire system without too much trouble. For example scanelf -r -s SYMBOL /lib/* /usr/* /opt/* will find most of the places libraries are hiding.
    – casey
    Commented Dec 5, 2013 at 3:41
  • @casey I think you mean -R for recursive search, see man page. Also, the * at the end of /lib/* is probably redundant.
    – rvernica
    Commented Jan 10, 2023 at 4:48
9

On GNU systems (when using the GNU libc dynamic linker), you can run your program as:

LD_DEBUG=bindings kst2

To find where the symbols resolve to.

0

I have run into this a number of times, trying to port code from one Linux system to another. Usually I just end up grep'ing all the standard directories. I couldn't find anything googling. So here is a quick script:

edt11x/findinsharedlibs

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .