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