Forum Programmation.c Une librairie pour convertir les adresses de programmes en nom de fonction ou de fichier et ligne ??

Posté par  .
Étiquettes : aucune
0
14
fév.
2006
Bonjour,

Je cherche une librairie pour faire le boulot de addr2line avec la table des symboles du programme courant.

En fait j'utilise :
void __cyg_profile_func_enter(void *this, void *callsite)
void __cyg_profile_func_exit(void *this, void *callsite)
pour enregistrer la stack d'appel sur 2 niveaux.

J'aimerais pouvoir écrire directement le nom de fonction et la ligne d'appel plutôt que l'adresse programme, lorsque je veux tracer la stack d'appel.

Est-ce que ça existe ?

Merci d'avance
  • # alors la je dis tout de suite

    Posté par  . Évalué à 2.

    que j'ai pas tres clairement compris ce que tu voulais faire.

    Moi pour mon debuggage j'utilise souvent dans un fichier trace la forme suivante
    printf("%s:%s:%s : Erreur d'argument",__FILE__,__FUNCTION__,__LINE__);

    ce qui donne a l'execution
    main.c:Assert:127 : Erreur d'argument

    __FILE__
    __FUNCTION__
    __LINE__
    sont de primitive que le compilateur remplace par les chaines qui vont bien
    Voila en utilisant ca
    sprintf(MaString,"%s:%s:%s : Erreur d'argument",__FILE__,__FUNCTION__,__LINE__);

    __cyg_profile_func_enter(&MaString, void *callsite)

    au lieu du void* tu peut avoir ce que tu veux peut etre?
    • [^] # Re: alors la je dis tout de suite

      Posté par  . Évalué à 1.

      Juste pour clarifier les choses :
      __cyg_profile_func_enter(&MaString, void *callsite) et son pendant sur exit sont des fonctions qui permettent de tracer toutes les entrees et sorties de fonctions d'un programme.
      Il suffit qu'elles soient definies dans ta table des symboles pour qu'elles soient automatiquement utilisées (...enter appellés sur appel de fonction et ...exit sur le retour).
      Ceci juste pour dire que je choisis pas le proto de ces fonctions et que je dois bien faire avec...!
      Merci quand meme pour ton soutien...!
  • # libdl

    Posté par  (site web personnel) . Évalué à 2.

    Avec la GNU libdl (installée en plus-que-standard sous Linux), tu appelles dladdr depuis tes wrappers et ça devrait faire le boulot.
    • [^] # Re: libdl

      Posté par  . Évalué à 1.

      Merci bien pour ton aide.
      Il faudra que je test un peu mieux tout ca mais a priori, seul le dli_fname est rempli avec le nom du fichier binaire et dli_sname est à nul...
      addr2line fonctionne tres bien lui ...

      Voici mon utilisation de mem_get_info
      ptr est une adresse programme valide et dl_info une structure non initialisée.
      dladdr renvoie toujours different de 0 et dli_sname est positionnée à null.

      static void mem_get_info(void * ptr,Dl_info * dl_info){
      if (!dladdr(ptr, dl_info)){
      dl_info->dli_fname = "error";
      dl_info->dli_sname = "error";
      }
      }

      Que devrais je m'attendre à avoir dans dli_sname (la ligne C, le numero de ligne ??)
      • [^] # Re: libdl

        Posté par  (site web personnel) . Évalué à 1.

        L'important est ce paragraphe du man : << If the executable was linked with the flag "-rdynamic" (or, synonymously, "--export-dynamic"), then the global symbols in the executable will also be used to resolve refer-ences in a dynamically loaded library. >> Si je compile le programme qui suit :
        /*
         * A compiler avec -rdynamic et linker avec libdl :
         *    gcc -o dladdr -rdynamic dladdr.c -ldl
         * cf man dlopen :
         *     If the executable was linked with
         *     the flag "-rdynamic" (or, synonymously, "--export-dynamic"),  then  the
         *     global  symbols  in  the executable will also be used to resolve refer-
         *     ences in a dynamically loaded library.
         */
        
        #ifndef _GNU_SOURCE
        #define _GNU_SOURCE 1
        #endif
        
        #include <stdio.h>
        #include <dlfcn.h>
        
        int main (void)
        {
          void *addr = (void *) (main + 0x42);
        
          Dl_info info;
          int ret = dladdr (addr, &info);
        
          printf ("lookup %p:\n", addr);
          printf ("  retval: %u\n", ret);
          printf ("  fname:  %s\n", info.dli_fname);
          printf ("  saddr:  %p\n", info.dli_saddr);
          printf ("  sname:  %s\n", info.dli_sname);
          printf ("  fbase:  %p\n", info.dli_fbase);
          printf ("  pretty: \"%s+0x%x\"\n",
        	  info.dli_sname, addr - info.dli_saddr);
        
          return 0;
        }
        
        de la façon suivante :
        gcc -o dladdr -rdynamic dladdr.c -ldl
        alors j'obtiens ce qu'on attend :
        [pollindd] work/svn/2006/divers >./dladdr                                  1032
        lookup 0x80486a6:
          retval: 1
          fname:  ./dladdr
          saddr:  0x8048664
          sname:  main
          fbase:  0x8048000
          pretty: "main+0x42"
        

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.