瀏覽代碼

utils: Add print_stack function for debugging

Nick Peng 4 年之前
父節點
當前提交
7f1dc8a311
共有 4 個文件被更改,包括 55 次插入3 次删除
  1. 2 2
      src/Makefile
  2. 1 1
      src/smartdns.c
  3. 50 0
      src/util.c
  4. 2 0
      src/util.h

+ 2 - 2
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

+ 1 - 1
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);
 }

+ 50 - 0
src/util.c

@@ -21,7 +21,9 @@
 #endif
 #include "util.h"
 #include "dns_conf.h"
+#include "tlog.h"
 #include <arpa/inet.h>
+#include <dlfcn.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <inttypes.h>
@@ -39,6 +41,7 @@
 #include <sys/types.h>
 #include <time.h>
 #include <unistd.h>
+#include <unwind.h>
 
 #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);
+	}
+}

+ 2 - 0
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 */