backtrace, backtrace_symbols, backtrace_symbols_fd - Outils
d'auto-débogage d'applications
Bibliothèque C standard (
libc,
-lc)
#include <execinfo.h>
int backtrace(void *buffer[.size], int size);
char **backtrace_symbols(void *const buffer[.size], int size);
void backtrace_symbols_fd(void *const buffer[.size], int size, int fd);
backtrace() renvoie une trace des appels du programme dans un tableau
pointé par
buffer. Une trace est une série d'appels de
fonction actuellement actifs d'un programme. Chaque élément du
tableau pointé par
buffer est de type
void *, et
correspond à l'adresse de retour du bloc de pile (stack frame)
correspondant. Le paramètre
size spécifie le nombre
maximal d'adresses qui peut être enregistré dans
buffer.
Si la trace est plus grande que
size, alors les adresses correspondant
aux
size plus récents appels de fonction sont renvoyées.
Pour obtenir une trace complète, assurez-vous que
buffer et
size soient assez grands.
À partir des adresses renvoyées par
backtrace() dans le
buffer,
backtrace_symbols() traduit les adresses en un tableau
de chaînes qui associe des symboles à ces adresses. Le
paramètre
size indique le nombre d'adresses dans le
buffer. La représentation symbolique de chaque adresse consiste
en un nom de fonction (s'il peut être déterminé), un
décalage hexadécimal à l'intérieur de la fonction
et l'adresse (hexadécimale) de renvoi. L'adresse du tableau de
pointeurs de chaînes est renvoyé comme résultat de la
fonction
backtrace_symbols(). Ce tableau est alloué avec
malloc(3) par
backtrace_symbols() et doit être
libéré par l'appelant. Les chaînes pointées par le
tableau de pointeurs n'ont pas et ne devraient pas être
libérées.
backtrace_symbols_fd() prend les mêmes paramètres
buffer et
size que
backtrace_symbols(), mais au lieu de
renvoyer un tableau de chaînes à l'appelant, elle écrit
les chaînes, une par ligne, dans le descripteur de fichier
fd.
backtrace_symbols_fd() n'appelle pas
malloc(3) et peut donc
être utilisée dans des conditions où cette
dernière fonction risque d'échouer, mais consultez NOTES.
backtrace() fournit le nombre d'adresses renvoyées dans le
buffer, qui ne sera pas supérieur à
size. Si la
valeur de retour est inférieure à
size, alors toute la
trace a pu être sauvée ; si elle est égale
à
size, alors il se peut qu'elle ait été
tronquée et les adresses des blocs de pile les plus anciens ne sont pas
renvoyées.
En cas de succès,
backtrace_symbols() renvoie un pointeur vers le
tableau alloué avec
malloc(3). En cas d'erreur NULL est
renvoyé.
backtrace(),
backtrace_symbols() et
backtrace_symbols_fd()
sont fournies depuis la glibc 2.1.
Pour une explication des termes utilisés dans cette section, consulter
attributes(7).
Interface |
Attribut |
Valeur |
backtrace(), backtrace_symbols(),
backtrace_symbols_fd() |
Sécurité des threads |
MT-Safe |
Ces fonctions sont des extensions GNU.
Ces fonctions font des suppositions sur la façon dont l'adresse
renvoyée d'une fonction est sauvegardée dans la pile. Prenez
note des points suivants :
- •
- L'omission du pointeur de bloc (comme le fait gcc(1)
avec les niveaux d'optimisation différents de zéro) peut
être incompatible avec ces suppositions.
- •
- Les fonctions incorporées
(« inline ») n’ont pas de blocs de
pile.
- •
- Avec les optimisations de type sous-routine finale
(tail-call) font qu’un bloc de pile en remplace un autre.
- •
-
backtrace() et backtrace_symbols_fd()
n'appellent pas malloc() explicitement, mais elles font partie de
la libgcc qui est chargée dynamiquement à sa
première utilisation. Le chargement dynamique déclenche
habituellement un appel à malloc(3). Si vous avez besoin que
certains appels à ces deux fonctions n'allouent pas de
mémoire (dans les gestionnaires de signal, par exemple) vous devez
vous assurer que la libgcc est chargée au
préalable.
Le nom des symboles peut ne pas être disponible si certaines options de
l'éditeur de liens n'ont pas été utilisées. Pour
les systèmes qui utilisent l'éditeur de liens GNU, il faut
utiliser l'option
-rdynamic. Notez que les noms des fonctions statiques
(avec le mot clef « static ») ne sont pas
exposés, et ne seront pas disponibles pour la trace.
Le programme ci-dessous explique l'utilisation de
backtrace() et
backtrace_symbols(). Les sessions d'interpréteur de commandes
montrent ce que produira l'exécution du programme :
$ cc -rdynamic prog.c -o prog
$ ./prog 3
backtrace() returned 8 addresses
./prog(myfunc3+0x5c) [0x80487f0]
./prog [0x8048871]
./prog(myfunc+0x21) [0x8048894]
./prog(myfunc+0x1a) [0x804888d]
./prog(myfunc+0x1a) [0x804888d]
./prog(main+0x65) [0x80488fb]
/lib/libc.so.6(__libc_start_main+0xdc) [0xb7e38f9c]
./prog [0x8048711]
#include <execinfo.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define BT_BUF_SIZE 100
void
myfunc3(void)
{
int nptrs;
void *buffer[BT_BUF_SIZE];
char **strings;
nptrs = backtrace(buffer, BT_BUF_SIZE);
printf("backtrace() returned %d addresses\n", nptrs);
/* L’appel backtrace_symbols_fd(buffer, nptrs, STDOUT_FILENO)
produirait une sortie semblable à ce qui suit : */
strings = backtrace_symbols(buffer, nptrs);
if (strings == NULL) {
perror("backtrace_symbols");
exit(EXIT_FAILURE);
}
for (size_t j = 0; j < nptrs; j++)
printf("%s\n", strings[j]);
free(strings);
}
static void /* « static » signifie ne pas exporter le symbole... */
myfunc2(void)
{
myfunc3();
}
void
myfunc(int ncalls)
{
if (ncalls > 1)
myfunc(ncalls - 1);
else
myfunc2();
}
int
main(int argc, char *argv[])
{
if (argc != 2) {
fprintf(stderr, "%s num-calls\n", argv[0]);
exit(EXIT_FAILURE);
}
myfunc(atoi(argv[1]));
exit(EXIT_SUCCESS);
}
addr2line(1),
gcc(1),
gdb(1),
ld(1),
dlopen(3),
malloc(3)
La traduction française de cette page de manuel a été
créée par Christophe Blaess
<
https://www.blaess.fr/christophe/>, Stéphan Rafin
<
[email protected]>, Thierry Vignaud
<
[email protected]>, François Micaux, Alain Portal
<
[email protected]>, Jean-Philippe Guérard
<
[email protected]>, Jean-Luc Coulon (f5ibh)
<
[email protected]>, Julien Cristau
<
[email protected]>, Thomas Huriaux <
[email protected]>,
Nicolas François <
[email protected]>, Florentin
Duneau <
[email protected]>, Simon Paillard
<
[email protected]>, Denis Barbier
<
[email protected]>, David Prévot <
[email protected]> et
Jean-Pierre Giraud <
[email protected]>
Cette traduction est une documentation libre ; veuillez vous reporter
à la
GNU
General Public License version 3 concernant les conditions de copie
et de distribution. Il n'y a aucune RESPONSABILITÉ LÉGALE.
Si vous découvrez un bogue dans la traduction de cette page de manuel,
veuillez envoyer un message à
[email protected]