Comment détecter si un binaire ARM ELF est à virgule flottante matérielle (ARMHF) ou à virgule flottante logicielle (ARMEL) ?

  • L'indice clé pour distinguer ARMHF d'ARMEL dans ELF est l'attribut Tag_ABI_VFP_args.
  • readelf -A affiche des informations dépendantes de l'architecture, notamment FP, Thumb et NEON.
  • arm-linux-gnueabihf et arm-linux-gnueabi peuvent coexister via multiarch, veillez à ne pas les confondre.

serveur ARM

Lorsqu'on travaille avec des exécutables et des bibliothèques pour ARM, tôt ou tard, la question se pose : Est-ce compilé avec du hard-float (ARMHF) ou avec du soft-float (ARMEL) ? Cette différence est significative, car elle influe sur la compatibilité binaire et les performances des opérations en virgule flottante. Heureusement, le fichier binaire ELF contient les indices nécessaires pour la déterminer avec certitude.

Dans cet article, nous expliquons comment inspecter un fichier ELF ARM à l'aide de l'utilitaire. lire Pour distinguer les deux variantes, nous aborderons les étiquettes à rechercher, les différences de sortie possibles selon la version de l'outil, et l'interprétation de détails tels que Thumb ou NEON. Nous expliquerons également pourquoi le choix entre ARMEL et ARMHF est effectué lors de la compilation. non présent dans le système d'exécutionet nous levons les doutes courants concernant les environnements multi-architectures où arm-linux-gnueabihf et arm-linux-gnueabi coexistent.

Que signifient ARMHF (flottant dur) et ARMEL (flottant souple) ?

Ce comportement est défini par la norme AAPCS (ARM Architecture Procedure Call Standard), qui décrit comment les paramètres sont transmis et les valeurs renvoyées. L'AAPCS comporte des variantesEt celui qui nous intéresse pour différencier ARMHF est celui associé à VFP, un indicateur que nous verrons se refléter dans les attributs du binaire.

ELF et son en-tête : pourquoi il nous donne toutes les informations

Le format ELF (Executable and Linkable Format) est la norme de facto sous Linux et stocke les données dans ses sections d'en-tête et d'attributs. informations sur l'architecture cible et les conventions ABI utilisées pour compiler l'exécutable ou la bibliothèque. Pour plus de détails, consultez la spécification d'en-tête ELF afin de visualiser tous les champs disponibles.

Pour inspecter un ELF, l'outil lire C'est la voie directe. L'option -a bouleverse pratiquement tout, et l'option -A permet se concentrer sur les informations dépendantes de l'architecture (ARM dans notre cas), affichant des attributs tels que le type de virgule flottante, si Thumb est activé, la prise en charge de NEON et d'autres indicateurs pertinents.

Préparez un environnement avec ARMEL et ARMHF

Si vous souhaitez comparer les résultats obtenus en conditions réelles, une solution pratique consiste à installer les chaînes d'outils gcc/g++ pour les deux variantes sur une machine Ubuntu. Ce faisant, Vous obtiendrez les bibliothèques système pour armel et armhf installé côte à côte grâce à multiarch.

Après l'installation, les itinéraires typiques des bibliothèques sont : /usr/arm-linux-gnueabihf/lib pour ARMHF y /usr/arm-linux-gnueabi/lib pour ARMELDisposer des deux permet de comparer, par exemple, la bibliothèque mathématique libm.so.6 et d'observer comment les attributs changent en fonction de la variante.

L'indice décisif : Tag_ABI_VFP_args avec readelf

L'épreuve pratique consiste à analyser le fichier ELF avec la commande `readelf` et à rechercher les références à FP dans ses attributs. Une méthode très simple consiste à filtrer la sortie par la chaîne de caractères FP afin de se concentrer sur les nombres à virgule flottante. puisque l'indicateur le plus révélateur est l'attribut Tag_ABI_VFP_args.

Dans la bibliothèque libm.so.6 compilée en tant qu'ARMEL (flottaison logicielle), vous verrez les attributs ARM typiques, mais La ligne Tag_ABI_VFP_args n'apparaîtra pas.En revanche, dans le fichier libm.so.6 ARMHF (flottant dur), une ligne supplémentaire avec cet attribut sera affichée, confirmant l'utilisation de la convention d'appel VFP.

readelf -A /usr/arm-linux-gnueabi/lib/libm.so.6 | grep FP

Dans ARMEL, le filtrage par FP affichera des informations relatives aux capacités générales en virgule flottante, mais sans l'attribut qui déclare les arguments VFPEn le répétant sur ARMHF :

readelf -A /usr/arm-linux-gnueabihf/lib/libm.so.6 | grep FP

Vous trouverez une entrée supplémentaire du type Tag_ABI_VFP_args ce qui est le signe indubitable d'un flottement dur. C'est ce détail qui, en pratique, Cela nous permet d'affirmer avec certitude que le binaire respecte la norme ABI à virgule flottante matérielle..

Les variations de résultats dépendent de la version de readelf

Selon l'implémentation et la version de readelf, la forme exacte du texte peut varier. Par exemple, avec readelf compilé à partir de elftoolchain-0.6.1La ligne supplémentaire indique non seulement l'attribut, mais peut être décrite comme suit : Tag_ABI_VFP_args : AAPCS (variante VFP).

Dans cette même famille de sorties, deux autres valeurs peuvent apparaître pour Tag_ABI_VFP_args : « AAPCS (variante de base) » et « spécifique à la chaîne d'outils »La littérature disponible mentionne ces alternatives, même si les conditions exactes de leur remise en œuvre ne sont pas toujours clairement définies. L'important est de comprendre que la mention de la variante VFP Il est associé au boîtier à flottement dur.

Au-delà de la formation professionnelle : -A enseigne également l'architecture, Thumb et NEON

Bien que nous nous concentrions ici sur la distinction entre ARMHF et ARMEL, il convient de rappeler que lire-elf -A Il offre une vue plus large du binaire. Son résultat affichera, outre les attributs à virgule flottante, l'architecture cible exacte, si le binaire Il est construit avec Thumb et si la prise en charge a été activée NEON, entre autres fonctionnalités pertinentes pour l'optimisation et la compatibilité.

Tout ceci contribue à valider que le fichier binaire correspond non seulement à la variante FP attendue, mais aussi Il est conforme au jeu d'instructions et aux extensions que vous avez à disposition sur l'appareil sur lequel il sera exécuté.

Exemple de flux de travail recommandé

Une séquence typique pour comparer les deux variantes de libm.so.6 pourrait être aussi simple que ceci : Lister les itinéraires, exécuter readelf et filtrer par FPCela vous permettra de voir en un coup d'œil la principale différence entre armel et armhf.

# ARMEL (soft-float)
ls -l /usr/arm-linux-gnueabi/lib/libm.so.6
readelf -A /usr/arm-linux-gnueabi/lib/libm.so.6 | grep FP

# ARMHF (hard-float)
ls -l /usr/arm-linux-gnueabihf/lib/libm.so.6
readelf -A /usr/arm-linux-gnueabihf/lib/libm.so.6 | grep FP

Si dans ARMHF vous observez la ligne avec Tag_ABI_VFP_args Et comme cela n'apparaît pas dans ARMEL, la différence est considérée comme vérifiée. Et si vous préférez tout voir, vous pouvez toujours utiliser lire-elf -a pour obtenir un dump complet des en-têtes, sections, attributs et symboles.

Compilation, et non système : qui décide ARMEL ou ARMHF ?

Il est important de souligner un concept : La variante ARMEL/ARMHF est déterminée par le code binaire.C'est le processus de compilation, et non le « système » abstrait, qui détermine la structure du fichier ELF. Si vous compilez votre exécutable avec la prise en charge des nombres à virgule flottante matérielle, vous obtiendrez un fichier ELF ARMHF ; sinon, il sera ARMEL. Cette distinction découle du processus de compilation et est inscrite dans les attributs du fichier ELF.

C’est pourquoi, si votre préoccupation est de choisir la voie à suivre pour votre propre projet, c’est généralement plus simple. Résolvez-le lors de la compilation. avec des options de compilation et d'édition de liens, et avec du code conditionné par le préprocesseur. Il est rare de vouloir basculer entre ARMEL et ARMHF dans le même binaire à l'exécution. parce que cela implique différents ABI.

En-têtes générés par le Makefile : une technique pratique

Si vous souhaitez que l'exécutable lui-même déclare son « identité » lors de la compilation, une technique très utile consiste à générer un en-tête du Makefile Lors de la phase de compilation, le système de compilation détecte si vous compilez pour armel ou armhf et insère une constante dans un fichier d'en-tête, qui est ensuite inclus dans le code source.

Avec cette approche, le binaire final peut exposer, par exemple, une commande -version qui indique si le système a été construit en tant qu'ARMEL ou ARMHF, sans avoir besoin de « détecter » quoi que ce soit à l'exécution. En général, cette pratique correspond mieux au fait que L'ABI est définie lors de la compilation et elle ne devrait pas varier de manière dynamique.

Pourquoi voudriez-vous le savoir au moment de l'exécution ?

Ceux qui posent cette question tentent parfois d'adapter leur comportement sur le coup de l'émotion. Mais la réalité est que La pratique courante consiste à séparer le code à l'aide de directives de préprocesseur. et compiler différentes variantes, une pour armel et une autre pour armhf. Mélanger les deux dans le même artefact n'est pas réaliste, car chacune dépend de son propre ensemble de bibliothèques et un ABI différent.

Par conséquent, la recommandation générale est de prendre la décision avant de compileret lors de l'exécution, il suffit de vérifier que l'environnement cible dispose des bibliothèques appropriées pour le binaire que vous vous apprêtez à lancer. Pour auditer un binaire déjà compilé, lire Il demeure l'outil le plus direct.

Multiarch : Pourquoi existe-t-il à la fois arm-linux-gnueabihf et arm-linux-gnueabi ?

Si, en listant les répertoires de votre système, vous constatez que vous avez arm-linux-gnueabihf et arm-linux-gnueabi La coexistence n'est pas nécessairement une erreur : c'est le cas multiarchIl permet d'installer et d'utiliser plusieurs architectures ou variantes ABI en parallèle, facilitant ainsi les compilations croisées et les tests.

Dans les environnements Debian, par exemple, il y a eu des moments où il a été décidé Supprimer le multiarch dans les images Wheezy par défaut car ce soutien était écologique et engendrait plus de problèmes que de bénéfices. Par conséquent, Jessie et les versions ultérieures ont amélioré la prise en charge multiarch, rendant la coexistence armel/armhf plus viable et sans autant de problèmes.

Interpréter correctement les itinéraires ne suffit pas

La présence d'une bibliothèque dans /usr/arm-linux-gnueabihf/lib suggère qu'il s'agit d'une architecture ARMHF, et de même pour /usr/arm-linux-gnueabi/lib pour ARMEL. Mais pour en être sûr, Ouvrez le fichier ELF et examinez ses attributsCes chemins sont utiles comme guide, bien que dans les systèmes complexes comportant plusieurs archives ou des sauvegardes manuelles, peut induire en erreur.

Encore une fois, la sortie de lire-elf -A Cela apporte une preuve concluante : la présence de Tag_ABI_VFP_args pour les nombres à virgule flottante matérielle et son absence pour les nombres à virgule flottante logicielle. De plus, les autres indicateurs le confirment. instructions et extensions que le binaire peut exiger.

Que peut-on apprendre d'autre de -A, outre FP ?

La section des attributs ARM qui affiche -A ne vous indique pas seulement s'il y a un VFP. Elle vous indique également si le binaire Il est marqué comme Pouce, la variante d'architecture (par exemple, ARMv7) et la prise en charge NEONCes détails vous aident à vérifier que le fichier binaire est compatible avec le matériel cible et à éviter les surprises lors du déploiement.

Prenons l’exemple de la validation d’un environnement d’exécution : outre la vérification de la compatibilité ARMEL/ARMHF, Vérifiez le pouce et le néon Il peut vous alerter sur des incompatibilités subtiles qui ne sont pas visibles au premier coup d'œil.

Questions fréquemment posées et conseils rapides

  • Puis-je le détecter sans readelf ? Techniquement, on pourrait le déduire du chemin d'accès ou de la façon dont votre projet a été construit, mais la méthode la plus fiable consiste à examiner le fichier ELF. La commande `readelf -A` fournit l'information directement dans le fichier binaire.
  • Suffit-il de voir « VFP » à la sortie ? Les références générales au VFP indiquent des capacités, mais la ligne décisive est Tag_ABI_VFP_args dans ARMHF. Son absence dans ARMEL est tout aussi significative.
  • Et si mon readelf indique « AAPCS (variante VFP) » ? Il s'agit d'une variante de la même idée que l'on retrouve dans certaines constructions, comme celles basées sur elftoolchain-0.6.1Il est également possible que les mentions « AAPCS (variante de base) » ou « spécifique à la chaîne d'outils » apparaissent.
  • Pourquoi ai-je les deux versions installées ? Par multiarchCeci est normal dans certains environnements. Assurez-vous simplement de lier et d'exécuter le programme avec la bibliothèque correspondant au binaire que vous utilisez.

Note succincte sur les sources et leur financement

Certaines publications techniques qui traitent de ces sujets incluent des messages pour soutenir leur travail par le biais de dons en cryptomonnaie, de plateformes comme Patreon ou de liens d'affiliation vers des boutiques comme Amazon ou AliExpress. C'est une pratique courante dans les médias indépendants, qui parfois Ils utilisent des liens d'affiliation dans leurs articles pour gagner une commission si vous effectuez un achat après avoir cliqué.

Liste de contrôle mentale lors de l'audit d'un binaire

Avant d'accepter une bibliothèque ou un fichier exécutable pour votre appareil, veuillez prendre en compte les points suivants : requête readelf -A, recherche la présence ou l'absence de Tag_ABI_VFP_argsExaminez l'architecture cible et vérifiez si Thumb et NEON sont compatibles avec le matériel sur lequel vous allez les exécuter.

Si vous travaillez avec plusieurs chaînes d'outils installées via multiarch, Portez une attention particulière aux itinéraires Les variables d'environnement du compilateur et de l'éditeur de liens doivent être configurées afin d'éviter de mélanger les en-têtes et les bibliothèques ARMEL avec les binaires ARMHF, et inversement. Un simple oubli peut entraîner des problèmes. symptômes déroutants lors de la liaison ou de l'exécution.

Erreurs typiques à éviter

Une erreur classique consiste à être trop confiant et à supposer qu'une bibliothèque est à virgule flottante matérielle parce qu'elle se trouve sous arm-linux-gnueabihf, sans confirmer les attributs ELFUne autre erreur courante consiste à essayer de lier un exécutable ARMHF avec des bibliothèques ARMEL (ou vice versa), ce qui entraîne généralement des erreurs de symboles ou un comportement étrange.

Il est également fréquent de vouloir « détecter à l'exécution » pour modifier les chemins d'accès aux bibliothèques à la volée. N'oubliez pas que Le choix ARMEL/ARMHF n'est pas improvisé lors de l'exécution.C'est intégré en dur dans le binaire. Adaptez vos déploiements et vos packages afin que chaque exécutable reçoive les bibliothèques correspondant à sa propre variante.

Si vous avez besoin d'une référence rapide, pensez à ces étapes : localiser la bibliothèque ou l'exécutable (par exemple, libm.so.6), lancer readelf -A Filtrez le fichier par FP si vous souhaitez aller droit au but, puis vérifiez s'il contient une ligne. Tag_ABI_VFP_args (float dur) ou, en l'absence de cette valeur, (float souple). Ensuite, vérifiez l'architecture, Thumb et NEON pour compléter le profil binaire.

Lorsqu'on compare ARMEL et ARMHF dans le même système, n'oubliez pas le contexte multi-architecture Et le fait que la principale différence réside dans l'ABI à virgule flottante définie par l'AAPCS. De ce point de vue, l'interprétation des attributs de readelf devient un exercice rapide et précis.

Il est clair qu'avec le bon outil et en sachant où chercher, Déterminer si un ARM ELF est ARMHF ou ARMEL ne prend que quelques secondes.L'essentiel est d'identifier l'attribut Tag_ABI_VFP_args pour les nombres à virgule flottante matérielle et d'utiliser readelf -A pour obtenir des informations supplémentaires sur l'architecture, Thumb et NEON. Compte tenu des spécificités des architectures multi-processeurs et du fait que le choix de l'ABI est fixé à la compilation, Vous éviterez toute confusion et gagnerez du temps. lors de la validation des fichiers binaires et des bibliothèques dans vos projets.

Que sont ARM Cortex-R et Cortex-M ?
Article connexe:
ARM Cortex-R et Cortex-M : définition, différences et quand choisir l'un ou l'autre