本文介绍: 经过一步步的摸索,将Linux内核成功运行到了Cuttlefish中,在Cuttlefish环境下,可以调试内核调试Native代码调试Framework代码,也可以当作你的常用“开发机”使用。该文章是笔者学习中的一个总结,由于知识面的狭隘总有认识不到的错误产生,请大家不吝赐教。如果大家学习中遇见问题,也欢迎大家交流沟通。

Android Kernel 编译调试指北

环境

指北基于以下代码环境编写

OS     :  Ubuntu 22.04.2 LTS
AOSP   :  master
kernel :  根据编译目标决定
targetaosp_cf_x86_64_phone-userdebug
设备    : Cuttlefish

在前一篇文章说过,因为工具链的原因,AOSP的代码不宜太旧,自上一篇文章以来Cuttlefish功能文档逐步健全,足以见得google对其的投入程度,所以如果版本不一样会遇见无此参数等这样那样的问题本文master测试通过

Android Kernel Repo源码下载

Linux Kernel是Android系统运行的基础,而Linux Kernel的源码在AOSP中并不存在,通常存在的是预构建内核映像,如果想对内核做一些定制化的修改,就需要下载代码构建,Linux Kernel像AOSP有各种各样的分支,并不是随便选择一个分支构建就可以正常运行。编译AOSP对应的Linux Kernel版本才能避免构建过程走很多弯路。每一个AOSP构建目标都预置了预编译的内核映像,可以从内核影像获取相应版本的蛛丝马迹。

需要说明的是Android的内核项目同样是由repo(android.googlesource.com/kernel/mani…) 管理的,其中Linux Kernel的源码存在kernel/common(android.googlesource.com/kernel/comm…) 目录下,其他目录是与构建相关工具链或者脚本等,在之前旧版本Linux Kernel构建中可以直接下载kernel/common代码使用make直接编译出内核镜像,但是随着Android GKI的推出,这套方法就行不通了。读者最好使用repo提供的编译脚本等进行构建

下面以aosp_cf_x86_64_phone-userdebugtarget为例,讲述如何一步找到对应的分支

查找Linux Kernel的versioncommitId

从Android设置界面查找

如果你编译的系统已经成功运行到虚拟机,你可以打开Settings – About Phone – Android Version -Kernel Version 可以看到对应的Kernel信息,Linux的版本号按照major.minor.patchbuild.desc格式通过匹配屏幕输出可以得出内核版本为6.1,从附加描述提取g开头的连续字符可以得知对应的commitId为963667856ef1

image.png

从AOSP树中查找

如果只有一个构建目标aosp_cf_x86_64_phone-userdebug)并没有运行成功虚拟机,可以遵循以下步骤获取

  1. 索引device/google/cuttlefish目录device目录存放芯片硬件厂商相关产品配置,其中cuttlefish作为一款虚拟器,也被添加到了该目录下。
  2. 通过mgrep ":kernel"查看配置文件(该方法不是很通用,可以通过“添加新设备”了解相关知识),最后查看搜索到的配置文件,通过下图可以看到该目标链接kernel映像文件位于kernel/prebuilts/6.1/x86_64/kernel-6.1
  3. 对该文件执行file kernel-6.1得到以下输出,同样可以得到commmitId为963667856ef1
kernel-6.1: Linux kernel x86 boot executable bzImage, version 6.1.25-android14-7-00377-g963667856ef1-ab10271074 (build-user@build-host) #1 SMP PREEMPT Tue Jun  6 23:03:20 UTC 2023, RO-rootFS, swap_dev 0X10, Normal VGA

截图_20230613203254413.png

根据分支拉取Kernel代码

通过上面的操作得到了Linux Kernel的版本commitId,准备就绪就可以着手拉取代码了,需要注意上文获取commitId是指android.googlesource.com/kernel/comm… 仓库的相应提交

根据kernel/commoncommitId找到对应repo分支

直接访问android.googlesource.com/kernel/comm… (注意按照实际输出更改commitId) 就可以得到对应的changeId,通过点击changeId链接就可以看到对应gerrit 地址如下所示,该页面同时标注了Linux kernel的分支[android14-6.1], 这里branch还是Linux Kernel的分支,那么如何得到repo分支内,只有了,通过在 android.googlesource.com/kernel/mani…搜索6.1找到多个结果,通过依次查看分支下的default.xml文件发现commonandroid14-6.1分支指向了Linux Kernel的android14-6.1分支,代码如下<project path="common" name="kernel/common" revision="android14-6.1" /&gt;

截图_20230614103105851.png 截图_20230614103159768.png

拉取Kernel代码

使用从上文得到的kernel的repo分支,使用repo下载Linux Kernel的源码和脚本等

mkdir android-kernel &amp;&amp; cd android-kernel
repo init -u https://android.googlesource.com/kernel/manifest -b common-android14-6.1
repo sync

如果一切OK,代码就下载好了,如果你遇见了任何网络问题,可以参照上一篇文章设置镜像源下载。

Bazel编译Kernel

Android11引入了GKI的特性用于将内核拆分为由 Google 维护的内核映像和由供应商维护模块两个模块分别构建。Android13开始使用Bazel进行编译,由于构建的分支是master分支,所以内核的编译需要使用bazel进行构建,并且需要分别构建两个内核。

//通用内核镜像的构建
$ tools/bazel run //common:kernel_x86_64_dist -- --dist_dir=out
//因为是虚拟机,所以是虚拟设备GKI virtual_device
$ tools/bazel run //common-modules/virtual-device:virtual_device_x86_64_dist -- --dist_dir=out

以上如果构建没有问题,在out目录下会生成bzImageinitramfs.img文件,请记住他们位置,之后会用到

Cuttlefish 应用新内核

使用kernel_pathinitramfs_path即可对Cuttlefish应用新内核,十分方便,需要注意launch_cvd的运行基于上一篇文章编译成功,在AOSP根目录下运行

source build/envsetup.sh
lunch aosp_cf_x86_64_phone-userdebug
launch_cvd -kernel_path /home/prosixe/ssd/Android/android-kernel/out/bzImage -initramfs_path /home/prosixe/ssd/Android/android-kernel/out/initramfs.img 

截图_20230614202847000.png

通过查看系统信息,内核已经发生了改变,系统可以正常开机

使用GDB调试Kernel

使用下面命令使内核可调试,读者实操时注意要区分aosp和android-kernel的目录。

//注意在aosp根目录
source build/envsetup.sh
lunch aosp_cf_x86_64_phone-userdebug
launch_cvd -kernel_path /home/prosixe/ssd/Android/android-kernel/out/bzImage -initramfs_path /home/prosixe/ssd/Android/android-kernel/out/initramfs.img -gdb_port 1234 -cpus=1  -extra_kernel_cmdline nokaslr

然后在另一个终端索引到android-kernel/common方便gdb索引符号

//切换android-kernel根目录
cd common
gdb ../out/vmlinux
(gdb) target remote :1234
(gdb) hbreak start_kernel
(gdb) c

image.png 可以看到内核在start_kernel时停止了,并且可以正常显示对应的源代码

总结

经过一步步的摸索,将Linux内核成功运行到了Cuttlefish中,在Cuttlefish的环境下,可以调试内核,调试Native代码,调试Framework代码,也可以当作你的常用“开发机”使用。
文章是笔者学习中的一个总结,由于知识面的狭隘总有认识不到的错误产生,请大家不吝赐教。如果大家学习中遇见问题,也欢迎大家交流沟通。

原文地址:https://blog.csdn.net/Eqiqi/article/details/131236435

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_37704.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注