C 如何在gdb中逐步完成longjmp
我正试图修复别人编写的代码中的一个bug,并且我正试图在gdb中一步一步地检查它,以了解到底发生了什么。但我遇到的一行是对longjmp()的调用,在该行中遇到“next”之后,gdb继续常规执行,而不是在正在执行的下一个源行中断。如果我在longjmp()行上尝试“step”,则会出现类似的continue。是否有任何gdb命令可用于在longjmp()之后执行的下一个源代码行中断?您需要通过C 如何在gdb中逐步完成longjmp,c,gdb,setjmp,C,Gdb,Setjmp,我正试图修复别人编写的代码中的一个bug,并且我正试图在gdb中一步一步地检查它,以了解到底发生了什么。但我遇到的一行是对longjmp()的调用,在该行中遇到“next”之后,gdb继续常规执行,而不是在正在执行的下一个源行中断。如果我在longjmp()行上尝试“step”,则会出现类似的continue。是否有任何gdb命令可用于在longjmp()之后执行的下一个源代码行中断?您需要通过setjmp在非零返回代码之后的行设置断点 例如: #include <stdio.h>
setjmp
在非零返回代码之后的行设置断点
例如:
#include <stdio.h>
#include <setjmp.h>
jmp_buf jb;
void f1()
{
printf("jumping\n");
longjmp(jb, 1);
printf("what???\n");
}
int main()
{
if (!setjmp(jb)) {
printf("calling f1\n");
f1();
} else {
printf("jumped!!\n"); // line 19
}
return 0;
}
在longjmp()之后执行的下一个源代码行上是否有任何gdb命令可以用来中断
据我所知,没有。您需要跟踪jmp_buf
的起源,备份调用堆栈以找到填充它的setjmp()
。如果<代码> SETJMP()>源代码中的调用很少,则可以考虑在每个设置后设置断点。否则,您可能只需单步执行程序,在每次传递setjmp()
后设置一个断点
还要注意,当到达相应的longjmp()
时,您确实应该在调用堆栈中的一个函数中找到相关的setjmp()
,否则jmp\u buf
无效
您可以使用
bt
命令获取调用堆栈,使用frame
命令切换并检查堆栈上的任何帧。值得注意的是,gdb的行为取决于系统
在Linux上,通过longjmp
或throw
执行的next
工作原理与您预期的大致相同:如果非本地跳转的目标位于或高于当前帧,则执行将停止在那里
这是在longjmp
和throw
的实现中使用调试挂钩实现的。对于throw
来说,这可以通过辅助函数(旧方法)和所谓的SystemTap探测(也称为“sdt探测”)来完成。对于longjmp
,这仅通过glibc中的sdt探针完成
为此,必须将探测支持编译到相关库中。您可以使用readelf-n
进行检查。至少Fedora做得很好
理论上,在gdb中为其他平台实现对longjmp
的支持是可能的。然而,这可能不是小事
您可以尝试解码jmp_buf
,如其他注释中所述。但是请注意,在某些系统上,例如Linux,出于安全原因,jmp_buf
中的目标PC被编码。所以你必须弄清楚如何解码它
另一种方法是单步执行
longjmp
本身。在那里设置一个断点,比如breaklongjmp
;使用拆解查看组件;然后执行si
,直到您单步执行将执行转移到目标的指令。您可以执行中断main
,然后运行并保持单步执行程序。然后它会在每一行提示输入,包括longjmp()之后的一行。(如果这回答了你的问题,我会把它放在一个答案中)如果你在那行中点击“步骤”而不是“下一步”,会发生什么?您可以做的一件事是在代码上添加一个断点,用于处理setjmp()
@MDXF中的非零返回值,很明显,您的目的是使用步骤
命令而不是下一个
命令吗?医生说那对他不起作用。我知道你特别建议在main
处中断,但我不明白为什么这会与在longjmp()
之前在其他地方中断有所不同。这基本上是可行的。花了一点搜索来找出最后调用的setjmp是什么,但是在足够多的setjmp非零返回后放置断点之后,我最终找到了程序的去向。