Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to know which library pulled in another one using ldd?

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.

like image 596
iksemyonov Avatar asked Jan 01 '26 03:01

iksemyonov


2 Answers

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.

like image 157
coolparadox Avatar answered Jan 03 '26 17:01

coolparadox


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.

like image 38
n. 1.8e9-where's-my-share m. Avatar answered Jan 03 '26 17:01

n. 1.8e9-where's-my-share m.



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!