2010-09-07 11 views
28

Supponiamo di voler prendere completamente in carico la chiamata di sistema open(), magari per avvolgere il syscall effettivo ed eseguire alcuni logging. One way to do this is to use LD_PRELOAD per caricare una libreria di oggetti condivisa (creata dall'utente) che riprende il punto di ingresso open().Come reimplementare (o avvolgere) una funzione di syscall su Linux?

La routine open() creata dall'utente ottiene quindi il puntatore alla funzione glibc open() per dlsym() e lo chiama.

La soluzione sopra proposta è tuttavia una soluzione dinamica. Supponiamo che io voglia collegare il mio wrapper open() staticamente. Come lo farei? Immagino che il meccanismo sia lo stesso, ma suppongo anche che ci sarà uno scontro di simboli tra lo open() definito dall'utente e la libc open().

Si prega di condividere altre tecniche per raggiungere lo stesso obiettivo.

+0

Che ne dici di inserire semplicemente una funzione/macro wrapper nel codice? –

+0

@Seamus: preferisco non utilizzare le macro. Non ho davvero un problema. Sto chiedendo solo di aumentare la conoscenza di SO e imparare qualche nuovo trucco. –

risposta

56

È possibile utilizzare la funzione di avvolgimento fornita da ld. Da man ld:

--wrap symbol utilizzare una funzione wrapper per simbolo. Qualsiasi riferimento non definito a symbol verrà risolto in __wrap_symbol.

Qualsiasi riferimento non definito a __real_symbol verrà risolto in symbol.

quindi basta usare il prefisso __wrap_ per la funzione wrapper e __real_ quando si vuole chiamare la funzione reale. Un semplice esempio è:

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; 
} 

Test application testapp.c:

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

quindi compilare l'applicazione:

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

L'output dell'applicazione risultante sarà:

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

+1 questo è veramente figo: D –

+1

Sembra che la funzione che chiama malloc non possa essere collegata dinamicamente. Ad esempio, ho scritto un tools.c, che contiene una funzione perform_alloc() che chiama malloc. Quindi se faccio prima un libtools.so e lo linkmo in modo dinamico con '-ltools',' -Wl, -wrap, malloc' non funzionerà. – xanpeng

+1

Come indicato in http: // StackOverflow.it/questions/3826108/has-any-a-esempio-per-wrapping-a-function-in-c è richiesto per il prefisso delle definizioni delle funzioni con 'extern" C "' quando si utilizza questo codice in un programma C++. – MKroehnert

2

I simboli vengono risolti dal linker nell'ordine in cui li si elenca sulla riga di comando, quindi se si elencava la libreria prima della libreria standard si avrebbe la precedenza. Per gcc devi specificare

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

In questo modo le tue librerie verrebbero cercate e trovate per prime.

Problemi correlati