viernes, 14 de junio de 2013

Tutorial de LD_PRELOAD, segunda parte

man ld.so

Un artículo previo mostraba cómo remplazar una función de la librería estándar de C con una versión personalizada. Esta nota explica lo que es preciso hacer para invocar la función original desde la nueva función.

Comencemos por recordar el ejemplo presentado anteriormente. Todo consistía en un programa llamado prog.c que invocaba la función fopen.


#include <stdio.h>

int main(void) {
    printf("Calling the fopen() function...\n");

    FILE *fd = fopen("test.txt", "r");
    if (!fd) {
        printf("fopen() returned NULL\n");
        return 1;
    }

    printf("fopen() succeeded\n");

    return 0;
}

¿Cómo hacer entonces una función que pueda remplazar a fopen y al mismo tiempo sea capaz de invocar la función fopen de la libraría estándar de C? Veamos el código de myfopen.c.


#define _GNU_SOURCE

#include <stdio.h>
#include <dlfcn.h>

FILE *fopen(const char *path, const char *mode) {
    printf("In our own fopen, opening %s\n", path);

    FILE *(*original_fopen)(const char*, const char*);
    original_fopen = dlsym(RTLD_NEXT, "fopen");
    return (*original_fopen)(path, mode);
}

Como se puede apreciar la librería exporta la versión personaizada de la función fopen. Prestando atención se puede constatar cómo se obtiene la referencia a la función original pasando el símbolo RTLD_NEXT a dlsym. Es muy importante definir el símbolo _GNU_SOURCE para tener acceso a RTLD_NEXT en dlfcn.h. De esta forma se coninua la resolución del símbolo en cuestión en el orden de búsqueda a continuación de la librería actual. La compilamos de la siguiente manera:

$ gcc -Wall -fPIC -shared -o myfopen.so myfopen.c -ldl

Al ejecutar el comando de ejemplo en cuestión con ayuda de la variable de entorno LD_PRELOAD, esto es lo que se obtiene:

$ LD_PRELOAD=./myfopen.so ./prog
Calling the fopen() function...
In our own fopen, opening test.txt
fopen() succeeded

Este truco es realmente útil para cambiar el funcionamiento de partes del sistema o depurar detalladamente ciertos detalles. Le invito a suscribirse mediante RSS para que no se pierda los próximos artículos de esta serie.

No hay comentarios:

Publicar un comentario