2011-07-08 10 views
7

En tiempo de ejecución necesito imprimir una dirección, y luego buscar de qué función forma parte esa dirección. Las funciones están en una biblioteca compartida, por lo que no están en una dirección fija. Mi archivo de mapa obviamente solo muestra los desplazamientos relativos para cada función de biblioteca compartida. ¿Es posible en tiempo de ejecución consultar dónde se ha cargado una biblioteca, de modo que pueda restar ese valor de mi dirección para obtener el desplazamiento correcto del archivo de mapa?Encontrar la dirección de carga de una biblioteca compartida en Linux

Actualmente estoy haciendo un acercamiento ligeramente hacky por el cual también imprimo la dirección de una función en la biblioteca, luego encuentro esa función en el archivo de mapa para averiguar dónde debe estar la dirección de carga. Preferiría tener un método genérico que no requiriera que nombraras una función de referencia.

(GDB no está disponible en mi configuración). Gracias.

Respuesta

4

En un Linux reciente, puede usar dl_iterate_phdr para conocer las direcciones de las bibliotecas compartidas.

1

GNU backtrace biblioteca?

No confiaría en los enfoques de hacky para algo como esto. No creo que haya ninguna garantía de que los contenidos de las bibliotecas se carguen en la memoria contigua.

3

Intente echar un vistazo al archivo/proc/[PID]/maps. Esto debe contener la dirección de la asignación de biblioteca en el espacio de direcciones de la memoria de proceso.

Si desea llegar a la parte ejecutable, use readelf en su biblioteca y encuentre el desplazamiento de la sección .text.

7

dladdr hace esto, fin de. :-)

Más comprensivamente, dladdr tomará una dirección y calculará a qué biblioteca y símbolo corresponde ... y luego le dará el nombre de la biblioteca, el nombre del símbolo y la base direcciones de cada uno Personalmente, creo que es ingenioso, también hace que mi trabajo de depuración actual sea más fácil.

Espero que esto ayude!

1

Compruebe el System V ABI, chapter 5. Para los perezosos por ahí, aquí es la manera estándar de hacer esto para sistemas que soportan el formato binario ELF:

#include <link.h> 

off_t load_offset; 
for (Elf64_Dyn *dyn = _DYNAMIC; dyn->d_tag != DT_NULL; ++dyn) { 
    if (dyn->d_tag == DT_DEBUG) { 
     struct r_debug *r_debug = (struct r_debug *) dyn->d_un.d_ptr; 
     struct link_map *link_map = r_debug->r_map; 
     while (link_map) { 
      if (strcmp(link_map->l_name, libname) == 0) { 
       load_offset = (off_t)link_map->l_addr; 
       break; 
      } 
      link_map = link_map->l_next; 
     } 
     break; 
    } 
} 

Esto no se basa en ninguna extensión de GNU.

En sistemas GNU, la macro ElfW (Dyn) devolverá Elf64_Dyn o Elf32_Dyn que es útil.

Cuestiones relacionadas