DevNews

Binutils 2.47 arrive avec un éditeur de liens plus rapide

Sur cette page
  1. Un niveau d'optimisation qui va dans l'autre sens
  2. La sémantique d'archive sans construire d'archive
  3. De meilleures réponses depuis objdump et readelf
  4. RISC-V, et une dépréciation
  5. Sources et pour aller plus loin

GNU Binutils 2.47 est sorti, publié le dimanche vingt six juillet par le mainteneur principal Nick Clifton, et le changement que vous sentirez vraiment est un nouveau niveau d'optimisation de l'éditeur de liens. Passer -O 0 à ld lui demande d'arrêter de fusionner le contenu des sections fusionnables, ce qui échange un binaire un peu plus gros contre une édition de liens plus rapide, et sur une journée de reconstructions incrémentales c'est en général l'échange que vous voulez. Arrivent aussi --start-lib et --end-lib pour traiter des fichiers objets isolés comme des membres d'archive, une option --debug-dir dans objdump et readelf, l'annotation de symboles dans deux désassembleurs, un lot d'extensions RISC-V et une dépréciation discrète à vérifier.

The short answer

Nick Clifton a annoncé GNU Binutils 2.47 sur la liste info-gnu le vingt six juillet. Pour le travail quotidien, l'essentiel est un nouveau niveau d'optimisation de l'éditeur de liens, -O 0, qui empêche l'éditeur de liens BFD de fusionner le contenu des sections fusionnables et achète de la vitesse d'édition de liens au prix d'un binaire plus gros. La version apporte aussi --start-lib et --end-lib à ld, --debug-dir à objdump et readelf, --map-global-vars à objdump, l'annotation de symboles dans les désassembleurs AArch64 et x86, plusieurs extensions RISC-V ratifiées, et la dépréciation de la cible s390 32 bits.

2.47publié le dimanche vingt six juillet
-O 0nouveau niveau ld, saute la fusion des sections
4 + 1extensions RISC-V en v1.0, plus les jeux constructeur
Carte réponse : GNU Binutils 2.47 a été publié le vingt six juillet 2026 par Nick Clifton, avec un niveau ld -O 0 qui cesse de fusionner les sections fusionnables, --start-lib et --end-lib pour les fichiers objets isolés, --debug-dir dans objdump et readelf, et de nouvelles extensions RISC-V.
Binutils 2.47, annoncé sur info-gnu le vingt six juillet. Source : l'annonce de publication de Nick Clifton. PNG

Les versions de chaîne de compilation passent d'habitude inaperçues, et c'est bien leur rôle. Celle ci contient deux ou trois choses qui méritent cinq minutes, surtout parce qu'elles changent ce que vous pouvez écrire dans un script de build plutôt que ce que le compilateur produit.

Un niveau d'optimisation qui va dans l'autre sens

Les niveaux d'optimisation demandent normalement à un outil de travailler davantage. Le nouveau -O 0 de l'éditeur de liens BFD lui demande de travailler moins.

Ce qu'il désactive, c'est la fusion des sections fusionnables. Quand le compilateur produit un littéral de chaîne ou une constante en lecture seule, il peut marquer la section SHF_MERGE, ce qui est une promesse faite à l'éditeur de liens : les entrées identiques sont interchangeables et peuvent être réduites à une seule. L'éditeur de liens prend la promesse et déduplique. Sur un projet avec beaucoup de chaînes, et les projets C++ en ont un nombre énorme, cette passe représente une part réelle du temps d'édition de liens.

Mettre -O 0 la saute. Vous obtenez un fichier de sortie plus gros, puisque les doublons restent, et vous récupérez du temps. C'est un gain net dans la boucle éditer, compiler, exécuter où vous liez des dizaines de fois par heure et où la taille du binaire intermédiaire n'intéresse personne, et c'est une mauvaise idée dans une compilation de release. Le geste utile consiste à le brancher sur le même interrupteur que votre système de build utilise déjà pour distinguer debug et release, pour que ce soit automatique et que personne n'ait à y penser.

Session terminal montrant les nouvelles options de binutils 2.47 en usage : ld avec -O 0 pour sauter la fusion des sections fusionnables, une ligne d'édition de liens encadrant des fichiers objets isolés par --start-lib et --end-lib pour qu'ils ne soient intégrés que s'ils résolvent un symbole, et objdump appelé avec --debug-dir pointant vers un répertoire de symboles de débogage décompressés.
Les trois options les plus susceptibles de finir dans un script de build, dans l'ordre où vous y viendrez. PNG

La sémantique d'archive sans construire d'archive

--start-lib et --end-lib encadrent une suite de fichiers objets sur la ligne de commande et demandent à l'éditeur de liens de les traiter comme il traite les membres d'une archive statique. La différence compte : les fichiers objets listés normalement sont tous intégrés, alors que les membres d'archive ne sont tirés que lorsqu'ils résolvent un symbole actuellement non défini.

Obtenir ce comportement sélectif imposait jusqu'ici de créer réellement un .a, de lancer ar et de trimballer l'archive comme artefact de build. Vous pouvez maintenant l'obtenir directement depuis la ligne d'édition de liens.

Si cela vous dit quelque chose, c'est que d'autres éditeurs de liens proposent ces options depuis longtemps et que des systèmes de build ont été écrits pour elles. Les avoir dans GNU ld supprime surtout une condition dans ces systèmes de build, ce qui est une petite chose qui va discrètement dispenser beaucoup de monde de se soucier de quel éditeur de liens se trouve en face.

Deux options voisines, --link-mapless et --no-link-mapless, arrivent dans la même version pour contrôler la façon dont l'éditeur de liens traite les entrées dépourvues de map.

De meilleures réponses depuis objdump et readelf

Deux ajouts ici, tous deux visant le moment où vous lisez un binaire et où il refuse de vous dire ce dont vous avez besoin.

--debug-dir=<REP> dans objdump comme dans readelf pointe l'outil vers un répertoire contenant des fichiers d'informations de débogage séparés. Toutes les distributions extraient aujourd'hui les symboles de débogage dans leurs propres fichiers et les livrent à part, et les outils ont historiquement cherché dans un chemin décidé à la compilation. Si vos symboles sont ailleurs, décompressés dans un répertoire temporaire ou extraits d'une couche de conteneur, vous pouvez maintenant le dire au lieu d'organiser le système de fichiers pour coller aux attentes de l'outil.

--map-global-vars dans objdump affiche les emplacements et les types des variables globales. C'est typiquement ce que vous pouviez déjà extraire en lisant la table des symboles et en la recoupant à la main avec les informations de débogage, autrement dit ce que personne ne fait à trois heures du matin.

Les désassembleurs ont aussi appris à annoter. Sur AArch64, -M annotate affiche des symboles pour les instructions non définies. Sur x86 et x86_64, -M annotate-immediates affiche les symboles associés aux valeurs immédiates, ce qui transforme un écran de nombres magiques en quelque chose de lisible.

RISC-V, et une dépréciation

Les ajouts RISC-V suivent le rythme habituel. Les extensions ratifiées arrivent dans l'assembleur par lots, et 2.47 apporte zalasr, svrsw60t59b, zvabd et smpmpmt en version 1.0, un groupe d'extensions de produit scalaire zvq et zvf, et des extensions constructeur de SpacemiT dont les variantes xsmtvdot.

La dépréciation concerne la cible s390 32 bits. La cible s390x 64 bits n'est pas touchée et c'est elle que fait tourner le Linux mainframe actuel, donc le public concerné par cet avis est très restreint. Si vous en faites partie, le moment de le dire est maintenant plutôt qu'une fois le code parti.

Une note structurelle pour les empaqueteurs : 2.47 est une version à numéro impair, et selon la politique de publication du projet les versions impaires ne livrent que l'archive binutils, sans les sources de l'éditeur de liens gold qui est déprécié. Si votre empaquetage suppose la présence de gold dans l'arbre, cette hypothèse est à corriger.

Sources et pour aller plus loin

Questions fréquentes

Que fait exactement le nouveau niveau ld -O 0 ?

Il demande à l'éditeur de liens BFD d'arrêter de fusionner le contenu des sections fusionnables. Ce sont les sections marquées SHF_MERGE, en général les littéraux de chaînes et les constantes en lecture seule, où l'éditeur de liens déduplique normalement les entrées identiques pour que la même chaîne soit stockée une fois plutôt que quarante. Cette déduplication coûte un temps proportionnel à son volume, et sur un gros arbre C++ ce volume est considérable. Mettre -O 0 saute la passe : vous liez plus vite et vous produisez un binaire qui traîne les doublons. C'est un réglage de développement, pas quelque chose à mettre dans une compilation de release.

Pourquoi voudrais je --start-lib et --end-lib ?

Ces options encadrent un groupe de fichiers objets ordinaires sur la ligne de commande et demandent à l'éditeur de liens de les traiter comme s'ils étaient membres d'une archive, c'est à dire de n'intégrer que ceux qui résolvent un symbole non défini au lieu de tous les lier inconditionnellement. C'est le comportement d'un fichier .a sans avoir à en construire un. D'autres éditeurs de liens portent ces options depuis des années, donc l'effet pratique dans 2.47 est que les systèmes de build écrits pour eux n'ont plus besoin d'un cas particulier pour GNU ld.

À quoi sert --debug-dir ?

Cette option indique à objdump et readelf où chercher les fichiers d'informations de débogage séparés. Les distributions extraient systématiquement les symboles de débogage dans leurs propres fichiers et les livrent dans un paquet à part, et jusqu'ici les outils cherchaient dans un chemin fixé à la compilation. Si vos symboles sont décompressés à un endroit non standard, dans une couche d'image de conteneur ou un répertoire d'artefacts de build, --debug-dir pointe l'outil dessus au lieu de vous laisser avec un binaire dépouillé et aucun numéro de ligne.

Quelles extensions RISC-V ont été ajoutées ?

La version ajoute la prise en charge par l'assembleur et le désassembleur de zalasr, svrsw60t59b, zvabd et smpmpmt en version 1.0, un ensemble d'extensions de produit scalaire zvq et zvf, et des extensions constructeur de SpacemiT dont la famille xsmtvdot. Si vous n'écrivez pas d'assembleur RISC-V cela ne change rien pour vous, mais c'est le schéma habituel de cette architecture : les extensions ratifiées arrivent dans la chaîne de compilation par lots, et l'assembleur est en général le premier endroit où elles apparaissent.

Est ce que quelque chose disparaît ?

La prise en charge de la cible s390 32 bits est dépréciée avec cette version. La cible s390x 64 bits n'est pas touchée et c'est ce que fait tourner la quasi totalité du Linux mainframe actuel, donc il s'agit du nettoyage d'une cible presque sans utilisateurs plutôt que d'un changement à planifier. À noter seulement si vous maintenez quelque chose qui construit encore des objets s390 31 ou 32 bits, auquel cas c'est le moment de le dire en amont.

Advertisement