ОС: GNU/Linux
Distro: OpenSuSe 13.1
Arch: x86-64
Версия GDB: 7.6.50.20130731-cvs
Язык программы: в основном C с младшими битами сборки
Представьте, что у меня довольно большая программа, которая иногда не открывается. Можно ли установить точку останова в GDB таким образом, что она останавливается после open(2)
syscall возвращает -1?
Конечно, я могу выполнить grep через исходный код и найти все вызовы open(2)
и сузить вызов open()
с ошибкой, но, возможно, лучший способ.
Я попытался использовать "catch syscall open"
, затем "condition N if $rax==-1"
, но, очевидно, это не попало.
BTW, возможно ли различать вызов в syscall (например, open(2)
) и возврат из syscall (например, open(2)
) в GDB?
В качестве текущего обходного пути я делаю следующее:
- Запустите эту программу под GDB
-
От другой системы запуска терминалов script:
stap -g -v -e 'probe process("PATH to the program run under GDB").syscall.return { if( $syscall == 2 && $return <0) raise(%{ SIGSTOP %}) }'
- После
open(2)
возвращает -1 Я получаю SIGSTOP в сеансе GDB, и я могу отладить проблему.
ТИА.
С уважением,
AlexZ.
UPD: Несмотря на то, что я пробовал подход, предложенный n.m раньше и не смог заставить его работать, я решил попробовать еще раз. Через 2 часа он теперь работает по назначению. Но с некоторым странным обходным путем:
- Я все еще не могу различить между вызовом и возвратом из syscall
-
Если я использую
finish
вcomm
, я не могу использоватьcontinue
, что в порядке в соответствии с документами GDB
то есть следующее: падение на gdb-запрос на каждый разрыв:gdb> comm gdb> finish gdb> printf "rax is %d\n",$rax gdb> cont gdb> end
-
На самом деле я могу избежать использования
finish
и проверить% rax вcommands
, но в этом случае мне нужно проверить -errno, а не -1 например если это "Permission denied", то я должен проверить "-13", и если это "Нет такого файла или указателя", то для -2. Это просто не правильно -
Таким образом, единственный способ заставить это работать для меня - определить пользовательскую функцию и использовать ее следующим образом:
(gdb) catch syscall open Catchpoint 1 (syscall 'open' [2] (gdb) define mycheck Type commands for definition of "mycheck". End with a line saying just "end". >finish >finish >if ($rax != -1) >cont >end >printf "rax is %d\n",$rax >end (gdb) comm Type commands for breakpoint(s) 1, one per line. End with a line saying just "end". >mycheck >end (gdb) r The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: /home/alexz/gdb_syscall_test/main ..... Catchpoint 1 (returned from syscall open), 0x00007ffff7b093f0 in __open_nocancel () from /lib64/libc.so.6 0x0000000000400756 in main (argc=1, argv=0x7fffffffdb18) at main.c:24 24 fd = open(filenames[i], O_RDONLY); Opening test1 fd = 3 (0x3) Successfully opened test1 Catchpoint 1 (call to syscall open), 0x00007ffff7b093f0 in __open_nocancel () from /lib64/libc.so.6 rax is -38 Catchpoint 1 (returned from syscall open), 0x00007ffff7b093f0 in __open_nocancel () from /lib64/libc.so.6 0x0000000000400756 in main (argc=1, argv=0x7fffffffdb18) at main.c:24 ---Type <return> to continue, or q <return> to quit--- 24 fd = open(filenames[i], O_RDONLY); rax is -1 (gdb) bt #0 0x0000000000400756 in main (argc=1, argv=0x7fffffffdb18) at main.c:24 (gdb) step 26 printf("Opening %s\n", filenames[i]); (gdb) info locals i = 1 fd = -1