Linux Cant Find Dynamically Linked Applications

Linux Cant find dynamically linked applications

I found the answers.. I mad a simple mistake of not putting the uClibc libraries on my filesystem.

I know have the libraries there and I can run non static applications!

How dynamic-linking know where to find the linked files?

It is well described in the man 8 ld-linux.so man page (links to proper upstream, Linux man-pages project).

In short, simplified a bit (ignoring preloaded libraries, ELF DT_RPATH/DT_RUNPATH, and various options in the binary itself that needs those dynamic libraries):

ld-linux.so looks the library up in the directories specified in LD_LIBRARY_PATH environment variable if defined.

If not defined, or not found there, ld-linux.so checks the /etc/ld.so.cache file: a binary cache, updated by ldconfig administration command (that is automatically run by your package manager whenever necessary), containing the paths to (most) known dynamic libraries.

If not found there, ld-linux.so checks if the library is found in the standard library directories.


Linux uses the ELF file format for binaries and dynamic libraries. This is a very structured format.

Whenever you execute a new ELF binary, at the very end, in Linux it boils down to an execve or execveat syscall (or exec_with_loader syscall on some architectures).

The Linux kernel opens the file, checking for proper permissions, and maps relevant parts of the ELF file into memory. (There is a module, binfmt_misc, for extending the types of files the kernel will execute. In addition to ELF files, the kernel recognizes #! at the very beginning of a file to indicate a script, followed by the path to the script interpreter that will be executed instead.)

If the ELF file was statically linked, the kernel lets the userspace continue execution at the ELF file start point. (Note that this is not the standard C library main(); the standard C library actually links in proper initialization and exit code.)

If the ELF file was dynamically linked, it has a DT_INTERP program header specifying the absolute path to the dynamic linker. (Note that there can be several; typically one for 64-bit binaries, and one for 32-bit binaries.) The kernel will map that into memory, and hand off execution to it instead.

The dynamic linker will stay in memory for the lifetime of the process. It provides useful features exposed by including <dlfcn.h> (see man 3 dl_iterate_phdr and man 3 dlsym in particular). For example, you can dynamically load and unload new ELF libraries at any time. This is commonly used for plugins and plugin-type functionality.

Not only does the dynamic linker find and map in memory all dynamically loaded libraries, and handle their relocation records and symbol tables, it also does some very useful things before handing execution off to the starting point of the original binary. For example, both the Linux dynamic linker and static linkers provide a way to execute functions after all dynamic libraries have been loaded, but before main() is executed (by simply marking the functions __attribute__((constructor)); and similarly for executing functions after main() returns or exit() is called (but not if the process dies due to a signal, or uses _exit()/_Exit(), by marking those functions __attribute__((destructor)).

Note that I above say "map" instead of "load". This is because the Linux kernel memory-maps the data from the storage to memory, instead of "loading" it in the traditional sense. Because of the page cache, this also means that no matter how many copies of a specific program or library you have running, only one copy actually resides in RAM (unless you do certain odd shenanigans, that is).

Finally, the Linux dynamic linker is actually a part of the C library, not the Linux kernel. For further details, go read the glibc runtime dynamic linker sources.

Shared library mysteriously doesn't get linked to application

tl;dr version: Add -Wl,--no-as-needed to the link command.

After a series of experimentation and conversations with the OP, I've figured out what's going on.

In the latest version of Ubuntu, ld uses --as-needed by default. What that does is to remove references to libraries that are not explicitly required.

The way Hoard works is as an LD_PRELOAD library. i.e., you are not supposed to need to use functions in libhoard.so directly. Of course, you could link in libhoard directly if you wanted to...unless --as-needed is used, of course.

After discovering this, the solution is simple. Just add -Wl,--no-as-needed to the gcc linking command.

Linux Program can't find Shared Library at run-time

Symlinks on libraries work fine, as long as the final target they trace to exists and is accessible.

You have built a dynamically-linked executable, that wishes to be linked against libid3-3.8.so.3 at execution time. This was likely linked during the build phase with something like -L/path/to/libid3/directory -lid3.

You have a few options to make libid3 available, in generally decreasing order of preference (since you didn't mention where the file was, I can only be general):

  • Create a symlink to libid3* in a directory listed in /etc/ld.so.conf (or /lib or /usr/lib)
  • Copy libid3* to a directory listed in /etc/ld.so.conf (or /lib or /usr/lib) (defaults)
  • Add the directory containing libid3* to /etc/ld.so.conf
  • Set LD_LIBRARY_PATH=/directory/path/to/libid3* before running your id3v2 executable.
  • Recompile id3v2 statically. (It will work, but don't bother.)

After any of the first 3, rerun ldconfig so the linker cache is updated. (You can then run ldconfig -v to verify it's resolvable.)

Note those aren't steps, they're options. You only need to do 1 of them.

Glad you updated the title. #include directives have nothing to do with linking.

How to show all shared libraries used by executables in Linux?

  1. Use ldd to list shared libraries for each executable.
  2. Cleanup the output
  3. Sort, compute counts, sort by count

To find the answer for all executables in the "/bin" directory:

find /bin -type f -perm /a+x -exec ldd {} \; \
| grep so \
| sed -e '/^[^\t]/ d' \
| sed -e 's/\t//' \
| sed -e 's/.*=..//' \
| sed -e 's/ (0.*)//' \
| sort \
| uniq -c \
| sort -n

Change "/bin" above to "/" to search all directories.

Output (for just the /bin directory) will look something like this:

  1 /lib64/libexpat.so.0
1 /lib64/libgcc_s.so.1
1 /lib64/libnsl.so.1
1 /lib64/libpcre.so.0
1 /lib64/libproc-3.2.7.so
1 /usr/lib64/libbeecrypt.so.6
1 /usr/lib64/libbz2.so.1
1 /usr/lib64/libelf.so.1
1 /usr/lib64/libpopt.so.0
1 /usr/lib64/librpm-4.4.so
1 /usr/lib64/librpmdb-4.4.so
1 /usr/lib64/librpmio-4.4.so
1 /usr/lib64/libsqlite3.so.0
1 /usr/lib64/libstdc++.so.6
1 /usr/lib64/libz.so.1
2 /lib64/libasound.so.2
2 /lib64/libblkid.so.1
2 /lib64/libdevmapper.so.1.02
2 /lib64/libpam_misc.so.0
2 /lib64/libpam.so.0
2 /lib64/libuuid.so.1
3 /lib64/libaudit.so.0
3 /lib64/libcrypt.so.1
3 /lib64/libdbus-1.so.3
4 /lib64/libresolv.so.2
4 /lib64/libtermcap.so.2
5 /lib64/libacl.so.1
5 /lib64/libattr.so.1
5 /lib64/libcap.so.1
6 /lib64/librt.so.1
7 /lib64/libm.so.6
9 /lib64/libpthread.so.0
13 /lib64/libselinux.so.1
13 /lib64/libsepol.so.1
22 /lib64/libdl.so.2
83 /lib64/ld-linux-x86-64.so.2
83 /lib64/libc.so.6

Edit - Removed "grep -P"



Related Topics



Leave a reply



Submit