Come sostituire pthread_create durante il collegamento

Voglio mantenere un elenco di tutti i thread in esecuzione con alcune informazioni aggiuntive su ogni thread. In questa risposta ho detto che è ansible fornire la mia versione di pthread_create e colbind il programma con esso. È anche importante che io voglia chiamare pthread_create originale alla fine della mia versione di override.

Qualcuno potrebbe spiegare in dettaglio come potrebbe essere fatto e / o fornire qualche esempio di codice?

Puoi cercare il simbolo per la funzione pthread_create originale chiamando:

 pthread_create_orig = dlsym(RTLD_NEXT, "pthread_create"); 

L’involucro sarebbe quindi simile a:

 #include  int (*pthread_create_orig)(pthread_t *, const pthread_attr_t *, void *(*) (void *), void *); int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start) (void *), void *arg) { if (!pthread_create_orig) pthread_create_orig = dlsym(RTLD_NEXT, "pthread_create"); return pthread_create_orig(thread, attr, start, arg); } 

Compilalo come una libreria condivisa e precaricalo all’avvio del tuo eseguibile.

Spiegazione: in genere, il primo argomento di dlsym() è un handle di una libreria aperta con dlopen() . L’handle speciale RTLD_NEXT viene utilizzato per cercare la successiva occorrenza di quel simbolo, ovvero quello che non sarebbe collegato per impostazione predefinita. Questo è quindi il simbolo in libpthread, non quello nella libreria precaricata.

Se vuoi veramente sostituire la funzione puoi compilare la tua libreria condivisa con la funzione pthread_create, dall’interno puoi caricare e chiamare dynamicmente la funzione originale phtread_create.

Codice libreria pthread.c :

 #include  #include  #include  int (*original_pthread_create)(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg) = NULL; void load_original_pthread_create() { void *handle = dlopen("libpthread-2.15.so", RTLD_LAZY); char *err = dlerror(); if (err) { printf("%s\n", err); } original_pthread_create = dlsym(handle, "pthread_create"); err = dlerror(); if (err) { printf("%s\n", err); } } int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg) { if (original_pthread_create == NULL) { load_original_pthread_create(); } printf("I am creating thread from my pthread_create\n"); return original_pthread_create(thread, attr, start_routine, arg); } 

Compilazione: gcc pthread.c -o libmypthread.so -shared -fpic -ldl

Utilizzo: LD_PRELOAD=./libmypthread.so some_program_using_pthread_create

some_program_using_pthread_create dovrebbe funzionare come al solito, ma con ogni chiamata di funzione pthread_create dovrebbe stampare una riga aggiuntiva.

Nota: inserisci il nome corretto della tua libreria pthread nella funzione dlopen.