这与我曾经问过的Probable instruction Cache Synchronization issue in self modifying code?有关。即使已接受的解决方案解决了相关问题,我遇到了一种新的间歇性故障模式,其中CPU在重新打开功能后尝试跳转到垃圾地址。但事后的反汇编(使用核心转储)显示了调用指令中的正确地址。
接下来是一些gdb分析。
Program terminated with signal 11, Segmentation fault.
#0 0x00000000014010d0 in ?? ()
(gdb) bt
#0 0x00000000014010d0 in ?? ()
#1 0x0000000000492e01 in FastPelY_14 ()
#2 0x000000000045d85d in SubPelBlockMotionSearch ()
#3 0x0000000000467a23 in BlockMotionSearch ()
#4 0x0000000000469c99 in PartitionMotionSearch ()
#5 0x0000000000487bf7 in encode_one_macroblock ()
#6 0x0000000000496ccd in encode_one_slice ()
#7 0x0000000000426081 in code_a_picture ()
#8 0x000000000042766f in frame_picture ()
#9 0x000000000042664b in encode_one_frame ()
#10 0x0000000000430a23 in main ()
(gdb) disas /r 0x0000000000492e01
0x0000000000492dfc <+38>: e8 cf e2 f6 ff callq 0x4010d0
=> 0x0000000000492e01 <+43>: 8b 45 e4 mov -0x1c(%rbp),%eax
这里要注意的有趣事情是,当正确的地址是0x4010d0时,垃圾地址在失败时总是 0x14010d0 。这让我觉得调用指令甚至以某种方式失败 - 尽管指令指针显示为指向回溯中的下一条指令。 (可能这是gdb的正确行为。我不太确定)。
所以如果是这样的话,显然CPU已经试图调用 e8 cf e2 f6 00 而不是 e8 cf e2 f6 ff 。最初生活在调用站点的5字节序列从0x0000000000492dfc开始,是一个5字节的NOP(根据在顶部链接的问题中给出的建议)0x0F1F440000。
有什么想法在这里发生了什么?如果需要更多背景,请告诉我。顺便说一句,我使用的是英特尔(R)Xeon(R)CPU E5-2670,但我尝试过的其他几台机器的行为似乎一致。
编辑:代码已使用以下附加选项进行编译,并具有-O2优化级别。
-fno-optimize-sibling-calls -finstrument-functions