Mac OS X Mavericks - gdb - Невозможно установить точки останова при подключении к процессу

Я недавно обновился с Mac OS X 10.7 до 10.9. Поскольку gdb больше не поддерживается в OS X, я установил GNU gdb через macports. Прежде чем я смог использовать его, мне пришлось подписать его, как описано здесь. Теперь я могу использовать 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, чтобы заставить процесс продолжить после присоединения. Вот результат:

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 в?? ()), что может быть в порядке, так как я, скорее всего, остановил процесс, когда он был внутри функции sleep(),

Однако, когда я пытаюсь установить точку останова на f(), я получаю сообщение об ошибке "невозможно получить доступ к памяти при", и точка останова явно не установлена. Действительно, когда я даю команду continue, процесс просто продолжается как обычно и завершается, не останавливаясь на f().

Более того, я также получаю эту "ошибку Маха при сбое [...] (os/kern) (0x5)" при попытке продолжить. Установка точек останова не работает даже с

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

Я также попытался выполнить поиск в сети и через stackru, но не нашел ответа на эту проблему. Любая помощь приветствуется.

2 ответа

Я нашел (не очень удовлетворительное) решение проблемы. Используя MacPorts, я установил яблочную версию GDB:

sudo port install gdb-apple

Эта версия GDB может подключаться к процессам и правильно устанавливать точки останова, даже в Eclipse CDT. Единственный недостаток, который я обнаружил, заключается в том, что в Eclipse мне нужно установить точки останова перед подключением к процессу. Если я пытаюсь установить точку останова, когда она уже подключена, процедура завершается ошибкой. Понятия не имею почему.

Я надеюсь, что этот ответ может кому-то помочь, и если кто-то из вас найдет лучшее решение, я был бы рад узнать его.

На самом деле это ошибка (отсутствует функциональность) в исходной GDB.

Я читал его исходный код, чтобы узнать, как он работает в macOS, а путь присоединения к запущенному процессу никогда не вызывает ptrace(PT_ATTACHEXC, ...), который перенаправит сигналы, доставленные отслеживаемому процессу, в порт исключения, используемый GDB.

Это называется ptrace(PT_SIGEXC) когда порождает ребенка, что объясняет, почему это работает в этом сценарии.

Другие вопросы по тегам