是什么让GDB拒绝破产?

时间:2011-09-21 01:26:48

标签: c gdb

我在这里不知所措。我正在用C编写一个编译器(用于爱好),并使用GDB 7.3在amd64 Linux 2.6.32上使用GCC 4.6.1进行编译。标志是“-Wall -Wextra -O0 -g”,除了通常的-I和诸如此类之外。我有一个函数,其目的是报告一个解析错误,定义如下:

void cerror_at (struct lex *lex, struct token *tok, const char *fmt, ...)

除了变数之外,没有什么奇怪的。问题是GDB不会破坏它。我已经尝试了我能想到的每一种方式(函数中的断点,函数内部,调用它之前,你的名字),但是只要我的程序在函数内部,我就会收到类似“警告:删除断点时出错”的消息0“和GDB只是让程序完成。它已经没有任何问题了(我已经修复了我试图找到的错误,并且一切都按照它应该运行),但我无法进入该功能。关于可能导致这种情况的任何想法?

修改:更多信息! GDB将断点设置为0x403057。该函数从0x403025开始。看看这部分反汇编:

0x0000000000403053 <+46>:   test   %al,%al
0x0000000000403055 <+48>:   je     0x403077 <cerror_at+82>

此时,它会向前跳到0x403077(超过断点)。我已经验证了将断点放在“je”之前的地址,以及跳转目标0x403077处或之后的地址,但不是介于两者之间(GDB试图放置它的地址)。为什么GDB会将断点放在函数的中间?甚至GDB也告诉我函数的地址实际上是0x403025。

4 个答案:

答案 0 :(得分:3)

也许我只是密集,但我遇到的调试器拒绝破解的最常见原因是最简单的原因。

  1. 我正在尝试调试的代码与调试器中的代码不完全匹配。
  2. 我忘了使用调试选项编译该库。
  3. 请确保在收到类似调试错误的任何时候检查这两个,即使您认为这不是问题。

答案 1 :(得分:1)

这听起来像是GDB中的一个错误。特别是,Error removing breakpoint 0非常可疑(它是一个断点GDB自动插入某处;用户插入的断点有正数)。

您应该尝试创建一个简化的测试用例并提交错误here

答案 2 :(得分:0)

如评论中所述,您应该尝试了解编译生成的机器代码:

在GDB中,您可以看到disassemble cerror_at的实际功能代码 应该给出类似(x86_64)的东西:

(gdb) disassemble dive
Dump of assembler code for function dive:
   0x0000000000400504 <+0>: push   %rbp
   0x0000000000400505 <+1>: mov    %rsp,%rbp
   0x0000000000400508 <+4>: sub    $0x10,%rsp
   0x000000000040050c <+8>: mov    %edi,-0x4(%rbp)
   0x000000000040050f <+11>:    mov    -0x4(%rbp),%eax
   0x0000000000400512 <+14>:    add    $0x1,%eax
   0x0000000000400515 <+17>:    mov    %eax,%edi
   0x0000000000400517 <+19>:    callq  0x400504 <dive>
   0x000000000040051c <+24>:    leaveq
   0x000000000040051d <+25>:    retq   
End of assembler dump.

然后检查子程序是否实际被调用:在函数调用之前中断执行一些指令,然后:

   (gdb) x/5i $p
=> 0x400539 <main+27>:  mov    $0x1,%esi
   0x40053e <main+32>:  mov    %rax,%rdi
   0x400541 <main+35>:  callq  0x400408 <fwrite@plt>
   0x400546 <main+40>:  mov    $0x1,%edi
-->0x40054b <main+45>:  callq  0x400504 <dive> <------

输出应该与另一个CPU架构略有不同,但是您应该能够看到指向函数地址的分支指令。

-

您可以在maint info breakpoint知道Error removing breakpoint 0设置位置的那一刻之前执行breakpoint 0 ,这可能有助于了解错误用它。

答案 3 :(得分:0)

根据您的最新编辑,我打赌这是一个编译器错误。具体来说,我打赌生成DWARF调试信息存在问题,GDB用它来映射目标代码中的地址和源中的文件/过程/行号。

您可以尝试使用-gdwarf-4-gdwarf-3甚至-gdwarf-2进行试验,看看它是否有所不同。

如果你可以将它减少到一个简单的测试用例,我怀疑gcc开发人员会接受它作为一个bug。

当然,这也可能是GDB中的一个错误。但鉴于这种行为,我认为这种可能性较小。