#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <execinfo.h>
#include <ucontext.h>
void handler(int signo, siginfo_t *info, void *context)
{
ucontext_t* ctx = (ucontext_t*)context;
void *trace[16];
char **messages = (char **)NULL;
int i, trace_size = 0;
trace_size = backtrace(trace, 16);
/* overwrite sigaction with caller's address */
trace[1] = (void *)ctx->uc_mcontext.gregs[REG_RIP];
messages = backtrace_symbols(trace, trace_size);
/* skip first stack frame (points here) */
printf("[bt] Execution path:\n");
for (i = 1; i < trace_size; ++i)
{
printf("[bt] #%d %s\n", i, messages[i]);
/* find first occurence of '(' or ' ' in message[i] and assume
* everything before that is the file name. (Don't go beyond 0 though
* (string terminator)*/
size_t p = 0;
while(messages[i][p] != '(' && messages[i][p] != ' ' && messages[i][p] != 0)
++p;
char syscom[256];
/* /usr/bin/addr2line */
sprintf(syscom,"addr2line %p -e %.*s", trace[i], p, messages[i]);
//last parameter is the file name of the symbol
system(syscom);
}
exit(EXIT_SUCCESS);
}
int func_a(int a, char b)
{
char *p = (char *)0xdeadbeef;
a = a + b;
*p = 10; /* CRASH here!! */
return 2 * a;
}
int func_b()
{
int res, a = 5;
res = 5 + func_a(a, 't');
return res;
}
int main()
{
struct sigaction sa={0} ;
/* Install our signal handler */
sa.sa_sigaction = &handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
sigaction(SIGSEGV, &sa, NULL);
sigaction(SIGUSR1, &sa, NULL);
/* Do something */
printf("%d\n", func_b());
//raise(SIGSEGV);
}
编译
gcc -g -rdynamic *.cpp -o bs