How can a shared library know where it resides?

651 views Asked by At

I'm developing a shared library for linux machines, which is dynamically loaded relative to the main executable with rpath. Now, the library itself tries to load other libraries dynamically relative to its location but without rpath (I use scandir to search for shared libraries in a certain folder - I don't know their names yet).

This works only, if the working directory is set to the shared libraries location, as otherwise I look in a different directory as intended.

Is there any practical, reliable way for the shared library to determine where it resides?

I know, I could use /proc/self/maps or something like that, to get the loaded files, but this works only, as long the library knows its own name.

Another idea is so use dlinfo(), but to use it, the shared library need to know its own handle.

2

There are 2 answers

3
yugr On BEST ANSWER

Is there any practical, reliable way for the shared library to determine where it resides?

I'd use dlinfo and /proc/self/maps (proc may not always be mounted, especially in containers).

I know, I could use /proc/self/maps or something like that, to get the loaded files, but this works only, as long the library knows its own name.

Not really, you can take a pointer to some code inside library (preferably to some internal label, to avoid messing with PLT/GOT) and compare result against memory range obtained from /proc/self/maps (or dlinfo).

0
Konrad Rudolph On

No need to muck around with the page mappings or dlinfo. You can use dladdr on any symbol defined in the shared library:

#define _GNU_SOURCE
#include <dlfcn.h>
#include <stdlib.h>

static char *lib_path(void) {
    Dl_info info;
    if (! dladdr((void *) lib_path, & info)) return NULL;
    return realpath(info.dli_fname, NULL);
}

Technically this isn’t portable; in practice, it works even on on-Linux systems such as macOS. You may want to manually allocate the storage for realpath to avoid non-standard behaviour there (on Linux and macOS, realpath itself mallocs the storage, and needs to be freed by the caller).

This returns the path to the shared library itself. If you want to obtain the directory, you could use something like dirname (careful: reentrant) or modify the string yourself.