在調試 android 某些應用時,需要打印調用棧, 但是高版本的5.0 以上已經去掉了libcorkscrew.so 和 libcutils.so 兩個庫, 改用其他的google 庫文件,但是可以使用andorid 4.4 , 4.3 系統使用。 使用時可以直接調用 getCallStack()該方法即可。
#include <utils/CallStack.h> #include <utils/Trace.h> #include <dlfcn.h> #include <unwind.h> #include <dlfcn.h>
#define MAX_DEPTH 66 #define MAX_BACKTRACE_LINE_LENGTH 800 #define PATH "/system/lib/libcorkscrew.so" #define PATH_uu "/system/lib/libcutils.so" typedef ssize_t (*unwindFn)(backtrace_frame_t *, size_t, size_t); typedef void (*unwindSymbFn)(const backtrace_frame_t *, size_t, backtrace_symbol_t *); typedef void (*unwindSymbFreeFn)(backtrace_symbol_t *, size_t); static void *gHandle = NULL; int getCallStack(void) { ssize_t i = 0; ssize_t result = 0; ssize_t count; backtrace_frame_t mStack[MAX_DEPTH]; backtrace_symbol_t symbols[MAX_DEPTH]; unwindFn unwind_backtrace = NULL; unwindSymbFn get_backtrace_symbols = NULL; unwindSymbFreeFn free_backtrace_symbols = NULL; if (gHandle == NULL) { gHandle = dlopen(PATH_uu, RTLD_NOW); } // open the so. if (gHandle == NULL) { gHandle = dlopen(PATH, RTLD_NOW); } // get the interface for unwind and symbol analyse if (gHandle != NULL) { unwind_backtrace = (unwindFn) dlsym(gHandle, "unwind_backtrace"); } else{ LOGD("tian>>>dleerr55>%s", dlerror()); } if (gHandle != NULL) { get_backtrace_symbols = (unwindSymbFn) dlsym(gHandle, "get_backtrace_symbols"); } else{ LOGD("tian>>>dleerr444>%s", dlerror()); } if (gHandle != NULL) { free_backtrace_symbols = (unwindSymbFreeFn) dlsym(gHandle, "free_backtrace_symbols"); } else{ LOGD("tian>>>dlee6666rr>%s", dlerror()); } if (!gHandle || !unwind_backtrace || !get_backtrace_symbols || !free_backtrace_symbols) { LOGD("tian Error! cannot get unwind info: handle:%p %p %p %p", gHandle, unwind_backtrace, get_backtrace_symbols, free_backtrace_symbols); return result; } count = unwind_backtrace(mStack, 1, MAX_DEPTH); LOGD("tian>>>dleecount>%d", count); get_backtrace_symbols(mStack, count, symbols); for (i = 0; i < count; i++) { char line[MAX_BACKTRACE_LINE_LENGTH]; const char *mapName = symbols[i].map_name ? symbols[i].map_name : "<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, "#%02d pc %08x %.*s (%.*s+%u)", i, symbols[i].relative_pc, fieldWidth, mapName, fieldWidth, symbolName, pc_offset); } else { snprintf(line, MAX_BACKTRACE_LINE_LENGTH, "#%02d pc %08x %.*s (%.*s)", i, symbols[i].relative_pc, fieldWidth, mapName, fieldWidth, symbolName); } } else { snprintf(line, MAX_BACKTRACE_LINE_LENGTH, "#%02d pc %08x %.*s", i, symbols[i].relative_pc, fieldWidth, mapName); } LOGD("tian>>>555>%s", line); } free_backtrace_symbols(symbols, count); return result; }
5.1 手機使用方法。
typedef int (*Unw_BackTrace_Func)(void**, int); void print_backtrace() { static Unw_BackTrace_Func unw_backtrace = NULL; if (!unw_backtrace) { void *hanle = dlopen("libunwind.so", RTLD_NOW); unw_backtrace = (Unw_BackTrace_Func)dlsym(hanle, "unw_backtrace"); } void *buffer[32] = { 0 }; int n = unw_backtrace((void**)&buffer, 32); for(int i = 1; i < n; i++) { const char *file = "\t\t\t\t"; const char *symbol = "\t\t\t\t"; Dl_info info; if (dladdr(buffer[i], &info)) { if (info.dli_sname) { symbol = info.dli_sname; } if (info.dli_fname) { file = info.dli_fname; } } LOGI("#%02d: %p \t %s \t %s", i, buffer[i], symbol, file); } }