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

5

我最近从Mac OS X 10.7升级到了10.9。由于OS X不再支持gdb,我通过macports安装了GNU gdb。在能够使用它之前,我必须像这里描述的那样对其进行代码签名。 现在我可以使用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()内部时,只需简单地发出继续命令即可。

如果我现在尝试附加到已经运行的进程上,我将无法设置断点,并且在发出继续命令以使进程在附加后继续运行时也会出现错误。以下是结果:

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 in ?? ())的任何信息,这可能是可以接受的,因为我很可能在sleep()函数内停止了进程。
但是,当我尝试在f()处设置断点时,我会收到“无法访问内存”的错误,并且明显未设置断点。实际上,当我给出继续命令时,进程会像平常一样继续运行并在不在f()处停止。
此外,在尝试继续操作时,我还会收到“Mach error at [...] (os/kern) failure (0x5)”错误。即使使用设置断点也无法正常工作。
(gdb) break a.c:5
Cannot access memory at address 0x100000edc

我试图在网上和stackoverflow上搜索,但是我没有找到解决这个问题的答案。非常感谢您的帮助。


为什么不使用作为 Xcode 一部分提供的 Apple 的 lldb? - Paul R
因为我经常使用Eclipse-CDT来调试我的代码,但它仍不支持lldb。有一个插件可以让lldb与Eclipse-CDT配合使用,但据我所知它还不够成熟。 无论如何,我希望解决这个问题,因为我一直在使用gdb,转换到另一个调试器对我来说并不是真正的解决方案 :) - Michele Segata
好的,但请注意lldb在操作上与gdb几乎相同,因此如果您想尝试它,就不需要太多时间和精力。祝你好运! - Paul R
是的,我想是这样,但是我仍然需要在Eclipse中使用gdb,所以我正在寻求这里的帮助。 - Michele Segata
1
我非常希望在Mavericks上使用(带有Emacs的)gdb。原因是:lldb没有Emacs模式,Xcode无法附加到任意进程(没有支持的Xcode项目),而lldb缺少“dir”命令,因此(在我们的情况下)lldb找不到我们的源代码。因此,对于我们的项目来说,lldb是无用的,并且功能远不及gdb。 - Per Mildner
2个回答

2
我找到了一个(不是很令人满意的)解决方案。使用MacPorts,我安装了苹果版本的GDB:
sudo port install gdb-apple

这个版本的GDB可以正确地附加到进程并设置断点,即使在Eclipse CDT中也可以。我唯一发现的缺陷是,在Eclipse中,我需要在附加到进程之前设置断点。如果我尝试在已经连接的情况下设置断点,则该过程失败。我不知道为什么。

我希望这个答案可以帮助某些人,如果你们中有人发现更好的解决方案,我会很高兴知道它。


0

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

我一直在阅读它的源代码,以了解它在 macOS 上的工作方式,“附加到运行中的进程”代码路径从未调用 ptrace(PT_ATTACHEXC, ...),这将重新路由传递给被跟踪进程的信号到 GDB 使用的异常端口。

当生成子进程时,它确实调用 ptrace(PT_SIGEXC),这就解释了为什么在这种情况下它能够工作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接