无需调试即可查找哪个汇编指令导致非法指令错误

pyt*_*nic 28 c linux assembly x86-64 yasm

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

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

也许我应该捕获SIGILL信号然后解码SA_SIGINFO以查看程序执行什么样的非法操作.

oua*_*uah 30

实际上你经常得到一个非法的指令错误,不是因为你的程序包含非法的操作码,而是因为程序中存在一个错误(例如,缓冲区溢出),这会使你的程序跳转到一个随机地址,包含普通数据或代码,但不是操作码的开始.

  • 就像失踪的回报 (3认同)

Die*_*ino 27

最近,由于132退出状态代码(128 + 4:程序被信号+非法指令信号中断),我遇到了崩溃.这是我如何找出导致崩溃的指令.

首先,我启用了核心转储:

$ ulimit -c unlimited
Run Code Online (Sandbox Code Playgroud)

有趣的是,我运行二进制文件的文件夹包含一个名为的文件夹core.我不得不告诉Linux将PID添加到核心转储:

$ sudo sysctl -w kernel.core_uses_pid=1
Run Code Online (Sandbox Code Playgroud)

然后我运行我的程序并获得一个名为的核心core.23650.我用gdb加载了二进制文件和核心.

$ gdb program core.23650
Run Code Online (Sandbox Code Playgroud)

进入gdb后,它显示以下信息:

Program terminated with signal SIGILL, Illegal instruction.
#0  0x00007f58e9efd019 in ?? ()
Run Code Online (Sandbox Code Playgroud)

这意味着我的程序因0x00007f58e9efd019地址存储器中的非法指令而崩溃.然后我切换到asm布局来检查最后执行的指令:

(gdb) layout asm
>|0x7f58e9efd019  vpmaskmovd (%r8),%ymm15,%ymm0
 |0x7f58e9efd01e  vpmaskmovd %ymm0,%ymm15,(%rdi)
 |0x7f58e9efd023  add    $0x4,%rdi
 |0x7f58e9efd027  add    $0x0,%rdi
Run Code Online (Sandbox Code Playgroud)

这是vpmaskmovd导致错误的指令.显然,我试图在一个缺乏对AVX2指令集支持的系统上运行针对AVX2架构的程序.

$ cat /proc/cpuinfo | grep avx2
Run Code Online (Sandbox Code Playgroud)

最后,我确认vpmaskmovd是一条AVX2指令.


Mic*_*urr 11

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

在我的系统上,一旦启用了核心转储,崩溃程序将在工作目录中编写一个名为"core"的文件.这可能足以满足您的需要,但更改核心转储文件的命名方式可让您保留核心转储的历史记录(如果有必要)(可能是更间歇性的问题).