在Linux x86上调用backtrace()时出现分段错误

在Linux x86上调用backtrace()时出现分段错误,linux,gcc,pthreads,backtrace,ld-preload,Linux,Gcc,Pthreads,Backtrace,Ld Preload,我正在尝试执行以下操作-为pthreads库编写一个包装器,每当调用它的每个API时,它都会记录一些信息。 我想记录的一条信息是堆栈跟踪 下面是原始代码中可以按原样编译和运行的最小代码段 初始化(文件libmutex.c): 为了测试这一点,我使用这个二进制文件(文件tst\u mutex.c): 跑 LD_PRELOAD=$(pwd)/libmutex.so ./tst_mutex 这在Linux x86上由于分段错误而崩溃。 在Linux PPC上,一切工作都完美无缺。 我尝试过几个版本的

我正在尝试执行以下操作-为pthreads库编写一个包装器,每当调用它的每个API时,它都会记录一些信息。 我想记录的一条信息是堆栈跟踪

下面是原始代码中可以按原样编译和运行的最小代码段

初始化(文件
libmutex.c
):

为了测试这一点,我使用这个二进制文件(文件
tst\u mutex.c
):

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_*函数打印堆栈工作正常

这是一个堆栈溢出,由无休止的递归引起(如@Chris Dodd所述)。 backtrace()函数运行不同的系统调用,这些调用来自使用pthread库编译的程序和不使用pthread库编译的程序。即使程序没有显式调用pthread函数

下面是一个简单的程序,它使用backtrace()函数,不使用任何pthread函数

#include <stdio.h>
#include <stdlib.h>
#include <execinfo.h>

int main(void)
{
 void* buffer[100];
 int num_ret_addr;

 num_ret_addr=backtrace(buffer, 100); 
 printf("returned number of addr %d\n", num_ret_addr);

 return 0;
}
不,让我们编译相同的代码,将其链接到pthread库,运行strace并查看其输出

$ gcc -o backtrace_with_thread backtrace.c -lpthread
$ strace -o backtrace_with_thread.out backtrace_with_thread
这一次,输出包含与互斥相关的系统调用(它们的名称可能取决于平台)。下面是在x86Linux机器上获得的strace输出文件的一个片段

futex(0x3240553f80, FUTEX_WAKE_PRIVATE, 2147483647) = 0
futex(0x324480d350, FUTEX_WAKE_PRIVATE, 2147483647) = 0

您现在尝试使用RTLD_了吗?问题不在于打开pthreads库。我尝试了您的步骤,但得到一个错误
/tst_mutex:symbol lookup error:libmutex.so:undefined symbol:dlopen
。我现在不打算对此进行故障排除,但可能在重现问题的步骤中缺少了一些东西。我猜
backtrace
调用
pthread\u mutex\u lock
在内部某个地方,因此最终会出现一个循环。当堆栈溢出时,会发生segfault。为了避免它,当你处于钩子中时,你不需要钩住入口点。@Gabriel:我已经编辑了这个问题。前两个代码段进入一个名为libmutex.c的文件,第三个代码段(测试)进入tst_mutex.c#include提供dlopen函数。
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
#include <stdio.h>
#include <stdlib.h>
#include <execinfo.h>

int main(void)
{
 void* buffer[100];
 int num_ret_addr;

 num_ret_addr=backtrace(buffer, 100); 
 printf("returned number of addr %d\n", num_ret_addr);

 return 0;
}
$ gcc -o backtrace_no_thread backtrace.c
$ strace -o backtrace_no_thread.out backtrace_no_thread
$ gcc -o backtrace_with_thread backtrace.c -lpthread
$ strace -o backtrace_with_thread.out backtrace_with_thread
futex(0x3240553f80, FUTEX_WAKE_PRIVATE, 2147483647) = 0
futex(0x324480d350, FUTEX_WAKE_PRIVATE, 2147483647) = 0