在GDB中调试时是否可以跳转到代码/可执行文件中的某个位置/地址?
假设我有类似于以下内容的内容
int main()
{
caller_f1() {
f1(); // breakpoint
f2() } // want to skip f2() and jump
caller_f2() { // jump to this this location ??
f1();
f2(); }
}
答案 0 :(得分:7)
似乎有一个跳转命令正是您正在寻找的:
http://idlebox.net/2010/apidocs/gdb-7.0.zip/gdb_18.html#SEC163
答案 1 :(得分:6)
要在新地址继续执行,请使用jump
(简称:j
):
jump LINENUM
jump *ADDRESS
The GDB manual建议在跳跃之前使用tbreak
(临时断点)。
亚麻布可以是任何linespec
表达式,例如下一行的+1
。
有关方便skip
宏的相关问题,请参阅@gospes's answer。
使用jump
只是"安全"在未优化的代码(-O0
)中,甚至只在当前函数中。 仅修改程序计数器;它不会改变任何其他寄存器或存储器。
只有gcc -O0
将每个源语句(或行?)编译成一个独立的指令块,从内存加载变量值并存储结果。这允许您在任何断点处使用调试器修改变量值,并使机器代码中的行之间的jump
工作,就像在C源代码行之间跳转一样。
这是-O0
制作如此慢代码的部分原因:不仅编译器不花时间优化,还需要制作慢速代码,在每个语句之后溢出/重新加载所有内容以支持异步修改变量和甚至程序计数器。 (在典型的x86上,存储/重新加载延迟大约是5个周期,因此在add
版本中,1个周期-O0
需要6个周期。
gcc's manual suggests using -Og
,但即使是那种轻量级的优化也会破坏jump
和变量的异步修改。如果您不希望在调试时这样做,那么这是一个不错的选择,特别是对于-O0
运行速度太慢以至于出现问题的项目。
要将程序计数器/指令指针设置为新地址而不恢复,您也可以使用:
set $pc = 0x4005a5
从反汇编窗口(layout asm
/ layout reg
)复制/粘贴地址。
这相当于tbreak
+ jump
,但您不能使用行号,只能使用指令地址。 (并且你没有得到警告+确认请求跳出当前功能)。
然后你可以stepi
从那里开始。 $pc
是一个通用的gdb名称,用于在目标体系结构中真正调用寄存器。例如RIP在x86-64中。 (另请参阅x86标记wiki的底部,了解gdb的asm调试技巧。)