我正在gdb会话中对崩溃进行事后分析,并且正在从函数的开头开始分析该函数的以下汇编代码:
0x0000000001b0af00 <+0>: push %rbp
0x0000000001b0af01 <+1>: mov %rsp,%rbp
0x0000000001b0af04 <+4>: push %rbx
0x0000000001b0af05 <+5>: mov %rdi,%rbx
0x0000000001b0af08 <+8>: sub $0x8,%rsp
0x0000000001b0af0c <+12>: mov 0x18(%rdi),%rdi
=> 0x0000000001b0af10 <+16>: mov (%rdi),%rdx
崩溃发生是因为rdi的空引用无效:
(gdb) info registers rdi
rdi 0x0 0
好。但是阅读该程序集(这很简单),我看不出rdi值如何为空。请注意,具有+5指令偏移量的rdi原始值的rbx具有以下功能:
(gdb) info registers rbx
rbx 0x7f4fb26b9690 139980272539280
从那里,rdi应该具有该地址的解引用值加上0x18(由于指令偏移量为+12):
(gdb) x/a (0x7f4fb26b9690 + 0x18)
0x7f4fb26b96a8: 0x7f4f74632bb0
请注意,它不为零。如我所见,rdi的值应为0x7f4f74632bb0
。我有什么误会?
这是从GCC 4.8编译C ++代码生成的x64程序集。
答案 0 :(得分:0)
是的,您正确地理解了asm。要么您的核心文件不是mem + reg的准确快照,要么是第一次和第二次加载之间发生了某种异步的内存修改(如建议的fifoforlifo)。
(或者我没有想到的其他解释。)
我猜0x7f4f74632bb0
也是一个有效的指针,因此如果该值出现得早,则load + deref应该已经起作用。
您的程序是多线程的,还是安装了任何信号处理程序?