GNU/Linux >> Linux Esercitazione >  >> Linux

Linux:un eseguibile Linux compilato su un "sapore" di Linux verrà eseguito su un altro?

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.

Correlati:Linux – Impossibile installare perf su slackware 13.1?

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...


Linux
  1. Esegui una macchina virtuale Linux in Podman

  2. Semplice comando Linux che mi dirà cos'è il Display Manager?

  3. Linux – I diversi kernel Linux/unix sono intercambiabili?

  4. Best practice per eseguire il servizio Linux come utente diverso

  5. Come eseguo un programma con una directory di lavoro diversa da quella corrente, dalla shell di Linux?

Ripristina un vecchio MacBook con Linux

Come rendere eseguibile un file in Linux

Esegui file binari in Linux

Come eseguire Windows 95 su Linux

Come eseguire più comandi Linux in un unico comando

Un eseguibile Linux compilato su un tipo di Linux verrà eseguito su un altro?