Home > Net >  How to force .so dependency to be in same directory as library
How to force .so dependency to be in same directory as library

Time:03-12

I have a libA.so that depends on libB.so and having trouble finding it even though it's in the same directory.

ldd libA.so
linux-vdso.so.1 (0x00007fff50bdb000)
libB.so => not found
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f4aeb902000)
/lib64/ld-linux-x86-64.so.2 (0x00007f4aebadb000)

I'm wondering if there is a way to make libA.so always look for libB.so in the same directory as this will be the case for my application? I know updating LD_LIBRARY_PATH is an option as well but wanted to reduce the amount of work required.

CodePudding user response:

From 'man 8 ld.so':

   If a shared object dependency does not contain a slash, then it
   is searched for in the following order:

   o  Using the directories specified in the DT_RPATH dynamic
      section attribute of the binary if present and DT_RUNPATH
      attribute does not exist.  Use of DT_RPATH is deprecated.

   o  Using the environment variable LD_LIBRARY_PATH, unless the
      executable is being run in secure-execution mode (see below),
      in which case this variable is ignored.

   o  Using the directories specified in the DT_RUNPATH dynamic
      section attribute of the binary if present.  Such directories
      are searched only to find those objects required by DT_NEEDED
      (direct dependencies) entries and do not apply to those
      objects' children, which must themselves have their own
      DT_RUNPATH entries.  This is unlike DT_RPATH, which is applied
      to searches for all children in the dependency tree.

   o  From the cache file /etc/ld.so.cache, which contains a
      compiled list of candidate shared objects previously found in
      the augmented library path.  If, however, the binary was
      linked with the -z nodeflib linker option, shared objects in
      the default paths are skipped.  Shared objects installed in
      hardware capability directories (see below) are preferred to
      other shared objects.

   o  In the default path /lib, and then /usr/lib.  (On some 64-bit
      architectures, the default paths for 64-bit shared objects are
      /lib64, and then /usr/lib64.)  If the binary was linked with
      the -z nodeflib linker option, this step is skipped.

The key here is to use the DT_RUNPATH, which can be embedded into the binary you are creating. You can link it so that it points to the same directory, as you wanted.

See this post about how to do this: https://stackoverflow.com/a/67131878

CodePudding user response:

The .dynamic section of an ELF file (.so libraries on Linux use ELF format) contains information to help the library find its dependencies. .dynamic entries with type DT_NEEDED contain the names of other .so files for the dynamic linker to find, but they do not contain any information on where to find those files. For that, as you mentioned, you can use LD_LIBRARY_PATH, but the ELF format also provides a way to specify it in the file itself.

A .dynamic entry with type DT_RUNPATH gives the dynamic linker a path to a directory where the dynamic linker should look for DT_NEEDED files. DT_RUNPATH allows a special variable, $ORIGIN, which refers to the file's current directory. This allows you to use relative paths, without requiring the user to invoke an executable from a specific working directory.

You use the -rpath linker flag to specify a DT_RUNPATH entry. In order to pass the literal string $ORIGIN, however, you must wrap it in single quotes to prevent your shell from interpreting it as an environment variable.

Assuming you are using gcc, you should use add this argument to the link step:

-Wl,-rpath,'$ORIGIN'
  • Related