2012-09-09 51 views
5

我正在嘗試使用LD_PRELOAD機制來調用pthread_cond_broadcast。我插入的pthread_cond_broadcast函數只是調用原始的pthread_cond_broadcast。然而,對於pthread_cond_wait和pthread_cond_broadcast都被調用的非常簡單的pthread代碼,我最終會在glibc中得到一個段錯誤(對於glibc 2.11.1)或程序​​掛起(對於glibc 2.15)。任何線索都在發生?pthread_cond_broadcast破解與dlsym?

的插入代碼(即獲取編譯作爲共享庫):

#define _GNU_SOURCE 
#include <stdio.h> 
#include <stdlib.h> 
#include <pthread.h> 
#include <dlfcn.h> 

static int (*orig_pthread_cond_broadcast)(pthread_cond_t *cond) = NULL; 

__attribute__((constructor)) 
static void start() { 
    orig_pthread_cond_broadcast = 
     (int (*)()) dlsym(RTLD_NEXT, "pthread_cond_broadcast"); 
    if (orig_pthread_cond_broadcast == NULL) { 
     printf("pthread_cond_broadcast not found!!!\n"); 
     exit(1); 
    } 
} 

__attribute__((__visibility__("default"))) 
int pthread_cond_broadcast(pthread_cond_t *cond) { 
    return orig_pthread_cond_broadcast(cond); 
} 

簡單並行線程程序:

#include <stdio.h> 
#include <pthread.h> 
#include <unistd.h> 

pthread_mutex_t cond_mutex; 
pthread_cond_t cond_var; 
int condition; 

void *thread0_work(void *arg) { 
    pthread_mutex_lock(&cond_mutex); 
    printf("Signal\n"); 
    condition = 1; 
    pthread_cond_broadcast(&cond_var); 
    pthread_mutex_unlock(&cond_mutex); 
    return NULL; 
} 

void *thread1_work(void *arg) { 
    pthread_mutex_lock(&cond_mutex); 
    while (condition == 0) { 
     printf("Wait\n"); 
     pthread_cond_wait(&cond_var, &cond_mutex); 
     printf("Done waiting\n"); 
    } 
    pthread_mutex_unlock(&cond_mutex); 
    return NULL; 
} 

int main() { 
    pthread_t thread1; 

    pthread_mutex_init(&cond_mutex, NULL); 
    pthread_cond_init(&cond_var, NULL); 

    pthread_create(&thread1, NULL, thread1_work, NULL); 

    // Slowdown this thread, so the thread 1 does pthread_cond_wait. 
    usleep(1000); 

    thread0_work(NULL); 

    pthread_join(thread1, NULL); 

    return 0; 
} 

編輯:

的Glibc 2.11.1,GDB BT給出:

(gdb) set environment LD_PRELOAD=./libintercept.so 
(gdb) run 
Starting program: /home/seguljac/intercept/main 
[Thread debugging using libthread_db enabled] 
[New Thread 0x7ffff7436700 (LWP 19165)] 
Wait 
Signal 
Before pthread_cond_broadcast 

Program received signal SIGSEGV, Segmentation fault. 
0x00007ffff79ca0e7 in [email protected]@GLIBC_2.3.2() from /lib/libpthread.so.0 
(gdb) bt 
#0 0x00007ffff79ca0e7 in [email protected]@GLIBC_2.3.2() from /lib/libpthread.so.0 
#1 0x00007ffff7bdb769 in pthread_cond_broadcast() from ./libintercept.so 
#2 0x00000000004008e8 in thread0_work() 
#3 0x00000000004009a4 in main() 

編輯2:

(已解決) 正如R ..(謝謝!)所建議的,問題是在我的平臺上,pthread_cond_broadcast是一個版本化符號,而dlsym給出了錯誤的版本。此博客解釋這個情況很詳細:http://blog.fesnel.com/blog/2009/08/25/preloading-with-multiple-symbol-versions/

+0

什麼是backtr如果您在調試器下運行王牌的樣子?你有沒有嘗試單步執行代碼? –

+3

我注意到它是一個版本化的符號。 「dlsym」能否給你錯誤的版本? –

回答

1

通過你的函數調用,似乎在不同版本的功能來結束:

With LD_PRELOAD: __pthread_cond_broadcast_2_0 (cond=0x804a060) at old_pthread_cond_broadcast.c:37 
Without LD_PRELOAD: [email protected]@GLIBC_2.3.2() at ../nptl/sysdeps/unix/sysv/linux/i386/i686/../i486/pthread_cond_broadcast.S:39 

所以你的情況與此類似的問題,即您是得到的並行線程功能不兼容的版本:symbol versioning and dlsym

本頁面給出瞭解決問題的一種方式,雖然有點複雜:http://blog.fesnel.com/blog/2009/08/25/preloading-with-multiple-symbol-versions/