我有两个程序:A
和B
。它们是不同的程序,B
不是A
的分支。A
启动B
。问题:我能从A
中得到B
分割故障的回溯吗?我无法修改B
程序的源代码。
它们是不同的程序,B不是a的分支。a启动B
所谓"启动",我想你的意思是A
做fork
,孩子做B
的execvp
我无法修改
B
程序的源代码。
这意味着有B
的源,但不能修改它,但可以用-g
、-O0
和其他类似-fno-omit-frame-pointer
的东西重新编译它,以获得调试符号,并有更好的机会进行更准确的堆栈回溯。
然而,另一种解释方法是,您只将B
作为二进制可执行文件,并且没有的源代码。
我还推断,您有A
[并且可以做任何必要的事情来使事情正常工作]。
问题:我能从A中得到B分割错误的回溯吗?
是的。有几种不同的方式。
A
在调用B
时可以使用ptrace
,就像gdb
或strace
一样。当B
出现故障时,A
可以获得控制权并返回堆栈并打印出来。
但是,这就引出了一个问题:您的主要目标是[只是]调试B
吗?让A
执行gdb B
的fork/exec
可能更容易,而不仅仅是B
,这样gdb
就可以执行"繁重的工作",因为堆栈回溯是一个简单的gdb
命令。更简单的方法是允许B
转储核心,方法是在shell命令中启用限制,然后用gdb
检查核心文件。
另一个可能的选择。使用readelf
查看B
中的符号,并通过ldd
查看所需的共享库列表。然后,您可以决定B
是否有任何"挂钩"点。也就是说,它想要从共享库(如open
)调用的任何符号。
您可以创建一个包含open
的特殊共享库,然后通过设置环境变量LD_PRELOAD
在B
上"强制"它。然后,当B
调用open
时,您的共享库将获得控制权。然后,您可以为SIGSEGV
安装一个信号处理程序,然后使用dlsym
获取"真正"打开的地址并完成open
调用。
现在,当B
分段故障时,您的特殊共享库中的信号处理程序可以通过__builtin_return_address
等返回堆栈,并将结果(通过管道或套接字)传达回A
还有一种方法是破解B
可执行文件,并添加一个钩子,以与A