2009-10-29 11 views
7

En Windows, varios argumentos se pasan al constructor DllMain:Linux: ¿Cómo obtener el nombre completo del objeto compartido recién cargado desde el constructor?

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

De hinstDLL puedo obtener el nombre completo del archivo de la misma DLL usando GetModuleFileName():

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

En el ejemplo arriba, str ahora contiene el nombre completo de la DLL que acaba de cargar, por ejemplo, C: \ Windows \ System32 \ MyFile.dll.

En Linux, no hay argumentos se pasan al constructor de objetos compartidos:

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

¿Cómo puedo obtener el nombre completo de la DLL en este caso? Crédito adicional si su solución también funciona en Mac. :-)

+0

No sé si hay una buena manera. Mi pregunta en situaciones como esta es "¿Por qué quieres saber?". Al retroceder un nivel, es posible que encuentre un camino hacia su objetivo real sin dar el paso que actualmente lo está bloqueando. – Omnifarious

+0

Buena pregunta. Quiero saber, porque estoy desarrollando un CSP y un módulo PKCS # 11 (archivos DLL), los cuales necesitan verificar su propia integridad cuando se carguen. Ambos archivos DLL son cargados por el sistema operativo, por lo que mi punto de entrada es el constructor. Actualmente, la mejor idea que tengo para verificar la integridad del archivo DLL es calcular un hash del archivo DLL en el constructor y luego enviar ese hash a un servidor central que puede verificar la corrección del hash. Sin embargo, necesito el nombre de archivo de la DLL para poder calcular el hash. –

Respuesta

3

Creo que la función dladdr puede hacer lo que quiera. Desde la página del manual:

La función dladdr() toma un puntero a función y trata de resolver nombre y archivo en el que se encuentra. La información se almacena en la estructura 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; 

Si se pudo encontrar ningún símbolo a juego addr, a continuación, dli_sname y dli_saddr se ponen a NULL.

dladdr() devuelve 0 en error y no cero en caso de éxito.

Así que solo tiene que darle un puntero a la función (como la dirección del propio constructor), y le dará el nombre de archivo y un montón de otra información. He aquí algunos ejemplos de código:

#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: Parece que existe esta función en OS X, también, con la misma semántica.

+0

Excelente respuesta, ¡muchas gracias! –

+0

Sí, estoy tan feliz de que la forma en que ambos pensamos no sea la respuesta correcta. :-) – Omnifarious

+0

Este método no funciona en Android: 'dli_fname' contiene solo el nombre del archivo, y no la ruta completa. – 18446744073709551615

1

Una forma supremamente fea y horrible de hacer esto es mirar a través de/proc/pid/maps y buscar la asignación que abarca la dirección de la función on_load que se está ejecutando.

+1

Empecé a ir por este camino ayer, y no lo he descartado * completamente * aún, porque actualmente es la única solución viable que conozco. Aunque me envía escalofríos por la espalda. –

Cuestiones relacionadas