这篇文章上次修改于 1346 天前,可能其部分内容已经发生变化,如有疑问可询问作者。
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
然后解压到/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
解包(注意它不能在中文路径下解包)得到对应参数,注意备份
这里没有P40,所以是打包后的解包效果
这里有一疑问,相关链接说的都是boot分区,但实际上应该是kernel分区(或者是不同时期的不一样?但这个输出文件夹就是boot,看来我缺少一点知识),至于这个疑问,是因为发现有的手机没有boot分区,最多有个bootinfo什么的
将对应参数替换后就能生成kernel.img文件了,然后就可以刷到kernel分区(如果是其他机型,开了ptrace编译选项的话,就能跑frida了)
以上
已有 4 条评论
大佬,请教下,同样碰到了Argument list too long的问题,按提示把整个opensource mv到根目录,还是提示一样的错误,还请大佬赐教移动哪个目录,修改哪个文件名?
@w /prebuilts
/home/kernel
这样就行了
问下没有ptrace这项,,怎么弄
基带问题有解决方法吗