JCD*_*een 65 linux compiling compatibility architecture
一个非常简单的小程序的可执行文件,比如下面显示的,在一种 Linux 上编译的,它会在不同的 Linux 上运行吗?还是需要重新编译?
在这种情况下,机器架构重要吗?
int main()
{
return (99);
}
Run Code Online (Sandbox Code Playgroud)
Dop*_*oti 72
简而言之:如果您使用相同(或兼容)架构将编译后的二进制文件从一台主机带到另一台主机,那么将它带到另一个发行版可能完全没问题。然而,随着代码复杂性的增加,链接到未安装的库的可能性;安装在另一个位置;或安装在不同的版本,增加。以您的代码为例ldd,gcc -o exit-test exit-test.c在(Debian 派生的)Ubuntu Linux 主机上编译时会报告以下依赖项:
$ ldd exit-test
linux-gate.so.1 => (0xb7748000)
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb757b000)
/lib/ld-linux.so.2 (0x8005a000)
Run Code Online (Sandbox Code Playgroud)
显然,如果我把它踢到 Mac ( ./exit-test: cannot execute binary file: Exec format error) 上,这个二进制文件就不会运行。让我们尝试将其移至 RHEL 框:
$ ./exit-test
-bash: ./exit-test: /lib/ld-linux.so.2: bad ELF interpreter: No such file or directory
Run Code Online (Sandbox Code Playgroud)
哦亲爱的。为什么会这样?
$ ls /lib/ld-l* # reference the `ldd` output above
ls: cannot access /lib/ld-l*: No such file or directory
Run Code Online (Sandbox Code Playgroud)
即使对于这个用例,由于缺少共享库,叉车也失败了。
但是,如果我用 编译它gcc -static exit-test-static exit-test.c,将它移植到没有库的系统中就可以了。当然,以磁盘空间为代价:
$ ls -l ./exit-test{,-static}
-rwxr-xr-x 1 username groupname 7312 Jan 29 14:18 ./exit-test
-rwxr-xr-x 1 username groupname 728228 Jan 29 14:27 ./exit-test-static
Run Code Online (Sandbox Code Playgroud)
另一个可行的解决方案是在新主机上安装必需的库。
与 U&L 世界中的许多事物一样,这是一只有很多皮肤的猫,上面概述了其中的两种。
thr*_*rig 50
这取决于。为 IA-32(英特尔 32 位)编译的东西可以在 amd64 上运行,因为英特尔上的 Linux 保留了与 32 位应用程序(安装了合适的软件)的向后兼容性。这是您code在 RedHat 7.3 32 位系统(大约 2002 年,gcc 版本 2.96)上编译,然后将二进制文件复制到 Centos 7.4 64 位系统(大约 2017 年)并在其上运行:
-bash-4.2$ file code
code: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.2.5, not stripped
-bash-4.2$ ./code
-bash: ./code: /lib/ld-linux.so.2: bad ELF interpreter: No such file or directory
-bash-4.2$ sudo yum -y install glibc.i686
...
-bash-4.2$ ./code ; echo $?
99
Run Code Online (Sandbox Code Playgroud)
古老的 RedHat 7.3 到 Centos 7.4(本质上是 RedHat Enterprise Linux 7.4)保持在同一个“发行版”系列中,因此可能比从 2002 年的一些随机“从头开始安装 Linux”安装到 2018 年的其他一些随机 Linux 发行版具有更好的可移植性.
为 amd64 编译的东西不能在仅 32 位版本的 Linux 上运行(旧硬件不知道新硬件)。对于在现代系统上编译的旨在在古老的旧事物上运行的新软件也是如此,因为库甚至系统调用可能无法向后移植,因此可能需要编译技巧,或获得旧编译器等,或者可能改为在旧系统上编译。(这是保留古代旧事物的虚拟机的一个很好的理由。)
建筑确实很重要;amd64(或 IA-32)与 ARM 或 MIPS 有很大不同,因此其中之一的二进制文件不会在另一个上运行。在汇编级别main,IA-32 上的代码部分通过编译gcc -S code.c为
main:
pushl %ebp
movl %esp,%ebp
movl $99,%eax
popl %ebp
ret
Run Code Online (Sandbox Code Playgroud)
amd64 系统可以处理的问题(在 Linux 系统上——相比之下,在 amd64上的OpenBSD不支持 32 位二进制文件;与旧架构的向后兼容性确实给攻击者提供了回旋余地,例如CVE-2014-8866和朋友)。同时在大端 MIPS 系统上 main编译为:
main:
.frame $fp,8,$31
.mask 0x40000000,-4
.fmask 0x00000000,0
.set noreorder
.set nomacro
addiu $sp,$sp,-8
sw $fp,4($sp)
move $fp,$sp
li $2,99
move $sp,$fp
lw $fp,4($sp)
addiu $sp,$sp,8
j $31
nop
Run Code Online (Sandbox Code Playgroud)
英特尔处理器将不知道如何处理,对于 MIPS 上的英特尔组件也是如此。
您可能会使用 QEMU 或其他一些模拟器来运行外部代码(可能非常非常慢)。
然而!您的代码是非常简单的代码,因此可移植性问题比其他任何东西都要少;程序通常使用随时间变化的库(glibc、openssl 等);对于那些可能还需要安装各种库的旧版本的人(例如,RedHat 通常会将“compat”放在包名中的某处)
compat-glibc.x86_64 1:2.12-4.el7.centos
Run Code Online (Sandbox Code Playgroud)
或者可能担心使用 glibc 的旧事物的 ABI 更改(应用程序二进制接口),或者最近由于 C++11 或其他 C++ 版本而发生的更改。还可以编译静态(大大增加磁盘上的二进制文件大小)以尽量避免库问题,尽管某些旧的二进制文件是否这样做取决于旧的 Linux 发行版是否正在编译大多数动态(RedHat:是)。另一方面,patchelf可以重新调整动态(ELF,但可能不是a.out格式)二进制文件以使用其他库。
然而!能够运行程序是一回事,实际上用它做一些有用的事情是另一回事。如果旧的 32 位 Intel 二进制文件依赖于其中存在一些可怕且未向后移植的安全问题的 OpenSSL 版本,则它们可能存在安全问题,或者该程序可能根本无法与现代 Web 服务器进行协商(如现代服务器拒绝旧程序的旧协议和密码),或不再支持 SSH 协议版本 1,或...
Rui*_*iro 25
添加到优秀的 @thrig 和 @DopeGhoti 答案:Unix 或类 Unix 操作系统,包括 Linux,传统上总是为了源代码的可移植性而不是二进制文件进行设计和调整。
如果没有任何特定于硬件的东西或像您的示例中那样是一个简单的源代码,只要目标服务器安装了 C 开发包,您就可以毫无问题地从几乎任何版本的 Linux 或体系结构之间移动它作为源代码,必要的库,并安装相应的开发库。
至于从较早版本的 Linux 中移植更高级的代码,或者更具体的程序,如用于不同内核版本的内核模块,您可能需要调整和修改源代码以解决不推荐使用的库/API/ABI。
bta*_*bta 21
通过默认情况下,你几乎肯定会碰到与外部库的问题。其他一些答案详细介绍了这些问题,因此我不会重复他们的工作。
但是,您可以编译许多程序——甚至是非平凡的程序——以便在 Linux 系统之间移植。关键是称为Linux Standard Base 的工具包。该LSB是专为刚刚创建这些类型的便携式应用。为 LSB v5.0 编译一个应用程序,它将在任何其他实现 LSB v5.0 的 Linux 环境(相同架构)上运行。一些 Linux 发行版符合 LSB,其他发行版包括 LSB 工具包/库作为可安装包。如果您使用 LSB 工具(如 的lsbcc包装器gcc)构建您的应用程序并链接到库的 LSB 版本,您将创建一个可移植的应用程序。
plu*_*ash 11
也许。
容易破坏它的事情包括。
如果您避免使用任何快速变化的库,避免更改架构并构建在您想要定位的最旧的发行版上,那么您很有可能在许多发行版上制作一个二进制文件。
小智 5
除了前面提到的一些东西之外,可执行文件格式也发生了一些变化。大多数情况下,linux 使用 ELF,但旧版本使用 a.out 或 COFF。
维基洞的开始:
https://en.wikipedia.org/wiki/Comparison_of_executable_file_formats
可能有一种方法可以让旧版本运行新格式,但我个人从未研究过它。
| 归档时间: |
|
| 查看次数: |
21213 次 |
| 最近记录: |