How can I get the path of the shared library from within the library itself?
In other words, let's say that library X is loaded using dlopen()
, how can I get access to the path that was used to load the said library from within the library itself?
Note that I cannot have the agent that loaded the library in the first place hand me this parameter.
UPDATED: Here is way that works with static variables:
std::string wdir;
namespace {
class dynamic_library_load_unload_handler {
public:
dynamic_library_load_unload_handler(){
Dl_info dl_info;
dladdr((void *) NP_Initialize, &dl_info);
std::string path(dl_info.dli_fname);
wdir = path.substr( 0, path.find_last_of( '/' ) +1 );
}
~dynamic_library_load_unload_handler(){
// Code to execute when the library is unloaded
}
} dynamic_library_load_unload_handler_hook;
}
The dynamic linker actually searches several places to find each dynamic library. These include (from man ld.so):
LD_LIBRARY_PATH
DT_RUNPATH
entryIf you want to get the path for a specific shared library, I would recommend the dladdr
function. From the man page:
The function dladdr() takes a function pointer and tries to resolve name and file where it is located. Information is stored in the
Dl_info
structure:typedef struct { const char *dli_fname; /* Pathname of shared object that contains address */ void *dli_fbase; /* Address at which shared object is loaded */ const char *dli_sname; /* Name of nearest symbol with address lower than addr */ void *dli_saddr; /* Exact address of symbol named in dli_sname */ } Dl_info;
If no symbol matching addr could be found, then
dli_sname
anddli_saddr
are set toNULL
.
dladdr()
returns 0 on error, and non-zero on success.
So you just give it a function pointer, and it will give you the name of the file which supplies it and a bunch of other information. So for instance, you could have a constructor in a library call this on itself to find out the full path of the library:
#define _GNU_SOURCE
#include <dlfcn.h>
#include <stdio.h>
__attribute__((constructor))
void on_load(void) {
Dl_info dl_info;
dladdr((void *)on_load, &dl_info);
fprintf(stderr, "module %s loaded\n", dl_info.dli_fname);
}
This function also works on OS X with the same semantics.