Add a dependency to an existing shared object library

0

Say that I have three libraries: libMissingSymbol.so, libMiddle.so, and libSymbolHaver.so. libMissingSymbol contains a symbol defined in libSymbolHaver, but only has a dependency on libMiddle. libMiddle is supposed to have a dependency on libSymbolHaver, but it doesn't. I don't have the source code or unlinked object files that these libraries were assembled from. Is it possible for me to link libMiddle with libSymbolHaver so that libMissingSymbol can find the symbol it needs at load time? Is there any way that I can fix this using only these three shared object files and any necessary tools? I have to end up with libraries with the same contents (including SONAMEs) barring the dependency change to libMiddle in order to not break things further down the line in my project.

Hypothetical readelf output (trimmed for relevance) to clarify:

$ readelf -s libMissingSymbol.so
123: 00000000     0 OBJECT  GLOBAL DEFAULT  UND MangledSymbol

$ readelf -d libMissingSymbol.so
Dynamic section at offset 0x42434 contains 37 entries:
  Tag        Type                         Name/Value
 0x00000001 (NEEDED)                     Shared library: [libMiddle.so]
 0x0000000e (SONAME)                     Library soname: [libMissingSymbol.so]

$ readelf -d libMiddle.so 
Dynamic section at offset 0x75b28 contains 29 entries:
  Tag        Type                         Name/Value
 0x0000000e (SONAME)                     Library soname: [libMiddle.so]

$ readelf -s libSymbolHaver.so
     35: 00064d0c     4 OBJECT  GLOBAL DEFAULT   22 MangledSymbol
c++
linker
ld
asked on Stack Overflow Jan 20, 2017 by Thomas DeSilva • edited Jan 20, 2017 by Thomas DeSilva

1 Answer

1

Is it possible for me to link libMiddle with libSymbolHaver so that libMissingSymbol can find the symbol it needs at load time?

No: all UNIX linkers, except the AIX one, consider .so the final link product and no further modification is possible.

Update:

viability of doing this a different way (e.g. decompiling libMiddle and rebuilding it with the correct dependencies)?

I don't believe that is viable either -- it is really hard to modify a fully-linked ELF file and not violate myriad of internal consistency constraints.

I suggest the following approach, which is very likely to just work(TM).

  1. Abandon your "only using these three libraries" restriction. It appears to be artificial and unnecessary.

  2. Copy libMiddle.so -> libZiddle.so (be sure to make a copy of the original libMiddle.so somewhere else in case things go wrong).

  3. binary-patch the SONAME in libZiddle.so to match the new name. The string "libMiddle.so" is in the .dynstr section of the library, and (I believe) is not hashed in any way, so changing one letter in it will not introduce any self-inconsistencies into the new library.

    Once you've done this, compare readelf -a libMiddle.so and readelf -a libZiddle.so, the SONAME should be the only difference.

  4. Remove libMiddle.so.

  5. Link a new libMiddle.so containing some_unused_function(), and having dynamic dependency on both libZiddle.so and libSymbolHaver.so.

Now any binary that currently links against libMiddle.so and fails with missing symbol (e.g. libMissingSymbol.so) will find the new (empty) libMiddle.so, but because the new libMiddle.so requires both libZiddle.so (where most of the symbols are) and libSymbolHaver.so, it should just work.

answered on Stack Overflow Jan 24, 2017 by Employed Russian • edited Jun 20, 2020 by Community

User contributions licensed under CC BY-SA 3.0