android native 调试 打印调用栈

Posted 明风的博客

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了android native 调试 打印调用栈相关的知识,希望对你有一定的参考价值。

在调试 android 某些应用时,需要打印调用栈, 但是高版本的5.0 
以上已经去掉了libcorkscrew.so 和 libcutils.so 两个库,
改用其他的google 库文件,但是可以使用andorid 4.4 , 4.3 系统使用。
使用时可以直接调用 getCallStack()该方法即可。
android 6.0 可用 

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;
            
        
        __android_log_print(ANDROID_LOG_INFO, TAG, "uuu:#%02d: %p,%s,%s", i, buffer[i], symbol, file);
    


/********************************hh********************************/

#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);
    

以上是关于android native 调试 打印调用栈的主要内容,如果未能解决你的问题,请参考以下文章

JNI——Android Native代码的内存泄漏问题

利用Xposed Hook打印Java函数调用堆栈信息的几种方法

无法将 Android 模拟器连接到 React Native 调试器

React Native api 调用不会在远程调试模式之外发生(仅限 iOS)

Android各种获取代码调用栈的方法[补]

linux 调用栈打印