39

在运行我用汇编编写的程序时,Illegal instruction出现错误。有没有办法知道是哪条指令导致了错误,而无需调试,因为我正在运行的机器没有调试器或任何开发系统。换句话说,我在一台机器上编译并在另一台机器上运行。我无法在我正在编译的机器上测试我的程序,因为它们不支持 SSE4.2。尽管如此,我正在运行程序的机器确实支持 SSE4.2 指令。

我想这可能是因为我需要告诉汇编程序(YASM)识别 SSE4.2 指令,就像我们通过传递-msse4.2标志来处理 gcc 一样。或者你认为这不是原因?知道如何告诉 YASM 识别 SSE4.2 指令吗?

也许我应该捕获SIGILL信号,然后对 SA_SIGINFO 进行解码,看看程序做了什么样的非法操作。

4

6 回答 6

46

最近我因为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地址内存中的非法指令而崩溃。然后我切换到asm 布局来检查最后执行的指令:

(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 指令

于 2016-10-24T17:01:00.183 回答
34

实际上,您经常遇到非法指令错误不是因为您的程序包含非法操作码,而是因为您的程序中存在错误(例如,缓冲区溢出)使您的程序跳转到带有纯数据或代码的随机地址而不是操作码的开始。

于 2012-04-27T16:15:50.967 回答
11

如果您可以在该系统上启用核心转储,只需运行程序,让它崩溃,然后将核心转储从目标机器上拉到您的开发机器上,并将其加载到为调试目标架构而构建的 GDB 中 - 这应该会告诉您确切的信息坠机发生的地方。只需使用 GDB 的core命令将核心文件加载到调试器中。

  • 要在目标上启用核心转储:

    ulimit -c unlimited
    
  • 控制核心文件如何命名的伪文件(cat这些以查看当前配置,写入它们以更改配置):

    /proc/sys/kernel/core_pattern
    /proc/sys/kernel/core_uses_pid
    

在我的系统上,一旦启用核心转储,崩溃的程序将在工作目录中写入一个简单命名为“核心”的文件。这对于您的目的可能已经足够了,但是更改核心转储文件的命名方式可以让您在必要时保留核心转储的历史记录(可能是为了更间歇性的问题)。

于 2012-04-27T18:08:25.143 回答
4

嗯...您当然可以插入跟踪打印输出,这样您就可以快速排除大面积的代码。完成后,运行例如

$ objdump --disassemble my-crashing-program | less

然后跳转到例如你知道导致错误的函数,并阅读代码,寻找任何看起来奇怪的东西。

我不完全确定如何objdump显示非法指令,但它们应该脱颖而出。

于 2012-04-27T16:13:09.873 回答
4

对于手写组装,我怀疑堆栈管理问题会导致无处返回。编写一个保存每个寄存器的调试打印输出例程,并在每个函数的顶部插入对它的调用。

然后你会看到你能走多远......

(顺便说一句,一个好的编辑器和对汇编器宏语法的良好理解是编写机器代码时的救星。)

于 2012-04-27T16:22:42.903 回答
4

return在函数末尾缺少语句可能会导致这种情况。

于 2018-07-23T15:07:16.957 回答