我正在嘗試執行以下操作 - 爲pthreads庫編寫一個封裝器,該封裝器將在每次調用其每個API時記錄一些信息。 我想記錄的一條信息是堆棧跟蹤。在Linux x86上調用backtrace()時發生分段錯誤
以下是原始代碼中的最小片段,可以按原樣編譯和運行。
初始化(文件libmutex.c
):
#include <execinfo.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <dlfcn.h>
static int (*real_mutex_lock)(pthread_mutex_t *) __attribute__((__may_alias__));
static void *pthread_libhandle;
#ifdef _BIT64
#define PTHREAD_PATH "/lib64/libpthread.so.0"
#else
#define PTHREAD_PATH "/lib/libpthread.so.0"
#endif
static inline void load_real_function(char* function_name, void** real_func) {
char* msg;
*(void**) (real_func) = dlsym(pthread_libhandle, function_name);
msg = dlerror();
if (msg != NULL)
printf("init: real_%s load error %s\n", function_name, msg);
}
void __attribute__((constructor)) my_init(void) {
printf("init: trying to dlopen '%s'\n", PTHREAD_PATH);
pthread_libhandle = dlopen(PTHREAD_PATH, RTLD_LAZY);
if (pthread_libhandle == NULL) {
fprintf(stderr, "%s\n", dlerror());
exit(EXIT_FAILURE);
}
load_real_function("pthread_mutex_lock", (void**) &real_mutex_lock);
}
的包裝和回溯呼叫。 我已經儘可能地從方法切碎了,所以是的,我知道我從來沒有調用原始的pthread_mutex_lock作爲例子。
void my_backtrace(void) {
#define SIZE 100
void *buffer[SIZE];
int nptrs;
nptrs = backtrace(buffer, SIZE);
printf("backtrace() returned %d addresses\n", nptrs);
}
int pthread_mutex_lock(pthread_mutex_t *mutex) {
printf("In pthread_mutex_lock\n"); fflush(stdout);
my_backtrace();
return 0;
}
爲了驗證這一點,我用這個二進制文件(文件tst_mutex.c
):
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
int main (int argc, char *argv[]) {
pthread_mutex_t x;
printf("Before mutex\n"); fflush(stdout);
pthread_mutex_lock(&x);
printf("after mutex\n");fflush(stdout);
return 0;
}
下面是這一切的編譯方式:
rm -f *.o *.so tst_mutex
cc -Wall -D_BIT64 -c -m64 -fPIC libmutex.c
cc -m64 -o libmutex.so -shared -fPIC -ldl -lpthread libmutex.o
cc -Wall -m64 tst_mutex.c -o tst_mutex
和運行
LD_PRELOAD=$(pwd)/libmutex.so ./tst_mutex
這與崩潰Linux x86上的分段錯誤。 在Linux上PPC一切都完美無瑕。 我已經嘗試了GCC編譯器,GLIBC庫和Linux發行版的幾個版本 - 都失敗了。
輸出是
init: trying to dlopen '/lib64/libpthread.so.0'
Before mutex
In pthread_mutex_lock
In pthread_mutex_lock
In pthread_mutex_lock
...
...
./run.sh: line 1: 25023 Segmentation fault LD_PRELOAD=$(pwd)/libmutex.so ./tst_mutex
提示有一個遞歸在這裏。 我已經看過backtrace()
的源代碼 - 有沒有調用鎖定機制。它所做的只是簡單地遍歷棧幀鏈表。 我也有,用objdump檢查庫代碼,但沒有透露任何異常。
這裏發生了什麼? 任何解決方案/解決方法?
哦,也許是最重要的事情。這隻發生在pthread_mutex_lock函數中! 從任何其他重寫的pthread_ *函數打印堆棧工作得很好...
你用RTLD_NOW試過了嗎? – stark 2013-04-24 16:41:58
問題不在於打開pthreads庫。 – 2013-04-24 22:00:18
我試過了你的步驟,但是我得到一個錯誤'./tst_mutex:symbol lookup error:libmutex.so:undefined symbol:dlopen'。我現在不打算排除這個問題,但是也許有一些步驟不能解決問題。 – 2013-04-24 22:36:11