/** * 获取JNI层调用栈 * @param out * @return 0:success 1:failure */ int get_callstack(std::string &out, pid_t tid) { const int MAX_DEPTH = 31; const int MAX_BACKTRACE_LINE_LENGTH = 800; ssize_t i = 0; ssize_t result = 0; ssize_t count = 0; backtrace_frame_t mstack[MAX_DEPTH]; backtrace_symbol_t symbols[MAX_DEPTH]; static unwindFn unwind_backtrace = NULL; static unwindSymbFn get_bt_syms = NULL; static unwindSymbFreeFn free_bt_syms = NULL; if (tid == -1) { tid = gettid(); } // open the so. static void *corkscrew_handle = NULL; if (corkscrew_handle == NULL) { // todo For Android N, dlopen will fail corkscrew_handle = dlopen(vxStrEnc("/system/lib/libcorkscrew.so"), RTLD_NOW); unwind_backtrace = (unwindFn) dlsym(corkscrew_handle, vxStrEnc("unwind_backtrace_thread")); get_bt_syms = (unwindSymbFn) dlsym(corkscrew_handle, vxStrEnc("get_backtrace_symbols")); free_bt_syms = (unwindSymbFreeFn) dlsym(corkscrew_handle, vxStrEnc("free_backtrace_symbols")); } if (!corkscrew_handle || !unwind_backtrace || !get_bt_syms || !free_bt_syms) { // cannot get unwind info return -1; } // get the interface for unwind and symbol analyse count = unwind_backtrace(tid, mstack, 0, MAX_DEPTH); // -1 as error get_bt_syms(mstack, count, symbols); out = ""; for (i = 0; i < count; i++) { char line[MAX_BACKTRACE_LINE_LENGTH]; const char *mapname = symbols[i].map_name ? symbols[i].map_name : vxStrEnc("<unknown>"); const char *symbolname = symbols[i].demangled_name ? symbols[i].demangled_name : symbols[i].symbol_name; size_t fieldwidth = (MAX_BACKTRACE_LINE_LENGTH - 80) / 2; if (symbolname) { uint32_t pc_offset = symbols[i].relative_pc - symbols[i].relative_symbol_addr; if (pc_offset) { snprintf(line, MAX_BACKTRACE_LINE_LENGTH, vxStrEnc("#%02d pc %08x %.*s (%.*s+%u)\n"), i, symbols[i].relative_pc, fieldwidth, mapname, fieldwidth, symbolname, pc_offset); } else { snprintf(line, MAX_BACKTRACE_LINE_LENGTH, vxStrEnc("#%02d pc %08x %.*s (%.*s)\n"), i, symbols[i].relative_pc, fieldwidth, mapname, fieldwidth, symbolname); } } else { snprintf(line, MAX_BACKTRACE_LINE_LENGTH, vxStrEnc("#%02d pc %08x %.*s\n"), i, symbols[i].relative_pc, fieldwidth, mapname); } out += line; } if (count >= 0) { free_bt_syms(symbols, count); } return 0; }