Как отладить входную точку процесса fork-exec в GDB?
У меня есть приложение C linux (A), которое запускает другой процесс (P) при его запуске. Когда я хочу отлаживать P, я запускаю A как обычно, и я соединяюсь с ddd/gdb с P.
Проблемы возникают, когда я хочу отлаживать начальную точку (начало основного) P. Если я буду следовать обычным подходам, когда я подключу отладчик к P, то уже поздно. Решение, которое я нашел, это вставить сон в начале основного P, чтобы у меня было время подключиться к gdb, но это не очень изящное решение.
Я также пробовал использовать asm("int $3")
, но он не работает.
У вас есть идея, как я могу решить эту проблему? (предпочтительно без изменения кода A или P)
Ответы
Ответ 1
Вы должны использовать эту опцию:
set follow-fork-mode
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.
Ответ 2
В дополнение к ответу Nathan Fellman, точки доступа пригождаются, например:
catch exec
Catchpoint работает как точка останова. Каждый раз, когда вызывается вызов функции sysall(), GDB останавливается. Это позволяет вам установить любую точку останова (например, break main
) в любой загруженный исполняемый файл перед продолжением. Другая точка catch catch fork
работает аналогично для обнаружения syscall fork().
Это особенно удобно:
- когда необходимо соблюдать как родительский, так и дочерний (
set detach-on-fork off
);
- когда родительские процессы вилки часто загружают различные исполняемые файлы.
Ответ 3
Вы должны сделать это, используя функции удаленной отладки gdb, в частности gdbserver
. По сути, запуск (P) с использованием gdbserver
. Эти ссылки содержат более подробную информацию:
Ответ 4
exec
часть с file
+ break main
Вилка была частично объяснена: fooobar.com/questions/257087/...
Теперь для 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/cirsan01/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/cirsan01/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.
Ответ 5
установите точку останова на main(), она также будет разбита на main() исполняемой программы.