我在这里不知所措。我正在用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。
答案 0 :(得分: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中的一个错误。但鉴于这种行为,我认为这种可能性较小。