Eclipse动态调试指南

本文对Eclipse进行动态调试做一个全面的讲解(动态调试还可以采用Android studio、netbeans等工具,请参见Android studio动态调试指南),旨在为广大只有apk而没有源代码的程序猿提供排查bug的另辟蹊径。

操作步骤

1.反编译

对目标apk使用apktool反编译出可调试的smali代码到out文件夹,目前apktool最新的版本是2.0.1。

e.g. java -jar apktool_2.0.1.jar d -d target.apk -o out

注意:-d参数是必须的,因为这样反编译出来的代码后缀均是java,因为只有java文件才能被eclipse/netbeans识别调试。

2.设置调试标记

在输出的out文件夹中,用文本编辑工具打开AndroidManifest.xml,在application节点中设置属性android:debuggable=”true”。

e.g. <application android:debuggable="true" android:icon="@drawable/icon" android:label="@string/app_name" android:name="com.boyaa.godsdk.core.MutiUnipayApplication">

3.在主Activity的onCreate事件中添加调试等待(可选)

注意:如果不需要在程序的开头调试的话,建议忽略这一步。

用文本编辑工具打开主类文件,找到onCreate方法,在第一句前插入invoke-static {}, Landroid/os/Debug;->waitForDebugger()V,记得添加a=0;//的前缀保持上下一致,结果如下:

a=0;// # virtual methods
a=0;// .method protected onCreate(Landroid/os/Bundle;)V
a=0;//     invoke-static {}, Landroid/os/Debug;->waitForDebugger()V
a=0;// 
a=0;//     .locals 1
a=0;//     .param p1, "savedInstanceState"    # Landroid/os/Bundle;
a=0;// 
a=0;//     .prologue
a=0;//     .line 11
a=0;//     invoke-super {p0, p1}, Landroid/app/Activity;->onCreate(Landroid/os/Bundle;)V

4.保存文件,用apktool重新编译打包为debug.apk

e.g. java -jar apktool_2.0.1.jar b -d out -o debug.apk

5.对debug.apk签名(建议采用安卓逆向助手),生成debug_sign.apk

当然也可以直接采用JDK里面的签名工具通过命令行手动进行签名:
e.g. “jarsigner” -keystore “C:\Users\CoulsonChen\Desktop\kop.keystore” -storepass “kop1122334” -keypass “kop1122334” “D:\t\125.apk” “kop” -sigalg SHA1withRSA -digestalg SHA1

6.上传debug_sign.apk至手机或模拟器,然后安装并运行。

如果启用第3步,这时你会看到程序运行后停留在白屏界面,这时不要动设备和退出程序,因为程序现在是运行到刚才添加的waitForDebugger代码这里,这行代码的意思是一直挂起中,等待调试器。

如果未启用第3步,则apk正常运行(与普通安装apk无异)。

7.启动eclipse,构建java项目

  1. File -> New -> Project -> Java Project -> Next
  2. Project Name随便起,Use default location选项去掉,Location选择第1步指定的out文件夹,然后Next
  3. 把smali文件夹设为Source Folder,然后Finish

8.在eclipse中,在需要关注的地方添加断点

设置断点示例:
设置断点示意图

打开DDMS(路径在%android-sdks%\tools\ddms.bat),如果在第6步中运行了修改后的程序,在DDMS的设备列表中会显示可以调试的程序。
DDMS的设备列表

从上图可以看到,调试的端口为8608

9.现在要做的就是把代码与调试程序关联即可

回到eclipse,配置远程调试

  1. 菜单Run -> Debug -> Debug Configurations
  2. 双击Remote Java Application,Host处默认localhost就行,Port填第9步得到的8608,然后Apply -> Debug。

示意图:
关联源码和程序

10.切换至debug视图

看到程序已经运行并中断在下一行可执行的代码了,相关的变量可以直接查看了。示意图:
最终调试