Add mbtk dump and
Change-Id: I510bbfa20d954d4212cbb7710337de029cfc95e1
diff --git a/mbtk/libmbtk_lib/Makefile b/mbtk/libmbtk_lib/Makefile
index 5e46530..efa293c 100755
--- a/mbtk/libmbtk_lib/Makefile
+++ b/mbtk/libmbtk_lib/Makefile
@@ -8,7 +8,7 @@
LIB_DIR +=
-LIBS += -llog -lubus -lubox -luci -lprop2uci -lrilutil -lblobmsg_json
+LIBS += -llog -lubus -lubox -luci -lprop2uci -lrilutil -lblobmsg_json -ldl
CFLAGS += -shared -Wl,-shared,-Bsymbolic
@@ -48,6 +48,10 @@
src/mbtk_device_info.c \
src/mbtk_version.c
+ifeq ($(MBTK_DUMP_SUPPORT), y)
+LOCAL_SRC_FILES += src/mbtk_debug.c
+endif
+
OBJS = $(patsubst %.c, %.o, $(patsubst %.cpp, %.o, $(LOCAL_SRC_FILES)))
$(info OBJS = $(OBJS))
diff --git a/mbtk/libmbtk_lib/src/mbtk_debug.c b/mbtk/libmbtk_lib/src/mbtk_debug.c
new file mode 100755
index 0000000..84e13e0
--- /dev/null
+++ b/mbtk/libmbtk_lib/src/mbtk_debug.c
@@ -0,0 +1,381 @@
+/*
+* mbtk_debug.c
+*
+* Generate application exception information.
+*
+*/
+/******************************************************************************
+
+ EDIT HISTORY FOR FILE
+
+ WHEN WHO WHAT,WHERE,WHY
+-------- -------- -------------------------------------------------------
+2024/6/5 LiuBin Initial version
+
+******************************************************************************/
+#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>
+#include <fcntl.h>
+#include <errno.h>
+#include <time.h>
+#include <sys/time.h>
+#include <stdarg.h>
+
+#include "mbtk_type.h"
+#include "mbtk_log.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
+
+#if (defined __x86_64__)
+#define REGFORMAT "%016lx"
+#elif (defined __i386__)
+#define REGFORMAT "%08x"
+#elif (defined __arm__)
+#define REGFORMAT "%lx"
+#endif
+
+#define MBTK_PROC_DUMP_DIR "persist.mbtk.dump_dir"
+#define MBTK_PROC_DUMP_FILE_DEF "/etc/mbtk/mbtk_dump.log"
+
+
+static char proc_name[100];
+static char proc_dump_name[100];
+static int proc_dump_fd = -1;
+
+#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__)
+void sigsegv_outp(const char* format, ...)
+{
+ if(proc_dump_fd > 0) {
+ char buf[1024] = {0};
+ va_list ap;
+ int length = 0;
+
+ va_start(ap, format);
+ length = vsnprintf(buf, sizeof(buf), format, ap);
+ if (length < 0 || 0 == length) {
+ return;
+ }
+
+ char *tmp = buf + length - 1;
+ while(tmp >= buf && (*tmp == '\r' || *tmp == '\n')) {
+ *tmp-- = '\0';
+ }
+ tmp++;
+ *tmp = '\n';
+
+ write(proc_dump_fd, buf, strlen(buf));
+
+ va_end(ap);
+ }
+}
+#endif
+
+static void print_reg(ucontext_t *uc)
+{
+#if (defined __x86_64__) || (defined __i386__)
+ int i;
+ for (i = 0; i < NGREG; i++)
+ {
+ sigsegv_outp("reg[%02d]: 0x"REGFORMAT, i, uc->uc_mcontext.gregs[i]);
+ }
+#elif (defined __arm__)
+ sigsegv_outp("reg[%02d] = 0x"REGFORMAT, 0, uc->uc_mcontext.arm_r0);
+ sigsegv_outp("reg[%02d] = 0x"REGFORMAT, 1, uc->uc_mcontext.arm_r1);
+ sigsegv_outp("reg[%02d] = 0x"REGFORMAT, 2, uc->uc_mcontext.arm_r2);
+ sigsegv_outp("reg[%02d] = 0x"REGFORMAT, 3, uc->uc_mcontext.arm_r3);
+ sigsegv_outp("reg[%02d] = 0x"REGFORMAT, 4, uc->uc_mcontext.arm_r4);
+ sigsegv_outp("reg[%02d] = 0x"REGFORMAT, 5, uc->uc_mcontext.arm_r5);
+ sigsegv_outp("reg[%02d] = 0x"REGFORMAT, 6, uc->uc_mcontext.arm_r6);
+ sigsegv_outp("reg[%02d] = 0x"REGFORMAT, 7, uc->uc_mcontext.arm_r7);
+ sigsegv_outp("reg[%02d] = 0x"REGFORMAT, 8, uc->uc_mcontext.arm_r8);
+ sigsegv_outp("reg[%02d] = 0x"REGFORMAT, 9, uc->uc_mcontext.arm_r9);
+ sigsegv_outp("reg[%02d] = 0x"REGFORMAT, 10, uc->uc_mcontext.arm_r10);
+ sigsegv_outp("FP = 0x"REGFORMAT, uc->uc_mcontext.arm_fp);
+ sigsegv_outp("IP = 0x"REGFORMAT, uc->uc_mcontext.arm_ip);
+ sigsegv_outp("SP = 0x"REGFORMAT, uc->uc_mcontext.arm_sp);
+ sigsegv_outp("LR = 0x"REGFORMAT, uc->uc_mcontext.arm_lr);
+ sigsegv_outp("PC = 0x"REGFORMAT, uc->uc_mcontext.arm_pc);
+ sigsegv_outp("CPSR = 0x"REGFORMAT, uc->uc_mcontext.arm_cpsr);
+ sigsegv_outp("Fault Address = 0x"REGFORMAT, uc->uc_mcontext.fault_address);
+ sigsegv_outp("Trap no = 0x"REGFORMAT, uc->uc_mcontext.trap_no);
+ sigsegv_outp("Err Code = 0x"REGFORMAT, uc->uc_mcontext.error_code);
+ sigsegv_outp("Old Mask = 0x"REGFORMAT, uc->uc_mcontext.oldmask);
+#endif
+}
+
+static void print_call_link(ucontext_t *uc)
+{
+ int i = 0;
+ void **frame_pointer = (void **)NULL;
+ void *return_address = NULL;
+ Dl_info dl_info = { 0 };
+
+#if (defined __i386__)
+ frame_pointer = (void **)uc->uc_mcontext.gregs[REG_EBP];
+ return_address = (void *)uc->uc_mcontext.gregs[REG_EIP];
+#elif (defined __x86_64__)
+ frame_pointer = (void **)uc->uc_mcontext.gregs[REG_RBP];
+ return_address = (void *)uc->uc_mcontext.gregs[REG_RIP];
+#elif (defined __arm__)
+ /* sigcontext_t on ARM:
+ unsigned long trap_no;
+ unsigned long error_code;
+ unsigned long oldmask;
+ unsigned long arm_r0;
+ ...
+ unsigned long arm_r10;
+ unsigned long arm_fp;
+ unsigned long arm_ip;
+ unsigned long arm_sp;
+ unsigned long arm_lr;
+ unsigned long arm_pc;
+ unsigned long arm_cpsr;
+ unsigned long fault_address;
+ */
+ frame_pointer = (void **)uc->uc_mcontext.arm_fp;
+ return_address = (void *)uc->uc_mcontext.arm_pc;
+#endif
+
+ sigsegv_outp("\nStack trace:");
+ while (frame_pointer && return_address)
+ {
+ if (!dladdr(return_address, &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, return_address, sname,
+ (unsigned long)return_address - (unsigned long)dl_info.dli_saddr,
+ dl_info.dli_fname);
+#ifndef NO_CPP_DEMANGLE
+ if (tmp) free(tmp);
+#endif
+ if (dl_info.dli_sname && !strcmp(dl_info.dli_sname, "main"))
+ {
+ break;
+ }
+
+#if (defined __x86_64__) || (defined __i386__)
+ return_address = frame_pointer[1];
+ frame_pointer = frame_pointer[0];
+#elif (defined __arm__)
+ return_address = frame_pointer[-1];
+ frame_pointer = (void **)frame_pointer[-3];
+#endif
+ }
+ sigsegv_outp("Stack trace end.");
+}
+
+static void proc_maps_print() {
+ char file[64] = {0x00};
+ sprintf(file,"/proc/%d/maps", getpid());
+ FILE *fptr = fopen(file, "r");
+ char line[1024];
+ if(fptr)
+ {
+ memset(line, 0, sizeof(line));
+ while(fgets(line, sizeof(line), fptr)) {
+ // printf("Line : %s", line);
+ if(strstr(line, "libmbtk_") || strstr(line, "liblynq_") || strstr(line, "libql_")) {
+ sigsegv_outp("%s", line);
+ }
+ memset(line, 0, sizeof(line));
+ }
+
+ fclose(fptr);
+ }
+}
+
+static void sigsegv_handler(int signo, siginfo_t *info, void *context)
+{
+ printf("sigsegv_handler - %d\n", signo);
+ if (context)
+ {
+ struct timeval log_time;
+ char tmp[50] = {0};
+ gettimeofday(&log_time, NULL);
+ struct tm* tm_t = localtime(&(log_time.tv_sec));
+ strftime(tmp, 50, "%F %T", tm_t);
+ snprintf(tmp + strlen(tmp), sizeof(tmp) - strlen(tmp), ".%d", (int)(log_time.tv_usec / 1000));
+ sigsegv_outp("----------------------------%s----------------------------", tmp);
+
+ proc_maps_print();
+
+ ucontext_t *uc = (ucontext_t *)context;
+ char proc[100] = {0};
+ int fd = open("/proc/self/cmdline", O_RDONLY);
+ if(fd > 0)
+ {
+ if(read(fd, proc, sizeof(proc)) > 0) {
+ sigsegv_outp("Segmentation Fault:%s", proc);
+ } else {
+ sigsegv_outp("Segmentation Fault:%s", "Unknown");
+ }
+ close(fd);
+ } else {
+ sigsegv_outp("Segmentation Fault:%s", "Unknown");
+ }
+
+ sigsegv_outp("info.si_signo = %d", signo);
+ 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 = 0x%x(%p)\n", info->si_addr, info->si_addr);
+
+ print_reg(uc);
+ print_call_link(uc);
+
+ signal(signo, SIG_DFL);
+ raise(signo);
+
+ printf("Segmentation Fault, refer to the log file:%s\n", proc_dump_name);
+ }
+
+ exit(0);
+}
+
+#if 1
+#define BACKTRACE_SIZE 32
+void sigsegv_handler_with_thread(int signo) {
+ struct timeval log_time;
+ char tmp[50] = {0};
+ gettimeofday(&log_time, NULL);
+ struct tm* tm_t = localtime(&(log_time.tv_sec));
+ strftime(tmp, 50, "%F %T", tm_t);
+ snprintf(tmp + strlen(tmp), sizeof(tmp) - strlen(tmp), ".%d", (int)(log_time.tv_usec / 1000));
+ sigsegv_outp("----------------------------%s----------------------------", tmp);
+
+ proc_maps_print();
+
+ char proc[100] = {0};
+ int fd = open("/proc/self/cmdline", O_RDONLY);
+ if(fd > 0)
+ {
+ if(read(fd, proc, sizeof(proc)) > 0) {
+ sigsegv_outp("Segmentation Fault:%s", proc);
+ } else {
+ sigsegv_outp("Segmentation Fault:%s", "Unknown");
+ }
+ close(fd);
+ } else {
+ sigsegv_outp("Segmentation Fault:%s", "Unknown");
+ }
+
+ sigsegv_outp("info.si_signo = %d", signo);
+
+ int j, nptrs;
+ void *buffer[BACKTRACE_SIZE];
+ char **strings;
+ nptrs = backtrace(buffer, BACKTRACE_SIZE);
+ //printf("backtrace() returned %d addresses\n", nptrs);
+ strings = backtrace_symbols(buffer, nptrs);
+ if(strings == NULL){
+ //perror("backtrace_symbols");
+ exit(EXIT_FAILURE);
+ }
+
+ sigsegv_outp("\nStack trace:");
+ if(nptrs > 0) {
+ for (j = 0; j < nptrs; j++) {
+ sigsegv_outp("%02d: %s", j, strings[j]);
+ }
+ }
+ free(strings);
+ sigsegv_outp("Stack trace end.");
+
+ signal(signo, SIG_DFL);
+ raise(signo);
+
+ printf("Segmentation Fault, refer to the log file:%s\n", proc_dump_name);
+ exit(0);
+}
+#endif
+
+#define SETSIG(sa, sig, fun, flags) \
+ do { \
+ sa.sa_sigaction = fun; \
+ sa.sa_flags = flags; \
+ sigemptyset(&sa.sa_mask); \
+ sigaction(sig, &sa, NULL); \
+ } while(0)
+
+
+void mbtk_debug_open(const char *log_file, bool thread_support)
+{
+ struct sigaction sa;
+
+#if 1
+ if(thread_support) {
+ SETSIG(sa, SIGSEGV, sigsegv_handler_with_thread, 0);
+ SETSIG(sa, SIGABRT, sigsegv_handler_with_thread, 0);
+ } else {
+ SETSIG(sa, SIGSEGV, sigsegv_handler, SA_SIGINFO);
+ SETSIG(sa, SIGABRT, sigsegv_handler, SA_SIGINFO);
+ }
+#else
+ SETSIG(sa, SIGSEGV, sigsegv_handler, SA_SIGINFO);
+#endif
+
+ memset(proc_name, 0, sizeof(proc_name));
+ memset(proc_dump_name, 0, sizeof(proc_dump_name));
+ int fd = open("/proc/self/cmdline", O_RDONLY);
+ if(fd > 0)
+ {
+ if(read(fd, proc_name, sizeof(proc_name)) <= 0) {
+ LOGE("Get PROC name fail.");
+ }
+ close(fd);
+ }
+
+ // Redirect stderr to log_file.
+ if(log_file) {
+ memcpy(proc_dump_name, log_file, strlen(log_file));
+ } else {
+ property_get(MBTK_PROC_DUMP_DIR, proc_dump_name, "");
+ if(strlen(proc_dump_name) > 0) {
+ snprintf(proc_dump_name + strlen(proc_dump_name),sizeof(proc_dump_name) - strlen(proc_dump_name), "/%s", proc_name);
+ } else {
+ memcpy(proc_dump_name, MBTK_PROC_DUMP_FILE_DEF, strlen(MBTK_PROC_DUMP_FILE_DEF));
+ }
+ }
+
+#if 0
+ if(freopen(proc_dump_name, "a", stderr) == NULL) {
+ LOGE("reopen stderr to %s fail.[%d]", proc_dump_name, errno);
+ }
+#else
+ proc_dump_fd = open(proc_dump_name, O_WRONLY | O_CREAT | O_APPEND, 0666);
+ if(proc_dump_fd < 0) {
+ LOGE("Open(%s) fail:%d.", proc_dump_name, errno);
+ }
+#endif
+}
+
diff --git a/mbtk/libmbtk_lib/src/mbtk_version.c b/mbtk/libmbtk_lib/src/mbtk_version.c
index cbc2e68..bc2499e 100755
--- a/mbtk/libmbtk_lib/src/mbtk_version.c
+++ b/mbtk/libmbtk_lib/src/mbtk_version.c
@@ -76,6 +76,15 @@
#endif
break;
}
+ case MBTK_BUILD_DEF_MBTK_DUMP_SUPPORT:
+ {
+ strcpy(name, STR_GET(MBTK_BUILD_DEF_MBTK_DUMP_SUPPORT));
+#ifdef MBTK_DUMP_SUPPORT
+ strcpy(value, "Y");
+#else
+ strcpy(value, "N");
+#endif
+ }
default:
{
strcpy(name, "Unknown");