I Need to List The Programs Which Have a Specified Shared Library Linked to Them in Unix/Linux (Like Ldd But Vice Versa)

I need to list the programs which have a specified shared library linked to them in UNIX/Linux (like ldd but vice versa)

I highly doubt there would be. That would require keeping a database of all executables and remembering what they depend on, which may be possible if you only install software from a specific channel, but it certainly won't be able to track executables you produce otherwise. Not to mention such a database is largely useless and therefore not attractive.

If you need to find such executables however (e.g. to know if it's safe to remove the shared library), you can easily find most of them. The key is that most of the executables you have are inside /usr/bin or /usr/local/bin or similar locations. So all you need is to run ldd on all files inside those directories and grep for the library you are looking for.

Is there a C++ API Linux System call that tells you which shared libraries your executable has linked?

You can use dl_iterate_phdr:

#define _GNU_SOURCE
#include <link.h>
#include <stdlib.h>
#include <stdio.h>

static int callback(struct dl_phdr_info *info, size_t size, void *data) {
printf("name=%s (%d segments)\n", info->dlpi_name, info->dlpi_phnum);
return 0;
}

int main() {
dl_iterate_phdr(callback, NULL);
return 0;
}

This program will produce the following output:

name= (9 segments)
name= (4 segments)
name=/lib64/libdl.so.2 (7 segments)
name=/lib64/libc.so.6 (10 segments)
name=/lib64/ld-linux-x86-64.so.2 (7 segments)

How to check shared library version in the binary

I use dl_iterate_phdr function to find out which shared objects are loaded. This is example of dl handler that prints shared libs info

static int header_handler(struct dl_phdr_info* info, size_t size, void* data)
{
printf("name=%s (%d segments) address=%p\n",
info->dlpi_name, info->dlpi_phnum, (void*)info->dlpi_addr);
for (int j = 0; j < info->dlpi_phnum; j++) {
printf("\t\t header %2d: address=%10p\n", j,
(void*) (info->dlpi_addr + info->dlpi_phdr[j].p_vaddr));
printf("\t\t\t type=%u, flags=0x%X\n",
info->dlpi_phdr[j].p_type, info->dlpi_phdr[j].p_flags);
}
printf("\n");
return 0;
}

It is taken from here

It prints for my video processing project following :

name=/usr/local/lib/libopencv_highgui.so.2.4 (7 segments) address=0x7f467935a000
name=/usr/local/lib/libopencv_imgproc.so.2.4 (7 segments) address=0x7f46796e9000
...

Opencv includes the version in the name of library libopencv_imgproc.so*.2.4* .
This way i know wich opencv version loaded. I don't know if it is good for your libraries, but it can be a starting point for your.

Why don't the programs implemented by Golang use the functions of libc.so.6, such as socket()?

Why don't the programs implemented by Go[...] use the functions of libc.so.6.

Because Go uses direct syscalls to the underlying OS.

Tracing linked libraries

Actually ldd gives you absolute path with filename of whatever from your application's shared library dependencies it's able to find.

    $ ldd v8test 
linux-gate.so.1 => (0xb78b2000)
libz.so.1 => /usr/lib/libz.so.1 (0xb787e000)
librt.so.1 => /lib/i686/cmov/librt.so.1 (0xb7875000)
libcppunit-1.12.so.1 => /usr/lib/libcppunit-1.12.so.1 (0xb782c000)
libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0xb7604000)
libm.so.6 => /lib/i686/cmov/libm.so.6 (0xb75dd000)
libgcc_s.so.1 => /lib/libgcc_s.so.1 (0xb75bf000)
libc.so.6 => /lib/i686/cmov/libc.so.6 (0xb7478000)
libpthread.so.0 => /lib/i686/cmov/libpthread.so.0 (0xb745f000)
libboost_system-mt.so.1.38.0 => /usr/lib/libboost_system-mt.so.1.38.0 (0xb745b000)
/lib/ld-linux.so.2 (0xb78b3000)
libdl.so.2 => /lib/i686/cmov/libdl.so.2 (0xb7456000)
libboost_thread-mt.so.1.38.0 => /usr/lib/libboost_thread-mt.so.1.38.0 (0xb7383000)
libboost_filesystem-mt.so.1.38.0 => /usr/lib/libboost_filesystem-mt.so.1.38.0 (0xb7370000)
libtinyxml.so.1 => /home/dmitry/tinyxml/libtinyxml.so.1 (0xb7359000)
libboost_regex-mt.so.1.38.0 => /usr/lib/libboost_regex-mt.so.1.38.0 (0xb728c000)
libmysqlclient_r.so.15 => /usr/lib/libmysqlclient_r.so.15 (0xb70a1000)
libicuuc.so.42 => /usr/lib/libicuuc.so.42 (0xb6f61000)
libicudata.so.42 => /usr/lib/libicudata.so.42 (0xb601a000)
libicui18n.so.42 => /usr/lib/libicui18n.so.42 (0xb5e6b000)
libcrypt.so.1 => /lib/i686/cmov/libcrypt.so.1 (0xb5e39000)
libnsl.so.1 => /lib/i686/cmov/libnsl.so.1 (0xb5e22000)

The libraries are searched by its soname (e.g. libboost_filesystem-mt.so.1.38.0) in paths mentioned in /etc/ld.so.conf, LD_LIBRARY_PATH or set with rpath in the binary itself.

If ldd is unable to find something it will look like

    libicuuc.so.42 => not found

In this case consider using one of the mentioned ways to give correct search path.

ldd will warn you when it's unable to load the library due to some reason.

$ ldd v8test 
./v8test: error while loading shared libraries: /home/dmitry/a/liba.so.2: invalid ELF header

Of course it can't protect you from the errors in the library itself. In fact it's possible your application to depend on libraries A and B, both depending on incompatible versions on some library C. In this situation your program has a good chance to crash (unless library C doesn't have symbol versioning) - ldd is not going to warn you, but you should be able to see it in the output.

Program-Library-HOWTO will be useful for you.

Check also some options of ldd or dynamic linker.

Do libraries reported by ldd resolve all undefined references of an input library?

Does ldd print only libraries from DT_NEEDED structures of .dynamic section?

No, that is what readelf --dynamic does.

what is the use of ldd at all?

ldd shows what libraries the runtime linker ld.so loads when starting your executable or loading a shared library. This is a recursive process, e.g. an executable needs a shared library (DT_NEEDED), so that library gets loaded. Then it proceeds to load the dependencies of the loaded library (DT_NEEDED) and so on.

You don't necessarily need ldd, you can just set LD_DEBUG=all environment variable to make ld.so print that information and more. See man ld.so for more information.

Each loaded executable or shared library expose their defined exported dynamic symbols as a lookup scope (a hash table). Lookup scopes form a list. When resolving an undefined symbol ld.so walks the lookup scopes and finds the first one that defines the symbol and resolve the symbol reference. If ld.so reaches the end of lookup scopes it reports the symbol as unresolved.

There is no correspondence between the unresolved symbol name and an executable/shared library it is supposed to come from. ld.so loads all shared libraries from DT_NEEDED sections recursively, builds that list of lookup scopes and then looks for unresolved symbols in there.

How To Write Shared Libraries by U. Drepper explains this in full detail.

How to check shared library version in the binary

I use dl_iterate_phdr function to find out which shared objects are loaded. This is example of dl handler that prints shared libs info

static int header_handler(struct dl_phdr_info* info, size_t size, void* data)
{
printf("name=%s (%d segments) address=%p\n",
info->dlpi_name, info->dlpi_phnum, (void*)info->dlpi_addr);
for (int j = 0; j < info->dlpi_phnum; j++) {
printf("\t\t header %2d: address=%10p\n", j,
(void*) (info->dlpi_addr + info->dlpi_phdr[j].p_vaddr));
printf("\t\t\t type=%u, flags=0x%X\n",
info->dlpi_phdr[j].p_type, info->dlpi_phdr[j].p_flags);
}
printf("\n");
return 0;
}

It is taken from here

It prints for my video processing project following :

name=/usr/local/lib/libopencv_highgui.so.2.4 (7 segments) address=0x7f467935a000
name=/usr/local/lib/libopencv_imgproc.so.2.4 (7 segments) address=0x7f46796e9000
...

Opencv includes the version in the name of library libopencv_imgproc.so*.2.4* .
This way i know wich opencv version loaded. I don't know if it is good for your libraries, but it can be a starting point for your.



Related Topics



Leave a reply



Submit