android native 調試 打印調用棧

在調試 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);
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章