Can I add a library refence to existing Shared Object?
Asked Answered
M

3

12

I have a system "fsimage.so" that requires mkdirp, which just happens to live in libgen.so. But fsimage.so does not know this. For example:

# ldd /usr/lib/python2.4/vendor-packages/fsimage.so
    libfsimage.so.1.0 =>     /usr/lib/libfsimage.so.1.0
    libxml2.so.2 =>  /lib/libxml2.so.2
    libgcc_s.so.1 =>         /usr/sfw/lib/libgcc_s.so.1
    libpthread.so.1 =>       /lib/libpthread.so.1
    libz.so.1 =>     /lib/libz.so.1
    libm.so.2 =>     /lib/libm.so.2
    libsocket.so.1 =>        /lib/libsocket.so.1
    libnsl.so.1 =>   /lib/libnsl.so.1
    libc.so.1 =>     /lib/libc.so.1
    libmp.so.2 =>    /lib/libmp.so.2
    libmd.so.1 =>    /lib/libmd.so.1

# ./test
Traceback (most recent call last):
  File "./test", line 26, in ?
    import fsimage
ImportError: ld.so.1: isapython2.4: fatal: relocation error: file /usr/lib/python2.4/vendor-packages/fsimage.so: symbol mkdirp: referenced symbol not found

# LD_PRELOAD=/usr/lib/libgen.so ./test
Usage: ./test

Naturally, if I had the sources etc, I could simply link it again, and add "-lgen", and it will add libgen.so as a dependency.

But as an exercise in hackery, say I do not have any sources, and simply wanted to add that fsimage.so needs to also load libgen.so. Using elfedit/objcopy etc, is this not possible? I don't suppose I can use "ld" to use .so as input, and write a new .so with extra library?

# elfdump /usr/lib/python2.4/vendor-packages/fsimage.so|grep NEEDED
   [0]  NEEDED            0x5187              libfsimage.so.1.0
   [1]  NEEDED            0x5152              libxml2.so.2
   [2]  NEEDED            0x5171              libgcc_s.so.1

First attempt at stackoverflow, go easy on me :)

Metz answered 19/11, 2010 at 3:37 Comment(0)
M
10

Thank you "Employed Russian", you gave me the information needed to search deeper. Solaris already ships with "elfedit", so if others wants to know, these are the instructions

# elfedit libfsimage.so.1.0.0 libfsimage.so.1.0.0-new
> dyn:value DT_NEEDED
 index  tag                value
   [0]  NEEDED            0x4f81              libpthread.so.1
   [1]  NEEDED            0x4fac              libxml2.so.2
   [2]  NEEDED            0x4fc2              libgcc_s.so.1
> dyn:value -add -s DT_NEEDED libscf.so
 index  tag                value
  [35]  NEEDED            0x500d              libscf.so
> dyn:value DT_NEEDED
 index  tag                value
   [0]  NEEDED            0x4f81              libpthread.so.1
   [1]  NEEDED            0x4fac              libxml2.so.2
   [2]  NEEDED            0x4fc2              libgcc_s.so.1
  [35]  NEEDED            0x500d              libscf.so
> :write
> :quit

# ldd libfsimage.so.1.0.0-new
    libpthread.so.1 =>       /lib/libpthread.so.1
    libxml2.so.2 =>  /lib/libxml2.so.2
    libgcc_s.so.1 =>         /usr/sfw/lib/libgcc_s.so.1
    libscf.so =>     /lib/libscf.so
    libz.so.1 =>     /lib/libz.so.1
    libm.so.2 =>     /lib/libm.so.2
    libsocket.so.1 =>        /lib/libsocket.so.1
    libnsl.so.1 =>   /lib/libnsl.so.1
    libc.so.1 =>     /lib/libc.so.1
    libuutil.so.1 =>         /lib/libuutil.so.1
    libgen.so.1 =>   /lib/libgen.so.1
    libnvpair.so.1 =>        /lib/libnvpair.so.1
    libsmbios.so.1 =>        /usr/lib/libsmbios.so.1
    libmp.so.2 =>    /lib/libmp.so.2
    libmd.so.1 =>    /lib/libmd.so.1
Metz answered 22/11, 2010 at 0:1 Comment(1)
I run elfedit with the so I want to edit as first arg and a newname for the second and nothing happens. The help is shown. I'm on Linux though.Cyrillic
H
7

Not easily.

Most UNIX systems (AIX is a notable exception) consider *.so a "final" link product, and it is not suitable as an input for any further link.

To add a new DT_NEEDED tag to the dynamic section of fsimage.so, you would need to rewrite its .dynamic section. Removing an entry from .dynamic is relatively easy -- you can just "slide" the other entries up, and replace the last entry with DT_NULL.

On the other hand, adding a new entry requires that you append a whole new .dynamic section to the file, and then update all pointers (offsets) within fsimage.so to point to the new section. This requires "deep" understanding of the ELF format.

There are existing tools to do this, e.g. rpath but I've had mixed success with it.

Hamm answered 20/11, 2010 at 16:43 Comment(1)
I suspected as such. I know Solaris will leave 512 bytes of space in ELF, so you can easily add new sections, like text etc. But not (directly/easily) expanding DT_NEEDED sections. Still interesting learning. For now, I could recompile my python and add the libraries I wanted, but entered a separate mess of 32bit vs 64bit. Sigh :)Metz
A
4

You can use PatchELF. Release 0.9 is out since 29 Feb 2016 and lets you:

  • Change the dynamic loader ("ELF interpreter") of executables
  • Change the RPATH of executables and libraries
  • Shrink the RPATH of executables and libraries
  • Remove declared dependencies on dynamic libraries (DT_NEEDED entries)
  • Add a declared dependency on a dynamic library (DT_NEEDED)
  • Replace a declared dependency on a dynamic library with another one (DT_NEEDED)
  • Change SONAME of a dynamic library

In your case:

$ patchelf --add-needed /usr/lib/libgen.so /usr/lib/python2.4/vendor-packages/fsimage.so
Alamo answered 24/9, 2015 at 9:14 Comment(1)
The most recent stable release [v0.8][1] has only --remove-needed LIBRARY and not add, probably for the reason stated by lundman in the accepted version. However the [development version in github][2] does have the --add-library option as well, so this could be the way to go [1]:github.com/NixOS/patchelf/blob/0.8/src/patchelf.cc [2]:github.com/NixOS/patchelf/blob/master/src/patchelf.ccLiegeman

© 2022 - 2024 — McMap. All rights reserved.