MIPS:合法的连续两次;“加载单词”;将指令放入同一寄存器?
Background:我们看到函数MIPS:合法的连续两次;“加载单词”;将指令放入同一寄存器?,mips,Mips,Background:我们看到函数foo(int*p)中出现了非常间歇性的崩溃。在取消引用p时发生崩溃,在这些情况下,其值为0xffffffff。对核心转储的分析表明,foo()是从以下程序集片段调用的: bne ... somewhere else lw $a0,44(sp) lw $a0,40(sp) jal foo() lui s1, 0x1000 检查内核转储中的内存表明44(sp)是0xffffff,而40(sp)是我们要取消引用的正确值。但是,碰撞时a0在foo()内的值为0xff
foo(int*p)
中出现了非常间歇性的崩溃。在取消引用p
时发生崩溃,在这些情况下,其值为0xffffffff
。对核心转储的分析表明,foo()
是从以下程序集片段调用的:
bne ... somewhere else
lw $a0,44(sp)
lw $a0,40(sp)
jal foo()
lui s1, 0x1000
检查内核转储中的内存表明44(sp)
是0xffffff
,而40(sp)
是我们要取消引用的正确值。但是,碰撞时a0
在foo()
内的值为0xffffffff
。(需要注意的是,foo()
在本例中只是访问一个成员;因此它实际上是foo()中的第一条指令。)
已经尝试通过a0
访问并崩溃。此外,ra
指向上述代码段后面的指令,s1
当前包含0x10000000
,因此我们非常确信foo()
确实是从上述代码段调用的。)
目前我们唯一的理论是,两个连续的lw
s进入a0
是一种危险——要么是有记录的,在这种情况下,这看起来像是一个编译器错误;或者一个没有文件的
因此:上述集会合法吗?如果是的话,关于这里可能发生的事情还有其他想法吗
谢谢
更新:事实证明,这完全是白费力气:一位同事对coredump的重复分析在代码中找到了一条我错过的路径,在将a0
设置为44(sp)
后,立即跳转到jal foo()
指令。换句话说,代码中有一条路径与我们看到的结果一致,它不涉及危险、或“跳过的指令”或任何东西。。。我想我检查过了,但我想我要么没有,要么错过了…:(
无论如何,我已经接受了markgz的回答,因为它回答了我最初关于这些指令合法性的问题(显然是这样)。快速搜索MIPS32R2 ISA的MIPS文档不会显示对
LW
指令之后的LW
的任何限制
您的CPU中的MIPS实现可能存在错误。要查看的内容包括:
- 44(sp)、40(sp)是什么地址?它们是在页面边界上还是在256MB的边界上,还是在其他有趣的地址上
- 两个加载是否都会触发页面错误
- 对二进制文件进行修补以在加载之间插入
、NOP
、或SSNOP
指令是否可以解决问题SYNC