1. 使用addr2line工具定位crash点

/home/youtaos/android4.0.4/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin/arm-eabi-addr2line -e /home/youtaos/chrome-git/chrome_webkit/out/target/product/generic/symbols/system/lib/libwebviewchromium.so -f 00e1fa08


2. find external/chromium_org/third_party/WebKit/ -name "*.cpp" | xargs grep "#if ENABLE" | awk -F ":" '{print $2}' | sort | uniq | wc -l


3. native log re-direct logcat

   #include <android/log.h>

    __android_log_print(ANDROID_LOG_DEBUG, "Tag", "JNI_OnLoad\n");


   mk file:

         LOCAL_LDFLAGS_Release := -L$(SYSROOT)/usr/lib   // no use now.

         LOCAL_SHARED_LIBRARIES := liblog


4. backtrace of c/c++

    1> 首先系统中要有libcorkscrew.so, 可用adb shell到/system/lib下查看

    2> 代码中直接使用Backtrace::getCallStack(); 实现代码如下:单独放在一个文件backtrace.cc中,编译到so文件即可。由于是调试chromium时使用,所以使用了chromimu中base/logging.h的log函数打印。(亲测可用)

        当然了,log输出的只是pc的值,所以还需要addr2line转换为具体文件的某一行或函数

    

#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
#include <corkscrew/backtrace.h>
#include <corkscrew/map_info.h>
#include <corkscrew/symbol_table.h>
#include <corkscrew/ptrace.h>
#include <corkscrew/demangle.h>
#include "base/logging.h"


#define MAX_DEPTH                       31  
#define MAX_BACKTRACE_LINE_LENGTH   8000  
#define PATH "/system/lib/libcorkscrew.so"  

namespace Backtrace {

    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){
        int result = 0;  
        int count = 0;  
        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;  

        // open the so.  
        if(gHandle == NULL) gHandle = dlopen(PATH, RTLD_NOW);  

		if (gHandle == NULL) {
			LOG(ERROR)<<"siyt: ================== gHandle is NULL";
			return result;
		}

        // get the interface for unwind and symbol analyse  
        if(gHandle != NULL) unwind_backtrace = (unwindFn)dlsym(gHandle, "unwind_backtrace");  
        if(gHandle != NULL) get_backtrace_symbols = (unwindSymbFn)dlsym(gHandle, "get_backtrace_symbols");  
        if(gHandle != NULL) free_backtrace_symbols = (unwindSymbFreeFn)dlsym(gHandle, "free_backtrace_symbols");  

        if(!gHandle ||!unwind_backtrace ||!get_backtrace_symbols || !free_backtrace_symbols  ){  
            //ALOGE("Error! cannot get unwind info: handle:%p %p %p %p",  
            //        gHandle, unwind_backtrace, get_backtrace_symbols, free_backtrace_symbols );
            LOG(ERROR)<<"siyt: ================== Error! cannot get unwind info: handle:"<<(void *)gHandle<<", "<<(void *)unwind_backtrace
            <<", "<<(void *)get_backtrace_symbols<<", "<<(void *)free_backtrace_symbols;
            return result;  
        }  

        count= unwind_backtrace(mStack, 1, MAX_DEPTH);  
        get_backtrace_symbols(mStack, count, symbols);  

        LOG(ERROR)<<"siyt: ===============================Backtrace:";
		char line[MAX_BACKTRACE_LINE_LENGTH] = {0};
		const char* mapName = NULL;
		const char* symbolName = NULL;
		size_t fieldWidth = 0;
        for (int i = 0; i < count; i++) {
            mapName = symbols[i].map_name ? symbols[i].map_name : "<unknown>";  
            symbolName =symbols[i].demangled_name ? symbols[i].demangled_name : symbols[i].symbol_name;  
            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 (%u)",  
                            i, symbols[i].relative_pc, mapName, pc_offset);  
                } else {
                    snprintf(line, MAX_BACKTRACE_LINE_LENGTH, "#%02d  pc %08x  %s",  
                            i, symbols[i].relative_pc, mapName);  
                }  
            } else {
                snprintf(line, MAX_BACKTRACE_LINE_LENGTH, "#%02d  pc %08x  %s",  
                        i, symbols[i].relative_pc, mapName);  
            }  

            LOG(ERROR)<<"siyt: "<<line;
        }  

        free_backtrace_symbols(symbols, count);  

        return result;  
    } 
} // namespace Backtrace</span><span style="font-size: 18px;">

    可以写一个简单的shell脚本,来自动转换,代码如下:

用法: 将log中的pc值放到一个文件中,shell脚本执行该文件即可。

#!/bin/sh

if [ "$1" = "" ];
then
    echo "No input file."
    exit
fi

addrs=`cat $1 | awk '{print $7}'` # 获取pc地址值
#echo $addrs

addr2line="$HOME/android4.0.4/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin/arm-eabi-addr2line -e"
symbolsLib="$PWD/out/target/product/generic/symbols/system/lib/libwebviewchromium.so"
for addr in $addrs
do
    echo `$addr2line $symbolsLib $addr`
done


使用ndk-stack打印crash log

./third_party/android_tools/ndk/ndk-stack -dump ~/log/1119-u1-8 -sym /home/xxx/chromium/src/out/Debug/lib/


5. android数据库操作error: SQLiteException: no such table

db.beginTransaction();
try{
   //批量处理操作
   //do something
   db.execSQL("SQL语句", new Object[]{});
   db.execSQL("SQL语句", new Object[]{});
   //设置事务标志为成功,当结束事务时就会提交事务
   db.setTransactionSuccessful(); // 如果在begin和end间没有set successful,则回滚,即之前sql语句执行失败。
}catch(Exception e){}
finally{
   //结束事务
   db.endTransaction();
}

endTransaction()之前调用了setTransactionSuccessful() 方法设置事务的标志为成功则提交事务,没有调用setTransactionSuccessful() 方法则回滚事务。

假设sql语句为create table,如果没有执行setTransactionSuccessful,则就在以后执行query等操作使就会找不到创建的table,即出现错误SQLiteException: no such table。原因就是create table没有成功,而是回滚了。


Logo

更多推荐