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?
- Use
ldd
to list shared libraries for each executable. - Cleanup the output
- 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
Selenium Doesn't Refresh Page on Jenkins
Sed Is Printing a Substituted Line Twice
Cannot Run Rake Db:Migrate, Relation Does Not Exist
Automating Linux Ebs Snapshots Backup and Clean-Up
Using a Command That Needs Backticks to Be Passed as Part of an Argument in Bash
Why Does Cmake Not Respect Library_Path and Cpath
Does Not Work to Execute Command in Double Brackets in Bash
How to Concatenate Files with the Same Prefix (And Many Prefixes)
Lazarus: How to List All the Available Network Connection on a System
Bash Tail the Newest File in Folder Without Variable
How to Install Poppler for Python 3 in Linux
Error While Installing Respinned/Customized Centos
Check If Opencv Is Compiled with Tbb
What Does Grep -Po '...\K...' Do? How Else Can That Effect Be Achieved