2010-09-07 16 views
28

Supongamos que deseo asumir por completo la llamada al sistema open(), tal vez para ajustar la llamada al sistema real y realizar algunos registros. One way to do this is to use LD_PRELOAD para cargar una biblioteca de objetos compartidos (creada por el usuario) que toma el punto de entrada open().¿Cómo puedo volver a implementar (o ajustar) una función syscall en Linux?

La rutina open() realizada por el usuario obtiene el puntero a la función glibc open() por dlsym() y la llama.

La solución propuesta anteriormente es una solución dinámica, sin embargo. Supongamos que quiero vincular mi propio contenedor open() estáticamente. ¿Cómo lo haría? Supongo que el mecanismo es el mismo, pero también creo que habrá un choque de símbolos entre el open() definido por el usuario y el open() libc.

Comparta cualquier otra técnica para lograr el mismo objetivo.

+0

¿Qué le parece si simplemente pega una función envoltura/macro en su código? –

+0

@Seamus: Prefiero no usar macros. Realmente no tengo un problema. Solo estoy pidiendo aumentar el conocimiento SO y aprender algún truco nuevo. –

Respuesta

56

Puede usar la función de ajuste proporcionada por ld. De man ld:

--wrap symbol Utilice una función de envoltura para el símbolo. Cualquier referencia indefinida a symbol se resolverá en __wrap_symbol.

Cualquier referencia indefinida a __real_symbol se resolverá en symbol.

lo que sólo hay que usar el prefijo __wrap_ para su función de contenedor y __real_ cuando se quiere llamar a la función real. Un ejemplo sencillo es:

malloc_wrapper.c:

#include <stdio.h> 
void *__real_malloc (size_t); 

/* This function wraps the real malloc */ 
void * __wrap_malloc (size_t size) 
{ 
    void *lptr = __real_malloc(size); 
    printf("Malloc: %lu bytes @%p\n", size, lptr); 
    return lptr; 
} 

aplicación de prueba testapp.c:

#include <stdio.h> 
#include <stdlib.h> 
int main() 
{ 
    free(malloc(1024)); // malloc will resolve to __wrap_malloc 
    return 0; 
} 

a continuación, compilar la aplicación:

gcc -c malloc_wrapper.c 
gcc -c testapp.c 
gcc -Wl,-wrap,malloc testapp.o malloc_wrapper.o -o testapp 

La salida de la aplicación resultante será:

$ ./testapp 
Malloc: 1024 bytes @0x20d8010 
+3

+1 esto es tan genial: D –

+1

Parece que la función que llama malloc no se puede vincular dinámicamente. Por ejemplo, escribí tools.c, que contiene una función perform_alloc() que llama a malloc. Entonces, si hago un libtools.so primero y lo vinculo dinámicamente con '-ltools',' -Wl, -wrap, malloc' no funcionará. – xanpeng

+1

Como se respondió en http: // stackoverflow.com/questions/3826108/has-anyone-a-example-for-wrapping-a-function-in-c Se requiere que prefija las definiciones de función con 'extern" C "' cuando se usa este código en un programa C++. – MKroehnert

2

Los símbolos se resuelven por el vinculador en el orden en que los enumera en la línea de comandos, por lo que si usted listó su biblioteca antes que la biblioteca estándar, tendría precidencia. Para gcc, deberá especificar

gcc <BLAH> -nodefaultlibs <BLAH BLAH> -lYOUR_LIB <OTHER_LIBS> 

De esta forma, se buscarán y encontrarán primero las bibliotecas.

Cuestiones relacionadas