#include "ivbacktrace.h" #ifndef USE_BOOSTBACKTRACE #ifdef Q_OS_WIN32 void RegisterIVBackTrace() { } #else #include #include #include #include #include #include #include #include #include void out_stack(char *sig); void signal_exit(int dunno) { char* signal_str = (char*)" "; char dunno_str[10] = {0}; sprintf(dunno_str, "%d", dunno); switch (dunno) { case 1: signal_str = (char*)"SIGHUP(1)"; break; case 2: signal_str = (char*)"SIGINT(2:CTRL_C)"; //CTRL_C break; case 3: signal_str = (char*)"SIGQUIT(3)"; break; case 6: { signal_str = (char*)"SIGABRT(6)"; out_stack(signal_str); } break; case 9: signal_str = (char*)"SIGKILL(9)"; break; case 15: signal_str = (char*)"SIGTERM(15 KILL)"; //kill break; case 11: { signal_str = (char*)"SIGSEGV(11)"; //SIGSEGV out_stack(signal_str); } break; default: signal_str = (char*)"OTHER"; break; } exit(0); } size_t get_executable_path( char* processdir,char* processname, size_t len) { char* path_end; int nsize; if((nsize =readlink("/proc/self/exe", processdir,len)) <=0) return -1; processdir[nsize] = '\0'; path_end = strrchr(processdir, '/'); if(path_end == NULL) return -1; ++path_end; strcpy(processname, path_end); *path_end = '\0'; return (size_t)(path_end - processdir); } void savetofile(char * stroutput) { qDebug("save file"); char strpath[1024]; QDateTime dt = QDateTime::currentDateTime(); char path[1000]; char processname[1024]; get_executable_path(path, processname, 1000); snprintf(strpath,255,"%s/log/%s-%d-%s.log",getenv("HOME"),processname, getpid(),dt.toString("yyyyMMddhhmmsszzz").toLatin1().data()); char strdir[1024]; snprintf(strdir,255,"%s/log",getenv("HOME")); QDir xdir; xdir.setPath(strdir); if(!xdir.exists()) { qDebug("create dir %s",strdir); xdir.mkdir(strdir); } qDebug("%s\n",strpath); FILE* file = fopen(strpath,"w+"); if(file != nullptr) { fwrite(stroutput,strnlen(stroutput,6000),1,file); } fclose(file); } static void output_addrline(char addr[],char * strtem) { char cmd[256]; char line[256]; char addrline[32]={0,}; char *str1, *str2; FILE* file; snprintf(strtem,1000," "); // str1 = strchr(addr,'['); // str2 = strchr(addr, ']'); str1 = strchr(addr,'('); str2 = strchr(addr, ')'); if(str1 == NULL || str2 == NULL) { return; } if((str2 -str1 -2)<=0) { // printf("can't find address,please use -g compile."); // strncpy(strtem,"can't find address,please use -g compile.",256); str1 = strchr(addr,'['); str2 = strchr(addr, ']'); if(str1 == NULL || str2 == NULL) { return; } if((str2 -str1 -2)<=0) { printf("can't find address,please use -g compile."); strncpy(strtem,"can't find address,please use -g compile.",256); return; } } memcpy(addrline, str1 + 1, str2 -str1 -1); snprintf(cmd, sizeof(cmd), "addr2line -e /proc/%d/exe %s ", getpid(), addrline); qDebug("%s\n",cmd); file = popen(cmd, "r"); if(NULL != fgets(line, 256, file)) { printf("%s\n", line); snprintf(strtem,1000,"%s\n",line); } if(strnlen(line,255) == 0) { printf("no addr.\n"); } pclose(file); } static void proc_addrline(int64_t xaddr,char * strtem) { char cmd[256]; char line[256]; FILE* file; snprintf(strtem,1000," "); snprintf(cmd, sizeof(cmd), "addr2line -e /proc/%d/exe %x ", getpid(), xaddr); qDebug("%s\n",cmd); file = popen(cmd, "r"); if(NULL != fgets(line, 256, file)) { printf("%s\n", line); snprintf(strtem,1000,"%s\n",line); } if(strnlen(line,255) == 0) { printf("no addr.\n"); } pclose(file); } void out_stack(char *sig) { void *array[32]; size_t size; char **strings; size_t i; char stroutput[6000]; char strtem[1000]; snprintf(stroutput,3000," "); printf("%s\n", sig); qDebug("%s\n", sig); size = backtrace (array, 32); //该函数用于获取当前线程的调用堆栈,获取的信息将会被存放在array中, //它是一个指针列表。参数 32 用来指定array中可以保存多少个void* 元素。 //函数返回值是实际获取的指针个数,最大不超过32大小. strings = backtrace_symbols (array, size); /* backtrace_symbols将从backtrace函数获取的信息转化为一个字符串数组. * 参数array应该是从backtrace函数获取的指针数组, * size是该数组中的元素个数(backtrace的返回值) * 函数返回值是一个指向字符串数组的指针,它的大小同array相同. * 每个字符串包含了一个相对于array中对应元素的可打印信息. * 它包括函数名,函数的偏移地址,和实际的返回地址 */ if (NULL == strings) { printf("backtrace_symbols\n"); return ; } qDebug("size is %d",(int)size); for (i = 0; i