views:

221

answers:

2

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. :-)

+1  A: 

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.

Omnifarious
I started going down this road yesterday, and I've not dismissed it *completely* yet, because it's currently the only viable solution I know. It sends chills down my spine, too, though.
Peter Vils
+3  A: 

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 and dli_saddr are set to NULL.

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.

Jay Conrod
Excellent answer, thank you very much!
Peter Vils
Yes, I'm so happy that the way we both thought of isn't the right answer. :-)
Omnifarious