Graphes d’appel en C et C++

Je viens de découvrir quelque chose que je cherchais sans le savoir depuis longtemps : la possibilité de faire un graphe des appels de fonction dans un programme. C’est un journal sur LinuxFR qui m’a donné envie de me pencher sur le sujet. La conclusion du journal était que la solution la plus simple est de :

  • - compiler le programme avec les options de profiling (-pg).
  • - lancer le programme : ./prog
  • - récupérer la sortie de gprof : gprof ./prog > fichier.out
  • - la parser pour en générer un fichier .dot. cat fichier.out | ./cgprof > fichier2.out
  • - avec graphviz, générer un graphique : dot -Tps fichier2.out -o prog.ps

Ca marche sans problèmes pour les programmes en C, mais c’est plus difficile avec les programmes en C++, car la sortie de gprof est un peu différente (en C, les paramètres des fonctions ne sont pas affichés, alors qu’en C++, oui). Je me suis attaqué au problème, et j’ai commencé à réécrire cgprof pour prendre en compte les paramètres. Mauvaise idée, le code est assez immonde. Du coup, j’ai changé d’approche : j’ai demandé à gprof de ne pas demangler les noms de fonctions (option –no-demangle), j’ai généré le .dot avec les noms de fonction manglés, et j’ai utilisé c++filt (livré dans binutils) pour démangler directement le .dot. Et ca marche !

Il peut aussi être souhaitable de ne pas afficher les arguments des fonctions, histoire de gagner un peu de place. C’est facile : sed -i ‘s/([^)])//g’ fichier2.out et hop !

Ah j’oubliais : dans mon exemple, j’ai supprimé les indications sur la couleur, car apparemment, la formule que cgprof utilise ne donne pas de supers résultats. Ca se fait avec un grep -v sur le .out.

Autres améliorations possibles, cette fois au niveau de gprof :

  • L’option –static-call-graph demande à gprof de faire une analyse statique du code pour déterminer le graphe d’appels.
  • Les options -q et -Q permettent de contrôler plus finement le graphe d’appels. -q permet de définir la racine de l’arbre (pour ne grapher q’un sous-arbre), alors que -Q permet d’exclure un sous-arbre.