How does this program statically link to a .so in a non-default path

A program I am using can only be installed with a custom installer (IDA Freeware Demo). I have installed it in my home dir, it all works fine.

Now I noticed when checking the program with ldd: it ships with its own Qt libraries, which is places as shared libraries in its install dir (so the same directory its main executable file resides in, not /usr/lib or similar).

$ ldd ida64
    linux-vdso.so.1 =>  (0x00007ffec5fb9000)
    libida64.so => /home/asdf/idafree-7.0/./libida64.so 
    libQt5PrintSupport.so.5 => /home/asdf/idafree-7.0/./libQt5PrintSupport.so.5
    libQt5Widgets.so.5 => /home/asdf/idafree-7.0/./libQt5Widgets.so.5 
....

(install dir = /home/asdf/idafree-7.0/)

Now I wonder: How does it do that? I execute the program directly without any LD_LIB_PATH magic.


Solution 1:

This is completely different from and unrelated to static linking. While I suppose a wrapper script could modify LD_LIBRARY_PATH before launching the program, that's not what IDA does.

When a shared library is first linked from its constituent object files, a runtime path can be specified, i.e. the --set-rpath (short form -r) flag. This informs the loader to look in the named directory before looking elsewhere. The path may be hard coded, or it may use the $ORIGIN flag.

The $ORIGIN flag allows the loader to resolve the executable's current filepath, which in turn allows an rpath to more readily work from any directory. IDA was likely just built with a flag such as -Wl,-r,$ORIGIN. If the Qt libraries had been in a subdirectory, it would just be -Wl,-r,$ORIGIN/qtlibdir.

There are also utilities that can edit this field after linking, such as patchelf.

All of this information may be found in the ld manual. https://man7.org/linux/man-pages/man1/ld.1.html