Reputation: 33
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.
Upvotes: 3
Views: 817
Reputation: 545588
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 malloc
s the storage, and needs to be free
d 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.
Upvotes: 0
Reputation: 21886
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
).
Upvotes: 1