linking library c linux compiler-construction linker shared-libraries

library - gcc



¿Cuándo/Cómo carga Linux las bibliotecas compartidas en el espacio de direcciones? (5)

"Ve directamente a la fuente y pregunta al caballo ..."

Drepper - Cómo escribir bibliotecas compartidas

Debe leer la documentación para los escritores de la biblioteca Linux. Explica la mecánica de la carga con cierto detalle.

Mi pregunta es la siguiente:

¿Cuándo se especifica la dirección de los objetos compartidos en los programas? Durante la vinculación? ¿Cargando? Si quisiera encontrar la dirección de memoria del comando del system dentro de libc dentro de mi programa, podría encontrarla fácilmente en gdb , pero ¿qué pasa si no quiero incluir el programa en un depurador?

¿Podría esta dirección cambiar de ejecución a ejecución? ¿Hay alguna otra herramienta de análisis estático que permita ver dónde se cargarán las bibliotecas o funciones en el espacio de memoria de este programa cuando se ejecute?

EDITAR: Quiero esta información fuera del programa (es decir, usando utilidades como objdump para recopilar información)


El comando nm , utilizado en libc.so , le mostrará la ubicación del símbolo del system en libc.so Sin embargo, si ASLR está habilitado, la dirección libc.so se carga en, y por lo tanto la dirección final del system variará aleatoriamente cada vez que se ejecute su programa. Incluso sin ASLR, deberá determinar la dirección en la que libc.so se carga y compensar la dirección del system en esa cantidad.



Las bibliotecas son cargadas por ld.so (enlazador dinámico o enlazador en tiempo de ejecución alias rtld, ld-linux.so.2 o ld-linux.so.* En el caso de Linux, parte de glibc). Se declara como "intérprete" (INTERP; .interp section) de todos los binarios ELF vinculados dinámicamente. Entonces, cuando inicie el programa, Linux iniciará ld.so (cargará en la memoria y saltará a su punto de entrada), luego ld.so cargará su programa en la memoria, lo preparará y luego lo ejecutará. También puede iniciar un programa dinámico con

/lib/ld-linux.so.2 ./your_program your_prog_params

ld.so hace un open y mmap real de todos los archivos ELF necesarios, tanto el archivo ELF de su programa como los archivos ELF de todas las bibliotecas necesarias. Además, llena las tablas GOT y PLT y resuelve las reubicaciones (escribe las direcciones de las funciones de las bibliotecas para llamar a los sitios, en muchos casos con llamadas indirectas).

La dirección de carga típica de alguna biblioteca puede obtenerse con la utilidad ldd . En realidad, es un script bash, que establece una variable de entorno de depuración de ld.so (en realidad LD_TRACE_LOADED_OBJECTS=1 en el caso de glibc''s rtld) e inicia un programa. Incluso puede hacerlo usted mismo sin necesidad de la secuencia de comandos, por ejemplo, con bash fácil cambio de variables de entorno para una sola ejecución:

LD_TRACE_LOADED_OBJECTS=1 /bin/echo

El ld.so verá esta variable y resolverá todas las bibliotecas necesarias e imprimirá las direcciones de carga de las mismas. Pero con este conjunto de variables, ld.so realidad no iniciará un programa (no está seguro acerca de los constructores estáticos del programa o las bibliotecas). Si la función ASLR está desactivada, la dirección de carga será la misma la mayoría de las veces. Los Linux modernos a menudo tienen ASLR activado, por lo que para desactivarlo, use echo 0 | sudo tee /proc/sys/kernel/randomize_va_space echo 0 | sudo tee /proc/sys/kernel/randomize_va_space .

Puede encontrar la compensación de la función del system dentro de libc.so con la utilidad nm de binutils. Creo que deberías usar nm -D /lib/libc.so u objdump -T /lib/libc.so y grep output.


Si solo quiere la dirección de una función sin codificar el nombre, puede dlopen() el programa principal:

void *self = dlopen(NULL, RTLD_NOW); dlsym(self, "system"); // returns the pointer to the system() function

Si solo desea la dirección de una función cuyo nombre conoce en tiempo de compilación, simplemente use void *addr = &system;