Android 系统调试(2)---android debug 方法
2018-04-01 11:35
323 查看
1、查看Android各个版本源码
http://androidxref.com/2. 获取Trace
调用栈信息(Trace)是分析异常经常使用的,这里简单划分两类情况:当前线程Trace: 当前执行流所在线程的调用栈信息;
目标进程Trace:可获取目标进程的调用栈,用于动态调试;
2.1 当前线程Trace
1) Java层Thread.currentThread().dumpStack(); //方法1 Log.d(TAG,"Gityuan", new RuntimeException("Gityuan")); //方法2 new RuntimeException("Gityuan").printStackTrace(); //方法32) Native层
#include <utils/CallStack.h> android::CallStack stack(("Gityuan"));
2.2 目标进程Trace
1) Java层adb shell kill -3 [pid] //方法1 Process.sendSignal(pid, Process.SIGNAL_QUIT) //方法2生成trace文件保存在文件
data/anr/traces.txt2) Native层
adb shell debuggerd -b [tid] //方法1 Debug.dumpNativeBacktraceToFile(pid, tracesPath) //方法2前两条命令输出内容相同:命令1输出到控制台
命令2输出到目标文件
对于debuggerd命令,若不带参数则输出tombstones文件,保存到目录
/data/tombstones3) Kernel层
adb shell cat /proc/[tid]/stack //方法1 WatchDog.dumpKernelStackTraces() //方法2其中dumpKernelStackTraces()只能用于打印当前进程的kernel线程
2.3 小节
以下分别列举输出Java, Native, Kernel的调用栈方式:类别 | 函数式 | 命令式 |
---|---|---|
Java | Process.sendSignal(pid, Process.SIGNAL_QUIT) | kill -3 [pid] |
Native | Debug.dumpNativeBacktraceToFile(pid, tracesPath) | debuggerd -b [pid] |
Kernel | WD.dumpKernelStackTraces() | cat /proc/[tid]/stack |
/data/anr/traces.txt /data/tombstones/tombstone_X /data/system/dropbox/
3. 时间调试
为了定位耗时过程,有时需要在关注点添加相应的systrace,而systrace可跟踪系统cpu,io以及各个子系统运行状态等信息,对于kernel是利用Linux的ftrace功能。当然也可以直接在方法前后加时间戳,输出log的方式来分析。3.1 新增systrace
1) Appimport android.os.Trace; void foo() { Trace.beginSection("app:foo"); ... Trace.endSection(); }2) Java Framework
import android.os.Trace; void foo() { Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "fw:foo"); ... Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); }3) Native Framework
#define ATRACE_TAG ATRACE_TAG_GITYUAN #include <utils/Trace.h> // used for C++ #include <cutils/trace.h> // used for C void foo() { ATRACE_CALL(); ... }或者
#define ATRACE_TAG ATRACE_TAG_GITYUAN #include <utils/Trace.h> // used for C++ #include <cutils/trace.h> // used for C void foo() { ATRACE_BEGIN(); ... ATRACE_END(); }
3.2 打印时间戳
1) Javaimport android.util.Log; void foo(){ long startTime = System.currentTimeMillis(); ... long spendTime = System.currentTimeMillis() - startTime; Log.i(TAG,"took " + spendTime + “ ms.”); }2) C/C++
#include <stdio.h> #include <sys/time.h> void foo() { struct timeval time; gettimeofday(&time, NULL); //精度us printf("took %lld ms.\n", time.tv_sec * 1000 + time.tv_usec /1000); }
3.3 kernel log
有时候Kernel log的输出是由级别限制,可通过如下命令查看:adb shell cat /proc/sys/kernel/printk 4 4 1 7参数解读:控制台日志级别:优先级高于该值的消息将被打印至控制台。
缺省的消息日志级别:将用该值来打印没有优先级的消息。
最低的控制台日志级别:控制台日志级别可能被设置的最小值。
缺省的控制台日志级别:控制台日志级别的缺省值
日志级别:
级别 | 值 | 说明 |
---|---|---|
KERN_EMERG | 0 | 致命错误 |
KERN_ALERT | 1 | 报告消息 |
KERN_CRIT | 2 | 严重异常 |
KERN_ERR | 3 | 出错 |
KERN_WARNING | 4 | 警告 |
KERN_NOTICE | 5 | 通知 |
KERN_INFO | 6 | 常规 |
KERN_DEBUG | 7 | 调试 |
logcat -L 或 cat /proc/last_kmsg
logcat -b events -b system
4. addr2line
addr2line功能是将函数地址解析为函数名。分析过Native Crash,那么对addr2line一定不会陌生。 addr2line命令参数:Usage: addr2line [option(s)] [addr(s)] The options are: @<file> Read options from <file> -a --addresses Show addresses -b --target=<bfdname> Set the binary file format -e --exe=<executable> Set the input file name (default is a.out) -i --inlines Unwind inlined functions -j --section=<name> Read section-relative offsets instead of addresses -p --pretty-print Make the output easier to read for humans -s --basenames Strip directory names -f --functions Show function names -C --demangle[=style] Demangle function names -h --help Display this information -v --version Display the program's version
4.1 Native地址转换
Step 1: 获取symbols表先获取对应版本的symbols,即可找到对应的so库。(最好是对应版本addr2line,可确保完全匹配)Step 2: 执行addr2line命令// 64位 cd prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin ./aarch64-linux-android-addr2line -f -C -e libxxx.so <addr1> //32位 cd /prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.9/bin ./arm-linux-androideabi-addr2line -f -C -e libxxx.so <addr1>另外,有兴趣可以研究下
development/scripts/stack,地址批量转换工具。
4.2 kernel地址转换
addr2line也适用于调试分析Linux Kernel的问题。例如,查询如下命令所对应的代码行号[<0000000000000000>] binder_thread_read+0x2a0/0x324Step 1: 获取符号地址通过命令arm-eabi-nm从vmlinux找到目标方法的符号地址,其中nm和vmlinux所在目录:arm-eabi-nm位于目录prebuilts/gcc/linux-x86/arm/arm-eabi-4.8/bin/
vmlinux位于目录out/target/product/xxx/obj/KERNEL_OBJ/
执行如下命令:(需要带上绝对目录)
arm-eabi-nm vmlinux |grep binder_thread_read则输出结果:
c02b2f28 T binder_thread_read,可知binder_thread_read的符号地址为c02b2f28, 其偏移量为0x2a0,则计算后的目标符号地址= c02b2f28 + 2a0,然后再采用addr2line转换得到方法所对应的行数Step 2: 执行addr2line命令
./aarch64-linux-android-addr2line -f -C -e vmlinux [目标地址]
相关文章推荐
- Android系统移植与调试之安装apk时MTK命令和出现Failure [INSTALL_FAILED_DEXOPT]问题解决方法
- Mac OS X系统下adb调试Android手机的方法
- android系统调试方法
- 关于Android系统调试程序经常出现的错误解决方法(一)
- Mac系统Android Studio获取调试版及开发版SHA1方法
- AndroidStudio的Debug调试方法学习
- Android 系统调试(1)---禁止Selinux 的方法
- Android系统adb调试命令及常用抓log方法
- android-kernel 增加debug-fs调试方法
- Android系统adb调试命令及常用抓log方法
- Android系统调试方法1
- Android系统移植与调试之安装apk时MTK命令和出现Failure [INSTALL_FAILED_DEXOPT]问题解决方法
- android.os.Debug调试工具使用方法
- Windows和Linux系统的Debug调试信息输出方法
- Android系统移植与调试之------->安装apk时出现错误Failure [INSTALL_FAILED_DEXOPT]问题解决的方法
- Android 系统源码调试方法
- 打开android debug设备系统调试
- [Android 调试] 解决linux系统不识别设备、手机问题方法
- Android部分厂商手机无法连接Mac系统进行调试的解决方法
- Android在sdk上编译调试系统原生应用的方法