有没有办法告诉gdb等待进程启动并附加到它?

时间:2010-12-07 22:34:39

标签: gdb

我有一个由另一个进程调用的进程,该进程由另一个进程调用,以此类似于ad nauseum。这是一个长工具链中的子进程。

此过程正在崩溃。

我想在gdb中捕获这个过程,以了解它崩溃的原因。但是,我能想到的唯一方法是:

  1. 在命令行中启动原始父进程。
  2. 轮询ps -C <name process I want to catch>并获取PID。
  3. 启动gdb,附加到该进程的PID。
  4. 这很麻烦,但通常可以胜任。问题是当前的故障运行得非常快,当我捕获PID并启动gdb时,它已经通过了故障点。

    我想启动gdb而不是:

    (gdb) attach <pid>
    

    我想这样做:

    (gdb) attach <process name when it launches>
    

    有没有办法做到这一点?


    我在linux上使用gdb 7.1

6 个答案:

答案 0 :(得分:20)

这是我的脚本,名为gdbwait:

#!/bin/sh
progstr=$1
progpid=`pgrep -o $progstr`
while [ "$progpid" = "" ]; do
  progpid=`pgrep -o $progstr`
done
gdb -ex continue -p $progpid

用法:

gdbwait my_program

当然可以写得更好,但Bourne shell脚本语法对我来说很痛苦,所以如果它有效,那么我就不管它了。 :) 如果新进程启动并且死得太快,请在您自己的程序中添加1秒的延迟以进行调试......

答案 1 :(得分:8)

在Mac OS X上,您可以使用:

(gdb) attach --waitfor <process-name>

但这有时也无法捕获退出非常快的进程。我不确定这是否支持其他平台。

GDB Release Notes for Mac OS X v10.5 WWDC Seed

答案 2 :(得分:5)

您可以附加到父进程并设置跟随分叉模式子。这将使分叉后的gdb调试子进程而不是父进程。 catch fork 也很有用。这将使gdb在每个fork之后停止。请参阅docs

答案 3 :(得分:1)

不完全符合您的期望,但它可能会帮助您进行调试。

valgrind --trace-children=yes your_program

将检查并打印进程的所有子进程中的内存错误,包括堆栈跟踪和有关错误的一些细节(例如,在双重自由的情况下,您将获得第一个免费的堆栈跟踪)。

此外,您可能会使崩溃过程生成核心转储,并调试此验尸。请参阅this answer for details

答案 4 :(得分:1)

我一直面临着与我正在尝试调试的问题类似的问题,我想出了一个使用ldpreload的解决方案,但在看到Joeys的回答后,我想我会先尝试一下。如果它对其他人有帮助,虽然这里的想法是:

创建一个LD_PRELOAD库来挂钩exec *调用(有很多关于如何执行此操作的指南,但如果我这样做,我将使用代码更新我的答案),检查通过exec时使用的路径*调用,如果它是我们的目标,那么将带有PID的消息输出到stderr并进入无限循环(使用睡眠以避免大量CPU使用)。然后你可以用gdb附加并修改循环中使用的寄存器来继续执行。

这可能涉及一些内联ASM,以确保编译器不会以难以突破的方式优化无限循环。更有说服力的方法是找到一种方法来检测gdb已附加然后触发断点(“asm(”int3“);”应该对后者进行操作)。

答案 5 :(得分:0)

Tom Tromey在GitHub上的gdb-helpers存储库中的程序之一是preattach,它将使gdb附加到使用给定名称创建的下一个进程。它需要Linux systemtap程序。

相关问题