#define _GNU_SOURCE
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <execinfo.h>
#include <ucontext.h>
/*
* backtrace和bacetrace_symbols打印出回溯信息
*/
#if 0
#include <execinfo.h>
int backtrace(void **buffer, int size);
char **backtrace_symbols(void *const *buffer, int size);
void backtrace_symbols_fd(void *const *buffer, int size, int fd);
#endif
static void signal_handler(int sig, siginfo_t *info, void *ctx)
{
ucontext_t *context = (ucontext_t *)ctx;
/* dump registers, x64 CPU specific */
printf( "Signal = %d Memory location = %p\n"
"RIP = %016X RSP = %016X RBP = %016X\n"
"RAX = %016X RBX = %016X RCX = %016X\n"
"RDX = %016X RSI = %016X RDI = %016X\n"
"R8 = %016X R9 = %016X R10 = %016X\n"
"R11 = %016X R12 = %016X R13 = %016X\n"
"R14 = %016X R15 = %016X RFLAGS = %016X\n\n",
sig, info->si_addr,
context->uc_mcontext.gregs[REG_RIP],
context->uc_mcontext.gregs[REG_RSP],
context->uc_mcontext.gregs[REG_RBP],
context->uc_mcontext.gregs[REG_RAX],
context->uc_mcontext.gregs[REG_RBX],
context->uc_mcontext.gregs[REG_RCX],
context->uc_mcontext.gregs[REG_RDX],
context->uc_mcontext.gregs[REG_RSI],
context->uc_mcontext.gregs[REG_RDI],
context->uc_mcontext.gregs[REG_R8],
context->uc_mcontext.gregs[REG_R9],
context->uc_mcontext.gregs[REG_R10],
context->uc_mcontext.gregs[REG_R11],
context->uc_mcontext.gregs[REG_R12],
context->uc_mcontext.gregs[REG_R13],
context->uc_mcontext.gregs[REG_R14],
context->uc_mcontext.gregs[REG_R15],
context->uc_mcontext.gregs[REG_EFL]);
/* get call stack and write to stdout */
void *buf[256] = {0};
int size = backtrace(buf, 256);
backtrace_symbols_fd(buf, size, fileno(stdout));
exit(-1);
}
void test_3(int *p)
{
*p = 1;
}
void test_2(int *p)
{
test_3(p);
}
void test_1(int *p)
{
test_2(p);
}
int main(int argc, char *argv[])
{
int *p = 0x12345678;
struct sigaction action;
sigemptyset(&action.sa_mask);
action.sa_sigaction = signal_handler;
action.sa_flags = SA_SIGINFO;
sigaction(SIGSEGV, &action, NULL);
test_1(p);
return 0;
}
// gcc -rdynamic backtrace2.c -o backtrace2
#if 0
000000000000143f <test_3>:
143f: f3 0f 1e fa endbr64
1443: 55 push %rbp
1444: 48 89 e5 mov %rsp,%rbp
1447: 48 89 7d f8 mov %rdi,-0x8(%rbp)
144b: 48 8b 45 f8 mov -0x8(%rbp),%rax
144f: c7 00 01 00 00 00 movl $0x1,(%rax) // SIGSEGV
1455: 90 nop
1456: 5d pop %rbp
1457: c3 retq
0000000000001458 <test_2>:
1458: f3 0f 1e fa endbr64
145c: 55 push %rbp
145d: 48 89 e5 mov %rsp,%rbp
1460: 48 83 ec 08 sub $0x8,%rsp
1464: 48 89 7d f8 mov %rdi,-0x8(%rbp)
1468: 48 8b 45 f8 mov -0x8(%rbp),%rax
146c: 48 89 c7 mov %rax,%rdi
146f: e8 cb ff ff ff callq 143f <test_3>
1474: 90 nop
1475: c9 leaveq
1476: c3 retq
0000000000001477 <test_1>:
1477: f3 0f 1e fa endbr64
147b: 55 push %rbp
147c: 48 89 e5 mov %rsp,%rbp
147f: 48 83 ec 08 sub $0x8,%rsp
1483: 48 89 7d f8 mov %rdi,-0x8(%rbp)
1487: 48 8b 45 f8 mov -0x8(%rbp),%rax
148b: 48 89 c7 mov %rax,%rdi
148e: e8 c5 ff ff ff callq 1458 <test_2>
1493: 90 nop
1494: c9 leaveq
1495: c3 retq
Signal = 11 Memory location = 0x12345678
RIP = 000000000C0E744F RSP = 00000000029CAB30 RBP = 00000000029CAB30
RAX = 0000000012345678 RBX = 000000000C0E7540 RCX = 00000000317BE166
RDX = 0000000000000000 RSI = 00000000029CAA20 RDI = 0000000012345678
R8 = 0000000000000000 R9 = 0000000000000000 R10 = 0000000000000008
R11 = 0000000000000246 R12 = 000000000C0E7140 R13 = 00000000029CAD20
R14 = 0000000000000000 R15 = 0000000000000000 RFLAGS = 0000000000010202
./backtrace2(+0x1407)[0x56150c0e7407] // backtrace
/lib/x86_64-linux-gnu/libc.so.6(+0x43090)[0x7f38317be090]
./backtrace2(test_3+0x10)[0x56150c0e744f] // SIGSEGV
./backtrace2(test_2+0x1c)[0x56150c0e7474] // test_2 -> test3
./backtrace2(test_1+0x1c)[0x56150c0e7493] // test_1 -> test2
./backtrace2(main+0x86)[0x56150c0e751c] // main -> test_1
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf3)[0x7f383179f083]
./backtrace2(_start+0x2e)[0x56150c0e716e]
#endif