【问题标题】:How do I compile on linux to share with all distributions?如何在 linux 上编译以与所有发行版共享?
【发布时间】:2011-02-15 09:52:06
【问题描述】:

我在 Fedora Core 12 上编译了一个 PHP 扩展,但是当我将它发送给使用 CentOS 的人时,他们收到错误:“ELF 文件操作系统 ABI 无效”

我不确定是什么原因导致此运行文件提供以下信息: ELF 64 位 LSB 共享对象,AMD x86-64,版本 1 (GNU/Linux),未剥离

加载良好的扩展从文件中提供以下内容: ELF 64 位 LSB 共享对象,AMD x86-64,版本 1 (SYSV),未剥离

所以看来我需要为某些发行版生成一个 SYSV 类型文件,而不是 GNU/LINUX 文件,但不知道该怎么做。有什么指点吗?

我也应该静态链接吗?

【问题讨论】:

    标签: php linux cross-platform


    【解决方案1】:

    声明:“ELF 文件操作系统 ABI 无效”,表示 Application Binary Interface 在所使用的二进制文件之间不兼容(即尝试混合主机和目标二进制文件,可能不能作为预期的)。 ELF 标头的 e_ident[EI_OSABI] 字节包含操作系统/ABI 标识。您的 Fedora 系统将其设置为 ELFOSABI_LINUX (3),而您朋友的 CentOS 系统将其设置为 ELFOSABI_SYSVELFOSABI_NONE0)。

    可能能够编译 FreeBSD brandelf 实用程序 (brandelf.c) 并使用它将 OSABI 设置为 ELFOSABI_SYSVbrandelf -f 0 <file>brandelf -t SVR4 <file>

    我不知道在编译/链接时指定此值的任何 gcc 标志。我相信你的 Fedora 系统上 gcc 使用的 binutils 版本负责将 OSABI 设置为 Linux。据我了解,链接器仅在 STT_GNU_IFUNC 符号出现在输出文件中时才指定 ABI(有关 STT_GNU_IFUNC 的详细信息,请参阅 ifunc.txt http://groups.google.com/group/generic-abi)。


    readelf(1) 命令可用于检索和显示存储在 ELF 标头 (readelf -h <file>) 中的 ABI 信息。


    这个similar question 也可能感兴趣。

    【讨论】:

    • 哇,非常感谢您提供的所有信息,我能够编译brandelf 并更改操作系统标头。我已经发送了修改后的二进制文件,希望它能运行。我会尝试找到一种方法来摆脱 STT_GNU_IFUNC 符号,但不知道该怎么做;似乎不是一件简单的事情。
    • 您可以尝试在源代码中搜索attribute ((ifunc))。我能够在从以下站点下载的 prog.C(具有 ifunc 属性的 C++ 程序)的 static Linux/ia32 二进制文件上将 OSABI 从 ELFOSABI_LINUX 更改为 ELFOSABI_SYSV,并且仍然在没有任何明显的副作用。这个二进制文件是静态链接的,这可能解释了没有副作用的原因。 - gcc.gnu.org/bugzilla/show_bug.cgi?id=40528
    【解决方案2】:

    编译的目标文件通常不能在不同的 Linux 发行版之间很好地传输。不同的发行版通常对库、存储位置、加载方式有不同的策略。

    它们之间有很多不同之处(是的,即使在 Fedora 和 RedHat/CentOS 中也是如此)。他们可能会为各个级别(内核、PHP、库位置)的组件提供自己的补丁。如果他们使用的是分发版 PHP 包,分发版可能已经对其进行了修补,以便更好地集成到他们的系统中。

    您可能会遇到的主要问题是发行版使用了不同的库/编译器设置。检查他的计算机上的 gcc 版本,并将其与您的计算机上的进行比较。 (Fedora 12 有很多比 CentOS 更新的库)。那可能是你的问题所在。

    另一个可能的问题是你的二进制文件很好,但它与它使用的所有库都不兼容。我不确定是否有一种不用编译目标分布(或变体)的好方法来解决这个问题。您可以使用lld <file> 命令查看每个共享对象/可执行文件使用的库。

    另外,在错误ELF file OS ABI invalid 之前是否有任何输出?我看到它被引用的大多数地方都有比这更多的信息。

    【讨论】:

    • 我知道 IonCube(一个 php 扩展)具有适用于所有发行版的 linux 二进制文件,我用文件检查了其中一个,它输出“ELF 64-bit LSB shared object, x86-64,版本 1 (SYSV),动态链接,剥离”。当我编译而不是 GNU/LINUX 时,我找不到任何将 OS 标头更改为 SYSV 的选项,但这似乎是问题所在。 ldd 在他的 CentOS 上显示“不是动态可执行文件”。
    • 您可能想查看 Linux 标准库 (LSB)。我个人没有这方面的经验,但它可能会提供您需要的二进制兼容性。 Ioncube 开发一个跨发行版工作的 PHP 库不是一项小任务,也许只做一个库而不是像 Firefox 这样的完整应用程序更简单(在某些发行版上与 Firefox 的可下载 linux 客户端发生冲突)
    【解决方案3】:

    您的朋友很可能没有运行 64 位系统。 ELF 是 Linux 可执行文件的标准格式,但 32 位系统无法运行 64 位可执行文件。

    从您的朋友那里获取uname -a 的输出。如果输出不包含“x86_64”,那么他使用的是 32 位版本的 CentOS。

    如果是这样,您要么需要设置一个交叉编译环境,或者一个用于编译 32 位二进制文​​件的虚拟机,要么只需向您的朋友提供源代码,以便他自己编译。

    【讨论】:

    • 他实际上是在 64 位上运行的,我之前给他发了一个 32 位的文件,他得到了一个错误。所以我不得不安装一个64位操作系统重新编译。我注意到我发送的 PHP 扩展和他编译的扩展之间的唯一区别是他说 'SYSV' 而我说 'GNU/Linux'。
    • 您是否在同一系统上的两个二进制文件上运行了file 命令?
    • 是的,这两个都是他在 CentOS 上运行的
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-08
    • 2016-09-27
    • 2012-08-11
    • 2013-07-15
    相关资源
    最近更新 更多