Linux: Как получить полное имя общего объекта, только что загруженного из конструктора? - PullRequest
8 голосов
/ 29 октября 2009

В Windows несколько конструкторов передаются конструктору DllMain:

BOOL WINAPI DllMain(  
  __in  HINSTANCE hinstDLL,  
  __in  DWORD fdwReason,  
  __in  LPVOID lpvReserved  
);

От hinstDLL я могу получить полное имя файла самой DLL, используя GetModuleFileName ():

LPTSTR str = new TCHAR[256];  
int libNameLength = GetModuleFileName(hinstDLL, str, 256);  
delete[] str;  

В приведенном выше примере str теперь содержит полное имя только что загруженной DLL, например, C: \ Windows \ System32 \ MyFile.dll.

В Linux никакие аргументы не передаются конструктору общего объекта:

void `__attribute__` ((constructor)) on_load(void);

Как получить полное имя DLL в этом случае? Дополнительный кредит, если ваше решение работает на Mac тоже. : -)

Ответы [ 2 ]

4 голосов
/ 30 октября 2009

Я думаю, что функция dladdr может делать то, что вы хотите. Со страницы руководства:

Функция dladdr () берет указатель на функцию и пытается разрешить имя и файл, где он находится. Информация хранится в Dl_info структура:

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;

Если не найдено ни одного символа, соответствующего адресу, тогда dli_sname и dli_saddr установлены на NULL.

dladdr() возвращает 0 в случае ошибки и ненулевое значение в случае успеха.

Так что вы просто даете ему указатель на функцию (например, адрес самого конструктора), и он даст вам имя файла и кучу другой информации. Вот пример кода:

#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);
}
<Ч />

РЕДАКТИРОВАТЬ: похоже, что эта функция существует и в OS X с той же семантикой.

1 голос
/ 29 октября 2009

Один из самых ужасных и ужасных способов сделать это - просмотреть / proc / pid / maps и найти отображение, которое охватывает адрес выполняемой функции on_load.

...