Pack Shared Libraries into the Elf

Pack shared libraries into the elf

Here are some projects you might find useful:

  • Statifier (basically does what you want)
  • ERESI (might do what you want, also allows for analysis of ELF targets)

NOTE: I've not used either application myself.

Can I add a library refence to existing Shared Object?

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

Linux ELF file: How to get the shared object belonging to an imported function


How can I find out from which shared library/shared object the strcp function is obtained?

In general you can't: that library can change at runtime. For example, if I compile the following source:

int strcpy(char *a, const char *src) { abort(); }

$ gcc -fPIC -shared -o foo.so foo.c

and then run your program like so:

LD_PRELOAD=./foo.so /bin/less

then the library from which strcpy is obtained is foo.so. Using LD_PRELOAD this way is called library interpositioning, and is useful in all kinds of circumstances.

There are other ways to inject a different library into the process besides LD_PRELOAD.

If you are not using any such mechanisms, and are using GLIBC, then you can ask the dynamic loader to answer that question for you. Here is one way:

 LD_DEBUG=bindings ldd -r /bin/less < /dev/null |& egrep '\Wstrcpy\W'
26623: binding file /bin/bash [0] to /lib/x86_64-linux-gnu/libc.so.6 [0]: normal symbol `strcpy' [GLIBC_2.2.5]
26633: binding file /lib/x86_64-linux-gnu/libtinfo.so.5 [0] to /lib/x86_64-linux-gnu/libc.so.6 [0]: normal symbol `strcpy' [GLIBC_2.2.5]
26633: binding file /bin/less [0] to /lib/x86_64-linux-gnu/libc.so.6 [0]: normal symbol `strcpy' [GLIBC_2.2.5]

Above you can see that ldd invokes bash and less as separate processes, and both of them bind to libc.so.6 for this particular symbol.

How can I programmatically find the corresponding shared object (.so file) to an (imported) function?

If you are using GLIBC, use dladdr to "ask" the dynamic linker. Returned "info" argument will tell you the filename.

How to combine shared libraries?

This assumes you have the source code to all shared objects:

Provided there are no name space conflicts (which there should not be if the two co-exist as it is), it would not be too terribly hard to build them into one shared object.

If the shared libraries themselves depend on code from another library, order is going to matter. The real work is just getting the dependencies worked out in the makefile. I've never seen circular dependencies in SO's successfully link, so I doubt that you have them to begin with. I.e. foo() depends on bar() which depends on foo().

I've done this several times, though the libraries themselves were trivial. I took parts from ustr (string handler), a configuration file handler, some other custom parsers and other utility functions and created a custom mash up.

The real pain is bringing in upstream improvements to each once you have combined them, however I'm not sure if that's an issue for you.

So if you have:

libfoo.so: $(LIB_FOO_OBJECTS) $(LIB_BAR_OBJECTS) $(LIBFOOBAR_OBJECTS)

Where:

LIB_FOO_OBJECTS = \
$(libfoo)/foo.o \
$(libfoo)/strings.o

LIB_BAR_OBJECTS = \
$(libbar)/bar.o
....

... and the order is correct .. the rest is pretty easy. Note I didn't show header deps, everyone does that a little differently. They are important when making mash-ups though, as you'd probably want to avoid recompiling the whole library every time one header changes.

NB: If all three projects are using autotools .. your task just got exponentially easier (or harder) depending.

If you DON'T have the source code

If there is a static version of each library, you may be able to extract the objects and use them. I.e.:

$ cp /usr/lib/foo.a ./foo.a
$ ar x foo.a
$ gcc -fPIC -shared *.o -o foo.so

Of course its quite a bit more involved than illustrated.

I have never tried that and don't know how to handle SOs that have main() when it comes to linking in that case.

Linux: How to modify shared library name in Dynamic Section of an ELF binary

You usually do it when building the shared library. There is a linker option called "soname" that sets it.

I don't know off-hand if you can edit it after the build, but if its possible it is probably included in the package called "elfutils". That package contains several programs designed to manipulate ELF object files.

GCC outputs an executable ELF file when I want a shared library

What's going wrong is essentially that you're targeting i686-elf, and nobody builds shared libraries for that target. -Wl,-shared will give you something which is marked as a shared library, but how exactly do you plan to load a shared library on a bare-metal target?



Related Topics



Leave a reply



Submit