在运行,我用汇编写一个程序,我得到Illegal instruction
错误。 有没有办法知道哪些指令导致错误,无需调试就是因为我的机器上运行没有调试器或任何研究与开发体系。 换句话说,我编译在一台机器和另一运行。 我不能,我编译,因为它们不支持SSE4.2机器上测试我的程序。 我上运行的程序的机器不支持SSE4.2指令仍然。
我想这也许是因为我需要向它传递一个告诉汇编(YASM)承认SSE4.2指令,就像我们一样用gcc -msse4.2
标志。 或者你认为它不是这个原因? 不知道如何告诉YASM认识到SSE4.2指令?
也许我应该陷阱SIGILL信号,然后解码SA_SIGINFO看到程序做什么样的非法操作的。
其实往往你得到一个非法指令错误,不是因为你的程序包含一个错误的代码,但因为有一个错误在你的程序(如缓冲区溢出),使你的程序的或与代码,但不能以纯数据的随机地址跳转操作码的开始。
最近,我经历碰撞由于132退出状态代码(128 + 4:程序由信号+非法指令信号中断)。 以下是我想通了什么指令是导致飞机坠毁。
首先,我启用核心转储:
$ ulimit -c unlimited
有趣的是,我在那里运行的二进制文件夹包含一个文件夹命名为core
。 我不得不告诉Linux下的PID添加到核心转储:
$ sudo sysctl -w kernel.core_uses_pid=1
然后我运行了一个程序,有一个核心命名core.23650
。 我装的二进制和用gdb的核心。
$ gdb program core.23650
一旦我进入GDB,它显示了以下信息:
Program terminated with signal SIGILL, Illegal instruction.
#0 0x00007f58e9efd019 in ?? ()
这意味着我的程序崩溃是由于在一个非法指令0x00007f58e9efd019
地址的内存。 然后我切换到在汇编布局 ,以检查执行的最后一条指令:
(gdb) layout asm
>|0x7f58e9efd019 vpmaskmovd (%r8),%ymm15,%ymm0
|0x7f58e9efd01e vpmaskmovd %ymm0,%ymm15,(%rdi)
|0x7f58e9efd023 add $0x4,%rdi
|0x7f58e9efd027 add $0x0,%rdi
这是指令vpmaskmovd
导致错误。 很显然,我试图运行旨在为AVX2架构,缺乏对AVX2指令集支持的系统上的程序。
$ cat /proc/cpuinfo | grep avx2
最后,我证实vpmaskmovd是AVX2指令只 。
如果您可以启用核心转储在该系统上,只要运行该程序,让它崩溃,然后将核心转储关闭目标机到开发计算机上,并将其加载到GDB建立调试目标架构 - 应该确切地告诉你其中,发生崩溃。 只需使用GDB的core
指令的核心文件加载到调试器。
在我的系统,一旦核心转储被启用,一个崩溃的程序会写一个简单的工作目录中名为“核心”的文件。 这可能是你的目的不够好,但改变核心转储文件被命名为如何让你保持核心的历史记录,如果这是必要的转储(也许一个更间歇性问题)。
嗯......当然,你可以插入曲线打印输出,让你可以快速排除代码的广大地区。 一旦你做到了这一点,如运行
$ objdump --disassemble my-crashing-program | less
然后跳到例如,你知道导致错误的功能,阅读代码,寻找任何看起来很奇怪。
我不完全知道如何objdump
显示器非法指令,但他们应该站出来。
对于手写汇编我会怀疑导致回流到无处堆栈管理问题。 写调试打印程序,节省每一个寄存器,并在每个函数的顶部插入到它的调用。
然后你会看到你走多远?
(顺便说一句,写机器代码时良好的编辑器和汇编的宏语法有很好的理解就是救星。)
文章来源: Find which assembly instruction caused an Illegal Instruction error without debugging