这篇文章上次修改于 1336 天前,可能其部分内容已经发生变化,如有疑问可询问作者。

title: 华为P40内核编译记录
date: 2020/12/11 21:49:05
updated: 2020/12/13 00:30:16
permalink: compile-p40-kernel-note/

toc: true


这里用p40举例,其实哪款机型其实都一样,下载源码,修改编译配置,编译~

网上有一些教程但还是不够图文并茂

为什么会记录这个呢,因为华为系的手机直接一般是用不了frida的,会出现这个错误:

Failed to attach: remote_write PTRACE_POKEDATA head failed: 5

而这个要重新编译内核,开启ptrace

翻车预警,请先看完再操作

环境和工具

  • kali linux 2019.4
  • make已经降级到3.81
  • p40内核源代码

配置与编译

首先前往华为的开源中心,搜索对应机型的内核源码

地址 -> https://consumer.huawei.com/en/opensource/detail/

有的机型直接搜品牌名可能搜不出来,这个时候请搜具体的机型代码关键词,比如p40就是ANA,p40p(+)就是ELS

为什么要用ndk的包不用官方的aarch64-linux-android-4.9呢,因为经过测试ndk下载)方便一点,更重要的是新版的aarch64-linux-android-4.9移除了aarch64-linux-android-gcc(实际上是改了名字?)

另外前人经验告诉我最好用老版本的,不然各种报错,ndk历史版本

地址 -> https://developer.android.com/ndk/downloads/older_releases

这里选择的是android-ndk-r14b-linux-x86_64.zip

网络不通记得上代理~

tar不要v参数可以省去大量的日志信息~

wget -O ANA-AN00-TN00_Code_Opensource.tar.gz "http://download-c1.huawei.com/download/downloadCenter?downloadId=101691&version=445661&siteCode=worldwide"
tar -xzf ANA-AN00-TN00_Code_Opensource.tar.gz
wget -O android-ndk-r14b-linux-x86_64.zip "https://dl.google.com/android/repository/android-ndk-r14b-linux-x86_64.zip?hl=zh_cn"
7z x android-ndk-r14b-linux-x86_64.zip

接下来修改编译参数

啊...不好意思,p40的内核源码里面好像没有ptrace编译的选项

如果是其他机型有的话,就是把# CONFIG_HUAWEI_PTRACE_POKE_ON is not set修改为CONFIG_HUAWEI_PTRACE_POKE_ON=y

不过重点是能顺利编译kernel,假设已经修改好编译参数了

这是原始的README_Kernel.txt

还需要一个clang-r346389c,可以在这个页面tgz下载,然后解压

cd /root/Desktop/Code_Opensource/kernel/
cd ..
mkdir -p prebuilts/clang/host/linux-x86/clang-r346389c
tar -xzf linux-x86-refs_tags_ndk-r20-clang-r346389c.tar.gz -C prebuilts/clang/host/linux-x86/clang-r346389c

那么开一个terminal,设置一下环境变量,进入kernel源码文件夹开始编译

注意下面两个路径

又是翻车的一篇文章,p40比较新,要用android-ndk-r20b编译才行,于是把下面的android-ndk-r14b命令改成android-ndk-r20b(假设已经下载解压了)

但是它解压出来后,aarch64-linux-android-4.9文件夹的路径太长,最后我还是去android.googlesource.com下载了aarch64-linux-android-4.9

具体是在这里下载的:https://android.googlesource.com/platform/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/+/d1da3473b004989cd0bc389d61a26d104ff5e22a/

然后解压到/root/Desktop/tmp下面了

然后编译的命令如下(如果编译失败记得删除中间创建的out文件夹):

export PATH=$PATH:/root/Desktop/tmp/aarch64-linux-android/bin
export CROSS_COMPILE=/root/Desktop/tmp/bin/aarch64-linux-android-
cd /c/kernel/
mkdir ../out
make ARCH=arm64 O=../out merge_kirin990_defconfig
make ARCH=arm64 O=../out -j8

编译现场

然后报错:

make[4]: *** [drivers/hisi/modem/modem_symbol.o] Error 127
make[3]: *** [drivers/hisi/modem] Error 2
make[3]: *** Waiting for unfinished jobs....

然后又测试了几次还是这样,但是不知道哪里错了,然后用单线程编译,发现错误是execvp: /bin/sh: Argument list too long,如图:

然后把对应文件改了一下,再次编译,结果还是不成,反反复复测试,最后把代码文件夹移动到根目录,并且把代码目录名改到只有一个字符,然后正常编译...

然后到vmlinux.o的时刻,会大量占用内存(?),然后崩掉,也就是link-vmlinux.sh: line 94: 17257 Killed这个错误

但是这似乎不太科学,想起来虚拟器的内存分配的地方提示:超出此大小可能会发生内存交换

emmm,那还是改成8G的内存吧...

后来经肉丝指点,不是这个问题,是因为内存和swap都不够大

于是内存上到12G,swap上到20G(实际上swap超过实际内存大小并没有意义)

dd if=/dev/zero of=/swapfile bs=1k count=20480000
mkswap /swapfile
swapon /swapfile

编译开始和编译到vmlinux.o时的内存情况



漫长的等待后,编译完成

这个时候还不能直接刷到手机,要通过pack_kernerimage_cmd.sh稍稍修改一下,路径是kernel/tools/pack_kernerimage_cmd.sh

本身是下面这个命令:

/mkbootimg --kernel kernel --base 0x0 --cmdline "loglevel=4 page_tracker=on printktimer=0xfa89b000,0x534,0x538 rcupdate.rcu_expedited=1 androidboot.selinux=enforcing buildvariant=user" --tags_offset 0x66000000 --kernel_offset 0x00080000 --ramdisk_offset 0x66200000 --header_version 2 --os_version 10 --os_patch_level 2020-05-01  --output kernel.img

out/arch/arm64/boot/Image.gz改名为kernel,复制到pack_kernerimage_cmd.sh同目录,执行命令或脚本即可

关于上面命令中的参数来源,可以通过dd命令将原手机的kernel分区备份出来,使用Android Image Kitchen解包(注意它不能在中文路径下解包)得到对应参数,注意备份

下载链接:https://forum.xda-developers.com/t/tool-android-image-kitchen-unpack-repack-kernel-ramdisk-win-android-linux-mac.2073775/

这里没有P40,所以是打包后的解包效果

这里有一疑问,相关链接说的都是boot分区,但实际上应该是kernel分区(或者是不同时期的不一样?但这个输出文件夹就是boot,看来我缺少一点知识),至于这个疑问,是因为发现有的手机没有boot分区,最多有个bootinfo什么的

将对应参数替换后就能生成kernel.img文件了,然后就可以刷到kernel分区(如果是其他机型,开了ptrace编译选项的话,就能跑frida了)

以上

参考链接