Développer des applications C et C dans RHEL 9
Configurer un poste de travail de développeur, développer et déboguer des applications C et C sous Red Hat Enterprise Linux 9
Résumé
Rendre l'open source plus inclusif
Red Hat s'engage à remplacer les termes problématiques dans son code, sa documentation et ses propriétés Web. Nous commençons par ces quatre termes : master, slave, blacklist et whitelist. En raison de l'ampleur de cette entreprise, ces changements seront mis en œuvre progressivement au cours de plusieurs versions à venir. Pour plus de détails, voir le message de notre directeur technique Chris Wright.
Fournir un retour d'information sur la documentation de Red Hat
Nous apprécions vos commentaires sur notre documentation. Faites-nous savoir comment nous pouvons l'améliorer.
Soumettre des commentaires sur des passages spécifiques
- Consultez la documentation au format Multi-page HTML et assurez-vous que le bouton Feedback apparaît dans le coin supérieur droit après le chargement complet de la page.
- Utilisez votre curseur pour mettre en évidence la partie du texte que vous souhaitez commenter.
- Cliquez sur le bouton Add Feedback qui apparaît près du texte en surbrillance.
- Ajoutez vos commentaires et cliquez sur Submit.
Soumettre des commentaires via Bugzilla (compte requis)
- Connectez-vous au site Web de Bugzilla.
- Sélectionnez la version correcte dans le menu Version.
- Saisissez un titre descriptif dans le champ Summary.
- Saisissez votre suggestion d'amélioration dans le champ Description. Incluez des liens vers les parties pertinentes de la documentation.
- Cliquez sur Submit Bug.
Chapitre 1. Mise en place d'un poste de travail de développement
Red Hat Enterprise Linux 9 prend en charge le développement d'applications personnalisées. Pour permettre aux développeurs de le faire, le système doit être configuré avec les outils et utilitaires requis. Ce chapitre énumère les cas d'utilisation les plus courants pour le développement et les éléments à installer.
1.1. Conditions préalables
- Le système doit être installé, y compris un environnement graphique, et souscrit.
1.2. Activation des dépôts de débogage et de sources
Une installation standard de Red Hat Enterprise Linux n'active pas les référentiels de débogage et de sources. Ces référentiels contiennent des informations nécessaires pour déboguer les composants du système et mesurer leurs performances.
Procédure
Activez les canaux du paquet d'informations de source et de débogage : La partie
$(uname -i)
est automatiquement remplacée par une valeur correspondant à l'architecture de votre système :Nom de l'architecture Valeur 64-bit Intel et AMD
x86_64
aRM 64 bits
aarch64
IBM POWER
ppc64le
iBM Z 64 bits
s390x
1.3. Mise en place de la gestion des versions des applications
Un contrôle de version efficace est essentiel pour tous les projets multi-développeurs. Red Hat Enterprise Linux est livré avec Git, un système de contrôle de version distribué.
Procédure
Installer le git paquet :
# dnf install git
Facultatif : Définissez le nom complet et l'adresse électronique associés à vos commits Git :
$
git config --global user.name "Full Name"
$git config --global user.email "email@example.com"
Remplacez Full Name et email@example.com par votre nom et votre adresse électronique réels.
Facultatif : Pour changer l'éditeur de texte par défaut lancé par Git, définissez la valeur de l'option de configuration
core.editor
:$
git config --global core.editor command
Remplacez command par la commande à utiliser pour lancer l'éditeur de texte sélectionné.
Ressources supplémentaires
Pages de manuel Linux pour Git et tutoriels :
$ man git $ man gittutorial $ man gittutorial-2
Notez que de nombreuses commandes Git ont leurs propres pages de manuel. A titre d'exemple, voir git-commit(1).
-
Git User’s Manual - La documentation HTML de Git se trouve à l'adresse suivante :
/usr/share/doc/git/user-manual.html
. - Pro Git - La version en ligne du livre Pro Git fournit une description détaillée de Git, de ses concepts et de son utilisation.
- Référence - Version en ligne des pages de manuel Linux pour Git
1.4. Mise en place du développement d'applications en C et C
Red Hat Enterprise Linux comprend des outils pour créer des applications C et C.
Conditions préalables
- Les référentiels debug et source doivent être activés.
Procédure
Installez le groupe de paquets Development Tools comprenant la collection de compilateurs GNU (GCC), le débogueur GNU (GDB) et d'autres outils de développement :
# dnf group install "Development Tools"
Installer la chaîne d'outils LLVM comprenant le compilateur
clang
et le débogueurlldb
:# dnf install llvm-toolset
Facultatif : Pour les dépendances Fortran, installez le compilateur GNU Fortran :
# dnf install gcc-gfortran
1.5. Mise en place du débogage des applications
Red Hat Enterprise Linux offre plusieurs outils de débogage et d'instrumentation pour analyser et dépanner le comportement des applications internes.
Conditions préalables
- Les référentiels debug et source doivent être activés.
Procédure
Installer les outils utiles au débogage :
# dnf install gdb valgrind systemtap ltrace strace
Installez le paquet dnf-utils afin d'utiliser l'outil
debuginfo-install
:# dnf install dnf-utils
Exécuter un script d'aide SystemTap pour configurer l'environnement.
# stap-prep
Notez que stap-prep installe les paquets correspondant au noyau actuellement running, qui peut être différent du ou des noyau(x) réellement installé(s). Pour s'assurer que stap-prep installe les bons paquets kernel-debuginfo et kernel-headers vérifiez la version actuelle du noyau en utilisant la commande
uname -r
et redémarrez votre système si nécessaire.-
Assurez-vous que les politiques de
SELinux
permettent aux applications concernées de fonctionner non seulement normalement, mais aussi dans les situations de débogage. Pour plus d'informations, voir Utilisation de SELinux.
1.6. Mise en place d'un système de mesure de la performance des applications
Red Hat Enterprise Linux comprend plusieurs applications qui peuvent aider un développeur à identifier les causes de la perte de performance d'une application.
Conditions préalables
- Les référentiels debug et source doivent être activés.
Procédure
Installer les outils de mesure de la performance :
# dnf install perf papi pcp-zeroconf valgrind strace sysstat systemtap
Exécuter un script d'aide SystemTap pour configurer l'environnement.
# stap-prep
Notez que stap-prep installe les paquets correspondant au noyau actuellement running, qui peut être différent du ou des noyau(x) réellement installé(s). Pour s'assurer que stap-prep installe les bons paquets kernel-debuginfo et kernel-headers vérifiez la version actuelle du noyau en utilisant la commande
uname -r
et redémarrez votre système si nécessaire.Activer et démarrer le service collecteur Performance Co-Pilot (PCP) :
# systemctl enable pmcd && systemctl start pmcd
Chapitre 2. Création d'applications C ou C
Red Hat propose de nombreux outils pour créer des applications à l'aide des langages C et C. Cette partie du livre énumère certaines des tâches de développement les plus courantes.
2.1. GCC dans RHEL 9
Red Hat Enterprise Linux 9 est distribué avec GCC 11 comme compilateur standard.
La norme linguistique par défaut de GCC 11 est C 17. Cela équivaut à utiliser explicitement l'option de ligne de commande -std=gnu 17
.
Les normes de langage ultérieures, telles que C 20 et ainsi de suite, et les fonctions de bibliothèque introduites dans ces normes de langage ultérieures sont encore considérées comme expérimentales.
Ressources supplémentaires
2.2. Construire un code avec GCC
Ce chapitre décrit les situations dans lesquelles le code source doit être transformé en code exécutable.
2.2.1. Relation entre les formes de code
Conditions préalables
- Comprendre les concepts de compilation et de liaison
Formes de code possibles
Les langages C et C ont trois formes de code :
Source code écrites en langage C ou C, présentées sous forme de fichiers de texte brut.
Les fichiers utilisent généralement des extensions telles que
.c
,.cc
,.cpp
,.h
,.hpp
,.i
,.inc
. Pour une liste complète des extensions supportées et de leur interprétation, voir les pages de manuel de gcc :$ man gcc
Object code compiling compileril s'agit d'une forme intermédiaire.
Les fichiers de code objet utilisent l'extension
.o
.Executable code, créé par le code objet linking avec un code objet linker.
Les fichiers exécutables des applications Linux n'utilisent aucune extension de nom de fichier. Les fichiers exécutables d'objets partagés (bibliothèques) utilisent l'extension de nom de fichier
.so
.
Il existe également des fichiers d'archives de bibliothèques pour l'établissement de liens statiques. Il s'agit d'une variante du code objet qui utilise l'extension de nom de fichier .a
. La liaison statique n'est pas recommandée. Voir Section 2.3.2, « Liaison statique et dynamique ».
Traitement des formes de code dans GCC
La production d'un code exécutable à partir d'un code source s'effectue en deux étapes, qui nécessitent des applications ou des outils différents. GCC peut être utilisé comme pilote intelligent pour les compilateurs et les éditeurs de liens. Cela vous permet d'utiliser une seule commande gcc
pour n'importe laquelle des actions requises (compilation et liaison). GCC sélectionne automatiquement les actions et leur ordre :
- Les fichiers sources sont compilés en fichiers objets.
- Les fichiers objets et les bibliothèques sont liés (y compris les sources compilées précédemment).
Il est possible d'exécuter GCC de manière à ce qu'il effectue uniquement la compilation, uniquement l'édition de liens, ou à la fois la compilation et l'édition de liens en une seule étape. Ceci est déterminé par les types d'entrées et le type de sortie(s) demandé(s).
Comme les grands projets nécessitent un système de compilation qui exécute généralement GCC séparément pour chaque action, il est préférable de toujours considérer la compilation et l'édition de liens comme deux actions distinctes, même si GCC peut exécuter les deux en même temps.
2.2.2. Compilation des fichiers source en code objet
Pour créer des fichiers de code objet à partir de fichiers source et non un fichier exécutable immédiatement, il faut demander à GCC de ne créer que des fichiers de code objet en sortie. Cette action représente l'opération de base du processus de construction pour les grands projets.
Conditions préalables
- Fichier(s) de code source C ou C
- GCC installé sur le système
Procédure
- Se rendre dans le répertoire contenant le(s) fichier(s) du code source.
Exécutez
gcc
avec l'option-c
:$ gcc -c source.c another_source.c
Des fichiers objets sont créés, dont les noms reflètent les fichiers du code source original :
source.c
donne lieu àsource.o
.NoteAvec le code source C, remplacez la commande
gcc
parg
pour une gestion pratique des dépendances de la bibliothèque standard C.
2.2.3. Débogage des applications C et C avec GCC
Les informations de débogage étant volumineuses, elles ne sont pas incluses par défaut dans les fichiers exécutables. Pour permettre le débogage de vos applications C et C avec elle, vous devez explicitement demander au compilateur de la créer.
Pour permettre la création d'informations de débogage avec GCC lors de la compilation et de l'édition de liens, utilisez l'option -g
:
$ gcc ... -g ...
-
Les optimisations effectuées par le compilateur et l'éditeur de liens peuvent aboutir à un code exécutable difficile à relier au code source original : les variables peuvent être optimisées, les boucles déroulées, les opérations fusionnées avec les opérations environnantes, etc. Cela a un impact négatif sur le débogage. Pour améliorer l'expérience de débogage, envisagez de définir l'optimisation avec l'option
-Og
. Cependant, la modification du niveau d'optimisation modifie le code exécutable et peut changer le comportement réel, y compris la suppression de certains bogues. -
Pour inclure également les définitions de macros dans les informations de débogage, utilisez l'option
-g3
au lieu de-g
. -
L'option
-fcompare-debug
GCC teste le code compilé par GCC avec des informations de débogage et sans informations de débogage. Le test est réussi si les deux fichiers binaires résultants sont identiques. Ce test garantit que le code exécutable n'est pas affecté par les options de débogage, ce qui permet de s'assurer qu'il n'y a pas de bogues cachés dans le code de débogage. Notez que l'utilisation de l'option-fcompare-debug
augmente de manière significative le temps de compilation. Voir la page de manuel de GCC pour plus de détails sur cette option.
Ressources supplémentaires
- Utilisation de la collection de compilateurs GNU (GCC) - Options pour déboguer votre programme
- Débogage avec GDB - Informations de débogage dans des fichiers séparés
La page du manuel GCC :
$ man gcc
2.2.4. Optimisation du code avec GCC
Un même programme peut être transformé en plusieurs séquences d'instructions machine. Vous pouvez obtenir un résultat plus optimal si vous allouez plus de ressources à l'analyse du code lors de la compilation.
Avec GCC, vous pouvez définir le niveau d'optimisation en utilisant l'option -Olevel
pour définir le niveau d'optimisation. Cette option accepte un ensemble de valeurs à la place de level.
Level | Description |
---|---|
| Optimiser la vitesse de compilation - pas d'optimisation du code (par défaut). |
| Optimiser pour augmenter la vitesse d'exécution du code (plus le nombre est élevé, plus la vitesse est grande). |
| Optimiser la taille du fichier. |
|
Identique à un réglage de niveau |
| Optimiser l'expérience de débogage. |
Pour les versions, utilisez l'option d'optimisation -O2
.
Pendant le développement, l'option -Og
est utile pour déboguer le programme ou la bibliothèque dans certaines situations. Comme certains bogues ne se manifestent qu'avec certains niveaux d'optimisation, testez le programme ou la bibliothèque avec le niveau d'optimisation de la version.
GCC offre un grand nombre d'options pour permettre des optimisations individuelles. Pour plus d'informations, voir les ressources supplémentaires suivantes.
Ressources supplémentaires
- Utilisation de la collection de compilateurs GNU - Options qui contrôlent l'optimisation
Page de manuel Linux pour GCC :
$ man gcc
2.2.5. Options de durcissement du code avec GCC
Lorsque le compilateur transforme le code source en code objet, il peut ajouter diverses vérifications afin d'éviter les situations couramment exploitées et d'accroître la sécurité. Le choix du bon ensemble d'options du compilateur peut aider à produire des programmes et des bibliothèques plus sûrs, sans avoir à modifier le code source.
Options de version
La liste d'options suivante est le minimum recommandé pour les développeurs ciblant Red Hat Enterprise Linux :
$ gcc ... -O2 -g -Wall -Wl,-z,now,-z,relro -fstack-protector-strong -fstack-clash-protection -D_FORTIFY_SOURCE=2 ...
-
Pour les programmes, ajoutez les options
-fPIE
et-pie
Position Independent Executable. -
Pour les bibliothèques liées dynamiquement, l'option obligatoire
-fPIC
(Position Independent Code) augmente indirectement la sécurité.
Options de développement
Utilisez les options suivantes pour détecter les failles de sécurité pendant le développement. Utilisez ces options en conjonction avec les options de la version release :
$ gcc ... -Walloc-zero -Walloca-larger-than -Wextra -Wformat-security -Wvla-larger-than ...
Ressources supplémentaires
- Guide de codage défensif
- Détection d'erreurs de mémoire à l'aide de GCC - Red Hat Developers Blog post
2.2.6. Lier le code pour créer des fichiers exécutables
L'édition de liens est la dernière étape de la construction d'une application C ou C. L'édition de liens combine tous les fichiers objets et les bibliothèques en un fichier exécutable.
Conditions préalables
- Un ou plusieurs fichier(s) objet(s)
- GCC doit être installé sur le système
Procédure
- Se rendre dans le répertoire contenant le(s) fichier(s) de code objet.
Exécuter
gcc
:$ gcc ... objfile.o another_object.o... -o executable-file
Un fichier exécutable nommé executable-file est créé à partir des fichiers objets et des bibliothèques fournis.
Pour lier des bibliothèques supplémentaires, ajoutez les options requises après la liste des fichiers objets.
NoteAvec le code source C, remplacez la commande
gcc
parg
pour une gestion pratique des dépendances de la bibliothèque standard C.
2.2.7. Exemple : Construction d'un programme C avec GCC (compilation et liaison en une seule étape)
Cet exemple montre les étapes exactes de la construction d'un programme C simple.
Dans cet exemple, la compilation et l'enchaînement du code se font en une seule étape.
Conditions préalables
- Vous devez savoir comment utiliser GCC.
Procédure
Créez un répertoire
hello-c
et accédez-y :$ mkdir hello-c $ cd hello-c
Créez le fichier
hello.c
avec le contenu suivant :#include <stdio.h> int main() { printf("Hello, World!\n"); return 0; }
Compiler et lier le code avec GCC :
$ gcc hello.c -o helloworld
Cette opération compile le code, crée le fichier objet
hello.o
et lie le fichier exécutablehelloworld
à partir du fichier objet.Exécutez le fichier exécutable obtenu :
$ ./helloworld Hello, World!
2.2.8. Exemple : Construction d'un programme C avec GCC (compilation et liaison en deux étapes)
Cet exemple montre les étapes exactes de la construction d'un programme C simple.
Dans cet exemple, la compilation et l'enchaînement du code sont deux étapes distinctes.
Conditions préalables
- Vous devez savoir comment utiliser GCC.
Procédure
Créez un répertoire
hello-c
et accédez-y :$ mkdir hello-c $ cd hello-c
Créez le fichier
hello.c
avec le contenu suivant :#include <stdio.h> int main() { printf("Hello, World!\n"); return 0; }
Compilez le code avec GCC :
$ gcc -c hello.c
Le fichier objet
hello.o
est créé.Lier un fichier exécutable
helloworld
à partir du fichier objet :$ gcc hello.o -o helloworld
Exécutez le fichier exécutable obtenu :
$ ./helloworld Hello, World!
2.2.9. Exemple : Construction d'un programme C avec GCC (compilation et liaison en une seule étape)
Cet exemple montre les étapes exactes de la construction d'un exemple de programme C minimal.
Dans cet exemple, la compilation et l'enchaînement du code se font en une seule étape.
Conditions préalables
-
Vous devez comprendre la différence entre
gcc
etg
.
Procédure
Créez un répertoire
hello-cpp
et accédez-y :$ mkdir hello-cpp $ cd hello-cpp
Créez le fichier
hello.cpp
avec le contenu suivant :#include <iostream> int main() { std::cout << "Hello, World!\n"; return 0; }
Compiler et lier le code avec
g
:$ g++ hello.cpp -o helloworld
Cette opération compile le code, crée le fichier objet
hello.o
et lie le fichier exécutablehelloworld
à partir du fichier objet.Exécutez le fichier exécutable obtenu :
$ ./helloworld Hello, World!
2.2.10. Exemple : Construction d'un programme C avec GCC (compilation et liaison en deux étapes)
Cet exemple montre les étapes exactes de la construction d'un exemple de programme C minimal.
Dans cet exemple, la compilation et l'enchaînement du code sont deux étapes distinctes.
Conditions préalables
-
Vous devez comprendre la différence entre
gcc
etg
.
Procédure
Créez un répertoire
hello-cpp
et accédez-y :$ mkdir hello-cpp $ cd hello-cpp
Créez le fichier
hello.cpp
avec le contenu suivant :#include <iostream> int main() { std::cout << "Hello, World!\n"; return 0; }
Compilez le code avec
g
:$ g++ -c hello.cpp
Le fichier objet
hello.o
est créé.Lier un fichier exécutable
helloworld
à partir du fichier objet :$ g++ hello.o -o helloworld
Exécutez le fichier exécutable obtenu :
$ ./helloworld Hello, World!
2.3. Utilisation de bibliothèques avec GCC
Ce chapitre décrit l'utilisation des bibliothèques dans le code.
2.3.1. Conventions de dénomination des bibliothèques
Une convention spéciale sur les noms de fichiers est utilisée pour les bibliothèques : une bibliothèque connue sous le nom de foo est censée exister sous la forme d'un fichier libfoo.so
ou libfoo.a
. Cette convention est automatiquement comprise par les options d'entrée de GCC, mais pas par les options de sortie :
Lors de l'établissement d'un lien avec la bibliothèque, celle-ci ne peut être spécifiée que par son nom foo avec l'option
-l
, comme suit-lfoo
:$ gcc ... -lfoo...
-
Lors de la création de la bibliothèque, le nom complet du fichier
libfoo.so
oulibfoo.a
doit être spécifié.
2.3.2. Liaison statique et dynamique
Les développeurs ont le choix d'utiliser la liaison statique ou dynamique lorsqu'ils construisent des applications avec des langages entièrement compilés. Il est important de comprendre les différences entre l'enchaînement statique et l'enchaînement dynamique, en particulier dans le contexte de l'utilisation des langages C et C sur Red Hat Enterprise Linux. En résumé, Red Hat déconseille l'utilisation de l'édition statique de liens dans les applications pour Red Hat Enterprise Linux.
Comparaison de la liaison statique et de la liaison dynamique
L'enchaînement statique intègre les bibliothèques dans le fichier exécutable résultant. L'enchaînement dynamique conserve ces bibliothèques dans des fichiers distincts.
La liaison dynamique et la liaison statique peuvent être comparées de plusieurs façons :
- Utilisation des ressources
L'établissement de liens statiques donne lieu à des fichiers exécutables plus volumineux qui contiennent plus de code. Ce code supplémentaire provenant des bibliothèques ne peut pas être partagé entre plusieurs programmes sur le système, ce qui augmente l'utilisation du système de fichiers et de la mémoire au moment de l'exécution. Plusieurs processus exécutant le même programme lié statiquement partageront toujours le code.
D'autre part, les applications statiques nécessitent moins de relocalisations pendant l'exécution, ce qui réduit le temps de démarrage, et requièrent moins de mémoire privée de taille d'ensemble résident (RSS). Le code généré pour l'enchaînement statique peut être plus efficace que pour l'enchaînement dynamique en raison de la surcharge introduite par le code indépendant de la position (PIC).
- Sécurité
- Les bibliothèques liées dynamiquement qui assurent la compatibilité ABI peuvent être mises à jour sans modifier les fichiers exécutables qui dépendent de ces bibliothèques. Ceci est particulièrement important pour les bibliothèques fournies par Red Hat dans le cadre de Red Hat Enterprise Linux, où Red Hat fournit des mises à jour de sécurité. L'établissement de liens statiques avec de telles bibliothèques est fortement déconseillé.
- Compatibilité
La liaison statique semble fournir des fichiers exécutables indépendants des versions des bibliothèques fournies par le système d'exploitation. Cependant, la plupart des bibliothèques dépendent d'autres bibliothèques. Avec l'édition de liens statiques, cette dépendance devient inflexible et, par conséquent, la compatibilité ascendante et descendante est perdue. L'enchaînement statique est garanti pour fonctionner uniquement sur le système où le fichier exécutable a été construit.
AvertissementLes applications liant statiquement les bibliothèques de la bibliothèque GNU C (glibc) nécessitent toujours que glibc soit présent sur le système en tant que bibliothèque dynamique. En outre, la variante de la bibliothèque dynamique glibc disponible au moment de l'exécution de l'application doit être une version bitwise identique à celle présente lors de l'édition de liens de l'application. Par conséquent, l'établissement de liens statiques n'est garanti que sur le système où le fichier exécutable a été créé.
- Couverture de soutien
- La plupart des bibliothèques statiques fournies par Red Hat se trouvent dans le canal CodeReady Linux Builder et ne sont pas prises en charge par Red Hat.
- Fonctionnalité
Certaines bibliothèques, notamment la bibliothèque GNU C (glibc), offrent des fonctionnalités réduites lorsqu'elles sont liées de manière statique.
Par exemple, lorsqu'il est lié statiquement, le site glibc ne prend pas en charge les threads et toute forme d'appel à la fonction
dlopen()
dans le même programme.
En raison de ces inconvénients, l'établissement de liens statiques doit être évité à tout prix, en particulier pour les applications entières et les bibliothèques glibc et libstdc .
Cas de la liaison statique
La création de liens statiques peut être un choix raisonnable dans certains cas, par exemple :
- Utilisation d'une bibliothèque qui n'est pas activée pour la liaison dynamique.
-
Une liaison entièrement statique peut être nécessaire pour exécuter un code dans un environnement ou un conteneur chroot vide. Cependant, l'établissement de liens statiques à l'aide du paquetage
glibc-static
n'est pas pris en charge par Red Hat.
2.3.3. Optimisation du temps de liaison
L'optimisation au moment de la liaison (LTO) permet au compilateur d'effectuer diverses optimisations sur toutes les unités de traduction de votre programme en utilisant sa représentation intermédiaire au moment de la liaison. Par conséquent, vos fichiers exécutables et vos bibliothèques sont plus petits et s'exécutent plus rapidement. En outre, vous pouvez analyser le code source du paquet au moment de la compilation de manière plus approfondie en utilisant l'OLT, ce qui améliore les différents diagnostics de GCC pour les erreurs de codage potentielles.
Problèmes connus
La violation de la règle de la définition unique (ODR) entraîne l'envoi d'un avertissement à l'adresse
-Wodr
Les violations de l'ODR entraînant un comportement indéfini produisent un avertissement à l'adresse
-Wodr
. Cela indique généralement un bogue dans votre programme. L'avertissement-Wodr
est activé par défaut.LTO entraîne une augmentation de la consommation de mémoire
Le compilateur consomme plus de mémoire lorsqu'il traite les unités de traduction du programme. Sur les systèmes disposant d'une mémoire limitée, désactivez le LTO ou réduisez le niveau de parallélisme lors de la construction de votre programme.
GCC supprime les fonctions apparemment inutilisées
GCC peut supprimer des fonctions qu'il considère comme inutilisées parce que le compilateur n'est pas en mesure de reconnaître les symboles auxquels une instruction asm() fait référence. Une erreur de compilation peut en résulter. Pour éviter cela, ajoutez
__attribute__((used))
aux symboles que vous utilisez dans votre programme.La compilation avec l'option
-fPIC
provoque des erreursGCC n'analysant pas le contenu des instructions asm(), la compilation de votre code avec l'option de ligne de commande
-fPIC
peut provoquer des erreurs. Pour éviter cela, utilisez l'option-fno-lto
lors de la compilation de votre unité de traduction.
Pour plus d'informations, consultez la FAQ LTO - Utilisation de symboles à partir du langage d'assemblage.Le versionnage des symboles à l'aide de la directive
.symver
n'est pas compatible avec LTOL'implémentation du versionnage des symboles en utilisant la directive
.symver
dans une instruction asm() n'est pas compatible avec le LTO. Cependant, il est possible d'implémenter le versionnage des symboles en utilisant l'attributsymver
. Par exemple, il est possible d'implémenter la version d'un symbole en utilisant l'attribut :__attribute__ ((_symver_ ("<symbol>@VERS_1"))) void <symbol>_v1 (void) { }
Ressources supplémentaires
2.3.4. Utilisation d'une bibliothèque avec GCC
Une bibliothèque est un ensemble de codes qui peuvent être réutilisés dans votre programme. Une bibliothèque C ou C se compose de deux parties :
- Le code de la bibliothèque
- Fichiers d'en-tête
Compiler un code qui utilise une bibliothèque
Les fichiers d'en-tête décrivent l'interface de la bibliothèque : les fonctions et les variables disponibles dans la bibliothèque. Les informations contenues dans les fichiers d'en-tête sont nécessaires à la compilation du code.
Généralement, les fichiers d'en-tête d'une bibliothèque sont placés dans un répertoire différent de celui du code de votre application. Pour indiquer à GCC où se trouvent les fichiers d'en-tête, utilisez l'option -I
:
$ gcc ... -Iinclude_path...
Remplacez include_path par le chemin d'accès au répertoire du fichier d'en-tête.
L'option -I
peut être utilisée plusieurs fois pour ajouter plusieurs répertoires contenant des fichiers d'en-tête. Lors de la recherche d'un fichier d'en-tête, ces répertoires sont parcourus dans l'ordre de leur apparition dans les options -I
.
Lier un code qui utilise une bibliothèque
Lors de la liaison du fichier exécutable, le code objet de votre application et le code binaire de la bibliothèque doivent être disponibles. Le code des bibliothèques statiques et dynamiques se présente sous différentes formes :
-
Les bibliothèques statiques sont disponibles sous forme de fichiers d'archive. Elles contiennent un groupe de fichiers objets. Le fichier d'archive a une extension de nom de fichier
.a
. -
Les bibliothèques dynamiques sont disponibles sous forme d'objets partagés. Elles constituent une forme de fichier exécutable. Un objet partagé a une extension de nom de fichier
.so
.
Pour indiquer à GCC où se trouvent les archives ou les fichiers d'objets partagés d'une bibliothèque, utilisez l'option -L
:
$ gcc ... -Llibrary_path -lfoo...
Remplacez library_path par le chemin d'accès au répertoire de la bibliothèque.
L'option -L
peut être utilisée plusieurs fois pour ajouter plusieurs répertoires. Lors de la recherche d'une bibliothèque, ces répertoires sont parcourus dans l'ordre des options -L
.
L'ordre des options est important : GCC ne peut pas établir un lien avec une bibliothèque foo s'il ne connaît pas le répertoire contenant cette bibliothèque. Par conséquent, utilisez les options -L
pour spécifier les répertoires de bibliothèques avant d'utiliser les options -l
pour l'édition de liens avec les bibliothèques.
Compiler et lier le code qui utilise une bibliothèque en une seule étape
Lorsque la situation permet de compiler et de lier le code en une seule commande gcc
, utilisez les options pour les deux situations mentionnées ci-dessus en une seule fois.
Ressources supplémentaires
- Utilisation de la collection de compilateurs GNU (GCC) - Options pour la recherche dans les répertoires
- Utilisation de la collection de compilateurs GNU (GCC) - Options pour l'établissement de liens
2.3.5. Utilisation d'une bibliothèque statique avec GCC
Les bibliothèques statiques sont disponibles sous forme d'archives contenant des fichiers objets. Après l'établissement d'un lien, elles font partie du fichier exécutable résultant.
Red Hat déconseille l'utilisation de liens statiques pour des raisons de sécurité. Voir Section 2.3.2, « Liaison statique et dynamique ». N'utilisez l'édition de liens statiques qu'en cas de nécessité, en particulier pour les bibliothèques fournies par Red Hat.
Conditions préalables
- GCC doit être installé sur votre système.
- Vous devez comprendre ce que sont les liens statiques et dynamiques.
- Vous disposez d'un ensemble de fichiers source ou objet formant un programme valide, nécessitant une bibliothèque statique foo et aucune autre bibliothèque.
-
La bibliothèque foo est disponible sous la forme d'un fichier
libfoo.a
, et aucun fichierlibfoo.so
n'est fourni pour la liaison dynamique.
La plupart des bibliothèques qui font partie de Red Hat Enterprise Linux ne sont prises en charge que pour l'édition de liens dynamiques. Les étapes ci-dessous ne fonctionnent que pour les bibliothèques qui sont not activées pour l'édition de liens dynamiques.
Procédure
Pour lier un programme à partir des fichiers source et objet, ajouter une bibliothèque statiquement liée foo, qui se trouve dans le fichier libfoo.a
:
- Allez dans le répertoire contenant votre code.
Compiler les fichiers sources du programme avec les en-têtes de la bibliothèque foo:
$ gcc ... -Iheader_path -c ...
Remplacez header_path par un chemin vers un répertoire contenant les fichiers d'en-tête de la bibliothèque foo.
Lier le programme à la bibliothèque foo:
$ gcc ... -Llibrary_path -lfoo...
Remplacez library_path par un chemin d'accès à un répertoire contenant le fichier
libfoo.a
.Pour exécuter le programme ultérieurement, il suffit de
$ ./program
L'option -static
de GCC relative à l'édition statique de liens interdit toute édition dynamique de liens. Utilisez plutôt les options -Wl,-Bstatic
et -Wl,-Bdynamic
pour contrôler plus précisément le comportement de l'éditeur de liens. Voir Section 2.3.7, « Utiliser des bibliothèques statiques et dynamiques avec GCC ».
2.3.6. Utilisation d'une bibliothèque dynamique avec GCC
Les bibliothèques dynamiques sont disponibles sous forme de fichiers exécutables autonomes, nécessaires à la fois au moment de l'établissement des liens et au moment de l'exécution. Elles restent indépendantes du fichier exécutable de votre application.
Conditions préalables
- GCC doit être installé sur le système.
- Ensemble de fichiers source ou objet formant un programme valide, nécessitant une bibliothèque dynamique foo et aucune autre bibliothèque.
- La bibliothèque foo doit être disponible sous la forme d'un fichier libfoo.so.
Lier un programme à une bibliothèque dynamique
Pour lier un programme à une bibliothèque dynamique foo:
$ gcc ... -Llibrary_path -lfoo...
Lorsqu'un programme est lié à une bibliothèque dynamique, le programme résultant doit toujours charger la bibliothèque au moment de l'exécution. Il existe deux options pour localiser la bibliothèque :
-
Utilisation d'une valeur
rpath
stockée dans le fichier exécutable lui-même -
Utilisation de la variable
LD_LIBRARY_PATH
au moment de l'exécution
Utilisation d'une valeur rpath
stockée dans le fichier exécutable
La valeur rpath
est une valeur spéciale enregistrée dans un fichier exécutable lorsqu'il est lié. Plus tard, lorsque le programme sera chargé à partir de son fichier exécutable, l'éditeur de liens utilisera la valeur rpath
pour localiser les fichiers de la bibliothèque.
Lors de l'établissement d'un lien avec GCC, le chemin library_path est enregistré sous rpath
:
$ gcc ... -Llibrary_path -lfoo -Wl,-rpath=library_path...
Le chemin library_path doit pointer vers un répertoire contenant le fichier libfoo.so.
N'ajoutez pas d'espace après la virgule dans l'option -Wl,-rpath=
.
Pour exécuter le programme ultérieurement :
$ ./program
Utilisation de la variable d'environnement LD_LIBRARY_PATH
Si le fichier exécutable du programme ne contient pas rpath
, l'éditeur de liens utilisera la variable d'environnement LD_LIBRARY_PATH
. La valeur de cette variable doit être modifiée pour chaque programme. Cette valeur doit représenter le chemin où se trouvent les objets de la bibliothèque partagée.
Pour exécuter le programme sans rpath
, avec les bibliothèques présentes dans le chemin library_path:
$ export LD_LIBRARY_PATH=library_path:$LD_LIBRARY_PATH
$ ./program
L'omission de la valeur rpath
offre une certaine souplesse, mais nécessite la définition de la variable LD_LIBRARY_PATH
à chaque fois que le programme doit être exécuté.
Placer la bibliothèque dans les répertoires par défaut
La configuration de l'éditeur de liens d'exécution spécifie un certain nombre de répertoires comme emplacement par défaut des fichiers de bibliothèque dynamique. Pour utiliser ce comportement par défaut, copiez votre bibliothèque dans le répertoire approprié.
Une description complète du comportement de l'éditeur de liens dynamiques n'entre pas dans le cadre de ce document. Pour plus d'informations, voir les ressources suivantes :
Pages de manuel Linux pour l'éditeur de liens dynamiques :
$ man ld.so
Contenu du fichier de configuration
/etc/ld.so.conf
:$ cat /etc/ld.so.conf
Rapport des bibliothèques reconnues par l'éditeur de liens dynamiques sans configuration supplémentaire, qui inclut les répertoires :
$ ldconfig -v
2.3.7. Utiliser des bibliothèques statiques et dynamiques avec GCC
Il est parfois nécessaire de lier certaines bibliothèques de manière statique et d'autres de manière dynamique. Cette situation pose quelques problèmes.
Conditions préalables
- Comprendre les liens statiques et dynamiques
Introduction
gcc reconnaît les bibliothèques dynamiques et statiques. Lorsque l'option -lfoo
est rencontrée, gcc tentera d'abord de localiser un objet partagé (un fichier .so
) contenant une version liée dynamiquement de la bibliothèque foo, puis cherchera le fichier d'archive (.a
) contenant une version statique de la bibliothèque. Ainsi, les situations suivantes peuvent résulter de cette recherche :
- Seul l'objet partagé est trouvé et gcc s'y réfère de manière dynamique.
- Seule l'archive est trouvée, et gcc s'y réfère de manière statique.
- L'objet partagé et l'archive sont tous deux trouvés et, par défaut, gcc sélectionne la liaison dynamique avec l'objet partagé.
- Aucun objet partagé ni archive n'est trouvé et la liaison échoue.
En raison de ces règles, la meilleure façon de sélectionner la version statique ou dynamique d'une bibliothèque pour l'édition de liens est de n'avoir que la version trouvée par gcc. Ceci peut être contrôlé dans une certaine mesure en utilisant ou en supprimant les répertoires contenant les versions des bibliothèques, lors de la spécification des options -Lpath
options.
En outre, comme l'enchaînement dynamique est la valeur par défaut, la seule situation où l'enchaînement doit être explicitement spécifié est celle où une bibliothèque dont les deux versions sont présentes doit être liée de manière statique. Il existe deux solutions possibles :
-
Spécification des bibliothèques statiques par chemin d'accès au lieu de l'option
-l
-
Utilisation de l'option
-Wl
pour passer des options à l'éditeur de liens
Spécifier les bibliothèques statiques par fichier
Habituellement, gcc est chargé d'établir un lien avec la bibliothèque foo à l'aide de l'option -lfoo
. Cependant, il est possible de spécifier le chemin complet du fichier libfoo.a
contenant la bibliothèque :
$ gcc ... path/to/libfoo.a ...
D'après l'extension du fichier .a
, gcc comprendra qu'il s'agit d'une bibliothèque à lier au programme. Cependant, spécifier le chemin complet du fichier de la bibliothèque est une méthode moins souple.
Utilisation de l'option -Wl
L'option gcc -Wl
est une option spéciale permettant de passer des options à l'éditeur de liens sous-jacent. La syntaxe de cette option diffère de celle des autres options gcc. L'option -Wl
est suivie d'une liste d'options de l'éditeur de liens séparée par des virgules, alors que les autres options gcc nécessitent une liste d'options séparées par des espaces.
L'éditeur de liens ld utilisé par gcc propose les options -Bstatic
et -Bdynamic
pour spécifier si les bibliothèques suivant cette option doivent être liées statiquement ou dynamiquement, respectivement. Après avoir transmis -Bstatic
et une bibliothèque à l'éditeur de liens, le comportement de liaison dynamique par défaut doit être rétabli manuellement pour que les bibliothèques suivantes soient liées dynamiquement avec l'option -Bdynamic
.
Pour lier un programme, liez la bibliothèque first de manière statique (libfirst.a
) et second de manière dynamique (libsecond.so
) :
$ gcc ... -Wl,-Bstatic -lfirst -Wl,-Bdynamic -lsecond...
gcc peut être configuré pour utiliser d'autres linkers que celui par défaut ld.
Ressources supplémentaires
- Utilisation de la collection de compilateurs GNU (GCC) - 3.14 Options d'édition de liens
- Documentation pour binutils 2.27 - 2.1 Options de ligne de commande
2.4. Créer des bibliothèques avec GCC
Ce chapitre décrit les étapes de création des bibliothèques et explique les concepts nécessaires utilisés par le système d'exploitation Linux pour les bibliothèques.
2.4.1. Conventions de dénomination des bibliothèques
Une convention spéciale sur les noms de fichiers est utilisée pour les bibliothèques : une bibliothèque connue sous le nom de foo est censée exister sous la forme d'un fichier libfoo.so
ou libfoo.a
. Cette convention est automatiquement comprise par les options d'entrée de GCC, mais pas par les options de sortie :
Lors de l'établissement d'un lien avec la bibliothèque, celle-ci ne peut être spécifiée que par son nom foo avec l'option
-l
, comme suit-lfoo
:$ gcc ... -lfoo...
-
Lors de la création de la bibliothèque, le nom complet du fichier
libfoo.so
oulibfoo.a
doit être spécifié.
2.4.2. Le mécanisme du soname
Les bibliothèques chargées dynamiquement (objets partagés) utilisent un mécanisme appelé soname pour gérer plusieurs versions compatibles d'une bibliothèque.
Conditions préalables
- Vous devez comprendre la liaison dynamique et les bibliothèques.
- Vous devez comprendre le concept de compatibilité ABI.
- Vous devez comprendre les conventions de dénomination des bibliothèques.
- Vous devez comprendre les liens symboliques.
Introduction du problème
Une bibliothèque chargée dynamiquement (objet partagé) existe en tant que fichier exécutable indépendant. Cela permet de mettre à jour la bibliothèque sans mettre à jour les applications qui en dépendent. Ce concept pose toutefois les problèmes suivants :
- Identification de la version actuelle de la bibliothèque
- Nécessité de disposer de plusieurs versions de la même bibliothèque
- Signalisation de la compatibilité ABI de chacune des multiples versions
Le mécanisme du soname
Pour résoudre ce problème, Linux utilise un mécanisme appelé soname.
La version de la bibliothèque foo
X.Y est ABI-compatible avec les autres versions dont le numéro de version contient la même valeur que X. Les modifications mineures préservant la compatibilité augmentent le numéro Y. Les modifications majeures qui rompent la compatibilité augmentent le numéro X.
La version actuelle de la bibliothèque foo
X.Y existe sous la forme d'un fichier libfoo.so.x.y
. Dans le fichier de la bibliothèque, un nom de son est enregistré avec la valeur libfoo.so.x
pour signaler la compatibilité.
Lorsque les applications sont construites, l'éditeur de liens recherche la bibliothèque dans le fichier libfoo.so
. Un lien symbolique portant ce nom doit exister et pointer vers le fichier de la bibliothèque. L'éditeur de liens lit ensuite le nom de son du fichier de la bibliothèque et l'enregistre dans le fichier exécutable de l'application. Enfin, l'éditeur de liens crée l'application qui déclare dépendre de la bibliothèque en utilisant le nom de son, et non un nom ou un nom de fichier.
Lorsque l'éditeur de liens dynamiques d'exécution lie une application avant de l'exécuter, il lit le soname dans le fichier exécutable de l'application. Ce nom de son est libfoo.so.x
. Un lien symbolique portant ce nom doit exister et pointer vers le fichier de la bibliothèque. Cela permet de charger la bibliothèque, quel que soit le composant Y d'une version, car le nom de son ne change pas.
La composante Y du numéro de version n'est pas limitée à un seul chiffre. En outre, certaines bibliothèques codent leur version dans leur nom.
Lecture du nom de famille à partir d'un fichier
Pour afficher le nom de son d'un fichier de bibliothèque somelibrary
:
$ objdump -p somelibrary | grep SONAME
Remplacez somelibrary par le nom du fichier de la bibliothèque que vous souhaitez examiner.
2.4.3. Créer des bibliothèques dynamiques avec GCC
Les bibliothèques liées dynamiquement (objets partagés) permettent :
- conservation des ressources par la réutilisation des codes
- une sécurité accrue en facilitant la mise à jour du code de la bibliothèque
Suivez les étapes suivantes pour créer et installer une bibliothèque dynamique à partir des sources.
Conditions préalables
- Vous devez comprendre le mécanisme du soname.
- GCC doit être installé sur le système.
- Vous devez disposer du code source d'une bibliothèque.
Procédure
- Se rendre dans le répertoire contenant les sources de la bibliothèque.
Compilez chaque fichier source en un fichier objet avec l'option de code indépendant de la position
-fPIC
:$ gcc ... -c -fPIC some_file.c...
Les fichiers objets portent le même nom que les fichiers du code source original, mais leur extension est
.o
.Lier la bibliothèque partagée à partir des fichiers objets :
$ gcc -shared -o libfoo.so.x.y -Wl,-soname,libfoo.so.x some_file.o ...
Le numéro de version majeure utilisé est X et le numéro de version mineure Y.
Copier le fichier
libfoo.so.x.y
à un emplacement approprié, où l'éditeur de liens dynamiques du système peut le trouver. Sur Red Hat Enterprise Linux, le répertoire des bibliothèques est/usr/lib64
:# cp libfoo.so.x.y /usr/lib64
Notez que vous devez disposer des droits de root pour manipuler les fichiers de ce répertoire.
Créer la structure de lien symbolique pour le mécanisme de soname :
# ln -s libfoo.so.x.y libfoo.so.x # ln -s libfoo.so.x libfoo.so
Ressources supplémentaires
- The Linux Documentation Project - Guide pratique sur les bibliothèques de programmes - 3 Bibliothèques partagées
2.4.4. Créer des bibliothèques statiques avec GCC et ar
La création de bibliothèques pour l'établissement de liens statiques est possible grâce à la conversion des fichiers objets en un type spécial de fichier d'archive.
Red Hat décourage l'utilisation de la liaison statique pour des raisons de sécurité. N'utilisez l'édition de liens statiques qu'en cas de nécessité, en particulier pour les bibliothèques fournies par Red Hat. Consultez Section 2.3.2, « Liaison statique et dynamique » pour plus de détails.
Conditions préalables
- GCC et binutils doivent être installés sur le système.
- Vous devez comprendre ce que sont les liens statiques et dynamiques.
- Le(s) fichier(s) source(s) contenant des fonctions à partager en tant que bibliothèque est (sont) disponible(s).
Procédure
Créer des fichiers objets intermédiaires avec GCC.
$ gcc -c source_file.c...
Ajoutez d'autres fichiers sources si nécessaire. Les fichiers objets résultants partagent le même nom de fichier mais utilisent l'extension de nom de fichier
.o
.Transformez les fichiers objets en une bibliothèque statique (archive) à l'aide de l'outil
ar
du paquetbinutils
.$ ar rcs libfoo.a source_file.o...
Le fichier
libfoo.a
est créé.Utilisez la commande
nm
pour inspecter l'archive résultante :$ nm libfoo.a
- Copiez le fichier de la bibliothèque statique dans le répertoire approprié.
Lors de l'édition de liens avec la bibliothèque, GCC reconnaît automatiquement, à partir de l'extension du nom de fichier
.a
, que la bibliothèque est une archive pour l'édition de liens statiques.$ gcc ... -lfoo...
Ressources supplémentaires
Page de manuel Linux pour ar(1):
$ man ar
2.5. Gérer plus de code avec Make
L'utilitaire GNU Make, communément abrégé make, est un outil permettant de contrôler la génération d'exécutables à partir de fichiers sources. make détermine automatiquement quelles parties d'un programme complexe ont été modifiées et doivent être recompilées. make utilise des fichiers de configuration appelés Makefiles pour contrôler la manière dont les programmes sont construits.
2.5.1. Aperçu de GNU make
et Makefile
Pour créer une forme utilisable (généralement des fichiers exécutables) à partir des fichiers sources d'un projet particulier, il convient d'effectuer plusieurs étapes nécessaires. Enregistrez les actions et leur séquence afin de pouvoir les répéter ultérieurement.
Red Hat Enterprise Linux contient GNU make
, un système de construction conçu à cet effet.
Conditions préalables
- Comprendre les concepts de compilation et de liaison
GNU make
GNU make
lit les Makefiles qui contiennent les instructions décrivant le processus de construction. Un Makefile contient plusieurs rules qui décrivent une manière de satisfaire une certaine condition (target) avec une action spécifique (recipe). Les règles peuvent dépendre hiérarchiquement d'une autre règle.
En lançant make
sans aucune option, il recherche un Makefile dans le répertoire courant et tente d'atteindre la cible par défaut. Le nom du fichier Makefile peut être l'un des noms suivants : Makefile
, makefile
, et GNUmakefile
. La cible par défaut est déterminée à partir du contenu du Makefile.
Détails du Makefile
Les Makefiles utilisent une syntaxe relativement simple pour définir variables et rules, qui consiste en une target et une recipe. La cible spécifie ce qui est produit si une règle est exécutée. Les lignes contenant des recettes doivent commencer par le caractère TAB.
Typiquement, un Makefile contient des règles pour la compilation des fichiers sources, une règle pour lier les fichiers objets résultants, et une cible qui sert de point d'entrée au sommet de la hiérarchie.
Considérons l'exemple suivant Makefile
pour la construction d'un programme C qui consiste en un seul fichier, hello.c
.
all: hello hello: hello.o gcc hello.o -o hello hello.o: hello.c gcc -c hello.c -o hello.o
Cet exemple montre que pour atteindre la cible all
, le fichier hello
est nécessaire. Pour obtenir hello
, il faut hello.o
(lié à gcc
), qui est à son tour créé à partir de hello.c
(compilé par gcc
).
La cible all
est la cible par défaut car c'est la première cible qui ne commence pas par un point (.). L'exécution de make
sans argument est donc identique à l'exécution de make all
, lorsque le répertoire courant contient ce Makefile
.
Fichier makefile typique
Un Makefile plus typique utilise des variables pour la généralisation des étapes et ajoute une cible "clean" - supprimer tout sauf les fichiers sources.
CC=gcc CFLAGS=-c -Wall SOURCE=hello.c OBJ=$(SOURCE:.c=.o) EXE=hello all: $(SOURCE) $(EXE) $(EXE): $(OBJ) $(CC) $(OBJ) -o $@ %.o: %.c $(CC) $(CFLAGS) $< -o $@ clean: rm -rf $(OBJ) $(EXE)
L'ajout de fichiers sources supplémentaires à un tel Makefile ne nécessite que de les ajouter à la ligne où la variable SOURCE est définie.
Ressources supplémentaires
- GNU make : Introduction - 2 Introduction aux Makefiles
2.5.2. Exemple : Construction d'un programme C à l'aide d'un fichier Makefile
Créez un exemple de programme C à l'aide d'un fichier Makefile en suivant les étapes de cet exemple.
Conditions préalables
-
Vous devez comprendre les concepts de Makefiles et de
make
.
Procédure
Créez un répertoire
hellomake
et allez dans ce répertoire :$ mkdir hellomake $ cd hellomake
Créez un fichier
hello.c
avec le contenu suivant :#include <stdio.h> int main(int argc, char *argv[]) { printf("Hello, World!\n"); return 0; }
Créez un fichier
Makefile
avec le contenu suivant :CC=gcc CFLAGS=-c -Wall SOURCE=hello.c OBJ=$(SOURCE:.c=.o) EXE=hello all: $(SOURCE) $(EXE) $(EXE): $(OBJ) $(CC) $(OBJ) -o $@ %.o: %.c $(CC) $(CFLAGS) $< -o $@ clean: rm -rf $(OBJ) $(EXE)
ImportantLes lignes de la recette du Makefile doivent commencer par le caractère tabulation ! Lorsque vous copiez le texte ci-dessus à partir de la documentation, le processus de copier-coller peut coller des espaces à la place des tabulations. Si cela se produit, corrigez le problème manuellement.
Exécuter
make
:$ make gcc -c -Wall hello.c -o hello.o gcc hello.o -o hello
Cela crée un fichier exécutable
hello
.Exécutez le fichier exécutable
hello
:$ ./hello Hello, World!
Exécutez la cible Makefile
clean
pour supprimer les fichiers créés :$ make clean rm -rf hello.o hello
2.5.3. Ressources documentaires pour make
Pour plus d'informations sur make
, voir les ressources listées ci-dessous.
Documentation installée
Utilisez les outils
man
etinfo
pour consulter les pages de manuel et les pages d'information installées sur votre système :$ man make $ info make
Documentation en ligne
- Le manuel GNU Make hébergé par la Free Software Foundation
- Guide de l'utilisateur de Red Hat Developer Toolset - Chapitre 3. GNU make
Chapitre 3. Débogage des applications
Le débogage des applications est un sujet très vaste. Cette partie fournit au développeur les techniques les plus courantes de débogage dans de multiples situations.
3.1. Activation du débogage avec les informations de débogage
Pour déboguer les applications et les bibliothèques, des informations de débogage sont nécessaires. Les sections suivantes décrivent comment obtenir ces informations.
3.1.1. Informations de débogage
Lors du débogage d'un code exécutable, deux types d'informations permettent aux outils, et par extension au programmeur, de comprendre le code binaire :
- le texte du code source
- une description de la manière dont le texte du code source est lié au code binaire
Ces informations sont appelées "informations de débogage".
Red Hat Enterprise Linux utilise le format ELF pour les binaires exécutables, les bibliothèques partagées ou les fichiers debuginfo
. Dans ces fichiers ELF, le format DWARF est utilisé pour contenir les informations de débogage.
Pour afficher les informations DWARF stockées dans un fichier ELF, exécutez la commande readelf -w file
commande.
STABS est un format plus ancien et moins performant, utilisé occasionnellement avec UNIX. Son utilisation est déconseillée par Red Hat. GCC et GDB fournissent la production et la consommation de STABS sur une base de meilleur effort seulement. D'autres outils tels que Valgrind et elfutils
ne fonctionnent pas avec STABS.
Ressources supplémentaires
3.1.2. Débogage des applications C et C avec GCC
Les informations de débogage étant volumineuses, elles ne sont pas incluses par défaut dans les fichiers exécutables. Pour permettre le débogage de vos applications C et C avec elle, vous devez explicitement demander au compilateur de la créer.
Pour permettre la création d'informations de débogage avec GCC lors de la compilation et de l'édition de liens, utilisez l'option -g
:
$ gcc ... -g ...
-
Les optimisations effectuées par le compilateur et l'éditeur de liens peuvent aboutir à un code exécutable difficile à relier au code source original : les variables peuvent être optimisées, les boucles déroulées, les opérations fusionnées avec les opérations environnantes, etc. Cela a un impact négatif sur le débogage. Pour améliorer l'expérience de débogage, envisagez de définir l'optimisation avec l'option
-Og
. Cependant, la modification du niveau d'optimisation modifie le code exécutable et peut changer le comportement réel, y compris la suppression de certains bogues. -
Pour inclure également les définitions de macros dans les informations de débogage, utilisez l'option
-g3
au lieu de-g
. -
L'option
-fcompare-debug
GCC teste le code compilé par GCC avec des informations de débogage et sans informations de débogage. Le test est réussi si les deux fichiers binaires résultants sont identiques. Ce test garantit que le code exécutable n'est pas affecté par les options de débogage, ce qui permet de s'assurer qu'il n'y a pas de bogues cachés dans le code de débogage. Notez que l'utilisation de l'option-fcompare-debug
augmente de manière significative le temps de compilation. Voir la page de manuel de GCC pour plus de détails sur cette option.
Ressources supplémentaires
- Utilisation de la collection de compilateurs GNU (GCC) - Options pour déboguer votre programme
- Débogage avec GDB - Informations de débogage dans des fichiers séparés
La page du manuel GCC :
$ man gcc
3.1.3. Paquets debuginfo et debugsource
Les paquets debuginfo
et debugsource
contiennent des informations de débogage et le code source de débogage pour les programmes et les bibliothèques. Pour les applications et les bibliothèques installées dans des paquets provenant des dépôts de Red Hat Enterprise Linux, vous pouvez obtenir des paquets distincts debuginfo
et debugsource
à partir d'un canal supplémentaire.
Types de paquets d'informations de débogage
Il existe deux types de paquets disponibles pour le débogage :
- Paquets Debuginfo
-
Les paquets
debuginfo
fournissent les informations de débogage nécessaires pour fournir des noms lisibles par l'homme pour les caractéristiques du code binaire. Ces paquets contiennent des fichiers.debug
, qui contiennent des informations de débogage DWARF. Ces fichiers sont installés dans le répertoire/usr/lib/debug
. - Paquets Debugsource
-
Les paquets
debugsource
contiennent les fichiers sources utilisés pour compiler le code binaire. Lorsque les paquetsdebuginfo
etdebugsource
sont installés, les débogueurs tels que GDB ou LLDB peuvent relier l'exécution du code binaire au code source. Les fichiers du code source sont installés dans le répertoire/usr/src/debug
.
3.1.4. Obtenir les paquets d'informations de débogage pour une application ou une bibliothèque à l'aide de GDB
Les informations de débogage sont nécessaires pour déboguer le code. Pour le code installé à partir d'un paquetage, le débogueur GNU (GDB) reconnaît automatiquement les informations de débogage manquantes, résout le nom du paquetage et fournit des conseils concrets sur la manière d'obtenir le paquetage.
Conditions préalables
- L'application ou la bibliothèque que vous souhaitez déboguer doit être installée sur le système.
-
GDB et l'outil
debuginfo-install
doivent être installés sur le système. Pour plus de détails, voir Configuration pour le débogage d'applications. -
Les dépôts fournissant les paquets
debuginfo
etdebugsource
doivent être configurés et activés sur le système. Pour plus de détails, voir Activation des référentiels de débogage et de sources.
Procédure
Lancez GDB attaché à l'application ou à la bibliothèque que vous souhaitez déboguer. GDB reconnaît automatiquement les informations de débogage manquantes et suggère une commande à exécuter.
$ gdb -q /bin/ls Reading symbols from /bin/ls...Reading symbols from .gnu_debugdata for /usr/bin/ls...(no debugging symbols found)...done. (no debugging symbols found)...done. Missing separate debuginfos, use: dnf debuginfo-install coreutils-8.30-6.el8.x86_64 (gdb)
Quittez GDB : tapez q et confirmez avec Enter.
(gdb) q
Exécutez la commande suggérée par GDB pour installer les paquets
debuginfo
requis :# dnf debuginfo-install coreutils-8.30-6.el8.x86_64
L'outil de gestion des paquets
dnf
fournit un résumé des changements, demande une confirmation et, une fois que vous avez confirmé, télécharge et installe tous les fichiers nécessaires.-
Si GDB n'est pas en mesure de suggérer le paquet
debuginfo
, suivez la procédure décrite dans Obtenir manuellement les paquets debuginfo pour une application ou une bibliothèque.
Ressources supplémentaires
- Guide d'utilisation de Red Hat Developer Toolset, section Installation des informations de débogage
- Comment puis-je télécharger ou installer des paquets debuginfo pour les systèmes RHEL ? - Solution de la base de connaissances de Red Hat
3.1.5. Obtenir manuellement les paquets d'informations de débogage pour une application ou une bibliothèque
Vous pouvez déterminer manuellement les paquets debuginfo
que vous devez installer en localisant le fichier exécutable, puis le paquet qui l'installe.
Red Hat vous recommande d'utiliser GDB pour déterminer les paquetages à installer. Utilisez cette procédure manuelle uniquement si GDB n'est pas en mesure de suggérer le paquetage à installer.
Conditions préalables
- L'application ou la bibliothèque doit être installée sur le système.
- L'application ou la bibliothèque a été installée à partir d'un paquetage.
-
L'outil
debuginfo-install
doit être disponible sur le système. -
Les canaux fournissant les paquets
debuginfo
doivent être configurés et activés sur le système.
Procédure
Rechercher le fichier exécutable de l'application ou de la bibliothèque.
Utilisez la commande
which
pour trouver le fichier d'application.$ which less /usr/bin/less
Utilisez la commande
locate
pour trouver le fichier de la bibliothèque.$ locate libz | grep so /usr/lib64/libz.so.1 /usr/lib64/libz.so.1.2.11
Si les raisons initiales du débogage comprennent des messages d'erreur, choisissez le résultat où le nom de fichier de la bibliothèque contient les mêmes nombres supplémentaires que ceux mentionnés dans les messages d'erreur. En cas de doute, essayez de suivre le reste de la procédure avec le résultat où le nom de fichier de la bibliothèque ne comporte pas de chiffres supplémentaires.
NoteLa commande
locate
est fournie par le paquetmlocate
. Pour l'installer et permettre son utilisation :# dnf install mlocate # updatedb
Rechercher le nom et la version du paquet qui a fourni le fichier :
$ rpm -qf /usr/lib64/libz.so.1.2.7 zlib-1.2.11-10.el8.x86_64
La sortie fournit des détails sur le paquet installé au format name:epoch-version.release.architecture.
ImportantSi cette étape ne donne aucun résultat, il n'est pas possible de déterminer quel paquet a fourni le fichier binaire. Plusieurs cas sont possibles :
- Le fichier est installé à partir d'un paquet qui n'est pas connu des outils de gestion des paquets dans leur configuration current.
-
Le fichier est installé à partir d'un paquet téléchargé localement et installé manuellement. Dans ce cas, il est impossible de déterminer automatiquement un paquetage
debuginfo
approprié. - Vos outils de gestion des paquets sont mal configurés.
-
Le fichier n'est pas installé à partir d'un paquetage. Dans ce cas, il n'existe pas de paquetage
debuginfo
correspondant.
Comme les étapes suivantes dépendent de celle-ci, vous devez résoudre cette situation ou interrompre la procédure. La description des étapes exactes du dépannage dépasse le cadre de cette procédure.
Installez les paquets
debuginfo
à l'aide de l'utilitairedebuginfo-install
. Dans la commande, utilisez le nom du paquet et les autres détails que vous avez déterminés à l'étape précédente :# debuginfo-install zlib-1.2.11-10.el8.x86_64
Ressources supplémentaires
3.2. Inspection de l'état interne de l'application avec GDB
Pour savoir pourquoi une application ne fonctionne pas correctement, il faut contrôler son exécution et examiner son état interne à l'aide d'un débogueur. Cette section décrit comment utiliser le débogueur GNU (GDB) pour cette tâche.
3.2.1. Débogueur GNU (GDB)
Red Hat Enterprise Linux contient le débogueur GNU (GDB) qui vous permet d'examiner ce qui se passe à l'intérieur d'un programme par le biais d'une interface utilisateur en ligne de commande.
Capacités de GDB
Une seule session GDB peut déboguer les types de programmes suivants :
- Programmes multithreads et forkings
- Plusieurs programmes à la fois
-
Programmes sur des machines distantes ou dans des conteneurs avec l'utilitaire
gdbserver
connecté via une connexion réseau TCP/IP
Exigences en matière de débogage
Pour déboguer un code exécutable, GDB a besoin d'informations de débogage pour ce code particulier :
- Pour les programmes que vous avez développés, vous pouvez créer les informations de débogage pendant la construction du code.
- Pour les programmes système installés à partir de paquets, vous devez installer leurs paquets debuginfo.
3.2.2. Attacher GDB à un processus
Afin d'examiner un processus, GDB doit se trouver à l'adresse attached.
Conditions préalables
- GDB doit être installé sur le système
Démarrer un programme avec GDB
Lorsque le programme n'est pas exécuté en tant que processus, démarrez-le avec GDB :
$ gdb program
Remplacez program par un nom de fichier ou un chemin d'accès au programme.
GDB se met en place pour démarrer l'exécution du programme. Vous pouvez configurer les points d'arrêt et l'environnement gdb
avant de commencer l'exécution du processus à l'aide de la commande run
.
Attacher GDB à un processus déjà en cours d'exécution
Pour attacher GDB à un programme déjà en cours d'exécution en tant que processus :
Recherchez l'ID du processus (pid) à l'aide de la commande
ps
:$ ps -C program -o pid h pid
Remplacez program par un nom de fichier ou un chemin d'accès au programme.
Attachez la GDB à ce processus :
$ gdb -p pid
Remplacer pid par un numéro d'identification de processus réel provenant de la sortie
ps
.
Attacher une GDB déjà en cours d'exécution à un processus déjà en cours d'exécution
Pour attacher une GDB déjà en cours d'exécution à un programme déjà en cours d'exécution :
Utilisez la commande GDB
shell
pour exécuter la commandeps
et trouver l'ID du processus du programme (pid) :(gdb) shell ps -C program -o pid h pid
Remplacez program par un nom de fichier ou un chemin d'accès au programme.
Utilisez la commande
attach
pour attacher GDB au programme :(gdb) attacher pid
Remplacer pid par un numéro d'identification de processus réel provenant de la sortie
ps
.
Dans certains cas, GDB peut ne pas être en mesure de trouver le fichier exécutable correspondant. Utilisez la commande file
pour spécifier le chemin d'accès :
(gdb) path/to/program
Ressources supplémentaires
- Débogage avec GDB - 2.1 Invocation de GDB
- Débogage avec GDB - 4.7 Débogage d'un processus en cours d'exécution
3.2.3. Parcourir le code d'un programme avec GDB
Une fois que le débogueur GDB est connecté à un programme, vous pouvez utiliser un certain nombre de commandes pour contrôler l'exécution du programme.
Conditions préalables
Vous devez disposer des informations de débogage nécessaires :
- Le programme est compilé et construit avec des informations de débogage, ou
- Les paquets debuginfo pertinents sont installés
- GDB doit être attaché au programme à déboguer
Commandes GDB pour parcourir le code
r
(courir)-
Lance l'exécution du programme. Si
run
est exécuté avec des arguments, ceux-ci sont transmis à l'exécutable comme si le programme avait été lancé normalement. Les utilisateurs lancent normalement cette commande après avoir défini des points d'arrêt. start
-
Lancer l'exécution du programme mais s'arrêter au début de la fonction principale du programme. Si
start
est exécuté avec des arguments, ceux-ci sont transmis à l'exécutable comme si le programme avait été lancé normalement.
c
(suite)Poursuivre l'exécution du programme à partir de l'état actuel. L'exécution du programme se poursuivra jusqu'à ce que l'une des conditions suivantes soit remplie :
- Un point d'arrêt est atteint.
- Une condition spécifiée est remplie.
- Un signal est reçu par le programme.
- Une erreur s'est produite.
- Le programme se termine.
n
(suite)Poursuivre l'exécution du programme à partir de l'état actuel, jusqu'à ce que la ligne de code suivante dans le fichier source actuel soit atteinte. L'exécution du programme se poursuivra jusqu'à ce que l'une des conditions suivantes soit remplie :
- Un point d'arrêt est atteint.
- Une condition spécifiée est remplie.
- Un signal est reçu par le programme.
- Une erreur s'est produite.
- Le programme se termine.
s
(étape)-
La commande
step
arrête également l'exécution à chaque ligne séquentielle de code dans le fichier source actuel. Cependant, si l'exécution est actuellement arrêtée à une ligne de source contenant un function call, GDB arrête l'exécution après avoir entré l'appel de fonction (au lieu de l'exécuter). until
location- L'exécution se poursuit jusqu'à ce que l'emplacement du code spécifié par l'option location soit atteint.
fini
(finition)Reprendre l'exécution du programme et s'arrêter lorsque l'exécution revient d'une fonction. L'exécution du programme se poursuit jusqu'à ce que l'une des conditions suivantes soit remplie :
- Un point d'arrêt est atteint.
- Une condition spécifiée est remplie.
- Un signal est reçu par le programme.
- Une erreur s'est produite.
- Le programme se termine.
q
(quitter)- Termine l'exécution et quitte GDB.
Ressources supplémentaires
- Débogage avec GDB - 4.2 Démarrage du programme
- Débogage avec GDB - 5.2 Continuer et avancer
3.2.4. Afficher les valeurs internes du programme avec GDB
L'affichage des valeurs des variables internes d'un programme est important pour comprendre ce que fait le programme. GDB propose plusieurs commandes que vous pouvez utiliser pour inspecter les variables internes. Les commandes suivantes sont les plus utiles :
p
(en caractères d'imprimerie)Affiche la valeur de l'argument donné. En général, l'argument est le nom d'une variable de toute complexité, d'une simple valeur unique à une structure. Un argument peut également être une expression valide dans le langage courant, y compris l'utilisation de variables de programme et de fonctions de bibliothèque, ou de fonctions définies dans le programme testé.
Il est possible d'étendre GDB avec pretty-printer Python ou Guile scripts pour un affichage personnalisé des structures de données (telles que les classes, les structures) en utilisant la commande
print
.bt
(backtrace)Affiche la chaîne d'appels de fonctions utilisée pour atteindre le point d'exécution actuel, ou la chaîne de fonctions utilisée jusqu'à la fin de l'exécution. Cette fonction est utile pour enquêter sur des bogues graves (tels que les erreurs de segmentation) dont les causes sont difficiles à cerner.
L'ajout de l'option
full
à la commandebacktrace
permet également d'afficher les variables locales.Il est possible d'étendre GDB avec des scripts Python frame filter pour un affichage personnalisé des données affichées à l'aide des commandes
bt
etinfo frame
. Le terme frame fait référence aux données associées à un seul appel de fonction.info
La commande
info
est une commande générique qui permet de fournir des informations sur divers éléments. Elle prend une option spécifiant l'élément à décrire.-
La commande
info args
affiche les options de l'appel de fonction correspondant au cadre sélectionné. -
La commande
info locals
affiche les variables locales dans le cadre sélectionné.
Pour obtenir une liste des éléments possibles, exécutez la commande
help info
dans une session GDB :(gdb) help info
-
La commande
l
(liste)-
Affiche la ligne du code source où le programme s'est arrêté. Cette commande n'est disponible que lorsque l'exécution du programme est arrêtée. Bien qu'il ne s'agisse pas à proprement parler d'une commande permettant d'afficher l'état interne,
list
aide l'utilisateur à comprendre les changements qui seront apportés à l'état interne lors de la prochaine étape de l'exécution du programme.
Ressources supplémentaires
- L'API Python GDB - Red Hat Developers Blog entry
- Débogage avec GDB - Jolie impression
3.2.5. Utilisation des points d'arrêt GDB pour arrêter l'exécution à des endroits définis du code
Souvent, seules de petites portions de code sont étudiées. Les points d'arrêt sont des marqueurs qui indiquent à GDB d'arrêter l'exécution d'un programme à un certain endroit du code. Les points d'arrêt sont le plus souvent associés à des lignes de code source. Dans ce cas, pour placer un point d'arrêt, il faut spécifier le fichier source et le numéro de ligne.
Pour place a breakpoint:
Spécifiez le nom du code source file et le line dans ce fichier :
(gdb) br file:line
Si file n'est pas présent, le nom du fichier source au point d'exécution actuel est utilisé :
(gdb) br line
Vous pouvez également utiliser le nom d'une fonction pour placer le point d'arrêt au début de celle-ci :
(gdb) br function_name
Un programme peut rencontrer une erreur après un certain nombre d'itérations d'une tâche. Pour spécifier un condition supplémentaire pour arrêter l'exécution :
(gdb) br file:line si condition
Remplacez condition par une condition en langage C ou C. La signification de file et line est la même que ci-dessus.
Pour inspect l'état de tous les points d'arrêt et de surveillance :
(gdb) info br
Pour remove un point d'arrêt en utilisant son number comme affiché dans la sortie de
info br
:(gdb) supprimer number
Pour remove un point d'arrêt à un endroit donné :
(gdb) effacer file:line
Ressources supplémentaires
- Débogage avec GDB - 5.1 Points d'arrêt, points de surveillance et points de capture
3.2.6. Utilisation des points de contrôle GDB pour arrêter l'exécution lors de l'accès aux données et de leur modification
Dans de nombreux cas, il est avantageux de laisser le programme s'exécuter jusqu'à ce que certaines données soient modifiées ou consultées. Les exemples suivants représentent les cas d'utilisation les plus courants.
Conditions préalables
- Comprendre GDB
Utilisation de points de contrôle dans GDB
Les points de contrôle sont des marqueurs qui indiquent à GDB d'arrêter l'exécution d'un programme. Les points de surveillance sont associés à des données : pour placer un point de surveillance, il faut spécifier une expression décrivant une variable, plusieurs variables ou une adresse mémoire.
Pour place un point de surveillance pour les données change (écriture) :
(gdb) veille expression
Remplacez expression par une expression qui décrit ce que vous voulez regarder. Pour les variables, expression est égal au nom de la variable.
Pour place un point de surveillance pour les données access (lecture) :
(gdb) rwatch expression
Pour place un point de surveillance pour any l'accès aux données (lecture et écriture) :
(gdb) awatch expression
Pour inspect l'état de tous les points de contrôle et d'arrêt :
(gdb) info br
Pour remove un point de surveillance :
(gdb) supprimer num
Remplacer l'option num par le numéro indiqué par la commande
info br
.
Ressources supplémentaires
- Débogage avec GDB - Définition des points de surveillance
3.2.7. Déboguer des programmes à fourche ou à threads avec GDB
Certains programmes utilisent le forking ou les threads pour obtenir une exécution parallèle du code. Le débogage de plusieurs chemins d'exécution simultanés nécessite des considérations particulières.
Conditions préalables
- Vous devez comprendre les concepts de processus de bifurcation et de threads.
Déboguer des programmes forkés avec GDB
La bifurcation est une situation dans laquelle un programme (parent) crée une copie indépendante de lui-même (child). Les paramètres et commandes suivants permettent d'influencer l'action de GDB en cas de bifurcation :
Le paramètre
follow-fork-mode
détermine si GDB suit le parent ou l'enfant après la fourche.set follow-fork-mode parent
- Après un fork, déboguer le processus parent. C'est l'option par défaut.
set follow-fork-mode child
- Après un fork, déboguer le processus enfant.
show follow-fork-mode
-
Affichage du réglage actuel de
follow-fork-mode
.
Le paramètre
set detach-on-fork
détermine si la GDB garde le contrôle de l'autre processus (non suivi) ou le laisse s'exécuter.set detach-on-fork on
-
Le processus qui n'est pas suivi (en fonction de la valeur de
follow-fork-mode
) est détaché et s'exécute de manière indépendante. Il s'agit de la valeur par défaut. set detach-on-fork off
-
GDB garde le contrôle des deux processus. Le processus qui est suivi (en fonction de la valeur de
follow-fork-mode
) est débogué comme d'habitude, tandis que l'autre est suspendu. show detach-on-fork
-
Affichage du réglage actuel de
detach-on-fork
.
Débogage de programmes threadés avec GDB
GDB a la capacité de déboguer des threads individuels, de les manipuler et de les examiner indépendamment. Pour que GDB n'arrête que le thread examiné, utilisez les commandes set non-stop on
et set target-async on
. Vous pouvez ajouter ces commandes au fichier .gdbinit
. Une fois cette fonctionnalité activée, GDB est prêt à procéder au débogage des threads.
GDB utilise le concept de current thread. Par défaut, les commandes ne s'appliquent qu'au thread en cours.
info threads
-
Affiche une liste de fils de discussion avec leurs numéros
id
etgid
, indiquant le fil de discussion en cours. thread id
-
Définit le fil d'exécution avec l'adresse
id
spécifiée comme le fil d'exécution actuel. thread apply ids command
-
Appliquer la commande
command
à tous les threads listés parids
. L'optionids
est une liste d'identifiants de threads séparés par des espaces. La valeur spécialeall
applique la commande à tous les threads. break location thread id if condition
-
Définir un point d'arrêt à un certain
location
avec un certaincondition
uniquement pour le numéro de threadid
. watch expression thread id
-
Fixer un point de surveillance défini par
expression
uniquement pour le numéro de threadid
. command&
-
Exécutez la commande
command
et revenez immédiatement à l'invite gdb(gdb)
, en poursuivant l'exécution du code en arrière-plan. interrupt
- Arrêter l'exécution en arrière-plan.
Ressources supplémentaires
- Débogage avec GDB - 4.10 Débogage de programmes avec plusieurs threads
- Débogage avec GDB - 4.11 Débogage des fourches
3.3. Enregistrement des interactions avec les applications
Le code exécutable des applications interagit avec le code du système d'exploitation et les bibliothèques partagées. L'enregistrement d'un journal d'activité de ces interactions peut fournir suffisamment d'informations sur le comportement de l'application sans déboguer le code réel de l'application. Par ailleurs, l'analyse des interactions d'une application peut aider à identifier les conditions dans lesquelles un bogue se manifeste.
3.3.1. Outils utiles pour l'enregistrement des interactions avec les applications
Red Hat Enterprise Linux propose plusieurs outils pour analyser les interactions d'une application.
- stresse
L'outil
strace
permet principalement d'enregistrer les appels système (fonctions du noyau) utilisés par une application.-
L'outil
strace
peut fournir un résultat détaillé sur les appels, carstrace
interprète les paramètres et les résultats en connaissant le code du noyau sous-jacent. Les nombres sont transformés en noms de constantes respectifs, les drapeaux combinés par bit sont développés en liste de drapeaux, les pointeurs vers les tableaux de caractères sont déréférencés pour fournir la chaîne de caractères actuelle, et plus encore. La prise en charge des fonctionnalités plus récentes du noyau peut être insuffisante. - Vous pouvez filtrer les appels tracés pour réduire la quantité de données capturées.
-
L'utilisation de
strace
ne nécessite aucune configuration particulière, si ce n'est la mise en place du filtre de journalisation. -
Tracer le code de l'application avec
strace
entraîne un ralentissement significatif de l'exécution de l'application. Par conséquent,strace
n'est pas adapté à de nombreux déploiements de production. Comme alternative, envisagez d'utiliserltrace
ou SystemTap. -
La version de
strace
disponible dans Red Hat Developer Toolset peut également altérer les appels système. Cette capacité est utile pour le débogage.
-
L'outil
- ltrace
L'outil
ltrace
permet d'enregistrer les appels de l'espace utilisateur d'une application vers des objets partagés (bibliothèques dynamiques).-
L'outil
ltrace
permet de tracer les appels à n'importe quelle bibliothèque. - Vous pouvez filtrer les appels tracés pour réduire la quantité de données capturées.
-
L'utilisation de
ltrace
ne nécessite aucune configuration particulière, si ce n'est la mise en place du filtre de journalisation. -
L'outil
ltrace
est léger et rapide, et offre une alternative àstrace
: il est possible de tracer les interfaces respectives dans des bibliothèques telles queglibc
avecltrace
au lieu de tracer les fonctions du noyau avecstrace
. -
Étant donné que
ltrace
ne gère pas un ensemble connu d'appels commestrace
, il ne tente pas d'expliquer les valeurs transmises aux fonctions de la bibliothèque. La sortie deltrace
ne contient que des nombres bruts et des pointeurs. L'interprétation de la sortieltrace
nécessite la consultation des déclarations d'interface des bibliothèques présentes dans la sortie.
NoteDans Red Hat Enterprise Linux 9, un problème connu empêche
ltrace
de tracer les fichiers exécutables du système. Cette limitation ne s'applique pas aux fichiers exécutables créés par les utilisateurs.-
L'outil
- SystemTap
SystemTap est une plateforme d'instrumentation permettant de sonder les processus en cours d'exécution et l'activité du noyau sur le système Linux. SystemTap utilise son propre langage de script pour programmer des gestionnaires d'événements personnalisés.
-
Par rapport à l'utilisation de
strace
etltrace
, la création de scripts d'enregistrement implique plus de travail lors de la phase d'installation initiale. Cependant, les capacités de script étendent l'utilité de SystemTap au-delà de la simple production de journaux. - SystemTap fonctionne en créant et en insérant un module dans le noyau. L'utilisation de SystemTap est efficace et ne crée pas de ralentissement significatif du système ou de l'exécution de l'application en soi.
- SystemTap est accompagné d'une série d'exemples d'utilisation.
-
Par rapport à l'utilisation de
- GDB
Le débogueur GNU (GDB) est principalement destiné au débogage et non à l'enregistrement. Cependant, certaines de ses fonctionnalités le rendent utile même dans le cas où l'interaction d'une application est la principale activité d'intérêt.
- Avec GDB, il est possible de combiner facilement la capture d'un événement d'interaction avec le débogage immédiat du chemin d'exécution qui s'ensuit.
- La GDB est mieux adaptée à l'analyse de la réponse à des événements peu fréquents ou singuliers, après l'identification initiale d'une situation problématique par d'autres outils. L'utilisation de la BDG dans un scénario avec des événements fréquents devient inefficace, voire impossible.
Ressources supplémentaires
3.3.2. Contrôler les appels système d'une application avec strace
L'outil strace
permet de surveiller les appels système (noyau) effectués par une application.
Conditions préalables
-
Vous devez avoir installé
strace
sur le système.
Procédure
- Identifier les appels système à surveiller.
Lancez
strace
et joignez-le au programme.Si le programme que vous voulez surveiller n'est pas en cours d'exécution, lancez
strace
et indiquez l'adresse program:$ strace -fvttTyy -s 256 -e trace=call program
Si le programme est déjà en cours d'exécution, recherchez son identifiant de processus (pid) et attachez-y
strace
:$ ps -C program (...) $ strace -fvttTyy -s 256 -e trace=call -ppid
-
Remplacez call par les appels système à afficher. Vous pouvez utiliser l'option
-e trace=call
plusieurs fois. Si elle n'est pas remplacée,strace
affichera tous les types d'appels système. Voir la page de manuel strace(1) pour plus d'informations. -
Si vous ne souhaitez pas suivre les processus ou les threads qui ont fait l'objet d'une bifurcation, n'utilisez pas l'option
-f
.
L'outil
strace
affiche les appels système effectués par l'application et leurs détails.Dans la plupart des cas, une application et ses bibliothèques effectuent un grand nombre d'appels et la sortie
strace
apparaît immédiatement, si aucun filtre pour les appels système n'est défini.L'outil
strace
se termine lorsque le programme se termine.Pour mettre fin à la surveillance avant que le programme suivi ne se termine, appuyez sur Ctrl C.
-
Si
strace
a démarré le programme, celui-ci se termine en même temps questrace
. -
Si vous avez joint
strace
à un programme déjà en cours d'exécution, le programme se termine en même temps questrace
.
-
Si
Analyser la liste des appels système effectués par l'application.
- Les problèmes d'accès ou de disponibilité des ressources sont signalés dans le journal par des appels renvoyant des erreurs.
- Les valeurs transmises aux appels système et les modèles de séquences d'appels permettent de comprendre les causes du comportement de l'application.
- Si l'application se bloque, les informations importantes se trouvent probablement à la fin du journal.
- Le résultat contient beaucoup d'informations inutiles. Cependant, vous pouvez construire un filtre plus précis pour les appels système qui vous intéressent et répéter la procédure.
Il est avantageux de voir la sortie et de l'enregistrer dans un fichier. Pour ce faire, utilisez la commande tee
:
$ strace ... |& tee your_log_file.log
Ressources supplémentaires
La page du manuel strace(1):
$ man strace
- Comment utiliser strace pour tracer les appels système effectués par une commande ? - Article de la base de connaissances
- Guide de l'utilisateur de Red Hat Developer Toolset - Chapitre strace
3.3.3. Contrôler les appels de fonctions de la bibliothèque d'une application avec ltrace
L'outil ltrace
permet de surveiller les appels d'une application à des fonctions disponibles dans des bibliothèques (objets partagés).
Dans Red Hat Enterprise Linux 9, un problème connu empêche ltrace
de tracer les fichiers exécutables du système. Cette limitation ne s'applique pas aux fichiers exécutables créés par les utilisateurs.
Conditions préalables
-
Vous devez avoir installé
ltrace
sur le système.
Procédure
- Identifiez les bibliothèques et les fonctions qui vous intéressent, si possible.
Lancez
ltrace
et joignez-le au programme.Si le programme que vous souhaitez surveiller n'est pas en cours d'exécution, lancez
ltrace
et indiquez program:$ ltrace -f -l library -e function program
Si le programme est déjà en cours d'exécution, recherchez son identifiant de processus (pid) et attachez-y
ltrace
:$ ps -C program (...) $ ltrace -f -l library -e function program -ppid
Utilisez les options
-e
,-f
et-l
pour filtrer les résultats :-
Fournir les noms des fonctions à afficher sous la forme function. L'option
-e function
peut être utilisée plusieurs fois. Si elle est omise,ltrace
affiche les appels à toutes les fonctions. -
Au lieu de spécifier des fonctions, vous pouvez spécifier des bibliothèques entières avec l'option
-l library
pour spécifier des bibliothèques entières. Cette option se comporte de la même manière que l'option-e function
cette option se comporte de la même manière que l'option -
Si vous ne souhaitez pas suivre les processus ou les threads qui ont fait l'objet d'une bifurcation, n'utilisez pas l'option
-f
.
Voir la page du manuel ltrace(1)_ pour plus d'informations.
-
Fournir les noms des fonctions à afficher sous la forme function. L'option
ltrace
affiche les appels à la bibliothèque effectués par l'application.Dans la plupart des cas, une application effectue un grand nombre d'appels et la sortie
ltrace
s'affiche immédiatement, si aucun filtre n'est défini.ltrace
se termine lorsque le programme se termine.Pour mettre fin à la surveillance avant que le programme suivi ne se termine, appuyez sur ctrl C.
-
Si
ltrace
a démarré le programme, celui-ci se termine en même temps queltrace
. -
Si vous avez joint
ltrace
à un programme déjà en cours d'exécution, le programme se termine en même temps queltrace
.
-
Si
Analyser la liste des appels à la bibliothèque effectués par l'application.
- Si l'application se bloque, les informations importantes se trouvent probablement à la fin du journal.
- Le résultat contient beaucoup d'informations inutiles. Cependant, vous pouvez construire un filtre plus précis et répéter la procédure.
Il est avantageux de voir la sortie et de l'enregistrer dans un fichier. Pour ce faire, utilisez la commande tee
:
$ ltrace ... |& tee your_log_file.log
Ressources supplémentaires
La page du manuel ltrace(1):
$ man ltrace
- Guide de l'utilisateur de Red Hat Developer Toolset - Chapitre ltrace
3.3.4. Contrôler les appels système d'une application avec SystemTap
L'outil SystemTap permet d'enregistrer des gestionnaires d'événements personnalisés pour les événements du noyau. Par rapport à l'outil strace
, il est plus difficile à utiliser mais plus efficace et permet une logique de traitement plus complexe. Un script SystemTap appelé strace.stp
est installé avec SystemTap et fournit une approximation de la fonctionnalité de strace
en utilisant SystemTap.
Conditions préalables
- SystemTap et les paquets de noyau respectifs doivent être installés sur le système.
Procédure
Recherchez l'ID du processus (pid) du processus que vous souhaitez surveiller :
$ ps -aux
Exécutez SystemTap avec le script
strace.stp
:# stap /usr/share/systemtap/examples/process/strace.stp -x pid
La valeur de pid est l'identifiant du processus.
Le script est compilé dans un module du noyau, qui est ensuite chargé. Cela introduit un léger délai entre la saisie de la commande et l'obtention de la sortie.
- Lorsque le processus effectue un appel système, le nom de l'appel et ses paramètres sont imprimés sur le terminal.
-
Le script se termine lorsque le processus se termine ou lorsque vous appuyez sur
Ctrl C
.
3.3.5. Utilisation de GDB pour intercepter les appels système des applications
Le débogueur GNU (GDB) vous permet d'arrêter l'exécution d'un programme dans diverses situations. Pour arrêter l'exécution lorsque le programme effectue un appel système, utilisez une commande GDB catchpoint.
Conditions préalables
- Vous devez comprendre l'utilisation des points d'arrêt GDB.
- GDB doit être attaché au programme.
Procédure
Fixer le point d'inflexion :
(gdb) catch syscall syscall-name
La commande
catch syscall
définit un type spécial de point d'arrêt qui interrompt l'exécution lorsque le programme effectue un appel système.L'option
syscall-name
spécifie le nom de l'appel. Vous pouvez spécifier plusieurs points de capture pour différents appels système. L'omission de l'optionsyscall-name
permet à GDB de s'arrêter sur n'importe quel appel système.Lancer l'exécution du programme.
Si le programme n'a pas commencé à s'exécuter, démarrez-le :
(gdb) r
Si l'exécution du programme est interrompue, reprenez-la :
(gdb) c
- GDB interrompt l'exécution après que le programme a exécuté un appel système spécifié.
Ressources supplémentaires
- Débogage avec GDB - Définition des points de surveillance
3.3.6. Utilisation de GDB pour intercepter la gestion des signaux par les applications
Le débogueur GNU (GDB) vous permet d'arrêter l'exécution dans diverses situations qui surviennent au cours de l'exécution du programme. Pour arrêter l'exécution lorsque le programme reçoit un signal du système d'exploitation, utilisez une commande GDB catchpoint.
Conditions préalables
- Vous devez comprendre l'utilisation des points d'arrêt GDB.
- GDB doit être attaché au programme.
Procédure
Fixer le point d'inflexion :
(gdb) signal de capture signal-type
La commande
catch signal
définit un type spécial de point d'arrêt qui interrompt l'exécution lorsqu'un signal est reçu par le programme. L'optionsignal-type
spécifie le type de signal. Utilisez la valeur spéciale'all'
pour capturer tous les signaux.Laissez le programme s'exécuter.
Si le programme n'a pas commencé à s'exécuter, démarrez-le :
(gdb) r
Si l'exécution du programme est interrompue, reprenez-la :
(gdb) c
- GDB interrompt l'exécution après que le programme a reçu un signal spécifié.
Ressources supplémentaires
- Déboguer avec GDB - 5.1.3 Définir des points d'arrêt
3.4. Débogage d'une application bloquée
Parfois, il n'est pas possible de déboguer une application directement. Dans ce cas, vous pouvez collecter des informations sur l'application au moment de son arrêt et les analyser par la suite.
3.4.1. Core dumps : ce qu'ils sont et comment les utiliser
Un core dump est une copie d'une partie de la mémoire de l'application au moment où l'application a cessé de fonctionner, stockée au format ELF. Il contient toutes les variables internes et la pile de l'application, ce qui permet d'inspecter l'état final de l'application. Lorsqu'il est complété par le fichier exécutable correspondant et les informations de débogage, il est possible d'analyser un fichier core dump avec un débogueur d'une manière similaire à l'analyse d'un programme en cours d'exécution.
Le noyau du système d'exploitation Linux peut enregistrer des core dumps automatiquement, si cette fonctionnalité est activée. Vous pouvez également envoyer un signal à toute application en cours d'exécution pour qu'elle génère un core dump, quel que soit son état actuel.
Certaines limites peuvent affecter la capacité à générer un core dump. Pour connaître les limites actuelles :
$ ulimit -a
3.4.2. Enregistrement des plantages d'application avec les core dumps
Pour enregistrer les pannes d'application, configurez l'enregistrement de la vidange du noyau et ajoutez des informations sur le système.
Procédure
Pour activer les vidages de noyau, assurez-vous que le fichier
/etc/systemd/system.conf
contient les lignes suivantes :DumpCore=yes DefaultLimitCORE=infinity
Vous pouvez également ajouter des commentaires décrivant si ces paramètres étaient présents auparavant, et quelles étaient les valeurs précédentes. Cela vous permettra d'annuler ces modifications ultérieurement, si nécessaire. Les commentaires sont des lignes commençant par le caractère
#
.La modification du fichier nécessite un accès de niveau administrateur.
Appliquer la nouvelle configuration :
# systemctl daemon-reexec
Supprimer les limites de taille du core dump :
# ulimit -c unlimited
Pour inverser ce changement, exécutez la commande avec la valeur
0
au lieu deunlimited
.Installez le paquet
sos
qui fournit l'utilitairesosreport
pour collecter des informations sur le système :# dnf install sos
-
Lorsqu'une application se bloque, un core dump est généré et traité par
systemd-coredump
. Créer un rapport SOS pour fournir des informations supplémentaires sur le système :
# sosreport
Cette opération crée une archive
.tar
contenant des informations sur votre système, telles que des copies des fichiers de configuration.Localiser et exporter le core dump :
$ coredumpctl list executable-name $ coredumpctl dump executable-name > /path/to/file-for-export
Si l'application s'est écrasée plusieurs fois, la sortie de la première commande énumère davantage de vidages de noyau capturés. Dans ce cas, construisez pour la deuxième commande une requête plus précise en utilisant les autres informations. Voir la page de manuel coredumpctl(1) pour plus de détails.
Transférez le core dump et le rapport SOS sur l'ordinateur où le débogage aura lieu. Transférez également le fichier exécutable, s'il est connu.
ImportantLorsque le fichier exécutable n'est pas connu, l'analyse ultérieure du fichier central permet de l'identifier.
- Facultatif : Supprimez le core dump et le rapport SOS après les avoir transférés, afin de libérer de l'espace disque.
Ressources supplémentaires
- Introduction à systemd dans le document Configuring basic system settings
- Comment activer les vidages de fichiers centraux lorsqu'une application se bloque ou qu'il y a des erreurs de segmentation - un article de la base de connaissances
- Qu'est-ce qu'un sosreport et comment en créer un dans Red Hat Enterprise Linux 4.6 et versions ultérieures ? - un article de la base de connaissances
3.4.3. Inspecter les états d'arrêt d'une application à l'aide de core dumps
Conditions préalables
- Vous devez disposer d'un fichier core dump et d'un rapport sos du système où la panne s'est produite.
- GDB et elfutils doivent être installés sur votre système.
Procédure
Pour identifier le fichier exécutable où le crash s'est produit, exécutez la commande
eu-unstrip
avec le fichier core dump :$ eu-unstrip -n --core=./core.9814 0x400000+0x207000 2818b2009547f780a5639c904cded443e564973e@0x400284 /usr/bin/sleep /usr/lib/debug/bin/sleep.debug [exe] 0x7fff26fff000+0x1000 1e2a683b7d877576970e4275d41a6aaec280795e@0x7fff26fff340 . - linux-vdso.so.1 0x35e7e00000+0x3b6000 374add1ead31ccb449779bc7ee7877de3377e5ad@0x35e7e00280 /usr/lib64/libc-2.14.90.so /usr/lib/debug/lib64/libc-2.14.90.so.debug libc.so.6 0x35e7a00000+0x224000 3ed9e61c2b7e707ce244816335776afa2ad0307d@0x35e7a001d8 /usr/lib64/ld-2.14.90.so /usr/lib/debug/lib64/ld-2.14.90.so.debug ld-linux-x86-64.so.2
La sortie contient les détails de chaque module sur une ligne, séparés par des espaces. Les informations sont listées dans cet ordre :
- L'adresse mémoire où le module a été mappé
- L'identifiant de construction du module et l'endroit où il a été trouvé dans la mémoire
-
Le nom du fichier exécutable du module, affiché sous la forme
-
s'il est inconnu, ou sous la forme.
si le module n'a pas été chargé à partir d'un fichier -
La source des informations de débogage, affichée sous la forme d'un nom de fichier lorsqu'elle est disponible, sous la forme de
.
lorsqu'elle est contenue dans le fichier exécutable lui-même, ou sous la forme de-
lorsqu'elle n'est pas présente du tout -
Le nom de la bibliothèque partagée (soname) ou
[exe]
pour le module principal
Dans cet exemple, les détails importants sont le nom du fichier
/usr/bin/sleep
et le build-id2818b2009547f780a5639c904cded443e564973e
sur la ligne contenant le texte[exe]
. Grâce à ces informations, vous pouvez identifier le fichier exécutable nécessaire à l'analyse du core dump.Obtenir le fichier exécutable qui s'est écrasé.
- Si possible, copiez-le à partir du système où la panne s'est produite. Utilisez le nom du fichier extrait du fichier principal.
Vous pouvez également utiliser un fichier exécutable identique sur votre système. Chaque fichier exécutable construit sur Red Hat Enterprise Linux contient une note avec une valeur build-id unique. Déterminez le build-id des fichiers exécutables pertinents disponibles localement :
$ eu-readelf -n executable_file
Utilisez ces informations pour faire correspondre le fichier exécutable du système distant avec votre copie locale. Le build-id du fichier local et le build-id listé dans le core dump doivent correspondre.
-
Enfin, si l'application est installée à partir d'un paquetage RPM, vous pouvez obtenir le fichier exécutable à partir du paquetage. Utilisez la sortie de
sosreport
pour trouver la version exacte du paquetage requis.
- Obtenez les bibliothèques partagées utilisées par le fichier exécutable. Utilisez les mêmes étapes que pour le fichier exécutable.
- Si l'application est distribuée sous forme de paquetage, chargez le fichier exécutable dans GDB, afin d'afficher des indications sur les paquets debuginfo manquants. Pour plus de détails, voir Section 3.1.4, « Obtenir les paquets d'informations de débogage pour une application ou une bibliothèque à l'aide de GDB ».
Pour examiner le fichier core en détail, chargez le fichier exécutable et le fichier core dump avec GDB :
$ gdb -e executable_file -c core_file
D'autres messages concernant les fichiers manquants et les informations de débogage vous aident à identifier ce qui manque pour la session de débogage. Revenez à l'étape précédente si nécessaire.
Si les informations de débogage de l'application sont disponibles sous la forme d'un fichier et non d'un paquet, chargez ce fichier dans GDB à l'aide de la commande
symbol-file
:(gdb) fichier-symbole program.debug
Remplacez program.debug par le nom réel du fichier.
NoteIl n'est peut-être pas nécessaire d'installer les informations de débogage pour tous les fichiers exécutables contenus dans le core dump. La plupart de ces fichiers exécutables sont des bibliothèques utilisées par le code de l'application. Ces bibliothèques peuvent ne pas contribuer directement au problème que vous analysez et vous n'avez pas besoin d'inclure les informations de débogage les concernant.
Utilisez les commandes GDB pour inspecter l'état de l'application au moment où elle s'est arrêtée. Voir Inspection de l'état interne de l'application avec GDB.
NoteLors de l'analyse d'un fichier core, GDB n'est pas attaché à un processus en cours d'exécution. Les commandes de contrôle de l'exécution n'ont aucun effet.
Ressources supplémentaires
- Débogage avec GDB - 2.1.1 Choix des fichiers
- Débogage avec GDB - 18.1 Commandes pour spécifier des fichiers
- Débogage avec GDB - 18.3 Informations de débogage dans des fichiers séparés
3.4.4. Créer et accéder à un core dump avec coredumpctl
L'outil coredumpctl
de systemd
peut considérablement rationaliser le travail avec les core dumps sur la machine où le crash s'est produit. Cette procédure explique comment capturer un core dump d'un processus qui ne répond pas.
Conditions préalables
Le système doit être configuré pour utiliser
systemd-coredump
pour la gestion du core dump. Pour vérifier que c'est bien le cas :$ sysctl kernel.core_pattern
La configuration est correcte si la sortie commence par ce qui suit :
kernel.core_pattern = |/usr/lib/systemd/systemd-coredump
Procédure
Trouver le PID du processus suspendu, sur la base d'une partie connue du nom du fichier exécutable :
$ pgrep -a executable-name-fragment
Cette commande produira une ligne sous la forme
PID command-line
Utilisez la valeur command-line pour vérifier que le site PID appartient au processus prévu.
Par exemple :
$ pgrep -a bc 5459 bc
Envoyer un signal d'abandon au processus :
# kill -ABRT PID
Vérifiez que le noyau a été capturé par
coredumpctl
:$ coredumpctl list PID
Par exemple :
$ coredumpctl list 5459 TIME PID UID GID SIG COREFILE EXE Thu 2019-11-07 15:14:46 CET 5459 1000 1000 6 present /usr/bin/bc
Examiner plus avant ou utiliser le fichier de base selon les besoins.
Vous pouvez spécifier le core dump par PID et d'autres valeurs. Voir la page de manuel coredumpctl(1) pour plus de détails.
Pour afficher les détails du fichier principal :
$ coredumpctl info PID
Pour charger le fichier core dans le débogueur GDB :
$ coredumpctl debug PID
En fonction de la disponibilité des informations de débogage, GDB suggérera des commandes à exécuter, telles que :
Missing separate debuginfos, use: dnf debuginfo-install bc-1.07.1-5.el8.x86_64
Pour plus de détails sur ce processus, voir Obtenir des paquets d'informations de débogage pour une application ou une bibliothèque à l'aide de GDB.
Pour exporter le fichier de base en vue d'un traitement ultérieur ailleurs :
$ coredumpctl dump PID > /path/to/file_for_export
Remplacez /path/to/file_for_export par le fichier dans lequel vous souhaitez placer le core dump.
3.4.5. Vider la mémoire du processus avec gcore
Le processus de débogage par vidage du noyau permet d'analyser l'état du programme hors ligne. Dans certains cas, vous pouvez utiliser ce processus avec un programme toujours en cours d'exécution, par exemple lorsqu'il est difficile d'accéder à l'environnement avec le processus. Vous pouvez utiliser la commande gcore
pour vidanger la mémoire de n'importe quel processus en cours d'exécution.
Conditions préalables
- Vous devez comprendre ce que sont les core dumps et comment ils sont créés.
- GDB doit être installé sur le système.
Procédure
Trouvez l'identifiant du processus (pid). Utilisez des outils tels que
ps
,pgrep
, ettop
:$ ps -C some-program
Vider la mémoire de ce processus :
$ gcore -o filename pid
Cette opération crée un fichier filename et y déverse la mémoire du processus. Pendant que la mémoire est vidée, l'exécution du processus est interrompue.
- Une fois le vidage du noyau terminé, le processus reprend son cours normal.
Créer un rapport SOS pour fournir des informations supplémentaires sur le système :
# sosreport
Cette opération crée une archive tar contenant des informations sur votre système, telles que des copies des fichiers de configuration.
- Transférez le fichier exécutable du programme, le core dump et le rapport SOS sur l'ordinateur où le débogage aura lieu.
- Facultatif : Supprimez le core dump et le rapport SOS après les avoir transférés, afin de libérer de l'espace disque.
Ressources supplémentaires
- Comment obtenir un fichier core sans redémarrer une application ? - Article de la base de connaissances
3.4.6. Vider la mémoire d'un processus protégé avec GDB
Vous pouvez marquer la mémoire des processus comme ne devant pas être vidée. Cela permet d'économiser des ressources et d'assurer une sécurité supplémentaire lorsque la mémoire du processus contient des données sensibles : par exemple, dans les applications bancaires ou comptables ou sur des machines virtuelles entières. Les vidanges du noyau (kdump
) et les vidanges manuelles du noyau (gcore
, GDB) ne vidangent pas la mémoire marquée de cette manière.
Dans certains cas, vous devez extraire tout le contenu de la mémoire du processus sans tenir compte de ces protections. Cette procédure montre comment procéder à l'aide du débogueur GDB.
Conditions préalables
- Vous devez comprendre ce que sont les core dumps.
- GDB doit être installé sur le système.
- GDB doit déjà être attaché au processus avec la mémoire protégée.
Procédure
Configurer GDB pour qu'il ignore les paramètres du fichier
/proc/PID/coredump_filter
:(gdb) set use-coredump-filter off
Configure GDB pour qu'il ignore le drapeau de page mémoire
VM_DONTDUMP
:(gdb) set dump-excluded-mappings on
Vider la mémoire :
(gdb) gcore core-file
Remplacez core-file par le nom du fichier dans lequel vous voulez vider la mémoire.
Ressources supplémentaires
- Débogage avec GDB - Comment produire un fichier Core à partir de votre programme
3.5. Changements de compatibilité dans GDB
La version de GDB fournie dans Red Hat Enterprise Linux 9 contient un certain nombre de changements qui rompent la compatibilité. Les sections suivantes fournissent plus de détails sur ces changements.
Commandes
La commande
gdb -P python-script.py
n'est plus prise en charge.Utilisez plutôt la commande
gdb -ex 'source python-script.py'
.La commande
gdb COREFILE
n'est plus prise en charge.Utilisez plutôt la commande
gdb EXECUTABLE --core COREFILE
pour charger l'exécutable spécifié dans le fichier core.GDB stylise désormais la sortie par défaut.
Cette nouvelle modification peut perturber les scripts qui essaient d'analyser la sortie de GDB. Utilisez la commande
gdb -ex 'set style enabled off'
pour désactiver le style dans les scripts.Les commandes définissent désormais la syntaxe des symboles en fonction de la langue.
Les commandes
info functions
,info types
,info variables
etrbreak
définissent désormais la syntaxe des entités en fonction de la langue choisie par la commandeset language
. En choisissantset language auto
, GDB choisira automatiquement la langue des entités affichées.Les commandes
set print raw frame-arguments
etshow print raw frame-arguments
sont obsolètes.Ces commandes sont remplacées par les commandes
set print raw-frame-arguments
etshow print raw-frame-arguments
. Les anciennes commandes pourront être supprimées dans les versions futures.Les commandes suivantes de l'interface utilisateur sont désormais sensibles à la casse :
-
focus
-
winheight
-
-
-
-
>
-
<
-
Les commandes
help
etapropos
n'affichent plus qu'une seule fois les informations relatives à la commande.Ces commandes n'affichent plus qu'une seule fois la documentation d'une commande, même si cette commande a un ou plusieurs alias. Ces commandes affichent désormais le nom de la commande, puis tous ses alias, et enfin la description de la commande.
L'interprète MI
La version par défaut de l'interpréteur MI est désormais la version 3.
L'édition d'informations sur les points d'arrêt multi-locaux (syntaxiquement incorrecte dans MI 2) a été modifiée dans MI 3, ce qui affecte les commandes et événements suivants :
-
-break-insert
-
-break-info
-
=breakpoint-created
-
=breakpoint-modified
Utilisez la commande
-fix-multi-location-breakpoint-output
pour activer ce comportement avec les versions précédentes de MI.-
API Python
Les symboles suivants sont désormais obsolètes :
-
gdb.SYMBOL_VARIABLES_DOMAIN
-
gdb.SYMBOL_FUNCTIONS_DOMAIN
-
gdb.SYMBOL_TYPES_DOMAIN
-
-
Le type
gdb.Value
dispose d'un nouveau constructeur, qui est utilisé pour construire ungdb.Value
à partir d'un objet tampon Python et d'ungdb.Type
. -
Les informations sur les trames imprimées par le code Python de filtrage des trames sont désormais cohérentes avec ce que la commande
backtrace
imprime lorsqu'il n'y a pas de filtres, ou lorsque l'option-no-filters
de la commandebacktrace
est utilisée.
Chapitre 4. Outils supplémentaires pour le développement
4.1. Utilisation de la boîte à outils GCC
4.1.1. Qu'est-ce que la boîte à outils GCC ?
Red Hat Enterprise Linux 9 poursuit la prise en charge de GCC Toolset, un flux d'applications contenant des versions plus récentes d'outils de développement et d'analyse des performances. GCC Toolset est similaire à Red Hat Developer Toolset pour RHEL 7.
GCC Toolset est disponible en tant que flux d'application sous la forme d'une collection de logiciels dans le référentiel AppStream
. GCC Toolset est entièrement pris en charge dans le cadre des accords de niveau d'abonnement à Red Hat Enterprise Linux, est fonctionnellement complet et est destiné à une utilisation en production. Les applications et les bibliothèques fournies par GCC Toolset ne remplacent pas les versions du système Red Hat Enterprise Linux, ne les annulent pas et ne deviennent pas automatiquement des choix par défaut ou préférés. En utilisant un cadre appelé collections de logiciels, un ensemble supplémentaire d'outils de développement est installé dans le répertoire /opt/
et est explicitement activé par l'utilisateur à la demande à l'aide de l'utilitaire scl
. Sauf indication contraire pour des outils ou des fonctionnalités spécifiques, le jeu d'outils GCC est disponible pour toutes les architectures prises en charge par Red Hat Enterprise Linux.
4.1.2. Installation du jeu d'outils GCC
L'installation de GCC Toolset sur un système permet d'installer les principaux outils et toutes les dépendances nécessaires. Notez que certaines parties du jeu d'outils ne sont pas installées par défaut et doivent être installées séparément.
Procédure
Pour installer la version du jeu d'outils GCC N:
# dnf install gcc-toolset-N
4.1.3. Installation de paquets individuels à partir du GCC Toolset
Pour n'installer que certains outils du GCC Toolset au lieu de l'ensemble du jeu d'outils, listez les paquets disponibles et installez ceux qui sont sélectionnés avec l'outil de gestion des paquets dnf
. Cette procédure est également utile pour les paquets qui ne sont pas installés par défaut avec le jeu d'outils.
Procédure
Liste des paquets disponibles dans la version du jeu d'outils GCC N:
$ dnf list available gcc-toolset-N-\*
Pour installer l'un de ces paquets :
# dnf install package_name
Remplacez package_name par une liste de paquets à installer, séparés par des espaces. Par exemple, pour installer les paquets
gcc-toolset-9-gdb-gdbserver
etgcc-toolset-9-gdb-doc
:# dnf install gcc-toolset-9-gdb-gdbserver gcc-toolset-9-gdb-doc
4.1.4. Désinstallation de GCC Toolset
Pour supprimer GCC Toolset de votre système, désinstallez-le à l'aide de l'outil de gestion des paquets dnf
.
Procédure
Pour désinstaller GCC Toolset version N:
# dnf remove gcc-toolset-N\N- \N- \N- \N- \N*
4.1.5. Exécution d'un outil à partir de la boîte à outils GCC
Pour exécuter un outil du GCC Toolset, utilisez l'utilitaire scl
.
Procédure
Pour exécuter un outil de la version du jeu d'outils GCC N:
$ scl enable gcc-toolset-N tool
4.1.6. Lancer une session shell avec GCC Toolset
GCC Toolset permet d'exécuter une session shell dans laquelle les versions des outils GCC Toolset sont utilisées à la place des versions système de ces outils, sans utiliser explicitement la commande scl
. Cette fonction est utile lorsque vous devez lancer les outils de manière interactive à plusieurs reprises, par exemple lors de la configuration ou du test d'une installation de développement.
Procédure
Pour lancer une session shell dans laquelle les versions des outils du Toolset GCC N remplacent les versions système de ces outils :
$ scl enable gcc-toolset-N bash
4.1.7. Ressources supplémentaires
4.2. Jeu d'outils GCC 12
Ce chapitre fournit des informations spécifiques à la version 12 du Toolset GCC et aux outils contenus dans cette version.
4.2.1. Outils et versions fournis par le GCC Toolset 12
Le jeu d'outils GCC 12 fournit les outils et versions suivants :
Tableau 4.1. Versions d'outils dans le Toolset 12 de GCC
Nom | Version | Description |
---|---|---|
CCG | 12.1.1 | Une suite de compilateurs portables prenant en charge le C, le C , et le Fortran. |
GDB | 11.2 | Un débogueur en ligne de commande pour les programmes écrits en C, C , et Fortran. |
binutils | 2.38 | Une collection d'outils binaires et d'autres utilitaires pour inspecter et manipuler les fichiers objets et les binaires. |
dwz | 0.14 | Outil permettant d'optimiser la taille des informations de débogage DWARF contenues dans les bibliothèques partagées ELF et les exécutables ELF. |
annobin | 10.76 | Un outil de vérification de la sécurité de la construction. |
4.2.2. Compatibilité avec le langage C dans le jeu d'outils GCC 12
Les informations de compatibilité présentées ici ne s'appliquent qu'au GCC du GCC Toolset 12.
Le compilateur GCC du GCC Toolset peut utiliser les normes C suivantes :
- C 14
Cette norme linguistique est disponible dans le jeu d'outils GCC 12.
L'utilisation de la version du langage C 14 est possible lorsque tous les objets C compilés avec le drapeau correspondant ont été construits à l'aide de la version 6 ou ultérieure de GCC.
- C 11
Cette norme linguistique est disponible dans le jeu d'outils GCC 12.
L'utilisation de la version du langage C 11 est possible lorsque tous les objets C compilés avec le drapeau correspondant ont été construits à l'aide de GCC version 5 ou ultérieure.
- C 98
- Cette norme de langage est disponible dans GCC Toolset 12. Les binaires, les bibliothèques partagées et les objets construits à l'aide de cette norme peuvent être librement mélangés, qu'ils soient construits avec GCC à partir de GCC Toolset, Red Hat Developer Toolset, et RHEL 5, 6, 7 et 8.
- C 17
Cette norme linguistique est disponible dans le jeu d'outils GCC 12.
Il s'agit de la norme de langage par défaut pour GCC Toolset 12, avec les extensions GNU, ce qui équivaut à l'utilisation explicite de l'option
-std=gnu 17
.L'utilisation de la version du langage C 17 est possible lorsque tous les objets C compilés avec le drapeau correspondant ont été construits à l'aide de la version 10 ou ultérieure de GCC.
- C 20 et C 23
Ce standard de langage n'est disponible dans GCC Toolset 12 qu'en tant que capacité expérimentale, instable et non supportée. En outre, la compatibilité des objets, des fichiers binaires et des bibliothèques construits à l'aide de ce standard ne peut être garantie.
Pour activer la prise en charge du C 20, ajoutez l'option de ligne de commande
-std=c 20
à votre ligne de commande g.Pour activer la prise en charge du C 23, ajoutez l'option de ligne de commande
-std=c 23
à votre ligne de commande g.
Toutes les normes de langage sont disponibles à la fois dans la variante conforme à la norme et avec les extensions GNU.
Lorsque l'on mélange des objets construits avec GCC Toolset et d'autres construits avec la chaîne d'outils RHEL (en particulier les fichiers .o
ou .a
), la chaîne d'outils GCC Toolset doit être utilisée pour toute liaison. Cela permet de s'assurer que toutes les nouvelles fonctionnalités des bibliothèques fournies uniquement par GCC Toolset sont résolues au moment de l'établissement des liens.
4.2.3. Spécificités de GCC dans GCC Toolset 12
Liaison statique des bibliothèques
Certaines fonctionnalités plus récentes de la bibliothèque sont liées statiquement dans les applications construites avec GCC Toolset pour prendre en charge l'exécution sur plusieurs versions de Red Hat Enterprise Linux. Cela crée un risque de sécurité mineur supplémentaire car les errata standard de Red Hat Enterprise Linux ne modifient pas ce code. Si les développeurs doivent reconstruire leurs applications en raison de ce risque, Red Hat le communiquera par le biais d'un erratum de sécurité.
En raison de ce risque de sécurité supplémentaire, il est vivement conseillé aux développeurs de ne pas lier statiquement l'ensemble de leur application pour les mêmes raisons.
Spécifier les bibliothèques après les fichiers objets lors de l'établissement des liens
Dans GCC Toolset, les bibliothèques sont liées à l'aide de scripts d'édition de liens qui peuvent spécifier certains symboles par le biais d'archives statiques. Ceci est nécessaire pour assurer la compatibilité avec plusieurs versions de Red Hat Enterprise Linux. Cependant, les scripts de l'éditeur de liens utilisent les noms des fichiers d'objets partagés respectifs. Par conséquent, l'éditeur de liens utilise des règles de gestion des symboles différentes de celles prévues et ne reconnaît pas les symboles requis par les fichiers objets lorsque l'option ajoutant la bibliothèque est spécifiée avant les options spécifiant les fichiers objets :
$ scl enable gcc-toolset-12 'gcc -lsomelib objfile.o'
L'utilisation d'une bibliothèque du GCC Toolset de cette manière entraîne le message d'erreur de l'éditeur de liens undefined reference to symbol
. Pour éviter ce problème, suivez la pratique standard d'édition de liens et spécifiez l'option ajoutant la bibliothèque après les options spécifiant les fichiers objets :
$ scl enable gcc-toolset-12 'gcc objfile.o -lsomelib'
Notez que cette recommandation s'applique également à l'utilisation de la version de base de Red Hat Enterprise Linux de GCC.
4.2.4. Spécificités de binutils dans GCC Toolset 12
Liaison statique des bibliothèques
Certaines fonctionnalités plus récentes de la bibliothèque sont liées statiquement dans les applications construites avec GCC Toolset pour prendre en charge l'exécution sur plusieurs versions de Red Hat Enterprise Linux. Cela crée un risque de sécurité mineur supplémentaire car les errata standard de Red Hat Enterprise Linux ne modifient pas ce code. Si les développeurs doivent reconstruire leurs applications en raison de ce risque, Red Hat le communiquera par le biais d'un erratum de sécurité.
En raison de ce risque de sécurité supplémentaire, il est vivement conseillé aux développeurs de ne pas lier statiquement l'ensemble de leur application pour les mêmes raisons.
Spécifier les bibliothèques après les fichiers objets lors de l'établissement des liens
Dans GCC Toolset, les bibliothèques sont liées à l'aide de scripts d'édition de liens qui peuvent spécifier certains symboles par le biais d'archives statiques. Ceci est nécessaire pour assurer la compatibilité avec plusieurs versions de Red Hat Enterprise Linux. Cependant, les scripts de l'éditeur de liens utilisent les noms des fichiers d'objets partagés respectifs. Par conséquent, l'éditeur de liens utilise des règles de gestion des symboles différentes de celles prévues et ne reconnaît pas les symboles requis par les fichiers objets lorsque l'option ajoutant la bibliothèque est spécifiée avant les options spécifiant les fichiers objets :
$ scl enable gcc-toolset-12 'ld -lsomelib objfile.o'
L'utilisation d'une bibliothèque du GCC Toolset de cette manière entraîne le message d'erreur de l'éditeur de liens undefined reference to symbol
. Pour éviter ce problème, suivez la pratique d'édition de liens standard et spécifiez l'option ajoutant la bibliothèque après les options spécifiant les fichiers objets :
$ scl enable gcc-toolset-12 'ld objfile.o -lsomelib'
Notez que cette recommandation s'applique également à l'utilisation de la version de base de Red Hat Enterprise Linux de binutils.
4.2.5. Spécificités de annobin dans GCC Toolset 12
Dans certaines circonstances, en raison d'un problème de synchronisation entre annobin
et gcc
dans GCC Toolset 12, votre compilation peut échouer avec un message d'erreur qui ressemble à ce qui suit :
cc1: fatal error: inaccessible plugin file
opt/rh/gcc-toolset-12/root/usr/lib/gcc/architecture-linux-gnu/12/plugin/gcc-annobin.so
expanded from short plugin name gcc-annobin: No such file or directory
Pour contourner le problème, créez un lien symbolique dans le répertoire du plugin du fichier annobin.so
vers le fichier gcc-annobin.so
:
# cd /opt/rh/gcc-toolset-12/root/usr/lib/gcc/architecture-linux-gnu/12/plugin
# ln -s annobin.so gcc-annobin.so
Remplacez architecture par l'architecture que vous utilisez dans votre système :
-
aarch64
-
i686
-
ppc64le
-
s390x
-
x86_64
4.3. Utilisation de l'image conteneur du jeu d'outils GCC
Seule l'image conteneur de GCC Toolset 12 est prise en charge. Les images conteneur des versions antérieures de GCC Toolset sont obsolètes.
Les composants du GCC Toolset 12 sont disponibles dans l'image du conteneur GCC Toolset 12 Toolchain.
L'image du conteneur GCC Toolset est basée sur l'image de base rhel9
et est disponible pour toutes les architectures prises en charge par RHEL 9 :
- Architectures AMD et Intel 64 bits
- L'architecture ARM 64 bits
- IBM Power Systems, Little Endian
- iBM Z 64 bits
4.3.1. Contenu de l'image du conteneur du jeu d'outils GCC
Les versions des outils fournies dans l'image du conteneur GCC Toolset 12 correspondent aux versions des composants de GCC Toolset 12.
Contenu de la chaîne d'outils du jeu d'outils GCC 12
L'image rhel8/gcc-toolset-12-toolchain
fournit le compilateur GCC, le débogueur GDB et d'autres outils de développement. L'image du conteneur se compose des éléments suivants :
Composant | Paquet |
---|---|
| gcc-toolset-12-gcc |
| gcc-toolset-12-gcc-c |
| gcc-toolset-12-gcc-gfortran |
| gcc-toolset-12-gdb |
Ressources supplémentaires
- Pour utiliser les composants du GCC Toolset sur RHEL 7, utilisez Red Hat Developer Toolset qui fournit des outils de développement similaires pour les utilisateurs de RHEL 7 - Guide d'utilisation de Red Hat Developer Toolset.
- Instructions sur l'utilisation de l'image de conteneur Red Hat Developer Toolset sur RHEL 7 - Red Hat Developer Toolset images.
4.3.2. Accéder à l'image conteneur du GCC Toolset et l'exécuter
La section suivante décrit comment accéder à l'image conteneur du jeu d'outils GCC et l'exécuter.
Conditions préalables
- Podman est installé.
Procédure
Accédez au Red Hat Container Registry à l'aide de vos identifiants du portail client :
$ podman login registry.redhat.io Username: username Password: ********
Extrayez l'image du conteneur dont vous avez besoin en exécutant la commande correspondante en tant que root :
# podman pull registry.redhat.io/rhel9/gcc-toolset-12-toolchain
NoteVous pouvez également configurer votre système pour travailler avec des conteneurs en tant qu'utilisateur non rooté. Pour plus de détails, voir Configuration de conteneurs sans racine.
Facultatif : Vérifiez que l'extraction a réussi en exécutant une commande qui répertorie toutes les images de conteneurs sur votre système local :
# podman images
Exécuter un conteneur en lançant un shell bash à l'intérieur d'un conteneur :
# podman run -it image_name /bin/bash
L'option
-i
crée une session interactive ; sans cette option, l'interpréteur de commandes s'ouvre et se ferme instantanément.L'option
-t
ouvre une session de terminal ; sans cette option, vous ne pouvez rien saisir dans l'interpréteur de commandes.
Ressources supplémentaires
- Construire, exécuter et gérer des conteneurs Linux sur RHEL 9
- Un article du blog de Red Hat - Understanding root inside and outside a container (Comprendre la racine à l'intérieur et à l'extérieur d'un conteneur)
- Entrées dans le Red Hat Container Registry - Images du conteneur GCC Toolset
4.3.3. Exemple : Utilisation de l'image conteneur de la chaîne d'outils GCC Toolset 12
Cet exemple montre comment extraire et commencer à utiliser l'image conteneur GCC Toolset 12 Toolchain.
Conditions préalables
- Podman est installé.
Procédure
Accédez au Red Hat Container Registry à l'aide de vos identifiants du portail client :
$ podman login registry.redhat.io Username: username Password: ********
Tirer l'image du conteneur en tant que root :
# podman pull registry.redhat.io/rhel9/gcc-toolset-12-toolchain
Lancer l'image du conteneur avec un shell interactif en tant que root :
# podman run -it registry.redhat.io/rhel9/gcc-toolset-12-toolchain /bin/bash
Exécutez les outils de la boîte à outils GCC comme prévu. Par exemple, pour vérifier la version du compilateur
gcc
, exécutez :bash-4.4$ gcc -v ... gcc version 12.1.1 20220628 (Red Hat 12.1.1-3) (GCC)
Pour lister tous les paquets fournis dans le conteneur, exécutez :
bash-4.4$ rpm -qa
4.4. Outils de compilation
RHEL 9 fournit les ensembles d'outils de compilation suivants en tant que flux d'applications :
- LLVM Toolset fournit le cadre d'infrastructure du compilateur LLVM, le compilateur Clang pour les langages C et C, le débogueur LLDB et les outils connexes pour l'analyse du code.
-
Rust Toolset fournit le compilateur du langage de programmation Rust
rustc
, l'outil de construction et le gestionnaire de dépendancescargo
, le plugincargo-vendor
et les bibliothèques nécessaires. -
Go Toolset fournit les outils et les bibliothèques du langage de programmation Go. Go est également connu sous le nom de
golang
.
Pour plus de détails et d'informations sur l'utilisation, consultez les guides d'utilisation des jeux d'outils du compilateur sur la page Red Hat Developer Tools.
4.5. Le projet Annobin
Le projet Annobin est une implémentation du projet de spécification Watermark. Le projet de spécification Watermark vise à ajouter des marqueurs aux objets ELF (Executable and Linkable Format) afin de déterminer leurs propriétés. Le projet Annobin se compose du plugin annobin
et du programme annockeck
.
Le plugin annobin
analyse la ligne de commande de GNU Compiler Collection (GCC), l'état de la compilation et le processus de compilation, et génère les notes ELF. Les notes ELF enregistrent la manière dont le binaire a été construit et fournissent des informations permettant au programme annocheck
d'effectuer des vérifications de renforcement de la sécurité.
Le vérificateur de renforcement de la sécurité fait partie du programme annocheck
et est activé par défaut. Il vérifie les fichiers binaires pour déterminer si le programme a été construit avec les options de renforcement de la sécurité nécessaires et s'il a été compilé correctement. annocheck
est capable d'analyser de manière récursive les répertoires, les archives et les paquets RPM à la recherche de fichiers objets ELF.
Les fichiers doivent être au format ELF. annocheck
ne gère aucun autre type de fichier binaire.
La section suivante décrit comment
-
Utiliser le plugin
annobin
-
Utiliser le programme
annocheck
-
Supprimer les notes redondantes de
annobin
4.5.1. Utiliser le plugin annobin
La section suivante décrit comment
-
Activer le plugin
annobin
-
Transmettre des options au plugin
annobin
4.5.1.1. Activation du plugin annobin
La section suivante décrit comment activer le plugin annobin
via gcc
et via clang
.
Procédure
Pour activer le plugin
annobin
avecgcc
, utilisez :$ gcc -fplugin=annobin
Si
gcc
ne trouve pas le pluginannobin
, utilisez :$ gcc -iplugindir=/path/to/directory/containing/annobin/
Remplacez /path/to/directory/containing/annobin/ par le chemin absolu vers le répertoire qui contient
annobin
.Pour trouver le répertoire contenant le plugin
annobin
, utilisez :$ gcc --print-file-name=plugin
Pour activer le plugin
annobin
avecclang
, utilisez :$ clang -fplugin=/path/to/directory/containing/annobin/
Remplacez /path/to/directory/containing/annobin/ par le chemin absolu vers le répertoire qui contient
annobin
.
4.5.1.2. Passer des options au plugin annobin
La section suivante décrit comment transmettre des options au plugin annobin
via gcc
et via clang
.
Procédure
Pour passer des options au plugin
annobin
avecgcc
, utilisez :gcc -fplugin=annobin -fplugin-arg-annobin-option file-name
Remplacez option par les arguments de la ligne de commande
annobin
et remplacez file-name par le nom du fichier.Exemple :
Pour afficher des détails supplémentaires sur ce que
annobin
est en train de faire, utilisez :$ gcc -fplugin=annobin -fplugin-arg-annobin-verbose file-name
Remplacez file-name par le nom du fichier.
Pour passer des options au plugin
annobin
avecclang
, utilisez :$ clang -fplugin=/path/to/directory/containing/annobin/ -Xclang -plugin-arg-annobin -Xclang option file-name
Remplacez option par les arguments de la ligne de commande
annobin
et remplacez /path/to/directory/containing/annobin/ par le chemin absolu du répertoire contenantannobin
.Exemple :
Pour afficher des détails supplémentaires sur ce que
annobin
est en train de faire, utilisez :$ clang -fplugin=/usr/lib64/clang/10/lib/annobin.so -Xclang -plugin-arg-annobin -Xclang verbose file-name
Remplacez file-name par le nom du fichier.
4.5.2. Utilisation du programme annocheck
La section suivante décrit comment utiliser annocheck
pour examiner :
- Dossiers
- Annuaires
- Paquets RPM
-
annocheck
outils supplémentaires
annocheck
analyse récursivement les répertoires, les archives et les paquets RPM à la recherche de fichiers objets ELF. Les fichiers doivent être au format ELF. annocheck
ne gère aucun autre type de fichier binaire.
4.5.2.1. Utiliser annocheck pour examiner les fichiers
La section suivante décrit comment examiner les fichiers ELF à l'aide de annocheck
.
Procédure
Pour examiner un fichier, utilisez :
$ annocheck file-name
Remplacez file-name par le nom d'un fichier.
Les fichiers doivent être au format ELF. annocheck
ne gère aucun autre type de fichier binaire. annocheck
traite les bibliothèques statiques qui contiennent des fichiers objets ELF.
Informations complémentaires
-
Pour plus d'informations sur
annocheck
et les options de ligne de commande possibles, voir la page de manuelannocheck
.
4.5.2.2. Utiliser annocheck pour examiner les répertoires
La section suivante décrit comment examiner les fichiers ELF dans un répertoire à l'aide de annocheck
.
Procédure
Pour scanner un répertoire, utilisez :
$ annocheck directory-name
Remplacez directory-name par le nom d'un répertoire.
annocheck
examine automatiquement le contenu du répertoire, de ses sous-répertoires et de toutes les archives et paquets RPM qui s'y trouvent.
annocheck
ne recherche que les fichiers ELF. Les autres types de fichiers sont ignorés.
Informations complémentaires
-
Pour plus d'informations sur
annocheck
et les options de ligne de commande possibles, voir la page de manuelannocheck
.
4.5.2.3. Utiliser annocheck pour examiner les paquets RPM
La section suivante décrit comment examiner les fichiers ELF dans un paquetage RPM à l'aide de annocheck
.
Procédure
Pour analyser un paquetage RPM, utilisez :
$ annocheck rpm-package-name
Remplacez rpm-package-name par le nom d'un paquetage RPM.
annocheck
analyse récursivement tous les fichiers ELF contenus dans le paquetage RPM.
annocheck
ne recherche que les fichiers ELF. Les autres types de fichiers sont ignorés.
Pour analyser un paquetage RPM avec l'info debug RPM fournie, utilisez :
$ annocheck rpm-package-name --debug-rpm debuginfo-rpm
Remplacez rpm-package-name par le nom d'un paquet RPM et debuginfo-rpm par le nom d'un RPM d'informations de débogage associé au RPM binaire.
Informations complémentaires
-
Pour plus d'informations sur
annocheck
et les options de ligne de commande possibles, voir la page de manuelannocheck
.
4.5.2.4. Utiliser les outils supplémentaires d'annocheck
annocheck
comprend plusieurs outils permettant d'examiner les fichiers binaires. Vous pouvez activer ces outils à l'aide des options de la ligne de commande.
La section suivante décrit comment activer la fonction :
-
built-by
outil -
notes
outil -
section-size
outil
Vous pouvez activer plusieurs outils en même temps.
Le vérificateur de durcissement est activé par défaut.
4.5.2.4.1. Activation de l'outil built-by
Vous pouvez utiliser l'outil annocheck
built-by
pour trouver le nom du compilateur qui a construit le fichier binaire.
Procédure
Pour activer l'outil
built-by
, utilisez$ annocheck --enable-built-by
Informations complémentaires
-
Pour plus d'informations sur l'outil
built-by
, voir l'option de ligne de commande--help
.
4.5.2.4.2. Activation de l'outil notes
Vous pouvez utiliser l'outil annocheck
notes
pour afficher les notes stockées dans un fichier binaire créé par le plugin annobin
.
Procédure
Pour activer l'outil
notes
, utilisez$ annocheck --enable-notes
Les notes sont affichées dans une séquence triée par plage d'adresses.
Informations complémentaires
-
Pour plus d'informations sur l'outil
notes
, voir l'option de ligne de commande--help
.
4.5.2.4.3. Activation de l'outil section-size
Vous pouvez utiliser l'outil annocheck
section-size
pour afficher la taille des sections nommées.
Procédure
Pour activer l'outil
section-size
, utilisez$ annocheck --section-size= (taille de la section)name
Remplacez name par le nom de la section nommée. La sortie est limitée à des sections spécifiques. Un résultat cumulé est produit à la fin.
Informations complémentaires
-
Pour plus d'informations sur l'outil
section-size
, voir l'option de ligne de commande--help
.
4.5.2.4.4. Principes de base du vérificateur de trempe
Le vérificateur d'endurcissement est activé par défaut. Vous pouvez le désactiver à l'aide de l'option de ligne de commande --disable-hardened
.
4.5.2.4.4.1. Options du vérificateur de durcissement
Le programme annocheck
vérifie les options suivantes :
-
Lazy binding est désactivée à l'aide de l'option
-z now
linker. - Le programme n'a pas de pile dans une région exécutable de la mémoire.
- Les emplacements de la table GOT sont définis en lecture seule.
- Aucun segment de programme ne possède les trois bits de permission de lecture, d'écriture et d'exécution.
- Il n'y a pas de relocalisation par rapport au code exécutable.
- Les informations relatives au chemin d'exécution permettant de localiser les bibliothèques partagées au moment de l'exécution ne comprennent que les répertoires ayant pour racine /usr.
-
Le programme a été compilé avec les notes
annobin
activées. -
Le programme a été compilé avec l'option
-fstack-protector-strong
activée. -
Le programme a été compilé avec
-D_FORTIFY_SOURCE=2
. -
Le programme a été compilé avec
-D_GLIBCXX_ASSERTIONS
. -
Le programme a été compilé avec
-fexceptions
activé. -
Le programme a été compilé avec
-fstack-clash-protection
activé. -
Le programme a été compilé à l'adresse
-O2
ou à une adresse supérieure. - Le programme n'a pas de relocalisation maintenue dans un élément inscriptible.
- Les exécutables dynamiques ont un segment dynamique.
-
Les bibliothèques partagées ont été compilées avec
-fPIC
ou-fPIE
. -
Les exécutables dynamiques ont été compilés avec
-fPIE
et liés avec-pie
. -
Si elle est disponible, l'option
-fcf-protection=full
a été utilisée. -
Si elle est disponible, l'option
-mbranch-protection
a été utilisée. -
Si elle est disponible, l'option
-mstackrealign
a été utilisée.
4.5.2.4.4.2. Désactivation du vérificateur de durcissement
La section suivante décrit comment désactiver le vérificateur de durcissement.
Procédure
Pour scanner les notes d'un fichier sans le vérificateur de durcissement, utilisez :
$ annocheck --enable-notes --disable-hardened file-name
Remplacez file-name par le nom d'un fichier.
4.5.3. Suppression des notes annobines redondantes
L'utilisation de annobin
augmente la taille des fichiers binaires. Pour réduire la taille des binaires compilés avec annobin
, vous pouvez supprimer les notes redondantes de annobin
. Pour supprimer les notes redondantes de annobin
, utilisez le programme objcopy
, qui fait partie du paquetage binutils
.
Procédure
Pour supprimer les notes redondantes de
annobin
, utilisez :$ objcopy --merge-notes file-name
Remplacez file-name par le nom du fichier.
4.5.4. Spécificités de annobin dans GCC Toolset 12
Dans certaines circonstances, en raison d'un problème de synchronisation entre annobin
et gcc
dans GCC Toolset 12, votre compilation peut échouer avec un message d'erreur qui ressemble à ce qui suit :
cc1: fatal error: inaccessible plugin file
opt/rh/gcc-toolset-12/root/usr/lib/gcc/architecture-linux-gnu/12/plugin/gcc-annobin.so
expanded from short plugin name gcc-annobin: No such file or directory
Pour contourner le problème, créez un lien symbolique dans le répertoire du plugin du fichier annobin.so
vers le fichier gcc-annobin.so
:
# cd /opt/rh/gcc-toolset-12/root/usr/lib/gcc/architecture-linux-gnu/12/plugin
# ln -s annobin.so gcc-annobin.so
Remplacez architecture par l'architecture que vous utilisez dans votre système :
-
aarch64
-
i686
-
ppc64le
-
s390x
-
x86_64