How to print the stack information when the program crashes?
黄晋
icanlearn at tom.com
Sat Jun 19 06:59:42 UTC 2010
I've tried to output the data in the program stack when the program has a segmentation fault. I need to print where the program executation has been, especially the function names, in order to know what operation in the code causes the crashes.
But when I invoke dladdr() on the addresses in the registers, dladdr() just fails, returning 0.
The following is my program:
#ifndef __USE_GNU
#define __USE_GNU
#endif
#include <stdio.h>
#include <signal.h>
#include <time.h>
#include <ucontext.h>
#include <dlfcn.h>
#include <strings.h>
#include <stdlib.h>
static void signal_segv(int signum, siginfo_t *info, void *ptr)
{
static const char *si_codes[3] = { "", "SEGV_MAP_ERR", "SEGV_ACC_ERR" };
int i;
int f = 0;
ucontext_t *ucontext = (ucontext_t *)ptr;
Dl_info dlinfo;
void **bp = 0;
void *ip = 0;
FILE *fp;
time_t cur_time;
struct tm *tfmt;
fp = fopen("stacktrace", "a");
if (!fp)
{
printf("fopen() failed.\n");
fclose(fp);
return;
}
fprintf(fp, "info.si_signo = %d\n", signum);
fprintf(fp, "info.si_errno = %d\n", info->si_errno);
fprintf(fp, "info.si_code = %d (%s)\n", info->si_code,
(info->si_code >= 0 && info->si_code <= 2) ? si_codes[info->si_code] : "");
fprintf(fp, "info.si_addr = %p\n", info->si_addr);
for (i = 0; i < NGREG; ++i)
fprintf(fp, "reg[%02d] = 0x%08x\n", i, ucontext->uc_mcontext.gpregs[i]);
ip = (void *)ucontext->uc_mcontext.gpregs[CTX_S7]; // this is only one register, but I tried every generic
// register, having the same results
bp = (void **)ucontext->uc_mcontext.gpregs[CTX_SP];
while (ip && bp)
{
if (!dladdr(ip, &dlinfo)) // the dladdr() failed here
break;
const char *symname = dlinfo.dli_sname;
fprintf(fp, "% 2d: %p <%s+%lu> (%s)\n", ++f, ip, symname,
(unsigned long)ip - (unsigned long)dlinfo.dli_saddr, dlinfo.dli_fname);
if (dlinfo.dli_sname && !strcmp(dlinfo.dli_sname, "main"))
break;
ip = bp[1];
bp = (void **)bp[0];
}
fclose(fp);
exit(0);
}
static void setup_sigsegv()
{
struct sigaction action;
bzero(&action, sizeof(action));
action.sa_sigaction = signal_segv;
action.sa_flags = SA_SIGINFO;
if (sigaction(SIGSEGV, &action, NULL) < 0)
printf("sigaction() failed.\n");
}
int main()
{
setup_sigsegv();
*(int *)0x1234 = 30;
return 0;
}
Can somebody figure out where the problem is and how should I write the tracing code?
Thanks!
More information about the uClibc
mailing list