“非法指示"指的是“非法指示".在其他计算机上运行预编译程序时 [英] "Illegal instruction" when run precompiled program on other machine

查看:262
本文介绍了“非法指示"指的是“非法指示".在其他计算机上运行预编译程序时的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我必须在CentOS 7上构建程序并在其他Linux机器上进行部署.该程序需要较新的版本glibc,并且某些库尚未(也不会)安装在目标计算机上.因此,我决定将可执行文件与动态库一起提供.我用patchelf修补了interpreterrpath.

I have to build my program on CentOS 7 and deploy on other Linux machine. The program required newer version glibc, and some library which was not (and will not be) installed on target machine. So I decided to ship the executable with dynamic library. I used patchelf to patch interpreter and rpath.

我在计算机上测试了可执行文件,并且可执行(也已通过ldd检查以确保使用了新的rpath).但是,当我使用libs复制到其他计算机时,该程序无法运行.仅打印此行:

I tested the executable on my machine and it work (also checked with ldd to make sure new rpath is used). But when I copy to other machine with libs, the program is failed to run. Only this line was printed:

非法指示

这里是gdb的回溯

Here is backtrace from gdb

更新: 二进位 因此,SIGILL是由__tls_init()函数中的shlx指令引起的.我不知道哪个库提供此功能,我不确定它来自glibc.

Update: Binary So the SIGILL was caused by shlx instruction in __tls_init() function. I don't know which library provide this function, I'm not sure it is from glibc.

我删除了从另一台计算机复制的glibc,并使用目标计算机上已安装的glibc,但问题并未得到解决.

I removed my glibc, which coppied from another computer and use glibc already installed on target computer, but the problem was not fixed.

推荐答案

我用patchelf修补了解释器和rpath

I used patchelf to patch interpreter and rpath

您的问题非常不清楚:您将解释器和rpath更改为什么?

Your question is very unclear: you changed the interpreter and the rpath to what?

认为您所做的是:

  1. 以非标准路径构建新的GLIBC版本
  2. 使用patchelf更改您的二进制文件以指向非标准路径
  3. 将二进制文件和非标准GLIBC复制到目标计算机
  4. 观察到的SIGILL.
  1. Build a new GLIBC version in non-standard path
  2. Used patchelf to change your binary to point to the non-standard path
  3. Copied the binary and the non-standard GLIBC to the target machine
  4. Observed SIGILL.

最可能的原因:您为目标处理器配置的不是您构建的非标准GLIBC,这与构建计算机上使用的处理器不同.

Most likely cause: the non-standard GLIBC you built is not configured for your target processor, which is different from the processor used on the build machine.

默认情况下,GCC将使用-march=native,这意味着如果您基于Haswell计算机,那么二进制文件将使用目标计算机不支持的AVX2指令.

By default, GCC will use -march=native, which means that if you build on e.g. Haswell machine, then the binary will use AVX2 instructions, which are not supported by the target machine.

要解决此问题,您需要在CFLAGS(和CXXFLAGS)中添加-march=generic-march=$target_architecture,然后重新构建GLIBC和主程序.

To fix this, you will need to add -march=generic or -march=$target_architecture to CFLAGS (and CXXFLAGS), and rebuild both GLIBC and the main program.

另一方面,您的GDB回溯显示了

  • standard 到GLIBC的路径:/lib64/ld-linux-x86-64.so.2/lib64/libc.so.6,所以也许我根本不理解您进行的步骤.

    On the other hand, your GDB backtrace shows standard paths to GLIBC: /lib64/ld-linux-x86-64.so.2 and /lib64/libc.so.6, so maybe I didn't understand the steps you made at all.

    更新:

    我没有构建新的glibc,而是将其从我的计算机复制到目标计算机.我的机器使用E5-2690v4,但目标机器使用E5-2470.

    I didn't build a new glibc but copy it from my machine to the target machine. My machine using E5-2690v4 but the target machine using E5-2470.

    E5-2690v4是

    The E5-2690v4 is a Broadwell. The E5-2470 is an Ivy Bridge.

    前者支持 AVX2 ,但后者不支持.完全按照您所描述的症状将使用AVX2构建的GLIBC复制到Ivy Bridge可能会失败(并且实际上应该使Ivy Bridge完全无法正常工作;我很惊讶 任何事情都可以解决这个问题.

    The former supports AVX2, but the latter doesn't. Copying GLIBC built with AVX2 to an Ivy Bridge is likely to fail with exactly the symptoms you described (and in fact should render the Ivy Bridge completely non-working; I am surprised anything works on it at all).

    使用GDB x/i $pc命令,您可以看到生成SIGILL的指令.如果这是AVX2指令,则可能是答案.

    Using GDB x/i $pc command, you can see which instruction generates SIGILL. If it's an AVX2 instruction, that's likely the answer.

    这篇关于“非法指示"指的是“非法指示".在其他计算机上运行预编译程序时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆