Domanda

Al momento sto lavorando su un progetto in cui ho bisogno di monitorare l'utilizzo di diverse chiamate di sistema e funzioni di basso livello come mmap, brk, sbrk. Finora, ho fatto questa funzione utilizzando interposizione: scrivo una funzione wrapper con lo stesso nome della funzione sto sostituendo (mmap per esempio), e lo carico in un programma impostando la variabile d'ambiente LD_PRELOAD. Chiamo la funzione reale attraverso un puntatore che si carica con dlsym.

Purtroppo, una delle funzioni che voglio per avvolgere, sbrk, è utilizzato internamente da dlsym, in modo che il programma va in crash quando cerco di caricare il simbolo. sbrk non è una chiamata di sistema in Linux, quindi non posso semplicemente utilizzare syscall chiamarlo indirettamente.

Quindi la mia domanda è: come posso chiamare una funzione di libreria da una funzione wrapper con lo stesso nome senza usare dlsym? C'è qualche trucco del compilatore (utilizzando GCC) che mi permette riferisco alla funzione originale?

È stato utile?

Soluzione

sede di ld opzione --wrap symbol. Dalla pagina man:

  

- simbolo involucro di utilizzare una funzione wrapper per simbolo. qualsiasi undefined   riferimento al simbolo sarà risolto   a "__wrap_symbol". qualsiasi undefined   riferimento al "__real_symbol" volontà   essere risolto al simbolo.

     

Questo può essere utilizzato per fornire un   wrapper per una funzione di sistema. Il   funzione involucro deve essere chiamata   "__wrap_symbol". Se si desidera chiamare   la funzione di sistema, occorre chiamare   "__real_symbol".

     

Ecco un esempio banale:

void *
__wrap_malloc (size_t c)
{
    printf ("malloc called with %zu\n", c);
    return __real_malloc (c);
}
  

Se si collega altro codice con questo   il file utilizzando malloc --wrap, allora tutto   chiamate a "malloc" chiamerà il   Funzione "__wrap_malloc" invece. Il   chiamare a "__real_malloc" in
  "__wrap_malloc" chiamerà il vero   funzione "malloc".

     

Si potrebbe desiderare di fornire un   Funzione "__real_malloc" e, in modo   che collega senza l'opzione --wrap   avrà successo. Se si esegue questa operazione,   non dovrebbe mettere la definizione di   "__real_malloc" nello stesso file come   "__wrap_malloc"; se lo fai, il   assemblatore può risolvere la chiamata prima   il linker ha la possibilità di avvolgerlo a   "Malloc".

L'altra opzione è quella forse guardare il sorgente per ltrace, è più o meno fa la stessa cosa :-P.

:

Ecco un'idea però. Si potrebbe avere la libreria LD_PRELOAD'ed modificare le voci PLT per puntare al codice. Questo vi tecnicamente la funzione sbrk() è ancora richiamabile dal codice nativly.

Altri suggerimenti

È possibile esaminare la funzione invocazione discretamente utilizzando strumenti come:

  • gdb
  • ltrace
  • systemtap

Questi strumenti consentono un programma monitor di informare quando viene chiamata una funzione, e permettono di interrogare gli argomenti.

Le differenze principali sono:

  • gdb è interattivo, ma potente
  • ltrace semplice da usare, ma è possibile stampare solo il nome della funzione
  • systemtap non è interattivo, ma può essere molto veloce, ed è potente.

Se si utilizza un sistema host con glibc, la libc ha qualche back-end interna al linker dinamico di runtime che ho usato qualche tempo fa. Se non ricordo male, mi pare si chiami '__libc_dlsym'. (Per controllare, "$ readelf -s /usr/lib/libc.a | grep dlsym" dovrebbe aiutare.) Dichiarare come una funzione legata esternamente con gli stessi argomenti e valore di ritorno che ha dlsym e usarlo per avvolgere dlsym sé.

La truss non funziona sul vostro sistema? Funziona perfettamente per questo genere di cose qui su Solaris.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top