Mac OS X Mavericks - gdb - 附加到进程时无法设置断点

时间:2014-01-31 09:56:37

标签: c macos debugging gdb attach-to-process

我最近从Mac OS X 10.7升级到10.9。由于OS X不再支持gdb,我通过macports安装了GNU gdb。在能够使用它之前,我必须按照here描述对其进行编码。 现在我可以使用gdb作为调试器,但是在附加到进程时我在设置断点时遇到问题。我会为你做一个例子。 我拿了这个示例C代码

#include <unistd.h>
#include <stdio.h>

void f() {
    printf("f()\n");
}

int main() {
    printf("sleeping 30 seconds...\n");
    sleep(30);
    printf("invoking f()\n");
    f();
}

并使用

进行编译
gcc -g a.c

如果我现在尝试通过

进行调试
gdb a.out

并在gdb中运行,结果如下(正如预期的那样)

GNU gdb (GDB) 7.6
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-apple-darwin13.0.0".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /private/tmp/a.out...Reading symbols from /private/tmp/a.out.dSYM/Contents/Resources/DWARF/a.out...done.
done.
(gdb) break f
Breakpoint 1 at 0x100000ee0: file a.c, line 5.
(gdb) r
Starting program: /private/tmp/a.out
sleeping 30 seconds...
invoking f()

Breakpoint 1, f () at a.c:5
5               printf("f()\n");
(gdb) c
Continuing.
f()
[Inferior 1 (process 78776) exited with code 012]
(gdb)

所以我做的是打开gdb,在函数f()处设置断点,运行程序,然后在f()内停止时简单地发出continue命令。 如果我现在执行相同但附加到已经运行的进程,我无法设置断点,并且在发出continue命令以使进程在连接后继续时也会出错。结果如下:

GNU gdb (GDB) 7.6
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-apple-darwin13.0.0".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
(gdb) attach 78794
Attaching to process 78794
Reading symbols from /private/tmp/a.out...Reading symbols from /private/tmp/a.out.dSYM/Contents/Resources/DWARF/a.out...done.
done.
0x00007fff8516da3a in ?? ()
(gdb) break f
Cannot access memory at address 0x100000edc
(gdb) c
Continuing.
warning: Mach error at "darwin-nat.c:726" in function "void darwin_resume_thread(struct inferior *, darwin_thread_t *, int, int)": (os/kern) failure (0x5)
[Inferior 1 (process 78794) exited normally]
(gdb)

首先,当附加时,gdb没有提供有关代码中当前位置的任何信息(??()中的0x00007fff8516da3a),这可能没问题,因为我很可能在睡眠时停止了该过程()函数。

但是,当我尝试在f()处设置断点时,我得到“无法访问内存”错误,并且断点明显没有设置。实际上,当我发出continue命令时,该过程会正常进行,并在不停止在f()的情况下终止。

此外,当我试图继续时,我也会在[...](os / kern)失败(0x5)时得到“马赫错误”。即使使用

,设置断点也不起作用
(gdb) break a.c:5
Cannot access memory at address 0x100000edc

我也尝试搜索网络和stackoverflow,但我找不到这个问题的答案。 任何帮助表示赞赏。

2 个答案:

答案 0 :(得分:2)

我发现了一个(不是真正令人满意的)解决方案。使用MacPorts,我安装了GDB的苹果版:

sudo port install gdb-apple

即使在Eclipse CDT中,此版本的GDB也能够正确附加到进程并设置断点。我发现的唯一缺陷是,在Eclipse中,我需要在连接到进程之前设置断点。如果我尝试在已经连接时设置断点,则该过程失败。我不明白为什么。

我希望这个答案可以帮到某个人,如果你们中的任何人找到了更好的解决方案,我很乐意知道。

答案 1 :(得分:0)

这实际上是上游GDB中的一个错误(缺少功能)。

我一直在阅读它的源代码,以了解它是如何在macOS上运行的,并且“附加到运行进程”代码路径从不调用ptrace(PT_ATTACHEXC, ...),这会将传递给跟踪进程的信号重新路由到使用的异常端口由GDB。

在产生孩子时会调用ptrace(PT_SIGEXC),这解释了为什么它在这种情况下有效。