GNU/Linux >> Tutoriels Linux >  >> Linux

Linux - Un exécutable Linux compilé sur une «saveur» de Linux fonctionnera-t-il sur un autre?

L'exécutable d'un petit programme extrêmement simple, tel que celui présenté ci-dessous, qui est compilé sur une version de Linux, fonctionnera-t-il sur une version différente ? Ou faudrait-il le recompiler ?

L'architecture de la machine est-elle importante dans un cas comme celui-ci ?

int main()
{
  return (99);
}

Réponse acceptée :

Ça dépend. Quelque chose compilé pour IA-32 (Intel 32 bits) peut fonctionner sur amd64 car Linux sur Intel conserve la rétrocompatibilité avec les applications 32 bits (avec le logiciel approprié installé). Voici votre code compilé sur le système RedHat 7.3 32 bits (vers 2002, gcc version 2.96), puis le binaire copié et exécuté sur un système Centos 7.4 64 bits (vers 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'ancien RedHat 7.3 à Centos 7.4 (essentiellement RedHat Enterprise Linux 7.4) reste dans la même famille de "distribution", il aura donc probablement une meilleure portabilité que de passer d'une installation aléatoire "Linux à partir de zéro" de 2002 à une autre distribution Linux aléatoire en 2018 .

Quelque chose compilé pour amd64 ne fonctionnerait pas sur les versions 32 bits de Linux uniquement (l'ancien matériel ne connaît pas le nouveau matériel). Cela est également vrai pour les nouveaux logiciels compilés sur des systèmes modernes destinés à être exécutés sur d'anciennes choses, car les bibliothèques et même les appels système peuvent ne pas être rétro-portables, ce qui peut nécessiter des astuces de compilation, ou l'obtention d'un ancien compilateur, etc., ou peut-être à la place compilation sur l'ancien système. (C'est une bonne raison de conserver des machines virtuelles d'anciennes choses.)

L'architecture compte; amd64 (ou IA-32) est très différent d'ARM ou de MIPS, de sorte que le binaire de l'un d'entre eux ne devrait pas fonctionner sur un autre. Au niveau de l'assemblage, le main section de votre code sur IA-32 compile via gcc -S code.c à

main:
    pushl %ebp
    movl %esp,%ebp
    movl $99,%eax
    popl %ebp
    ret

qu'un système amd64 peut gérer (sur un système Linux - OpenBSD en revanche sur amd64 ne le fait pas prend en charge les binaires 32 bits ; la rétrocompatibilité avec les anciennes arches donne aux attaquants une marge de manœuvre, par ex. CVE-2014-8866 et amis). Pendant ce temps sur un système MIPS big-endian main compile à la place :

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

dont un processeur Intel n'aura aucune idée de quoi faire, et de même pour l'assemblage Intel sur MIPS.

Vous pouvez éventuellement utiliser QEMU ou un autre émulateur pour exécuter du code étranger (peut-être très, très lentement).

Cependant! Votre code est un code très simple, il aura donc moins de problèmes de portabilité qu'autre chose ; les programmes utilisent généralement des bibliothèques qui ont changé au fil du temps (glibc, openssl, …) ; pour ceux-ci, il peut également être nécessaire d'installer des versions plus anciennes de diverses bibliothèques (RedHat, par exemple, met généralement "compat" quelque part dans le nom du package pour cela)

compat-glibc.x86_64                     1:2.12-4.el7.centos

ou peut-être s'inquiéter des changements ABI (Application Binary Interface) pour des choses très anciennes qui utilisent glibc, ou plus récemment des changements dus à C++11 ou à d'autres versions C++. On pourrait également compiler statique (augmentant considérablement la taille du binaire sur le disque) pour essayer d'éviter les problèmes de bibliothèque, bien que le fait que certains anciens binaires le fassent dépend du fait que l'ancienne distribution Linux compilait presque tout dynamique (RedHat :oui) ou non. D'un autre côté, des choses comme patchelf peut rejigger dynamique (ELF, mais probablement pas a.out format) binaires pour utiliser d'autres bibliothèques.

En relation:Linux - Échec de l'installation de perf sur slackware 13.1 ?

Cependant! Être capable d'exécuter un programme est une chose, et en faire quelque chose d'utile en est une autre. Les anciens binaires Intel 32 bits peuvent avoir des problèmes de sécurité s'ils dépendent d'une version d'OpenSSL qui présente un problème de sécurité horrible et non rétroporté, ou le programme peut ne pas être en mesure de négocier du tout avec les serveurs Web modernes (comme le les serveurs rejettent les anciens protocoles et chiffrements de l'ancien programme), ou le protocole SSH version 1 n'est plus supporté, ou …


Linux
  1. Commande Linux simple qui me dira ce qu'est le gestionnaire d'affichage ?

  2. Linux - Comment tester si un binaire Linux a été compilé en tant que code indépendant de la position ?

  3. Commande qui forcera Linux à vider le cache d'un fichier sur un partage NFS ?

  4. Meilleure pratique pour exécuter le service Linux en tant qu'utilisateur différent

  5. Comment exécuter un programme avec un répertoire de travail différent de l'actuel, à partir du shell Linux ?

Exécuter une machine virtuelle Linux dans Podman

Restaurer un ancien MacBook avec Linux

Comment rendre un fichier exécutable sous Linux

Exécuter des fichiers binaires sous Linux

Comment exécuter Windows 95 sous Linux

Comment exécuter plusieurs commandes Linux en une seule commande