5
votes

I recently upgraded from Mac OS X 10.7 to 10.9. As gdb is no longer supported in OS X, I installed GNU gdb via macports. Before being able to use it, I had to codesign it as described here. Now I can use gdb as debugger but I have problems in setting up breakpoints when attaching to a process. I will make an example for you. I took this sample C code

#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();
}

and compile it with

gcc -g a.c

If I now try to debug by doing

gdb a.out

and running it within gdb, the outcome is the following (as expected)

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)

So what I did was to open gdb, set a breakpoint at function f(), run the program, and then simply issue a continue command when stopping within f(). If I now do the same but attaching to the already running process, I cannot set the breakpoint, and I also get an error when issuing the continue command to make the process continue after attaching. Here is the outcome:

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)

So first of all when attaching, gdb does not give any information about the current position in the code (0x00007fff8516da3a in ?? ()) which might be ok, as I most probably have stopped the process when it was within the sleep() function.

However, when I try to set the breakpoint at f(), I get the "cannot access memory at" error, and the breakpoint is clearly not set. Indeed, when I give the continue command, the process simply goes on as normal and terminates without stopping at f().

Moreover, I also get this "Mach error at [...] (os/kern) failure (0x5)" when trying to continue. Setting breakpoints does not work even with

(gdb) break a.c:5
Cannot access memory at address 0x100000edc

I tried searching the web and stackoverflow too, but I found no answer to this problem. Any help is appreciated.

2
Why not use Apple's lldb that comes as part of Xcode ?Paul R
Because I am often using Eclipse-CDT to debug my code, and it still does not support lldb. There is a plugin to make lldb work with Eclipse-CDT, but it is still not mature enough, as far as I understand. In any case, I want to have this problem fixed, because I always worked with gdb, and switching to another debugger does not seem to me a real solution :)Michele Segata
OK, but note that lldb is almost identical in operation to gdb, so there is no big investment in time/effort if you want to try it. Good luck!Paul R
Yes I guess so, but still I would need gdb for Eclipse, so I am searching for help in hereMichele Segata
I would also very much like a gdb that works on Mavericks (with Emacs). Reasons: there is no Emacs mode for lldb, and Xcode can not attach to an arbitrary process (without a supporting Xcode project), and lldb lacks the 'dir' command so (in our case) lldb can not find our sources. So basically, for our project, lldb is useless and nowhere near gdb in functionality.Per Mildner

2 Answers

2
votes

I found a (not really satisfying) solution to the problem. Using MacPorts, I installed the apple version of GDB:

sudo port install gdb-apple

This version of GDB is able to attach to processes and to set breakpoints correctly, even within Eclipse CDT. The only flaw I found is that, in Eclipse, I need to set the breakpoints before attaching to the process. If I try to set a breakpoint when already attached, the procedure fails. I have no idea why.

I hope this answer can help somebody, and if any of you finds a better solution, I would be glad to know it.

0
votes

This is actually a bug (missing functionality) in upstream GDB.

I've been reading through its source code to learn how it works on macOS and the "attach to running process" codepath never calls ptrace(PT_ATTACHEXC, ...), which would reroute signals delivered to the traced process into the exception port used by GDB.

It does call ptrace(PT_SIGEXC) when spawning the child, which explains why it works in this scenario.