Я хочу игнорировать попадания в точки останова / наблюдения в зависимости от некоторых условий.На первый взгляд, использование continue
внутри hook-stop
кажется решением проблемы.Тем не менее, кажется, что GDB игнорирует / отключает ловушку после возобновления выполнения, но затем каким-то образом включает его, а затем снова отключает его при попадании и т. Д.
Вот минимальный пример с шагами для воспроизведения.
Программа, которую мы собираемся отладить ("1.c"):
#include <stdio.h>
FILE *f;
int foo()
{
static int v = 0;
fprintf(f, "%d\n", v);
fflush(f);
if (v++ == 42)
return v;
return foo();
}
int main()
{
f = fopen("/tmp/log", "a");
foo();
return 0;
}
Компилировать, например, с помощью gcc -Og -g 1.c
.
Командный файл "cmd":
set $cont = 1
def hook-stop
if ($cont == 1)
python with open("/tmp/log", "a") as ofile: print("cont", file=ofile)
continue
end
end
b foo
r
Выполнить: rm /tmp/log; gdb -x cmd --args ./a.out
Сессия GDB:
Breakpoint 1, foo () at 1.c:4
(gdb) i b
breakpoint already hit 2 times
(gdb) c
Continuing.
Breakpoint 1, foo () at 1.c:4
(gdb) i b
breakpoint already hit 4 times
В результате /tmp/log
:
cont
0
1
cont
2
И если я продолжу нажиматьc
это продолжается следующим образом: 2 3 продолжение 4 5 продолжение ... то есть выполнение возобновляется ловушкой, но только через раз.
Это ошибка GDB?
Как мне автоматически возобновить выполнение на основе некоторого сложного условия (в моей исходной задаче у меня есть точка наблюдения, но я хочу игнорировать попадания в функции, которые меня не интересуют)? - Правка: на эту часть уже есть ответ, спасибо Employed Russian за то, что поставил меня на правильный путь.Когда другой человек удивился тому же самому почти в тот же день, я отправил свой ответ там , единственная оставшаяся магическая пустота - это сам фильтр: return gdb.selected_frame().name() in ["foo", "bar"]
.
Мой GDBверсия 8.3.
До публикации я некоторое время смотрел на реализацию, но пока не пытался ее отладить.Этот код в infrun.c
выглядит подозрительно:
normal_stop (void):
...
TRY
{
execute_cmd_pre_hook (stop_command);
}
CATCH (ex, RETURN_MASK_ALL)
{
exception_fprintf (gdb_stderr, ex,
"Error while running hook_stop:\n");
}
END_CATCH
/* If the stop hook resumes the target, then there's no point in
trying to notify about the previous stop; its context is
gone. Likewise if the command switches thread or inferior --
the observers would print a stop for the wrong
thread/inferior. */
if (stop_context_changed (saved_context))
{
do_cleanups (old_chain);
return 1;
}