diff --git a/src/Makefile b/src/Makefile index 229c9c2..354c1e1 100644 --- a/src/Makefile +++ b/src/Makefile @@ -20,7 +20,7 @@ OBJS=smartdns.o fast_ping.o dns_client.o dns_server.o dns.o util.o tlog.o dns_co # cflags ifndef CFLAGS -CFLAGS =-O2 -g -Wall -Wstrict-prototypes -fno-omit-frame-pointer -Wstrict-aliasing +CFLAGS =-O2 -g -Wall -Wstrict-prototypes -fno-omit-frame-pointer -Wstrict-aliasing -funwind-tables endif override CFLAGS +=-Iinclude override CFLAGS += -DBASE_FILE_NAME=\"$(notdir $<)\" @@ -35,7 +35,7 @@ override CXXFLAGS +=-Iinclude ifeq ($(STATIC), yes) override LDFLAGS += -lssl -lcrypto -Wl,--whole-archive -lpthread -Wl,--no-whole-archive -ldl -static else -override LDFLAGS += -lssl -lcrypto -lpthread +override LDFLAGS += -lssl -lcrypto -lpthread -ldl endif .PHONY: all clean diff --git a/src/smartdns.c b/src/smartdns.c index 70508d2..416c5be 100644 --- a/src/smartdns.c +++ b/src/smartdns.c @@ -363,7 +363,7 @@ static void _sig_error_exit(int signo, siginfo_t *siginfo, void *ct) "%s %s)\n", signo, siginfo->si_code, siginfo->si_errno, siginfo->si_pid, getpid(), PC, (unsigned long)siginfo->si_addr, __DATE__, __TIME__, arch); - + print_stack(); sleep(1); _exit(0); } diff --git a/src/util.c b/src/util.c index 1c25efa..e1fa339 100644 --- a/src/util.c +++ b/src/util.c @@ -21,7 +21,9 @@ #endif #include "util.h" #include "dns_conf.h" +#include "tlog.h" #include +#include #include #include #include @@ -39,6 +41,7 @@ #include #include #include +#include #define TMP_BUFF_LEN_32 32 @@ -1009,3 +1012,50 @@ uint64_t get_free_space(const char *path) return size; } + +struct backtrace_state { + void **current; + void **end; +}; + +static _Unwind_Reason_Code unwind_callback(struct _Unwind_Context *context, void *arg) +{ + struct backtrace_state *state = (struct backtrace_state *)(arg); + uintptr_t pc = _Unwind_GetIP(context); + if (pc) { + if (state->current == state->end) { + return _URC_END_OF_STACK; + } else { + *state->current++ = (void *)(pc); + } + } + return _URC_NO_REASON; +} + +void print_stack(void) +{ + const size_t max_buffer = 30; + void *buffer[max_buffer]; + + struct backtrace_state state = {buffer, buffer + max_buffer}; + _Unwind_Backtrace(unwind_callback, &state); + int frame_num = state.current - buffer; + if (frame_num == 0) { + return; + } + + tlog(TLOG_FATAL, "Stack:"); + for (size_t idx = 0; idx < frame_num; ++idx) { + const void *addr = buffer[idx]; + const char *symbol = ""; + + Dl_info info; + memset(&info, 0, sizeof(info)); + if (dladdr(addr, &info) && info.dli_sname) { + symbol = info.dli_sname; + } + + void *offset = (void *)((char *)(addr) - (char *)(info.dli_fbase)); + tlog(TLOG_FATAL, "#%.2d: %p %s from %s+%p", idx + 1, addr, symbol, info.dli_fname, offset); + } +} \ No newline at end of file diff --git a/src/util.h b/src/util.h index 9efa737..e7e5622 100644 --- a/src/util.h +++ b/src/util.h @@ -108,6 +108,8 @@ int set_sock_lingertime(int fd, int time); uint64_t get_free_space(const char *path); +void print_stack(void); + #ifdef __cplusplus } #endif /*__cplusplus */