Как отладить точку входа процесса fork-exec в GDB? - PullRequest
15 голосов
/ 18 декабря 2008

У меня есть приложение на C linux (A), которое запускает другой процесс (P) при его запуске. Когда я хочу отладить P, я запускаю A как обычно и подключаюсь с помощью ddd / gdb к P.

Проблемы появляются, когда я хочу отладить точку входа (начало основного) P. Если я следую обычному подходу, когда я подключаю отладчик к P, уже поздно. Решение, которое я нашел, состояло в том, чтобы вставить сон в начале основного P, чтобы у меня было время подключиться к gdb, но это не очень элегантное решение.

Я также пытался использовать asm("int $3"), но, похоже, он не работает.

Ты хоть представляешь, как я могу решить эту проблему? (желательно без изменения кода А или Р)

Ответы [ 5 ]

19 голосов
/ 18 декабря 2008

Вы должны использовать эту опцию:

<code>set follow-fork-mode</code> <i>mode</i>

Где mode это один из parent, child или ask.

Чтобы следовать за родителем (это по умолчанию), используйте:

set follow-fork-mode parent

Чтобы следовать за ребенком:

set follow-fork-mode child

Чтобы отладчик каждый раз спрашивал вас:

set follow-fork-mode ask

Таким образом, в основном вы начинаете подключать GDB к A, затем настраиваете GDB, чтобы следовать за дочерним элементом, а затем, когда A порождает P, GDB подключается к P и отсоединяется от A.

6 голосов
/ 30 октября 2012

В дополнение к ответу Натана Феллмана , поймать пригодятся, например:

catch exec

Catchpoint работает как точка останова. Каждый раз, когда обнаруживается вызов exec () syscall, GDB останавливается. Это позволяет вам установить любую точку останова (например, break main) в любом недавно загруженном исполняемом файле перед продолжением. Другая точка перехвата catch fork работает аналогично для fork () обнаружения системного вызова.

Особенно удобно:

  • когда нужно следить и за родителем, и за ребенком (set detach-on-fork off);
  • когда родительские процессы часто загружают различные исполняемые файлы.
0 голосов

exec часть с file + break main

Вилка была частично объяснена по адресу: https://stackoverflow.com/a/377295/895245

Теперь для exec:

a.c:

#include <unistd.h>

int main(void) {
    execl("./b", "./b", "ab", "cd", (char*)NULL);
    return 1;
}

b.c:

#include <stdio.h>

int main(int argc, char **argv ) {
    printf("%s\n", argv[0]);
    printf("%s\n", argv[1]);
}

Тогда:

gcc -g a.c -o a
gcc -g b.c -o b
gdb -nh -q a

Теперь на интерактивной сессии:

Reading symbols from a...done.
(gdb) start
Temporary breakpoint 1 at 0x4004ea: file a.c, line 4.
Starting program: /home/ciro/test/gdb-exec/a 

Temporary breakpoint 1, main () at a.c:4
4           execl("./b", "./b", "ab", "cd", (char*)NULL);
(gdb) file b
A program is being debugged already.
Are you sure you want to change the file? (y or n) y
Load new symbol table from "b"? (y or n) y
Reading symbols from b...done.
(gdb) b main
Breakpoint 2 at 0x4004f5: file b.c, line 4.
(gdb) n

Breakpoint 2, main (argc=0, argv=0x7fffffffa570) at b.c:4
4               printf("%s\n", argv[1]);
(gdb) n
process 4877 is executing new program: /home/ciro/test/gdb-exec/b

Breakpoint 2, main (argc=3, argv=0x7fffffffa598) at b.c:4
4               printf("%s\n", argv[1]);
(gdb) n
ab
5               printf("%s\n", argv[2]);
(gdb) n
cd
6       }
(gdb) 

Вам просто нужно убедиться, что вы поднялись до exec перед запуском файла, возможно, с b execl, так как после этого вы будете использовать символы из нового файла.

Протестировано в Ubuntu 14.04, gdb 7.7.1.

0 голосов
/ 25 ноября 2012

устанавливает точку останова в main (), она также прерывается в main () программы, для которой выполняется исключение.

0 голосов
/ 18 декабря 2008

Вы можете сделать это, используя функции удаленной отладки gdb, в частности gdbserver. По сути, запустите (P), используя gdbserver. Эти ссылки имеют более подробную информацию:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...