Considering lshw
as a sample program, here is what ldd
gives:
$ ldd /usr/sbin/lshw
linux-vdso.so.1 => (0x00007fff8bdaf000)
libresolv.so.2 => /lib64/libresolv.so.2 (0x000000360e400000)
libsqlite3.so.0 => /lib64/libsqlite3.so.0 (0x0000003631600000)
libstdc++.so.6 => /lib64/libstdc++.so.6 (0x000000360ec00000)
libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x000000360d800000)
libc.so.6 => /lib64/libc.so.6 (0x000000360c000000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x000000360cc00000)
libdl.so.2 => /lib64/libdl.so.2 (0x000000360c800000)
libm.so.6 => /lib64/libm.so.6 (0x000000360c400000)
/lib64/ld-linux-x86-64.so.2 (0x000000360bc00000)
If I want to find the absolute locations of the shared libraries (and want to exclude linux-vdso.so.1 for obvious reasons), how do I go about it? Using
awk with regular expressions seems brittle here. ldd
has a verbose flag (-v) which does print the complete paths of the shared libraries, but it is not very friendly for machine reading.
Is there another way to go about this? If someone knows of a system call to do so, I am fine with that too.
PS: For a bit of context, I want to run this program in chroot
jail, so I need to make sure that the shared libraries are all available. Compiling it statically works without all this drama, but that is a path I am looking to avoid.
Update:
I think I may have found something which may be more suitable while reading Michael Kerrisk's book, "The Linux Programming Interface". If I run a program as $ LD_DEBUG=libs lshw
, it outputs various helpful information. For example:
$ LD_DEBUG=libs lshw
32058: find library=libresolv.so.2 [0]; searching
32058: search cache=/etc/ld.so.cache
32058: trying file=/lib64/libresolv.so.2
32058:
32058: find library=libstdc++.so.6 [0]; searching
32058: search cache=/etc/ld.so.cache
32058: trying file=/lib64/libstdc++.so.6
32058:
32058: find library=libgcc_s.so.1 [0]; searching
32058: search cache=/etc/ld.so.cache
32058: trying file=/lib64/libgcc_s.so.1
32058:
32058: find library=libc.so.6 [0]; searching
32058: search cache=/etc/ld.so.cache
32058: trying file=/lib64/libc.so.6
32058:
32058: find library=libm.so.6 [0]; searching
32058: search cache=/etc/ld.so.cache
32058: trying file=/lib64/libm.so.6
32058:
32058:
32058: prelink checking: ok
32058:
32058: calling init: /lib64/ld-linux-x86-64.so.2
32058:
32058:
32058: calling init: /lib64/libc.so.6
32058:
32058:
32058: calling init: /lib64/libm.so.6
32058:
32058:
32058: calling init: /lib64/libgcc_s.so.1
32058:
32058:
32058: calling init: /lib64/libstdc++.so.6
32058:
32058:
32058: calling init: /lib64/libresolv.so.2
<more output>
I think, if I look for the 'calling init' lines, I will have the shared library paths it is initializing before starting to execute the program.