TIPS16_Illegal Instruction錯誤小談

1 現象

當執行一段程序時,發生錯誤,並報”illegal instruction”錯

typedef void(*FUNC)(void);int main(void)
{    const static unsigned char insn[4] = { 0xff, 0xff, 0xff, 0xff };    FUNC function = (FUNC) insn;
    function();
}

編譯執行之:

$ gcc -o sigill illegal_instruction.c
$ ./sigill
Illegal instruction

2 關於“illegal instruction”

illegal instruction,即SIGILL, 是POSIX標準中提供的一類錯誤。 從名字上看,SIGILL是啓動的某個進程中的某一句不能被CPU識別成正確的指令。 此類錯誤是由操作系統發送給進程的,在進程試圖執行一些形式錯誤、未知或者特權指令時操作系統會使用SIGILL信號終止程序。 SIGILL對應的常數是4.

3 造成SIGILL的原因

3.1 將不正確的數據寫入代碼段

進程在代碼段中的數據是要被作爲一個指令執行的。 若不小心覆蓋了已有的代碼段,可能會得到錯誤格式的指令。 這種錯誤尤其在Just-In-Time即時編譯器中最可能出現。

同樣,如果不小心覆蓋了棧上活躍記錄中的返回地址,程序就可能根據這個錯誤地址,執行沒有意義的內存中的數據,進而操作。

進一步可以認爲,任何導致數據錯誤的問題都可能帶來illegal instruction問題。比如硬盤發生故障。

3.2 指令集的演進

比如SIMD指令,自從奔騰4開始有MMX,X86的芯片就開始不停的增加和拓寬SIMD支持,SSE、SSE2、SSE3、SSE42、AVX、AVX2。 默認情況下,很多編譯器都在O2或者O3中開了自動向量化,這就導致很多在新體系結構中編譯的可執行程序,在老機器上運行時會有illegal instruction問題。

3.3 工具鏈bug

對於普通C語言通過編譯器生成的可執行程序。一般都已經通過嚴格的測試,不會隨便發生這種問題。 所以如果你遇到這種錯,並且試過了靜態鏈,而且程序中沒有嵌入式彙編,基本可以斷定是工具鏈出了問題。 編譯器?彙編器或者鏈接器。

3.4訪存對齊或浮點數格式問題

根據Heiher的經驗,請注意出現錯誤的指令可能和訪存地址指令有關。 另外,浮點數的格式是否符合IEEE的標準也可能會有影響。

4 錯誤排查指南

程序中有沒有特權指令、或者訪問特權寄存器

有沒有將在較新CPU上編譯得到的可執行文件拿到老CPU上運行

程序中有沒有嵌入式彙編,先檢查。

    一般編譯器很少會生成有這種問題的代碼

    X86平臺上要尤其注意64位彙編指令和32位彙編指令的混用問題

程序有在進程代碼段空間寫數據的機會嗎?

棧操作夠安全嗎?

注意程序的ABI是否正確

    尤其是動態鏈和靜態鏈是否處理的正確,儘量避免動態鏈的可執行文件調用錯誤庫的問題(ARM的EABI,MIPS的N32/O32/N64都很可能出這種問題)

用的工具鏈靠譜嗎?

5 舉例

wifimanager使用中,wifi名設置中文字符大於2個字,調用wifid -t查看狀態時將wifi_daemon守護線程殺死.
此爲異常退出,分析發現在拷貝ssid時出現目的地址長度不對.
strncpy(s->ssid,staInfo->ssid,strlen(staInfo->ssid)); 默認s->ssid的結構體長度設置太小了

6 參考

http://en.wikipedia.org/wiki/SIGILL

http://www.slac.stanford.edu/BFROOT/www/Computing/Environment/Tools/Batch/exitcode.html

http://stackoverflow.com/questions/6934592/is-this-a-valid-x86-assembly-instruction

http://blog.csdn.net/qiaoliang328/article/details/4866367

http://www.justlinux.com/forum/archive/index.php/t-117434.html
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章