¿El ejecutable de un programa pequeño y extremadamente simple, como el que se muestra a continuación, que está compilado en un tipo de Linux, se ejecutará en un tipo diferente? ¿O sería necesario volver a compilarlo?
¿Importa la arquitectura de la máquina en un caso como este?
int main()
{
return (99);
}
Respuesta aceptada:
Depende. Algo compilado para IA-32 (Intel de 32 bits) puede ejecutarse en amd64, ya que Linux en Intel conserva la compatibilidad con aplicaciones de 32 bits (con el software adecuado instalado). Aquí está tu code
compilado en el sistema RedHat 7.3 de 32 bits (alrededor de 2002, gcc versión 2.96) y luego el binario copiado y ejecutado en un sistema Centos 7.4 de 64 bits (alrededor de 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
Ancient RedHat 7.3 a Centos 7.4 (esencialmente RedHat Enterprise Linux 7.4) permanece en la misma familia de "distribución", por lo que probablemente tendrá una mejor portabilidad que pasar de una instalación aleatoria de "Linux desde cero" de 2002 a alguna otra distribución aleatoria de Linux en 2018 .
Algo compilado para amd64 no se ejecutaría en versiones de Linux de solo 32 bits (el hardware antiguo no conoce el hardware nuevo). Esto también es cierto para el nuevo software compilado en sistemas modernos destinados a ejecutarse en cosas antiguas, ya que las bibliotecas e incluso las llamadas al sistema pueden no ser portátiles hacia atrás, por lo que pueden requerir trucos de compilación, u obtener un compilador antiguo, etc., o posiblemente en su lugar. compilando en el sistema anterior. (Esta es una buena razón para mantener las máquinas virtuales de cosas antiguas).
La arquitectura importa; amd64 (o IA-32) es muy diferente de ARM o MIPS, por lo que no se espera que el binario de uno de ellos se ejecute en otro. En el nivel de ensamblaje, el main
sección de su código en IA-32 se compila a través de gcc -S code.c
a
main:
pushl %ebp
movl %esp,%ebp
movl $99,%eax
popl %ebp
ret
que puede manejar un sistema amd64 (en un sistema Linux, OpenBSD por el contrario en amd64 no admite binarios de 32 bits; la compatibilidad con versiones anteriores de los arcos antiguos les da a los atacantes margen de maniobra, p. CVE-2014-8866 y amigos). Mientras tanto, en un sistema MIPS big-endian main
en su lugar compila a:
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
con el que un procesador Intel no tendrá idea de qué hacer, y lo mismo ocurre con el ensamblaje de Intel en MIPS.
Posiblemente podría usar QEMU o algún otro emulador para ejecutar código extranjero (quizás muy, muy lentamente).
¡Sin embargo! Su código es un código muy simple, por lo que tendrá menos problemas de portabilidad que cualquier otra cosa; los programas suelen hacer uso de bibliotecas que han cambiado con el tiempo (glibc, openssl, …); para aquellos, también es posible que deba instalar versiones anteriores de varias bibliotecas (RedHat, por ejemplo, generalmente coloca "compat" en algún lugar del nombre del paquete para tales)
compat-glibc.x86_64 1:2.12-4.el7.centos
o posiblemente preocuparse por los cambios de ABI (interfaz binaria de aplicaciones) para cosas muy antiguas que usan glibc, o cambios más recientes debido a C++ 11 u otras versiones de C++. También se podría compilar estático (aumentando en gran medida el tamaño binario en el disco) para tratar de evitar problemas con la biblioteca, aunque si algún binario antiguo hizo esto depende de si la antigua distribución de Linux compilaba casi todo lo dinámico (RedHat:sí) o no. Por otro lado, cosas como patchelf
puede reajustar la dinámica (ELF, pero probablemente no a.out
) formato) binarios para usar otras bibliotecas.
¡Sin embargo! Ser capaz de ejecutar un programa es una cosa y hacer algo útil con él es otra. Los viejos binarios de Intel de 32 bits pueden tener problemas de seguridad si dependen de una versión de OpenSSL que tiene algún problema de seguridad horrible y no respaldado, o es posible que el programa no pueda negociar en absoluto con los servidores web modernos (como el moderno los servidores rechazan los protocolos antiguos y los cifrados del programa antiguo), o el protocolo SSH versión 1 ya no es compatible, o...