L'eseguibile di un programma piccolo ed estremamente semplice, come quello mostrato di seguito, compilato su una versione di Linux, verrà eseguito su una versione diversa? O dovrebbe essere ricompilato?
L'architettura della macchina è importante in un caso come questo?
int main()
{
return (99);
}
Risposta accettata:
Dipende. Qualcosa di compilato per IA-32 (Intel 32-bit) può essere eseguito su amd64 poiché Linux su Intel mantiene la retrocompatibilità con le applicazioni a 32 bit (con software adatto installato). Ecco il tuo code
compilato su sistema RedHat 7.3 a 32 bit (circa 2002, gcc versione 2.96) e quindi il binario copiato ed eseguito su un sistema Centos 7.4 a 64 bit (circa 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
L'antico RedHat da 7.3 a Centos 7.4 (essenzialmente RedHat Enterprise Linux 7.4) rimane nella stessa famiglia di "distribuzione", quindi probabilmente avrà una portabilità migliore rispetto al passaggio da un'installazione casuale "Linux da zero" dal 2002 a qualche altra distribuzione Linux casuale nel 2018 .
Qualcosa compilato per amd64 non funzionerebbe solo su versioni a 32 bit di Linux (il vecchio hardware non conosce il nuovo hardware). Questo vale anche per il nuovo software compilato su sistemi moderni destinati a essere eseguiti su cose antiche, poiché le librerie e persino le chiamate di sistema potrebbero non essere portabili all'indietro, quindi potrebbero richiedere trucchi di compilazione o ottenere un vecchio compilatore e così via, o forse invece compilazione sul vecchio sistema. (Questa è una buona ragione per mantenere in giro macchine virtuali di cose antiche.)
L'architettura conta; amd64 (o IA-32) è molto diverso da ARM o MIPS, quindi il binario di uno di questi non dovrebbe essere eseguito su un altro. A livello di assembly il main
la sezione del tuo codice su IA-32 viene compilata tramite gcc -S code.c
a
main:
pushl %ebp
movl %esp,%ebp
movl $99,%eax
popl %ebp
ret
che un sistema amd64 può gestire (su un sistema Linux, OpenBSD al contrario su amd64 non supporta binari a 32 bit; la retrocompatibilità con i vecchi archi offre agli attaccanti spazio di manovra, ad es. CVE-2014-8866 e amici). Nel frattempo su un sistema MIPS big-endian main
invece compila in:
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 cui un processore Intel non avrà idea di cosa fare, e allo stesso modo per l'assembly Intel su MIPS.
Potresti usare QEMU o qualche altro emulatore per eseguire codice esterno (forse molto, molto lentamente).
Tuttavia! Il tuo codice è un codice molto semplice, quindi avrà meno problemi di portabilità rispetto a qualsiasi altra cosa; i programmi tipicamente fanno uso di librerie che sono cambiate nel tempo (glibc, openssl, …); per quelli potrebbe anche essere necessario installare versioni precedenti di varie librerie (RedHat, ad esempio, in genere mette "compat" da qualche parte nel nome del pacchetto per tali)
compat-glibc.x86_64 1:2.12-4.el7.centos
o forse preoccuparti delle modifiche ABI (Application Binary Interface) per cose molto vecchie che usano glibc o modifiche più recenti dovute a C++ 11 o altre versioni di C++. Si potrebbe anche compilare statico (aumentando notevolmente la dimensione del binario sul disco) per cercare di evitare problemi con la libreria, anche se se qualche vecchio binario lo ha fatto dipende dal fatto che la vecchia distribuzione Linux stesse compilando quasi tutto dinamico (RedHat:sì) o meno. D'altra parte, cose come patchelf
può rejigger dinamico (ELF, ma probabilmente non a.out
format) binari per utilizzare altre librerie.
Tuttavia! Essere in grado di eseguire un programma è una cosa, e effettivamente fare qualcosa di utile con esso un'altra. I vecchi binari Intel a 32 bit potrebbero avere problemi di sicurezza se dipendono da una versione di OpenSSL che contiene qualche problema di sicurezza orribile e senza backport, oppure il programma potrebbe non essere in grado di negoziare affatto con i moderni server web (come il moderno i server rifiutano i vecchi protocolli e le crittografie del vecchio programma), oppure il protocollo SSH versione 1 non è più supportato, oppure...