Changes to update Tomato RAF.
[tomato.git] / release / src / router / dnscrypt / src / proxy / stack_trace.c
blob24a7f8f7c8fc6084b75b204b87d11ea47dc79e9e
2 #include <config.h>
3 #ifdef HAVE_SYS_CDEFS_H
4 # include <sys/cdefs.h>
5 #elif defined(HAVE_SYS_FEATURE_TESTS_H)
6 # include <sys/feature_tests.h>
7 #else
8 # include <sys/types.h>
9 #endif
10 #if !defined(_XOPEN_SOURCE) || _XOPEN_SOURCE < 500
11 # undef _XOPEN_SOURCE
12 # define _XOPEN_SOURCE 500
13 #endif
14 #ifndef _GNU_SOURCE
15 # define _GNU_SOURCE 1
16 #endif
17 #if !defined(HAVE_SYS_CDEFS_H) && !defined(HAVE_SYS_FEATURE_TESTS_H)
18 # include <sys/types.h>
19 #endif
21 #ifndef _WIN32
22 # include <dlfcn.h>
23 #endif
24 #ifdef HAVE_EXECINFO_H
25 # include <execinfo.h>
26 #endif
27 #include <signal.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <unistd.h>
32 #include "stack_trace.h"
34 #ifdef __OpenBSD__
35 # undef HAVE_BACKTRACE
36 #endif
38 void
39 stack_trace(void)
41 #ifndef HAVE_BACKTRACE
42 fputs("This platform doesn't support backtrace() yet.\n", stderr);
43 #else
44 void *trace[100];
45 char **messages = NULL;
46 int i;
47 int trace_size = 0;
49 trace_size = backtrace(trace, sizeof(trace) / sizeof(trace[0]));
50 messages = backtrace_symbols(trace, trace_size);
51 fprintf(stderr, "======== Stack trace ========\n");
52 for (i = 1; i < trace_size; ++i) {
53 fprintf(stderr, "%s\n", messages[i]);
55 #endif
58 #ifdef HAVE_BACKTRACE
59 static void
60 stack_trace_signal_handler(int sig, siginfo_t *info, void *f) {
61 (void) info;
62 (void) f;
63 stack_trace();
64 kill(getpid(), sig);
65 abort();
66 /* NOTREACHED */
68 #endif
70 int
71 stack_trace_on_crash(void)
73 #ifdef HAVE_BACKTRACE
74 struct sigaction act;
76 sigemptyset(&act.sa_mask);
77 act.sa_flags = SA_NODEFER | SA_ONSTACK | SA_RESETHAND | SA_SIGINFO;
78 act.sa_sigaction = stack_trace_signal_handler;
79 sigaction(SIGABRT, &act, NULL);
80 sigaction(SIGBUS, &act, NULL);
81 sigaction(SIGFPE, &act, NULL);
82 # ifdef SIGILL
83 sigaction(SIGILL, &act, NULL);
84 # endif
85 sigaction(SIGSEGV, &act, NULL);
86 #endif
88 return 0;
91 #ifdef GCC_TRACE
92 # ifndef __APPLE__
93 # define profile_func_enter(A, B) __cyg_profile_func_enter(A, B)
94 # define profile_func_exit(A, B) __cyg_profile_func_exit(A, B)
95 # endif
97 static unsigned int call_level = 0U;
99 void
100 profile_func_enter(void *this_fn, void *call_site)
101 __attribute__((no_instrument_function));
103 void profile_func_enter(void *this_fn, void *call_site)
105 unsigned int level = 0U;
107 (void) call_site;
108 ++call_level;
109 Dl_info info;
110 this_fn = __builtin_return_address(0);
111 if (dladdr(this_fn, &info) == 0) {
112 return;
114 if (info.dli_sname != NULL &&
115 info.dli_sname[0] == '_' && info.dli_sname[1] == '_') {
116 return;
118 while (level < call_level) {
119 fputs("┃ ", stderr);
120 level++;
122 fputs("┣━━┈", stderr);
123 if (info.dli_sname != NULL && info.dli_sname[0] != 0) {
124 fprintf(stderr, "%s()\n", info.dli_sname);
125 } else {
126 fprintf(stderr, "<%p>()\n", this_fn);
130 void
131 profile_func_exit(void *this_fn, void *call_site)
132 __attribute__((no_instrument_function));
134 void
135 profile_func_exit(void *this_fn, void *call_site)
137 (void) this_fn;
138 (void) call_site;
139 if (call_level > 0U) {
140 call_level--;
143 #endif