ОС: GNU / Linux
Дистрибутив: OpenSuSe 13.1
Arch: x86-64
Версия GDB: 7.6.50.20130731-cvs
Язык программы: в основном C с небольшими фрагментами сборки
Представьте, что у меня есть довольно большая программа, которая иногда не может открыть файл. Можно ли установить точку останова в GDB таким образом, чтобы она останавливалась после того, как системный вызов open(2)
вернет -1?
Конечно, я могу просмотреть исходный код с помощью grep и найти все open(2)
вызовы и сузить open()
вызов, вызывающий ошибку, но, возможно, есть способ получше.
Я попытался использовать "catch syscall open"
, затем "condition N if $rax==-1"
, но, очевидно, ничего не вышло.
Кстати, возможно ли различить вызов системного вызова (например, open(2)
) и возврат из системного вызова (например, open(2)
) в GDB?
В качестве текущего обходного пути я делаю следующее:
- Запустите рассматриваемую программу под GDB
Из другого терминала запустите скрипт systemtap:
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 и могу отладить проблему.
TIA.
С уважением,
alexz.
UPD: хотя я пробовал подход, предложенный n.m, раньше и не смог заставить его работать, я решил попробовать еще раз. Через 2 часа он работает как задумано. Но есть странный обходной путь:
- Я все еще не могу различить вызов и возврат из системного вызова
Если я использую
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, например. если это «В доступе отказано», то я должен проверить на «-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
gdb
из исходного кода, с расширяемостью Python и Guile, могла бы быть полезной. - person Basile Starynkevitch   schedule 22.09.2014eax
, а неrax
. - person Matt McHenry   schedule 19.02.2017