是否可以在GDB调试器中"跳转"/"跳过"?

new*_*int 8 c debugging gdb

在GDB中调试时是否可以跳转到代码/可执行文件中的某个位置/地址?

假设我有类似以下的内容

int main()
{
  caller_f1() {  

   f1();  // breakpoint  
   f2() } // want to skip f2() and jump 

  caller_f2() { // jump to this this location ??       
   f1();  
   f2(); }  
}
Run Code Online (Sandbox Code Playgroud)

Pet*_*des 8

要继续在新地址执行,请使用jump(简短形式:) j:

jump LINENUM
jump *ADDRESS
Run Code Online (Sandbox Code Playgroud)

GDB手册建议tbreak在跳跃之前使用(临时断点).

亚麻布可以是任何linespec表达,就像+1下一行一样.

请参阅@ gospes关于相关问题的答案,以获得一个方便的skip宏.


jump在非优化代码(-O0)中使用只是"安全",即使只在当前函数中使用.它只是修改程序计数器; 它不会改变任何其他寄存器或内存.

gcc -O0将每个源语句(或行?)编译成一个独立的指令块,从内存加载变量值并存储结果.这允许您在任何断点处使用调试器修改变量值,并使jump机器代码中的行之间的工作类似于在C源中的行之间跳转.

这就是为什么-O0编写这么慢的代码的一部分:不仅编译器不花时间优化,还需要制作慢速代码,在每个语句之后溢出/重新加载所有内容,以支持异步修改变量甚至程序计数器.(在典型的x86上,存储/重载延迟大约为5个周期,因此1 add个周期在-O0构建中需要6个周期).

gcc的手册建议使用-Og通常的编辑 - 编译 - 调试周期,但即使是那种轻量级的优化也会破坏jump变量的异步修改.如果您不想在调试时这样做,那么这是一个不错的选择,特别是对于-O0运行速度太慢以至于存在问题的项目.


要将程序计数器/指令指针设置为新地址而不恢复,您还可以使用:

set $pc = 0x4005a5
Run Code Online (Sandbox Code Playgroud)

从反汇编窗口(layout asm/ layout reg)复制/粘贴地址.

这相当于tbreak+ jump,但不能使用行号,只能使用指令地址.(并且你没有收到警告+确认请求跳过当前功能).

然后你可以stepi从那里. $pc是目标体系结构中实际调用的寄存器的通用gdb名称.例如,x86-64中的RIP.(有关gdb的asm调试技巧,另请参阅标记wiki 的底部.)

  • 可能会破坏一些逻辑,例如常数传播或其他不变量。例如,如果还有一个“ptr++”并且它们被优化为一个,则不要期望在循环体中重新运行“i++”能够工作。或者跳入循环很可能不会运行循环设置并完全中断。基本上任何涉及寄存器值的事情都有可能被破坏。 (2认同)

hoj*_*ram 7

似乎有一个跳转命令正是您正在寻找的:

http://idlebox.net/2010/apidocs/gdb-7.0.zip/gdb_18.html#SEC163

更新链接:http://web.archive.org/web/20140101193811/http: //idlebox.net/2010/apidocs/gdb-7.0.zip/gdb_18.html#SEC163