我想根据某些条件忽略断点/观察点命中。乍看之下,在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 cont 4 5 cont ...即执行通过钩子恢复,但只能每隔一次。
这是GDB错误吗?
如何基于某些复杂条件自动恢复执行(在我最初的问题中,我有一个监视点,但我想忽略不感兴趣的函数中的命中点)? —编辑:这部分已经得到了答复,这要归功于Employed Russian使我走上了正确的道路。当另一个人几乎差不多在同一天想知道同一件事时,我发布了答案there,唯一剩下的魔咒就是过滤器本身: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;
}