Crash排查系列第五篇|掌握源码调试技巧

336 阅读5分钟

背景: 在我们平常开发中经常会遇到一些framework, system_process, art中的一些问题。很多时候我们是需要翻阅代码去查看问题。但是很容易因为某个分支判断不对走错路。 掌握调试技巧后可以帮我更清晰的梳理代码逻辑及复现问题。

image.png

准备工作:准备好一台手机或模拟器(建议使用pixel真机,我这边用的是pixel 3xl)用于刷机(用于调试的代码必须和刷入的镜像文件保持一致) .

Java 层调试

第一种方式

[这种方式比较麻烦耗时比较长,这边主要介绍第二种方式]

自己从asop仓库拉取分支代码构建

  1. 下面地址中选择自己手机机型匹配的代码分支进行代码clone 自己打包镜像文件刷机。

source.android.com/docs/setup/… 我这边选择了

在 Android 8.0.0 (Oreo) 及更高版本中,每个 build 均采用 build ID 格式 PVBB.YYMMDD.bbb[.Cn] 进行标识,其中:

  • P 表示平台版本代号的第一个字母,例如 O 表示 Oreo。
  • V 表示支持的类别。按照惯例,P 表示主要平台分支。
  • BB 是由字母和数字组成的代码,Google 可通过该代码识别 build 所属的确切代码分支。
  • YYMMDD 表示相应版本从开发分支细分出来或与开发分支同步的日期。它并不一定是 build 的确切构建日期,因为 Google 常常会在现有 build 中增加细微的更改,并在新 build 中重复使用与现有 build 相同的日期代码。
  • bbb 表示具有相同日期代码的不同版本,从 001 开始。
  • Cn 是可选的字母数字,表示在现有 PVBB.YYMMDD.bbb build 之上构建的修补程序,从 A1 开始
  1. 搭建构建环境 (我这里磁盘映像设置200G才够用)
  2. 下载源代码 (这里需要注意切换到自己需要的分支拉取 不然文件特别多,导致后面不够打包)
  3. 构建
  4. 刷写设备

第二种方式

看手机里系统版本号下载对应版本源码 或者下载已有镜像进行刷机

在aosp相应版本对应分支只下载自己需要调试的代码即可。

分为刷机和代码导入android studio 两个步骤

刷机

下面地址可以找到对应pixel手机的镜像文件。

developers.google.com/android/ima…

  1. 解锁

    1. 如需在设备上启用 OEM 解锁功能,请执行以下操作:
    2. 在“设置”中,点按关于手机,然后点按版本号七次。
    3. 当看到“您已处于开发者模式”这条消息后,点按返回按钮。
    4. 点按开发者选项,然后启用 OEM 解锁USB 调试(如果 OEM 解锁处于停用状态,请连接到互联网,以便设备可以至少检入一次。如果“OEM 解锁”仍处于停用状态,说明设备可能已被运营商锁定 SIM 卡,系统无法解锁引导加载程序。)
  • 重新启动进入引导加载程序,然后使用 fastboot 解锁。

    • adb reboot bootloader
  • 对于新款设备(2015 年及之后发布的设备):

    • fastboot flashing unlock
  • 对于老款设备(2014 年及之前发布的设备):

    • fastboot oem lock
  1. 下载对应镜像文件 解压刷机

    1. 重新启动进入引导加载程序
  • adb reboot bootloader
  • Mac 下执行flash-all.sh文件就行。
  • 等待刷机完成重启。

源码导入studio

AOSP仓库地址

  1. 下载源码导入android studio

    1. 下载自己需要调试的代码就行,比如要查看ActivityThread.java代码
    2. android.googlesource.com/platform/fr… 点击链接下载压缩包

  1. 获取android.iml,和android.ipr 文件(这俩个文件可以在aosp下 development/tools/idegen 生成 也可以网上下载)

  2. 新建文件目录

注意这里我们上面下载的app代码是没有前面的frameworks这种路径的 我需要自己手动创建

最后使用studio的import project将我们新建的目录导入。 新增一个android configuration

  1. 调试例子 我们在ActivityThread的 handleResumeActivity下一个断点。找到debug按钮 attach到指定进程。来个切换后台前台操作就可以看断点有没有断到了。然后就可以单步调试了。

image.png

image.png

Native 层调试

native层调试需要带有符号文件的so支持。这个so一般是编译的时候生成的。 以调试art为例子

我这边64位产物路径在/AOSP/out/target/product/crosshatch/symbols/system/lib64/libart.so下。 下面用调试crash 处理举个例子。

  1. attach进程 选择java+native调试模式

  2. 点击以下pause按钮

image.png

在LLDB控制台下使用add-dsym添加so目录

br s -n HandleUncaughtExceptions 在HandleUncaughExceptions方法处添加断点

(lldb 使用命令可以查相关文档)

点击运行 再触发crash

image.png

System process调式

System process进程Java调试方式和上面说的java层调试有些区别。因为调式的进程必须要是debugable的。我们默认用上面方式刷机System process是非debugable。

下面介绍如何让System process debugable

首先root

  1. oem解锁 上文有介绍

  2. 安装MagisjManager apk

  3. 获取镜像文件中的boot.img文件 推到手机sdcard下

    1. adb push /youpath/boot.img /sdcard/Download

  1. 使用MagisjManager path boot.image 获取到magisk_patched.img

    1. 将magisk_patched.img 拉到pc本地
    2. adb reboot bootloader
    3. fastboot flash boot /youpath/magisk_patched.img
    4. 重启手机 adb shell ,su 看看能不能申请到root权限。

Android 13需要将boot.img 统一改为init_boot.img flash命令也需要改

fastboot flash init_boot /youpath/magisk_patched.img

  1. 修改全局debugable
adb shell 

su

magisk resetprop ro.debuggable 1

stop;start
  1. 通过上面java 层调试方法attach到system_process进行调试

APK Smali调试

适用于排查线上包问题 无法通过源码调试排查问题

  1. 将apk改为可调试

    1. 使用上述System process方式 全局设置为debugable
    2. 使用重打包软件手机端(MT管理器) PC端(ApkTool) 修改AndroidManifest 中的debugable为true.
  2. Android studio 安装以下插件 smartdea-0.06

  3. 使用AndroidStudio 打开apk

  1. 在smali文件中打断点 ,点击调试按钮