Android调试之Framewrok Native调试

概述

转载请注明出处:https://blog.csdn.net/wangzaieee/article/details/83895089

我们知道Android Framework层不仅仅是只有java代码,还有许多c/c++代码,比如init进程和MediaPlayerService,CameraService等本地系统服务,都是用c和c++实现的。这个时候我们要分析问题和追踪代码最好的方式就是调试。如果想要了解Framework Java的调试方法,请看本文

今天我们主要讲解两种情况下的native代码调试:

  • 调试运行中的native进程(以CameraService connect方法为例)
  • 调试native进程的启动 (以init进程的启动为例)

调试CameraService connect方法

准备条件

  • 有已经编译好的安卓源码(debug版)
  • 使用上述镜像的debug设备

调试步骤

调试CameraService的connect方法,流程如下:

  • 初始化调试环境(进入源码根目录执行)
# 运行shell脚本,配置环境
$ source build/envsetup.sh 
# 然后选择自己要调试的编译版本
$ lunch
  • 将设备连接上服务器(如果服务器是远程服务器呢?见下面思考1
  • 查看要调试的进程ID
# CameraService运行在mediaserver进程,获得其进程id
$ adb shell ps | grep mediaserver
  • 然后链接gdb调试该进程。
$ adb root #否则gdbserver(64)没有足够的权限attach到mediaserver进程
$ gdbclient [mediaserver的进程id]

# 这个时候进入了gdb调试模式
# 给CameraService的connect方法打断点
# c++方法需要加上前面的命名空间
(gdb) b android::CameraService::connect 
(gdb) i b #查看当前的断点
#打开摄像头,这个时候会黑屏,因为之前打的断点
(gdb) c #运行到断点
(gdb) bt #查看当前函数栈(可以看到栈顶是connect方法)
(gdb) n #单步调试(nexti 单步指令,l 查看当前的代码,p status打印status的值)
(gdb) c #继续执行至下一个断点(没断点就直接执行完成)

以上就是所有的调试步骤。

调试Init进程的启动

init进程是用户空间的第一个进程,init进程的启动流程可以查看这篇文章。接下来我们来看看这么调试init进程呢?

准备条件

  • 有已经编译好的安卓源码(debug版)
  • 使用上述镜像的debug设备

调试步骤

  • 初始化调试环境(同上)
  • 将设备连上服务器(同上)
  • 启动要调试的进程(如果是wifi调试,就在设备端执行)
$ adb root #否则gdbserver(64)没有足够的权限运行init进程
$ adb shell gdbserver(64) :5039 ./init #Init进程会启动,并且会打印对应的进程id

并且init进程在本机的5039的端口监听之下。

  • 转发端口(如果是wifi调试,在服务端执行)
#将设备的端口转发的服务器的端口(6.0以后不用执行,gdbclient的脚本会执行)
$ adb forward tcp:5039 tcp:5039 

这个时候gdb只要连接本地的5039端口,就相当于连接上了设备的5039端口,gdb就间接通过gdbserver连接上init进程。

  • gdb开始调试init进程的启动
$ gdbclient <PID> #<PID>表示init的进程id
  • 进入gdb调试模式
(gdb) b main #给init.c(pp)的main方法打断点
(gdb) c #执行到断点
(gdb) ni #向下走一条指令
(gdb) n #向下走一条代码

step(进入函数体),fin(退出当前函数体),还有很多GDB的指令,有兴趣的可以使用man gdb查看相关参数

思考1: 如果源码在远程服务器上,这个时候应该怎么调试呢?
通过wifi调试,设备连接wifi,保证服务器和设备在同一个局域网内

$ adb tcpip 5555 #在设备端运行
$ adb connect <设备ip地址> #在服务端运行

思考2: gdbclient是什么,做了哪些操作呢?

 #(要求Android 6.0及以上,5.0在build/envsetup.sh中找gdbclient()方法即可)
 $ which gdbclient 
 # 可以看到gdbclient脚本的位置

然后我们查看里面的代码就可以发现,它做了如下几个操作:

1.设置端口转发(adb forward)
2.启动gdbserver,并将gdbserver attach到想要调试的进程
3.gdb 连接上gdbserver进行调试

PS: gdbclient [pid]如果连接过程中报错,也可以分析gdbclient源码来解决哦

总结

调试运行中的进程调试本地进程的启动,操作步骤大致相同,都是先通过gdbserver进行监听,然后设置端口转发,gdb通过gdbserver进行远程调试。调试技巧对于分析源码,了解执行流程都起到了至关重要的作用。

以上就是Framework Native代码的调试流程,如果觉得对你有帮助请留下一个赞吧~ 觉得写的不好也请批评指出~

参考资料:
使用GDB

Android Framework 中添加自定义库,可以通过以下步骤实现: 1. 将自定义库的源代码添加到 Android Framework 中,通常情况下位于 `frameworks/base/core/java` 或 `frameworks/base/services/core/java` 目录下。 2. 在 `frameworks/base/core/res` 或 `frameworks/base/services/core/res` 目录下添加自定义库的资源文件,比如布局文件、字符串资源等。 3. 在 Android.mk 文件中添加自定义库的编译配置信息,包括源代码的编译和资源文件的打包。 4. 在 AndroidManifest.xml 文件中注册自定义库,以便系统可以识别和加载该库。 5. 在 Java 代码中使用 `import` 语句导入自定义库的类,并在代码中调用该类的方法。 需要注意的是,自定义库需要在 APK 中进行引用才能被 APK 调用。可以通过以下步骤将自定义库引用到 APK 中: 1. 在 APK 的 build.gradle 文件中添加依赖库的引用,例如: ``` dependencies { implementation project(':mylibrary') } ``` 其中 `mylibrary` 是自定义库的名称。 2. 在 APK 的 AndroidManifest.xml 文件中添加自定义库的使用权限,例如: ``` <uses-library android:name="mylibrary" android:required="true" /> ``` 其中 `mylibrary` 是自定义库的名称。 完成以上步骤后,自定义库就可以被 APK 调用了。需要注意的是,自定义库只能被具有相应权限的应用调用。如果需要让所有应用都能调用该库,可以考虑将库打包成系统级别的 APK,并将其放置到 `/system/app` 目录下。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值