-
Notifications
You must be signed in to change notification settings - Fork 12
/
sigsegv_builtin.c
118 lines (103 loc) · 2.59 KB
/
sigsegv_builtin.c
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
117
118
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <stdio.h>
#include <dlfcn.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>
#include <ucontext.h>
/* 纯C环境下,不定义宏NO_CPP_DEMANGLE */
#if (!defined(__cplusplus)) && (!defined(NO_CPP_DEMANGLE))
#define NO_CPP_DEMANGLE
#endif
#ifndef NO_CPP_DEMANGLE
#include <cxxabi.h>
#ifdef __cplusplus
using __cxxabiv1::__cxa_demangle;
#endif
#endif
#ifdef HAS_ULSLIB
#include <uls/logger.h>
#define sigsegv_outp(x) sigsegv_outp(, gx)
#else
#define sigsegv_outp(x, ...) fprintf(stderr, x"\n", ##__VA_ARGS__)
#endif
static void sigsegv_handler(int signo, siginfo_t *info, void *context)
{
sigsegv_outp("Segmentation Fault!");
sigsegv_outp("info.si_signo = %d", signo);
if (info) {
sigsegv_outp("info.si_errno = %d", info->si_errno);
sigsegv_outp("info.si_code = %d (%s)", info->si_code,
(info->si_code == SEGV_MAPERR) ? "SEGV_MAPERR" : "SEGV_ACCERR");
sigsegv_outp("info.si_addr = %p\n", info->si_addr);
}
int i = 0;
Dl_info dl_info;
const void *pc = __builtin_return_address(0);
const void **fp = (const void **)__builtin_frame_address(1);
sigsegv_outp("\nStack trace:");
while (pc) {
memset(&dl_info, 0, sizeof(Dl_info));
if (!dladdr((void *)pc, &dl_info)) break;
const char *sname = dl_info.dli_sname;
#ifndef NO_CPP_DEMANGLE
int status;
char *tmp = __cxa_demangle(sname, NULL, 0, &status);
if (status == 0 && tmp) {
sname = tmp;
}
#endif
/* No: return address <sym-name + offset> (filename) */
sigsegv_outp("%02d: %p <%s + %lu> (%s)", ++i, pc, sname,
(unsigned long)pc - (unsigned long)dl_info.dli_saddr, dl_info.dli_fname);
#ifndef NO_CPP_DEMANGLE
if (tmp) free(tmp);
#endif
if (sname && !strcmp(sname, "main")) break;
if (!fp) break;
#if (defined __x86_64__) || (defined __i386__)
pc = fp[1];
fp = (const void **)fp[0];
#elif (defined __arm__)
pc = fp[-1];
fp = (const void **)fp[-3];
#endif
}
sigsegv_outp("Stack trace end.");
_exit(0);
}
#define SETSIG(sa, signo, func, flags) \
do { \
sa.sa_sigaction = func; \
sa.sa_flags = flags; \
sigemptyset(&sa.sa_mask); \
sigaction(signo, &sa, NULL);\
} while(0)
static void __attribute((constructor)) setup_sigsegv(void)
{
struct sigaction sa;
SETSIG(sa, SIGSEGV, sigsegv_handler, SA_SIGINFO);
}
#if 1
void func3(void)
{
char *p = (char *)0x12345678;
*p = 10;
}
void func2(void)
{
func3();
}
void func1(void)
{
func2();
}
int main(int argc, const char *argv[])
{
func1();
exit(EXIT_SUCCESS);
}
#endif