web-dev-qa-db-fra.com

Comment utiliser la commande addr2line sous Linux?

J'essaie d'utiliser la commande addr2line sous Unix mais à chaque fois, elle donne la même sortie que ??: 0. Je donne le commandement en tant que addr2line -e a.out 0x4005BDC. J'ai obtenu cette adresse lors de l'exécution de cet exécutable a.out avec l'outil valgrind pour trouver la fuite de mémoire. J'ai également compilé le code source avec -g option.

44
Prak

Vous pouvez également utiliser gdb au lieu de addr2line pour examiner l'adresse mémoire. Chargez le fichier exécutable dans gdb et imprimez le nom d'un symbole qui est stocké à l'adresse. 16 Examen de la table des symboles .

(gdb) info symbol 0x4005BDC 
30
ks1322

Vérifiez s'il vous plaît:

  • Que toutes les fonctions de votre binaire soient compilées avec -g, addr2line Seules les fonctions de support ont des informations de débogage, qui sont compilées avec -g
  • Si votre décalage est un décalage valide. Cela signifie que votre décalage ne doit pas être une adresse de mémoire virtuelle et ne doit être qu'un décalage dans la section .text. Dans la section .text Signifie que l'adresse doit pointer vers une instruction dans le binaire

utilisation addr2line

Voici le message de man addr2line.

addr2line - convertit les adresses en noms de fichiers et numéros de ligne.

addresses doit être l'adresse dans un exécutable ou un décalage dans une section d'un objet déplaçable.

La sortie est quelque chose comme FILENAME:LINENO, Le nom du fichier source et le numéro de ligne dans le fichier

Exemple.

Prenons l'exemple de helloworld.

#include <stdio.h>
int main()
{
    printf("hello\n");
    return 0;
}

Après l'avoir compilé avec gcc -g hello.c, Nous pourrions d'abord utiliser objdump pour avoir une idée des informations de décalage dans le fichier a.out Généré.

Ce qui suit fait partie du démontage sous-évalué:

Disassembly of section .text:

0000000000400440 <_start>:
  400440:       31 ed                   xor    %ebp,%ebp
  400442:       49 89 d1                mov    %rdx,%r9
  400445:       5e                      pop    %rsi
  400446:       48 89 e2                mov    %rsp,%rdx
  400449:       48 83 e4 f0             and    $0xfffffffffffffff0,%rsp
  40044d:       50                      Push   %rax
  40044e:       54                      Push   %rsp
  40044f:       49 c7 c0 c0 05 40 00    mov    $0x4005c0,%r8
  400456:       48 c7 c1 50 05 40 00    mov    $0x400550,%rcx
  40045d:       48 c7 c7 36 05 40 00    mov    $0x400536,%rdi
  400464:       e8 b7 ff ff ff          callq  400420 <__libc_start_main@plt>
  400469:       f4                      hlt
  40046a:       66 0f 1f 44 00 00       nopw   0x0(%rax,%rax,1)

  ...

   0000000000400536 <main>:

#include <stdio.h>
int main()
{
  400536:       55                      Push   %rbp
  400537:       48 89 e5                mov    %rsp,%rbp
    printf("hello\n");
  40053a:       bf d4 05 40 00          mov    $0x4005d4,%edi
  40053f:       e8 cc fe ff ff          callq  400410 <puts@plt>
    return 0;
  400544:       b8 00 00 00 00          mov    $0x0,%eax
}
  400549:       5d                      pop    %rbp
  40054a:       c3                      retq
  40054b:       0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)

La colonne la plus à gauche du code est l'offset dans le fichier binaire. La fonction __start Provient de la bibliothèque C standard et est précompilée sans informations de débogage. La fonction main provient de notre code helloworld qui contient des informations de débogage puisque nous compilons le fichier avec -g.

Voici la sortie de addr2line:

$ addr2line -e a.out 0x400442 #offset in the `__start` function
??:?
$ addr2line -e a.out 0x400536 #offset in the `main` function
hello.c:21
$ addr2line -e a.out 0x40054b -f #The last instruction of the `main` function
main
??:?

Nous pourrions tirer quelques conclusions de la sortie ci-dessus:

  1. Seul le segment de code généré avec l'indicateur -g (Ce qui signifie que le segment contient des informations de débogage) peut générer avec succès des informations sur le nom de fichier et le numéro de ligne.
  2. Tous les décalages d'un corps de fonction compilé avec l'indicateur -g Ne sortiront pas correctement le nom de fichier et le numéro de lin. Le décalage 0x40054b Est la dernière instruction après l'instruction ret de la fonction main, mais nous n'avons pas pu obtenir les informations.
21
Kun Ling

Vous devez spécifier un offset pour addr2line, pas une adresse virtuelle (VA). Vraisemblablement, si la randomisation de l'espace d'adressage était désactivée, vous pourriez utiliser un VA complet, mais dans la plupart des systèmes d'exploitation modernes, les espaces d'adressage sont randomisés pour un nouveau processus.

Étant donné le VA 0x4005BDC par valgrind, trouvez l'adresse de base de votre processus ou bibliothèque en mémoire. Pour ce faire, examinez le /proc/<PID>/maps fichier pendant l'exécution de votre programme. La ligne d'intérêt est le segment text de votre processus, qui est identifiable par les autorisations r-xp et le nom de votre programme ou bibliothèque.

Disons que la base VA est 0x0x4005000. Ensuite, vous trouverez la différence entre le valgrind fourni VA et le VA de base: 0xbdc. Ensuite, fournissez cela à add2line:

addr2line -e a.out -j .text 0xbdc

Et voyez si cela vous donne votre numéro de ligne.

17
tdenniston

C'est exactement comme ça que vous l'utilisez. Il est possible que l'adresse que vous avez ne corresponde pas à quelque chose directement dans votre code source.

Par exemple:

$ cat t.c
#include <stdio.h>
int main()
{
    printf("hello\n");
    return 0;
}
$ gcc -g t.c
$ addr2line -e a.out 0x400534
/tmp/t.c:3
$ addr2line -e a.out 0x400550
??:0

0x400534 est l'adresse de main dans mon cas. 0x400408 est également une adresse de fonction valide dans a.out, mais c'est un morceau de code généré/importé par GCC, qui n'a pas d'informations de débogage. (Dans ce cas, __libc_csu_init. Vous pouvez voir la disposition de votre exécutable avec readelf -a your_exe.)

Autres fois où addr2line échouera si vous incluez une bibliothèque sans informations de débogage.

11
Mat

Essayez d'ajouter le -f option pour afficher les noms des fonctions:

addr2line -f -e a.out 0x4005BDC
5
Penghe Geng