illegal instruction問題窺探

最近調程序,出現illegal instruction問題,沒有頭緒。 索性把illegal instruction好好窺探一下。php

1 現象

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

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

編譯執行之:linux

$ 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問題。好比硬盤發生故障。this

3.2 指令集的演進

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

3.3 工具鏈bug

對於普通C語言經過編譯器生成的可執行程序。通常都已經經過嚴格的測試,不會隨便發生這種問題。因此若是你遇到這種錯,而且試過了靜態鏈,並且程序中沒有嵌入式彙編,基本能夠判定是工具鏈出了問題。 編譯器?彙編器或者連接器。操作系統

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

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

4 錯誤排查指南

  • 程序中有沒有特權指令、或者訪問特權寄存器
  • 有沒有將在較新CPU上編譯獲得的可執行文件拿到老CPU上運行
  • 程序中有沒有嵌入式彙編,先檢查。
    • 通常編譯器不多會生成有這種問題的代碼
    • X86平臺上要尤爲注意64位彙編指令和32位彙編指令的混用問題
  • 程序有在進程代碼段空間寫數據的機會嗎?
  • 棧操做夠安全嗎?
  • 注意程序的ABI是否正確
    • 尤爲是動態鏈和靜態鏈是否處理的正確,儘可能避免動態鏈的可執行文件調用錯誤庫的問題(ARM的EABI,MIPS的N32/O32/N64都極可能出這種問題)
  • 用的工具鏈靠譜嗎?
相關文章
相關標籤/搜索