背景:我們看到一個非常間歇的崩潰的函數foo(int *p)
。崩潰發生在取消引用p
時,其值在這些情況下結果爲0xffffffff
。核心轉儲的分析表明,foo()
從下面的彙編代碼段稱爲:MIPS:合法將兩個連續的「加載字」指令放入同一個寄存器?
bne ... somewhere else
lw $a0,44(sp)
lw $a0,40(sp)
jal foo()
lui s1, 0x1000
在覈心轉儲檢查內存表明44(sp)
是0xffffffff
,而40(sp)
是我們打算取消引用正確的值。但是,在foo()
的崩潰時間a0
的值是0xffffffff
。 (需要注意的是,在這種情況下,foo()
只是訪問一個成員;所以它實際上是foo()
中的第一條指令,該指令已經試圖通過a0
訪問,並且崩潰。而且,ra
指向上述代碼片段之後的指令, s1
目前包含0x10000000
,所以我們完全相信,foo()
,的確,從上面的代碼中調用)
我們目前唯一的理論是,兩個連續的lw
s轉換a0
是一個危險 - 無論是記錄一個,在這種情況下,這看起來像一個編譯器錯誤;或無證件。
那麼:是上述程序集合法嗎?如果是的話,還有什麼其他想法可以在這裏發生?
謝謝!
UPDATE:嗯,原來這一切都是白費力氣:由同事信息轉儲的重複分析翻起來,我已經錯過了,那裏有一個直接跳轉到jal foo()
代碼路徑指令後,立即將a0
設置爲44(sp)
。換句話說,代碼中有一條路徑與我們看到的不涉及危險或「跳過指令」或任何其他內容的結果一致......我想我已經檢查了這一點,但是我想我或者沒有做出任何決定, T,或者錯過了... :(
無論如何,我已經接受markgz的答案,因爲它回答了關於這些指令(顯然他們是)合法我原來的問題。
謝謝!這些地址不在任何特殊邊界(0x17409e8和0x17409ec),也不應該觸發頁面錯誤(它們都在堆棧上)。我們還沒有嘗試修補二進制文件,我們的下一步將是/試圖重現與最小的測試案例... –
有趣的。這些信息使得硬件錯誤對我來說似乎不太可能。 – markgz
重新分析表明問題的整個前提是錯誤的......請參閱原始問題中的UPDATE以瞭解詳細信息。再次感謝你的幫助! –