Reputation: 4196
Once an application has been linked with the dynamic libraries it requires, is it possible to find out which exact library has pulled in another one that I'm seeing in the list?
For example, today I had a situation where a library that shouldn't have been there at all in the first place was present in the ldd
output, and was crashing the application. By logical deduction, I could figure it out and isolate the problem, then rebuild the respective project to not include the faulty lib anymore. But is it possible to do the same without any additional knowledge about the application and the libraries it depends on, using an exterrnal tool from the likes of ldd
? (The problem was that the library in question wasn't being used directly by the application, rather by another library that the application was linking to directly.)
In essence, it looks like I'm searching for a way to restore the linking dependency graph once the application has been linked together.
Upvotes: 3
Views: 2419
Reputation: 518
ldd
is ultimately a wrapper script for executing the dynamic linker/loader with variable LD_TRACE_LOADED_OBJECTS
set in environment. For example the following command outputs the same as ldd /bin/ls
in my system:
user@localhost ~ $ LD_TRACE_LOADED_OBJECTS=1 /lib/ld-linux.so.* /bin/ls
linux-gate.so.1 (0xb77bd000)
libacl.so.1 => /lib/libacl.so.1 (0xb7798000)
libc.so.6 => /lib/libc.so.6 (0xb75ef000)
libattr.so.1 => /lib/libattr.so.1 (0xb75e9000)
/lib/ld-linux.so.2 (0x80065000)
There is a plethora of other environment variables for tuning the dynamic linker documented in ld.so(8)
manpage. One of particular interest for discovering the reason a specific library was pulled is LD_DEBUG=files
, that traces what files the linker goes after during processing of the executable:
user@localhost ~ $ LD_TRACE_LOADED_OBJECTS=1 LD_DEBUG=files /lib/ld-linux.so.* /bin/ls
27831: file=/bin/ls [0]; generating link map
27831: dynamic: 0x08064f0c base: 0x00000000 size: 0x0001e034
27831: entry: 0x0804bffc phdr: 0x08048034 phnum: 10
27831:
27831:
27831: file=libacl.so.1 [0]; needed by /bin/ls [0]
27831: file=libacl.so.1 [0]; generating link map
27831: dynamic: 0xb772ced8 base: 0xb7724000 size: 0x0000917c
27831: entry: 0xb77257f0 phdr: 0xb7724034 phnum: 7
27831:
27831:
27831: file=libc.so.6 [0]; needed by /bin/ls [0]
27831: file=libc.so.6 [0]; generating link map
27831: dynamic: 0xb771fda4 base: 0xb757b000 size: 0x001a8eac
27831: entry: 0xb75937b0 phdr: 0xb757b034 phnum: 11
27831:
27831:
27831: file=libattr.so.1 [0]; needed by /lib/libacl.so.1 [0]
27831: file=libattr.so.1 [0]; generating link map
27831: dynamic: 0xb7579ef0 base: 0xb7575000 size: 0x000050bc
27831: entry: 0xb7575ed0 phdr: 0xb7575034 phnum: 7
27831:
linux-gate.so.1 (0xb7749000)
libacl.so.1 => /lib/libacl.so.1 (0xb7724000)
libc.so.6 => /lib/libc.so.6 (0xb757b000)
libattr.so.1 => /lib/libattr.so.1 (0xb7575000)
/lib/ld-linux.so.2 (0x80094000)
In the above example, we see that libacl.so.1
and libc.so.6
were required by /bin/ls
itself, and libattr.so.1
was pulled as a requirement of libacl.so.1
.
Upvotes: 6
Reputation: 119877
Run ldd on each of the libraries reported by ldd executable
. Continue recursively until the culprit is found.
Alternatively, run
objdump -p /path/to/program-or-library | grep NEEDED
recursively.
Upvotes: 2
Reputation: 62563
To know this you will have to use readelf
recursively. First run it on your executable, and look for NEEDED libraries. This will tell you what your executable needs directly. After that you should iteratively repeat the process for every library which is needed, and once you arrive at the library in question you will know the inclusion path.
Upvotes: 1