IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Linux Discussion :

Obtenir call stack d'un programme java/C++ ?


Sujet :

Linux

  1. #1
    Membre habitué Avatar de SteelBox
    Profil pro
    Inscrit en
    Novembre 2002
    Messages
    446
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Novembre 2002
    Messages : 446
    Points : 194
    Points
    194
    Par défaut Obtenir call stack d'un programme java/C++ ?
    Bonjour,
    Je cherche à récuper la call stack (pile des appels) pour un programme écrit en java et utilisant des fonctions C++ (avec JNI). Savez vous comment je peux faire ? java possède une méthodge (printStackTrace dans la classe Exception) mais en C++ ? je peux éventuellement utiliser un debugger et déclencher une exception dans mon code C++ mais y'a t-il des debugger qui donne l'enchainement des fonctions (et non pas l'enchainement des sauts à des adresses mémoires) ?

    Merci
    La vitesse de la lumière étant supérieure à celle du son, il apparaît normal que beaucoup de gens paraissent brillants jusqu'à ce qu'ils l'ouvrent.

  2. #2
    Membre actif
    Avatar de vosaray
    Profil pro
    Architecte technique
    Inscrit en
    Mai 2004
    Messages
    217
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Architecte technique
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Mai 2004
    Messages : 217
    Points : 299
    Points
    299
    Par défaut
    En c++ je ne sais pas mais su tu sais recuperer le pid process (genre avec pgrep ) tu peux faire un

    kill -3 <pid> 2>&1 /tmp/stack.trace

    ca va dumper la stack de ton programme java dans /tmp/stack.trace

    En c++ c'est tout de meme un pov appel systeme pour executer 2 process, aliors devrait pas y a voir de soucis.

    [edit]: et si ta vm fork sur +eurs process, prends le process pere ( pstree peut t'aider )

  3. #3
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Points : 20 970
    Points
    20 970
    Par défaut
    Je remonte ce sujet ma fois fort intéressant. Sous Windows, il existe une bibliothèque complète fournie par Microsoft, dbghelp, mais sous Linux, je cherche encore après avoir chercher pendant 2 bonnes heures sur Google Quelqu'un a une idée ?
    Il existerait une fonction qui s'appelle dump_stack ou show_stack, mais elle nexiste pas sous FC5, certains sites proposent le header ucontext, mais ce n'est apparemment le cas de tous

    Même quelques fonction C permettant de dumper sur un FILE* serait appréciables !

  4. #4
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Points : 20 970
    Points
    20 970
    Par défaut
    Je viens de trouver dans "execinfo.h" une fonction backtrace et backtrace_symbols qui font un minimum ce dont nous aurions besoin, je crois

  5. #5
    Rédacteur

    Avatar de gege2061
    Femme Profil pro
    Administrateur de base de données
    Inscrit en
    Juin 2004
    Messages
    5 840
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur de base de données

    Informations forums :
    Inscription : Juin 2004
    Messages : 5 840
    Points : 11 625
    Points
    11 625
    Par défaut
    La glib propose la fonction g_on_error_stack_trace basée sur gdb

  6. #6
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Points : 20 970
    Points
    20 970
    Par défaut
    Ce qui est intéressant, c'est d'afficher simplement la trace des appels, sans avoir gdb à côté, on ne sait pas si tout le monde en dispose.
    J'ai testén ça marche presque bien, ce qu'il manque encore, c'est afficher la liste des variables locales.

  7. #7
    Rédacteur

    Avatar de gege2061
    Femme Profil pro
    Administrateur de base de données
    Inscrit en
    Juin 2004
    Messages
    5 840
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur de base de données

    Informations forums :
    Inscription : Juin 2004
    Messages : 5 840
    Points : 11 625
    Points
    11 625
    Par défaut
    Citation Envoyé par Miles
    Ce qui est intéressant, c'est d'afficher simplement la trace des appels, sans avoir gdb à côté, on ne sait pas si tout le monde en dispose.
    J'ai testén ça marche presque bien, ce qu'il manque encore, c'est afficher la liste des variables locales.
    Jamais content (remarque moi non plus, je n'arrive pas à rediriger la trace vers un fichier, je cherche donc une autre solution)

    man pstack (c'est un exécutable)

    Sinon tu fouille dans les sources de gdb pour savoir comment ils font

  8. #8
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Points : 20 970
    Points
    20 970
    Par défaut
    Citation Envoyé par gege2061
    Jamais content (remarque moi non plus, je n'arrive pas à rediriger la trace vers un fichier, je cherche donc une autre solution)

    man pstack (c'est un exécutable)

    Sinon tu fouille dans les sources de gdb pour savoir comment ils font
    J'ai regardé les sources de gdb, c'est imbitable
    A la fin, je pense que je vais faire un tuto à ce niveau pour rendre tout ça transparent...

  9. #9
    Rédacteur

    Avatar de gege2061
    Femme Profil pro
    Administrateur de base de données
    Inscrit en
    Juin 2004
    Messages
    5 840
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur de base de données

    Informations forums :
    Inscription : Juin 2004
    Messages : 5 840
    Points : 11 625
    Points
    11 625
    Par défaut
    Bon j'ai un peu avancé dans mes recherches, dans le fichier d'en tête linux/user.h il existe des structures pour obtenir des info sur la pile et les registres du processeurs :
    user.h
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    struct user_regs_struct {
            long ebx, ecx, edx, esi, edi, ebp, eax;
            unsigned short ds, __ds, es, __es;
            unsigned short fs, __fs, gs, __gs;
            long orig_eax, eip;
            unsigned short cs, __cs;
            long eflags, esp;
            unsigned short ss, __ss;
    };
     
    struct user{
    /* We start with the registers, to mimic the way that "memory" is returned
        from the ptrace(3,...) function.  */
       struct user_regs_struct regs;         /* Where the registers are actually stored */
    /* ptrace does not yet supply these.  Someday.... */
      int u_fpvalid;                /* True if math co-processor being used. */
                                     /* for this mess. Not yet used. */
      struct user_i387_struct i387; /* Math Co-processor registers. */
    /* The rest of this junk is to help gdb figure out what goes where */
      unsigned long int u_tsize;    /* Text segment size (pages). */
      unsigned long int u_dsize;    /* Data segment size (pages). */
      unsigned long int u_ssize;    /* Stack segment size (pages). */
      unsigned long start_code;     /* Starting virtual address of text. */
      unsigned long start_stack;    /* Starting virtual address of stack area.
                                        This is actually the bottom of the stack,
                                        the top of the stack is always found in the
                                        esp register.  */
      long int signal;              /* Signal that caused the core dump. */
      int reserved;                 /* No longer used */
      struct user_pt_regs * u_ar0;  /* Used by gdb to help find the values for */
                                     /* the registers. */
      struct user_i387_struct* u_fpstate;   /* Math Co-processor pointer. */
      unsigned long magic;          /* To uniquely identify a core file */
      char u_comm[32];              /* User command that was responsible */
      int u_debugreg[8];
    };
    Dans le fichier sys/user.h (qui ressemble fortement à celui-ci), il est même écrit quelque chose du genre : "Pas touche, ceci est uniquement pour gdb".

    Le problème c'est que je n'arrive pas à récupérer les info Il semblerai que ptrace soit la clé mais je n'arrive pas à l'utiliser.

  10. #10
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Points : 20 970
    Points
    20 970
    Par défaut
    Merci pour ces infos
    Au moins, sous Windows, c'est plus documenter - pas plus facile à utiliser, mais bon -

  11. #11
    Rédacteur

    Avatar de gege2061
    Femme Profil pro
    Administrateur de base de données
    Inscrit en
    Juin 2004
    Messages
    5 840
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur de base de données

    Informations forums :
    Inscription : Juin 2004
    Messages : 5 840
    Points : 11 625
    Points
    11 625
    Par défaut
    Trouvé sur fr.comp.os.linux.moderated (je ne sais pas pourquoi je n'y ai pas pensé avant )
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    /*
     * trace_stack.c (c) 1998, Frederic Abiven <fabi...@teaser.fr>
     *
     * Installation d'un gestionnaire de signaux
     * pour afficher la pile des appels apres une erreur fatale
     *
     * necessite la commande systeme ``addr2line'' (binutils >= 2.8.0)
     *
     * Usage :
     * dans le main(), mettre
     *
     *   install_trace_stack(argv[0], 1);
     *
     */
     
    #ifndef __GNUC__
    ... trace_stack ne compile que pour GCC ...
    #endif
     
    #include <stdio.h>
    #include <string.h>
    #include <signal.h>
     
    #define MAX_STACK 10
    #define GET_ADDR(p,i)  if (! (p[i-1] = __builtin_return_address(i))) break;
     
    #define SYSTEM_CMD      "addr2line %s -e %s "
     
    static char exec_name[256];
    static int  with_funcname;
     
    static struct {
      int signum;
      void (*sighandler)(int);
    } Hdl[] = {
     
      { SIGILL,  0},
    #if 0
      { SIGABRT, 0},
    #endif
      { SIGFPE,  0},
      { SIGSEGV, 0},
      { SIGBUS,  0},
      {      0,  0}
     
    };
     
    static void
    print_stack(int sig)
    {
      static char *p[MAX_STACK];
      static char tmp[20];
      static char cmd[1024];
      static int i;
     
      psignal(sig, exec_name);
     
      do {
     
        GET_ADDR(p, 1); /* __builtin... exige une vraie constante */
        GET_ADDR(p, 2);
        GET_ADDR(p, 3);
        GET_ADDR(p, 4);
        GET_ADDR(p, 5);
        GET_ADDR(p, 6);
        GET_ADDR(p, 7);
        GET_ADDR(p, 8);
        GET_ADDR(p, 9);
        GET_ADDR(p, 10);
     
      } while (0);
     
      sprintf(cmd, SYSTEM_CMD, (with_funcname ? "-f -C" : ""), exec_name);
     
      for (i = 0; i < MAX_STACK; i++) {
        if (p[i]) {
          sprintf(tmp,"0x%x ",p[i]);
          strcat(cmd,tmp);
        }
        else
          break;
      }
     
      system(cmd);
     
      /* call old handler if exist */
      for (i = 0; Hdl[i].signum; i++)
        if (Hdl[i].signum == sig) {
          if (Hdl[i].sighandler)
            (Hdl[i].sighandler)(sig);
          else
            abort(); /* -> core dump */
        }
     
    }
     
    void install_trace_stack(char *name,
                             int with_fname)
    {
      int i;
     
      /* name doit contenir le chemin complet de l'executable */
      if (name)
        strcpy(exec_name, name);
     
      with_funcname = with_fname;
     
      for (i = 0; Hdl[i].signum; i++)
        Hdl[i].sighandler = signal(Hdl[i].signum,
                                   print_stack);
     
    }
     
    /*
     * fin de trace_stack.c
     */

    C'est quand même plus beau que sous Windows

  12. #12
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Points : 20 970
    Points
    20 970
    Par défaut
    Tu trouves ?? Bof, tu fais appel à une fonction externe, alors que backtrace fait exactement la même chose

  13. #13
    Rédacteur

    Avatar de gege2061
    Femme Profil pro
    Administrateur de base de données
    Inscrit en
    Juin 2004
    Messages
    5 840
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur de base de données

    Informations forums :
    Inscription : Juin 2004
    Messages : 5 840
    Points : 11 625
    Points
    11 625
    Par défaut
    Citation Envoyé par Miles
    Tu trouves ?? Bof, tu fais appel à une fonction externe, alors que backtrace fait exactement la même chose
    Voilà par ta faute j'ai récupéré les sources de addr2line et je vais passer ma soirée à l'embarquer dans ce code

    T'es vraiment pénible

  14. #14
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Points : 20 970
    Points
    20 970
    Par défaut
    Citation Envoyé par gege2061
    Voilà par ta faute j'ai récupéré les sources de addr2line et je vais passer ma soirée à l'embarquer dans ce code

    T'es vraiment pénible
    Mais non, pas la peine
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
        void *array[callStackDepth];
        size_t size;
        char **strings;
        size = backtrace(array, callStackDepth);
        strings = backtrace_symbols(array, size);
     
        for(size_t i = 0; i < size; ++i)
        {
          std::cout << strings[i];
        }
        free(strings);
    Et tu mets ça dans une fonction appelée par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
      std::set_terminate(selfTerminate);
    Avec selfTerminate la fonction qui encapsule le premier code. Ca marche juste pour les programmes appelés en C++

  15. #15
    Rédacteur

    Avatar de gege2061
    Femme Profil pro
    Administrateur de base de données
    Inscrit en
    Juin 2004
    Messages
    5 840
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur de base de données

    Informations forums :
    Inscription : Juin 2004
    Messages : 5 840
    Points : 11 625
    Points
    11 625
    Par défaut
    Citation Envoyé par Miles
    Mais non, pas la peine
    Ah mais je n'avais pas vu ton post sur backtrace

    Comme je préfère le C :
    The GNU C Library - Backtraces
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    #include <execinfo.h>
    #include <stdio.h>
    #include <stdlib.h>
     
    /* Obtain a backtrace and print it to stdout. */
    void
    print_trace (void)
    {
      void *array[10];
      size_t size;
      char **strings;
      size_t i;
     
      size = backtrace (array, 10);
      strings = backtrace_symbols (array, size);
     
      printf ("Obtained %zd stack frames.\n", size);
     
      for (i = 0; i < size; i++)
         printf ("%s\n", strings[i]);
     
      free (strings);
    }
     
    /* A dummy function to make the backtrace more interesting. */
    void
    dummy_function (void)
    {
      print_trace ();
    }
     
    int
    main (void)
    {
      dummy_function ();
      return 0;
    }

    Cool je vais pouvoir coder un gestionnaire de plantage ce soir

  16. #16
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Points : 20 970
    Points
    20 970
    Par défaut
    Maintenant, faudrait juste aussi avoir le passage pour dumper le contenu des variables.

  17. #17
    Rédacteur

    Avatar de gege2061
    Femme Profil pro
    Administrateur de base de données
    Inscrit en
    Juin 2004
    Messages
    5 840
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur de base de données

    Informations forums :
    Inscription : Juin 2004
    Messages : 5 840
    Points : 11 625
    Points
    11 625
    Par défaut
    Citation Envoyé par Miles
    Maintenant, faudrait juste aussi avoir le passage pour dumper le contenu des variables.
    Bof j'ai essayé les codes, aucun ne donne le nom des fonction juste l'adresse, c'est pas très pratique

  18. #18
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Points : 20 970
    Points
    20 970
    Par défaut
    Citation Envoyé par gege2061
    Bof j'ai essayé les codes, aucun ne donne le nom des fonction juste l'adresse, c'est pas très pratique
    Ah ?? J'ai testé, j'ai eu le nom des fonctions, pourtant...

  19. #19
    Membre habitué Avatar de SteelBox
    Profil pro
    Inscrit en
    Novembre 2002
    Messages
    446
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Novembre 2002
    Messages : 446
    Points : 194
    Points
    194
    Par défaut
    J'avais complètement oublié ce message depuis le temps. Je m'étais débrouillé avec gdb et l'adresse des fonctions. En tout cas, j'ai testé le code et j'obtiens aussi l'adresse des fonctions uniquement
    La vitesse de la lumière étant supérieure à celle du son, il apparaît normal que beaucoup de gens paraissent brillants jusqu'à ce qu'ils l'ouvrent.

  20. #20
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Points : 20 970
    Points
    20 970
    Par défaut
    Ca doit dépendre des options de compilation aussi, j'imagine. C'est quoi les tiennes ?

Discussions similaires

  1. Réponses: 1
    Dernier message: 27/01/2011, 13h13
  2. [Avis] Les meilleurs programmes Java ?
    Par christopheJ dans le forum ImageJ
    Réponses: 69
    Dernier message: 07/10/2008, 01h12
  3. [Apis]parser les arguments d'un programme Java
    Par sacofan dans le forum API standards et tierces
    Réponses: 4
    Dernier message: 06/08/2005, 14h32
  4. [votre avis m'interesse] Interface avec un programme Java
    Par LineLe dans le forum Interfaces Graphiques en Java
    Réponses: 29
    Dernier message: 11/12/2004, 11h39
  5. Lancement d'un programme java depuis un script php
    Par gexti dans le forum Développement Web en Java
    Réponses: 8
    Dernier message: 07/05/2004, 17h40

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo