2010-11-07 104 views
5

我是GDB新手(一般调试)。 在GDB中调试时,是否可以跳转到代码/可执行文件中的某个位置/地址?是否可以在GDB调试器中“跳转”/“跳过”?

让说我有类似以下

int main() 
{ 
    caller_f1() { 

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

    caller_f2() { // jump to this this location ??  
    f1(); 
    f2(); } 
} 

感谢的东西!

回答

1

要在新的地址恢复执行,使用jump(短形式:j):

jump LINENUM 
jump *ADDRESS 

The GDB manual建议在跳跃前使用tbreak(临时断点)。

亚麻可以是任何linespec表达式,如下一行的+1

请参阅@gospes's answer关于一个方便的相关问题skip宏就是这么做的。


使用jump仅是“安全的”,在未优化的代码(-O0,甚至然后仅在当前功能。它只有修改程序计数器;它不会更改任何其他寄存器或内存。

只有gcc -O0将每个源语句(或行?)编译成独立的指令块,从存储器加载变量值并存储结果。这使您可以在任何断点处使用调试器修改变量值,并使机器代码中的行之间的行数变为jump,例如在C源代码行之间跳转。

这是-O0编码速度如此之慢的一部分:编译器不仅花费时间进行优化,而且还需要编写缓慢的代码,以便在每个语句之后溢出/重新加载所有内容,以支持异步修改变量,计数器。 (在典型的x86上,存储/重新加载延迟约为5个周期,因此在-O0版本中,1个周期add需要6个周期)。

gcc's manual suggests using -Og用于通常的编辑 - 编译 - 调试周期,但即使那样的优化级别也会中断jump和异步修改变量。如果您在调试时不想这样做,那么这是一个不错的选择,尤其是对于-O0运行速度非常慢并且存在问题的项目。


设置程序计数器/指令指针到一个新的地址,而不恢复,你也可以使用这样的:从反汇编窗口

set $pc = 0x4005a5 

复制/粘贴地址(layout asm/layout reg )。

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

然后你可以从stepi那里。 $pc是无论在目标体系结构中真正调用寄存器的通用gdb名称。例如RIP在x86-64。 (另请参阅标记wiki的底部,了解gdb的asm调试技巧。)