【问题标题】:gdb is skipping instructionsgdb 正在跳过指令
【发布时间】:2019-01-15 20:55:34
【问题描述】:

总的来说,我在 gdb 和调试共享对象方面的经验有限,所以我想知道是否有人可以对我所看到的行为有所了解。

基本上,我试图了解一个文档记录不佳的库的内部结构。为此,我编写了一个程序,最大限度地减少了对库的使用,并尝试逐步了解它发生了什么。

问题是在gdb中使用“step”命令几次后,程序执行了不止一条指令。我相信这一点的一个原因是,最终 gdb 表明已经启动了三个线程,但是我在代码中的任何地方都看不到为什么会发生这种情况。

过去我曾尝试使用调试符号重建库,但这似乎并没有让我更进一步。我什至不确定这是否相关,因为我认为 gbd 仍然可以在没有调试符号的情况下单步执行指令(即使没有调试符号也意味着它会给我更少的信息)。

如果相关:我正在调试一个我编写的 3 行程序,该程序动态链接到感兴趣的库。我有这个库的源代码,但它很复杂,所以我希望 gdb 能对事情有所了解。

提前致谢!

【问题讨论】:

  • 您使用了哪些优化选项?优化得越多,调试器就越难使用。
  • 您是否尝试在 gdb 中逐步执行优化的 C++ 代码?那会非常混乱。
  • @Shawn 查看相关库的构建脚本会发现,将其 DEBUG 参数设置为“true”意味着使用了 -O0。
  • @Shawn 没关系!我没有正确使用构建脚本。我刚刚重建并适当地设置了调试选项,所以现在优化似乎已经关闭。
  • 如果有人想发布有关优化的答案,我会将其标记为正确。非常感谢!

标签: c++ gdb shared-objects


【解决方案1】:

我认为 gbd 仍然可以逐步执行指令

可以,但执行此操作的命令是 stepi,而不是您正在使用的 step

单步跳过,这需要在源代码中提供调试信息。

【讨论】:

    【解决方案2】:

    关于优化的一点点

    例如,这是一个 C 代码:

    int main(int argc, char** argv) {
      printf("Hello World\n");
      return 0;
    }
    

    当你用 -O0 构建时,几乎没有进行代码优化,而且代码运行很慢。这是未优化的代码(gcc -m32):

    ; Variables:
            ;    arg_4: 12
            ;    arg_0: 8
            ;    var_4: -4
            ;    var_8: -8
            ;    var_C: -12
            ;    var_10: -16
            ;    var_18: -24
    push       ebp
    mov        ebp, esp
    sub        esp, 0x18
    call       _main+11
    pop        eax                            ; CODE XREF=_main+6
    
    -- These lines are gone after optimization --
    mov        ecx, dword [ebp+arg_4]
    mov        edx, dword [ebp+arg_0]
    --                                    --
    lea        eax, dword [eax-0x1f5b+0x1fa6] ; "Hello World!\\n"
    
    -- There lines are gone after optimization --
    mov        dword [ebp+var_4], 0x0
    mov        dword [ebp+var_8], edx
    mov        dword [ebp+var_C], ecx
    
    mov        dword [esp+0x18+var_18], eax  ; method imp___symbol_stub__printf
    call       imp___symbol_stub__printf
    xor        ecx, ecx                           
    mov        dword [ebp+var_10], eax
    mov        eax, ecx                                    
    add        esp, 0x18                           
    pop        ebp
    ret
    

    当您使用 -03 构建时,您会注意到行数减少了。优化后的代码(gcc -m32 -O3):

    push       ebp
    mov        ebp, esp
    sub        esp, 0x8
    call       _main+11
    pop        eax                             ; CODE XREF=_main+6
    lea        eax, dword [eax-0x1f6b+0x1f9e]  ; "Hello World!"
    mov        dword [esp+0x8+var_8], eax      ; "%s" for imp___symbol_stub__puts
    call       imp___symbol_stub__puts
    xor        eax, eax
    add        esp, 0x8
    pop        eep
    ret
    

    未优化的代码有不必要的行的原因是因为 main 接受两个参数并将它们保存到寄存器中,无论您是 使用或不使用优化,但优化编译器 删除这些 mov 指令,因为既不使用参数 也不需要。同样,寄存器的值也保存到 堆栈变量作为参数被复制到堆栈变量中。

    【讨论】:

      猜你喜欢
      • 2019-06-26
      • 1970-01-01
      • 2011-12-04
      • 2018-09-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多