获取子进程的段错误回溯

Get segfault backtrace of child process

我有两个程序:AB。它们是不同的程序,B 不是 A 的分支。 A 启动 B。问题:我可以从 A 获取 B 的分段错误的回溯吗?我无法修改 B 程序的源代码。

They are different programs,B is not a fork of A. A launches B

"launch",我猜你的意思是 Afork 而 child 做 execvp of B

I cannot modify source code of B program.

这意味着您拥有B的来源,但不能修改它,但是可以-g-O0和其他类似-fno-omit-frame-pointer的东西重新编译它以获得调试符号和更准确的堆栈回溯的更好机会。

但是,另一种解释方式是,您只有 B 作为二进制可执行文件,没有 它的源代码。

我还推断你 A 的来源 [并且可以做任何必要的事情来使事情正常进行]。

Question: can I get backtrace of segmentation fault of B from A?

是的。有几种不同的方法。

A 可以在调用 B 时使用 ptrace,就像 gdbstrace 一样。当 B 出现段错误时,A 可以获得控制权并返回堆栈并打印出来。

但是,这引出了一个问题:您的主要目标是 [只是] 调试 B 吗?让 Agdb Bfork/exec 而不是仅仅 B 可能更容易,这样 gdb 就可以做 "heavy lifting" 作为堆栈回溯是一个简单的 gdb 命令。更简单的方法是通过在 shell 命令中启用限制并随后使用 gdb 检查核心文件来允许 B 转储核心。

另一个可能的选择。使用 readelf 查看 B 中的符号,并通过 ldd 查看所需的共享库列表。然后您可以决定 B 是否有任何 "hook" 点。也就是说,它想从共享库调用的任何符号,例如 open.

您可以通过设置环境变量 LD_PRELOAD 创建一个包含 open 的特殊共享库,然后在 B 上 "force" 它。然后,当 B 调用 open 时,您的共享库获得控制权。然后,您可以为 SIGSEGV 安装信号处理程序,然后使用 dlsym 获取 "real" 打开的地址并完成 open 调用。

现在,当 B 出现段错误时,您特殊共享库中的信号处理程序可以通过 __builtin_return_address 等返回堆栈。阿尔。并将结果传回 A(通过管道或套接字)

另一种方法是破解 B 可执行文件并添加一个与 A

通信的挂钩