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都极可能出这种问题)
  • 用的工具链靠谱吗?
相关文章
相关标签/搜索