android
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
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没有成功,而是回滚了。
更多推荐
所有评论(0)