compile-time ^ run-time linking

https://en.wikipedia.org/wiki/Dynamic_linker describes the “magic” of linking *.so files with some a.out at runtime, This is more unknown and “magical” than compile-time linking.

“Linking is often referred to as a process that is performed when the executable is compiled, while a dynamic linker is a special part of an operating system that loads external shared libraries into a running process”

I now think when the technical literature mentions linking or linker I need to ask “early linker or late linker?”

Can a.so file get loaded 5min after process starts@@

Q: Can some shared library abc.so file get loaded 5 min after my process pid123 starts?

https://stackoverflow.com/questions/7767325/replacing-shared-object-so-file-while-main-program-is-running says NO. This abc.so file has to be loaded into pid123 memory (then dynamically linked into the executable) before main() is called.

Among the 3 major mechanism 1) static linker 2) dynamic linker 3) dlopen, dlopen is able to achieve this purpose but I’m unfamiliar with dlopen.

If pid123 reads a config file to decide whether to load abc.so, then dlopen is the only solution. I saw such an industrial strength implementation in 2019.

A remotely related note — The same stackoverflow webpage also shows that after pid123 starts, you can actually remove (and replace) abc.so without affecting pid123, since the old file content is already loaded into pid123 memory.

LDLibPath ^ classpath

See also compile-time ^ run-time linking

Q: when I run the a.out, where does the runtime linker search for those *.so files?

Now I know the a.out file remembers/stores the dependency *.so file locations. Suppose a.out remembers pspc.so was loaded from ~/a/b/c. At runtime, the linker will try ~/a/b/c/pspc.so  but likely fail… completely normal.

https://docs.oracle.com/cd/E19683-01/816-1386/chapter3-10898/index.html clearly explains that *.so file locations can be saved in a.out as a ‘runpath’. The 2nd-best solution is the ldLIbPath env var.

https://superuser.com/questions/192573/how-do-you-specify-the-location-of-libraries-to-a-binary-linux lead me to the -R and -rpath linker-options.

https://ftp.gnu.org/old-gnu/Manuals/ld-2.9.1/html_node/ld_3.html describes q[ -rpath ] linker option

A c++ executable like a.out using dynamic lib is comparable a java main class using a bunch of jar files.

q[cannot open shared object file] abc.so

strace -e trace=open myprogram can be used on a working instance to see where all the SO files are successfully located.

— Aug 2018 case: in QA host, I hit “error while loading shared libraries: libEazyToFind.so: … No such file or directory”

I can see this .so file so I used LD_LIBRARY_PATH to resolve it.

Then I get “error while loading shared libraries: libXXXXX.so: … No such file or directory”. I can’t locate this .so, but the same executable is runnable in a separate HostB. (All machines can access the same physical file using the same path.)

I zoomed into the HostB and used “ldd /path/to/executable”. Lo and behold, I can see why HostB is lucky. The .so files are located in places local in HostB … for reasons to be understood.

— May 2018 case:

The wording should be “cannot locate ….”

I fixed this error using $LD_LIBRARY_PATH

The *.so  file is actually specified as a -lthr_gcc34_64 option on the g++ command line, but the file libthr_gcc34_64.so was not found at startup.

I managed to manually locate this file in /a/b/c and added it :

LD_LIBRARY_PATH=$LD_LIBRATY_PATH:/a/b/c/

LD_LIBRARY_PATH ^ objdump RUNPATH

This is related to q[cannot open shared object file] abc.so

See https://amir.rachum.com/blog/2016/09/17/shared-libraries/#rpath-and-runpath for the RUNPATH

q(objdump) can inspect the binary file better than q(ldd) does.

q(ldd) shows the final, resolved path of each .so file, but (AFAIK) doesn’t show how it’s resolved. The full steps of resolution is described in http://man7.org/linux/man-pages/man8/ld.so.8.html

q(objdump) can shed some light … in terms of DT_RUNPATH section of the binary file.