在其他计算机上运行预编译程序时出现“非法指令”

时间:2018-06-20 09:52:25

标签: glibc dynamic-linking rpath

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

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

  

非法指示

这里是gdb的回溯 enter image description here

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

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

1 个答案:

答案 0 :(得分:1)

  

我用patchelf修补了解释器和rpath

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

认为您所做的是:

  1. 以非标准路径构建新的GLIBC版本
  2. 使用patchelf将二进制文件更改为指向非标准路径
  3. 将二进制文件和非标准GLIBC复制到目标计算机
  4. 观察到的SIGILL

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

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

要解决此问题,您需要将-march=generic-march=$target_architecture添加到CFLAGS(和CXXFLAGS)中,并重新构建GLIBC和主程序。

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

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

    更新

      

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

    E5-2690v4是Broadwell。 E5-2470是Ivy Bridge

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

    使用GDB x/i $pc命令,您可以查看哪个指令生成了SIGILL。如果这是AVX2指令,则可能是答案。