Linux: How to get full name of shared object just loaded from the constructor?
-
10-07-2019 - |
Question
On Windows, several arguments are passed to the DllMain constructor:
BOOL WINAPI DllMain(
__in HINSTANCE hinstDLL,
__in DWORD fdwReason,
__in LPVOID lpvReserved
);
From hinstDLL I can get the fully qualified file name of the DLL itself using GetModuleFileName():
LPTSTR str = new TCHAR[256];
int libNameLength = GetModuleFileName(hinstDLL, str, 256);
delete[] str;
In the example above, str now contains the full name of the DLL just loaded, e.g., C:\Windows\System32\MyFile.dll.
On Linux, no arguments are passed to the shared object constructor:
void `__attribute__` ((constructor)) on_load(void);
How do I get the full name of the DLL in this case? Extra credit if your solution works on Mac, too. :-)
Solution
I think the dladdr
function might do what you want. 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 (like the address of the constructor itself), and it will give you the filename and a bunch of other information. Here's some sample code:
#define _GNU_SOURCE
#include <dlfcn.h>
#include <stdio.h>
__attribute__((constructor))
void on_load(void) {
Dl_info dl_info;
dladdr(on_load, &dl_info);
fprintf(stderr, "module %s loaded\n", dl_info.dli_fname);
}
EDIT: It looks like this function exists on OS X, too, with the same semantics.
OTHER TIPS
One supremely ugly and horrible way to do this is to look through /proc/pid/maps and look for the mapping that encompasses the address of the on_load
function being executed.