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
*/ |
Partager