Parcourir la pile vous-même est assez rapide - la plupart de la lenteur dans le processus de création de la pile est due à l'utilisation d'un logiciel de gestion de la pile. backtrace()
c'est en cherchant les noms des symboles. Sur x86, vous pouvez faire ce qui suit :
inline uint32_t get_ebp(void)
{
__asm__ __volatile__("mov %%ebp, %%eax");
}
int get_stack_depth(void)
{
uint32_t ebp = get_ebp();
int stack_depth = 0;
while(ebp != 0)
{
ebp = *(uint32_t *)ebp;
stack_depth++;
}
return stack_depth;
}
Cela permettra de parcourir la chaîne de ebp
pointeurs. Gardez à l'esprit que ceci est extrêmement non-portable. Notez également que cela ne comptera pas les fonctions qui ont été inlined ou optimisées par tail-call (bien sûr, backtrace()
a le même problème).
Un autre problème important est la condition de terminaison -- une fois que vous avez fait un backtrace jusqu'à main()
il n'y a souvent aucune garantie sur ce que vous trouverez dans la pile. Donc, si la libc ne met pas un pointeur de trame nul, vous aurez très probablement un défaut de segmentation. Vous pouvez obtenir la valeur de terminaison en la regardant au tout début du fichier main()
.