Linux load library at runtime

dynamically loading static library?

A static library is more or less just a collection of object files. If you want to use a static library in a program, you have to link the executable with it. The executable will then contain the static library (or the parts that you used).

If you want to load a static library at runtime using dlopen , you will have to first create a dynamic library libfoo.so containing it.

That workaround implies that I would have to create a shared library from a static library if I want to dynamically load it. This means that loading a static library dynamically is not possible and that only shared libraries can be used for dynamical loading? If so, than the quote I’ve stated from the source is not correct.

Opening a .a file using dlopen does not work (tested on Ubuntu 10.04). With the following example program:

dlopen error=/usr/lib/libz.a: invalid ELF header lib_handle=(nil) 

while when using /usr/lib/libz.so instead, I get:

dlopen error=(null) lib_handle=0x19d6030 

so the same code works for a shared object.

A .a is an archive containing one or more .o elf objects. Readelf and objdump won’t parse them. You must use ar to xtract the .o files from the archive. It is important to realize that if you are willing to spend the time writing and debugging a variant of load_elf() that can wrap one or more static libraries in a HAL you can load them dynamically and provide clients with a way to introspect their call entry points. This is nonstandard, and I can already feel the literati twitching like The Walking Jed. However, the ELF contains enough information to drop a library into a runtime environment and give properly coded client functions a way to discover the interface to the functions provided, and call them. This isn’t rocket science. It is simply tedious. An important concept here is that a developer who provides the .a archive and a include suite with the idea that they are restricting your use of the libraries, is just being annoying. It is not a serious impediment to using the library, or discovering how it does it’s job.

Linked

Hot Network Questions

Subscribe to RSS

To subscribe to this RSS feed, copy and paste this URL into your RSS reader.

Читайте также:  Запуск приложения команда linux

Site design / logo © 2023 Stack Exchange Inc; user contributions licensed under CC BY-SA . rev 2023.7.13.43531

By clicking “Accept all cookies”, you agree Stack Exchange can store cookies on your device and disclose information in accordance with our Cookie Policy.

Источник

How to use libraries installed by nix at run-time?

I’m using nix in «single-user mode» in a system where I’m not the root (see below for a description of my nix setup). I wanted to quickly run one of my binaries which is dynamically linked with a library which is absent in the system. So, I’ve installed the library with nix :

$ nix-env -qa 'gmp' gmp-4.3.2 gmp-5.1.3 $ nix-env -i gmp-5.1.3 
$ ldd -r ../valencies ../valencies: /lib64/libc.so.6: version `GLIBC_2.15' not found (required by ../valencies) ../valencies: /lib64/libc.so.6: version `GLIBC_2.14' not found (required by ../valencies) linux-vdso.so.1 => (0x00007fffbbf28000) /usr/local/lib/libsnoopy.so (0x00007f4dcfbdc000) libgmp.so.10 => not found libffi.so.5 => /usr/lib64/libffi.so.5 (0x00007f4dcf9cc000) libm.so.6 => /lib64/libm.so.6 (0x00007f4dcf748000) librt.so.1 => /lib64/librt.so.1 (0x00007f4dcf540000) libdl.so.2 => /lib64/libdl.so.2 (0x00007f4dcf33c000) libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f4dcf11f000) libc.so.6 => /lib64/libc.so.6 (0x00007f4dced8b000) /lib64/ld-linux-x86-64.so.2 (0x00007f4dcfde7000) undefined symbol: __gmpz_gcd (../valencies) undefined symbol: __gmpn_cmp (../valencies) undefined symbol: __gmpz_mul (../valencies) undefined symbol: __gmpz_fdiv_r (../valencies) undefined symbol: __gmpz_fdiv_q_2exp (../valencies) undefined symbol: __gmpz_com (../valencies) undefined symbol: __gmpn_gcd_1 (../valencies) undefined symbol: __gmpz_sub (../valencies) symbol memcpy, version GLIBC_2.14 not defined in file libc.so.6 with link time reference (../valencies) undefined symbol: __gmpz_fdiv_q (../valencies) undefined symbol: __gmpz_fdiv_qr (../valencies) undefined symbol: __gmpz_add (../valencies) undefined symbol: __gmpz_init (../valencies) undefined symbol: __gmpz_ior (../valencies) undefined symbol: __gmpz_mul_2exp (../valencies) undefined symbol: __gmpz_xor (../valencies) undefined symbol: __gmpz_and (../valencies) symbol __fdelt_chk, version GLIBC_2.15 not defined in file libc.so.6 with link time reference (../valencies) undefined symbol: __gmpz_tdiv_qr (../valencies) undefined symbol: __gmp_set_memory_functions (../valencies) undefined symbol: __gmpz_tdiv_q (../valencies) undefined symbol: __gmpz_divexact (../valencies) undefined symbol: __gmpz_tdiv_r (../valencies) $ 
$ find / -name 'libgmp.so.10' 2>/dev/null /nix/store/mnmzq0qbrvw6dv1k2vj3cwz9ffdh05zr-user-environment/lib/libgmp.so.10 /nix/store/fnww2w81hv5v3dl9gsb7p4llb7z7krzd-gmp-5.1.3/lib/libgmp.so.10 $ 

What do I do so that libraries installed by nix are «visible»? Probably, the standard user-installation script of nix modifies .bash_profile to add its bin/ into PATH , but does not do something analogous for libraries.

My nix setup:

The only thing I have asked the root to do for me was: mkdir -m 0755 /nix && chown ivan /nix , otherwise I’ve followed the standard simple nix installation procedure. So now I can use custom programs from nix packages. I couldn’t do this nicely without any help from the root at all, i.e., without /nix/ , because /nix/ was not available for me; I could of course use another directory, but then the pre-built binary packages wouldn’t be valid and all packages would have to be rebuilt, according to the nix documentation. In my case, it was simpler to ask for /nix/ for me. Another thing I’ve done is adding to ~/.bash_profile :

export NIX_CONF_DIR=/nix/etc/nix 

so that I can edit nix.conf . (It was supposed to be in the root-controlled /etc/ otherwise. I did it because I wanted to build-max-jobs and build-cores settings in it.)

Читайте также:  Переименовать имя сервера linux

Источник

Automatically executed functions when loading shared libraries

When loading shared libraries in Windows, LoadLibrary() call causes DllMain in library to execute for each new process and thread library attaches to, and for each process and thread library deattaches from. Is there similar mechanism for Mac OS X, Linux and possibly other POSIX-compatible OSs?

4 Answers 4

You can define an on-load function for a linux library using the .init mechanism. This is the same as specifying the load-time entry point for a binary (e.g. using something other than main as the entry point for a program).

When linking using ld directly you use the:

or if you’re using cc/gcc to link, you use:

This is at it’s most simple level.

Edit For destructors/finalizers, you use the .fini mechanism. This operates in the same manner as the init option, and you use:

when invoking ld . Availability is limited to the -init option on the Mac OSX platform.

You should also be able to use the __attribute__((constructor)) syntax for gcc:

static void con() __attribute__((constructor)); void con()

Which is probably a more portable way rather than screwing with the linker options. All constructors should be invoked at load-time, but don’t depend on the order of their initialization, that leads to insanity and unreproducible bugs that cost time and effort to debug.

Edit 2 The use of the __attribute__((constructor))/__attribute__((destructor)) semantic is the most preferable mechanism for the C/C++ programming language.

For the D programming language you should really use the static module constructor/destructor:

Or the static class constructor:

This is strongly hinted at in the writing win32 DLLS and in the language specification relating to static constructors/destructors.

Edit 3 You will need to link in a .o that exports constructor/destructor routines, that will allow the use of the static initializers. As all it should do is call Runtime.initialize(), this actually invokes all the static constructors/destructors in the D code.

Stub d code for the initializer (in a file called myshared.d ):

import core.runtime; extern (C) < void attach(); void detach(); >export void attach() < Runtime.initialize(); >export void detach()

Create the .o for this stub:

Читайте также:  Поменять графическую оболочку линукс

Check the names of the attach/detach functions:

0000001c S _D8myshared6attachFZv 00000034 S _D8myshared6detachFZv 

sample .c code for invoking this (called export.c in this case), we reference the names of the exported routines from the my shared.o file:

extern void D8myshared6attachFZv(void); extern void D8myshared6detachFZv(void); void __attach(void) __attribute__((constructor)); void __detach(void) __attribute__((destructor)); void __attach(void) < D8myshared6attachFZv(); >void __detach(void)

Note that the extern void references need to use the mangled name of the exported function. These must match or the code will not link.

link the .c.o and the .d.o files together using:

cc -o libmyshared.dylib -m32 -shared myshared.o export.o -lphobos2 

Assuming that the phobos2 library is in your standard linker search path. The smatterings of -m32 options for the compiler and linker are because the version of the D compiler that I built locally only supported 32bit.

This produces a .dylib that can be linked to. It seems to work based on the limited testing I performed. It looks like support for shared objects/dynamic libraries is very limited, so there is a good chance that there will be another hurdle to overcome.

Источник

Embedded Guru

In Linux, libraries which are linked during linking stage of the program, gets loaded during the startup of the program, unless a copy is already present in memory.

Another approach provided by Linux operating system is to load/unload the libraries at run time whenever it is needed.

API’s are provided by Linux for

  • Loading the Library — dlopen()
  • Looking up for symbols — dlsym()
  • Handling Errors — dlerror()
  • Unloading the Library — dlclose()

Flow:
1. Process begins with a call to dlopen API, providing the path of the shared library and the mode. Main two values for this mode are RTLD_NOW, RTLD_LAZY. This informs the dynamic linker when to perform relocations. RTLD_NOW will make all the necessary relocations at the dlopen call time, whereas RTLD_LAZY will perform relocations only when they’re needed. dlopen function returns a handle which is used in all the subsequent API’s
2. You then call dlsym() to get the addresses of the symbols (functions)
3. dlerror() function will returns a human readable error message if an API fails
4. When all the functions are accessed of the library, you can unload the shared library with a call to dlclose()

Example Code:

Let’s create a shared library which we want to load at runtime using dlopen, dlsym calls

Then write application code for loading this library at run time

Источник

Оцените статью
Adblock
detector