三、Android系統內核編譯及刷機實戰 (修改反調試標誌位)

前言

二、Android系統源碼編譯及刷機實戰 一文中,我們成功編譯了Android 4.4.4_r1源碼並刷入系統了 Nexus 5 設備,下面是設置界面的信息。上面顯示的內核版本信息是3.4.0-gd59db4e,內核的編譯時間是Mon Mar 17 15:16:36 PDT 2014,也就是說內核之前就已經編譯過了,我們編譯系統源碼的時候並沒有編譯內核源碼!那麼編譯好的內核文件放在了哪裏呢?答案是device/<vendor>/<name>目錄,針對Nexus 5 設備,就是device/lge/hammerhead-kernel目錄

這裏寫圖片描述

系統源碼和內核源碼是可以分開編譯的,如果僅僅對內核修改,就沒必要編譯系統源碼。所以下面的過程是在假設我們沒有下載系統源碼的情況下操作的!爲了編譯成功,沒下載系統源碼的同學一定要 參考 一、Android系統源碼下載實戰一文把編譯環境配置一下。類似於Android源碼根目錄,可以新建一個內核編譯項目的根目錄文件夾AndroidKernal,把後面的各種操作下載在該目錄下進行。至於已經下載系統源碼的同學,就在Android系統源碼根目錄下新建kernel文件夾作爲根目錄。Google 官方教程:https://source.android.com/source/building-kernels

一、選擇內核項目

我們首先應當確定自己設備所對應的內核。Google官方給出了二進制文件的名稱及內核源代碼所在Android源碼樹中的位置:(這時內核源代碼還沒有下載本地)

這裏寫圖片描述

各個版本內核源碼項目所對應的下載命令:Google也給出了相應的下載命令:

$ git clone https://android.googlesource.com/kernel/common.git
$ git clone https://android.googlesource.com/kernel/hikey-linaro
$ git clone https://android.googlesource.com/kernel/x86_64.git
$ git clone https://android.googlesource.com/kernel/exynos.git
$ git clone https://android.googlesource.com/kernel/goldfish.git
$ git clone https://android.googlesource.com/kernel/msm.git
$ git clone https://android.googlesource.com/kernel/omap.git
$ git clone https://android.googlesource.com/kernel/samsung.git
$ git clone https://android.googlesource.com/kernel/tegra.git

由於網絡連接問題,可以把上面所有 git clone命令中https://android.googlesource.com/網址換成清華鏡像站的https://aosp.tuna.tsinghua.edu.cn/ 網址。

各個內核項目所支持的設備

  • goldfish 項目包含適用於所模擬的平臺的內核源代碼。
  • msm 項目包含適用於 ADP1、ADP2、Nexus One、Nexus 4、Nexus 5、Nexus 6、Nexus 5X、Nexus 6P、Nexus 7 (2013)、Pixel 和 Pixel XL 的源代碼,可用作使用 Qualcomm MSM 芯片組的起點。
  • omap 項目用於 PandaBoard 和 Galaxy Nexus,可用作使用 TI OMAP 芯片組的起點。
  • samsung 項目用於 Nexus S,可用作使用 Samsung Hummingbird 芯片組的起點。
  • tegra 項目用於 Xoom、Nexus 7 (2012)、Nexus 9,可用作使用 NVIDIA Tegra 芯片組的起點。
  • exynos 項目包含適用於 Nexus 10 的內核源代碼,可用作使用 Samsung Exynos 芯片組的起點。
  • x86_64 項目包含適用於 Nexus Player 的內核源代碼,可用作使用 Intel x86_64 芯片組的起點。
  • hikey-linaro 項目用於 HiKey 參考板,可用作使用 HiSilicon 620 芯片組的起點。

我用是Nexus 5手機, 代號 harmmerhead(錘頭),查找上表知道,內核二進制文件所在系統源碼樹的device/lge/hammerhead-kernel目錄,內核源碼在系統源碼樹的kernel/msm目錄,內核對應的編譯配置爲hammerhead_defconfig, 該版本內核項目對應的下載命令爲

git clone https://aosp.tuna.tsinghua.edu.cn/kernel/msm.git

二、下載內核源碼項目,檢出內核分支代碼

msm內核項目是Google公司針對高通msm移動芯片組(驍龍處理器)而開發的內核項目,我們在之前創建的AndroidKernel目錄下執行git命令下載該項目(已經下載Android系統源碼的同學在系統根目錄下創建kernel目錄下進行下載)

$ git clone https://aosp.tuna.tsinghua.edu.cn/kernel/msm.git

這裏寫圖片描述

這時msm 項目的.git倉庫 下載到了新創建的msm目錄中,而msm內核的代碼還沒有從本地.git倉庫中檢出來,所以整個msm目錄空空的。
進入 msm 目錄後,查看msm項目的所有分支。下面的只列出了Nexus 5(代號:harmmerhead)相關的內核分支

aosp444@aosp444-virtual-machine:~/AndroidKernel/msm$ git branch -a

* master
  remotes/origin/HEAD -> origin/master
  remotes/origin/android-4.4
  remotes/origin/android-4.4.y
  remotes/origin/android-msm-2.6.35
  remotes/origin/android-msm-3.9-usb-and-mmc-hacks

......
  remotes/origin/android-msm-hammerhead-3.4-kitkat-mr1
  remotes/origin/android-msm-hammerhead-3.4-kitkat-mr2
  remotes/origin/android-msm-hammerhead-3.4-kk-fr1
  remotes/origin/android-msm-hammerhead-3.4-kk-fr2
  remotes/origin/android-msm-hammerhead-3.4-kk-r1
  remotes/origin/android-msm-hammerhead-3.4-l-preview
  remotes/origin/android-msm-hammerhead-3.4-lollipop-mr1
  remotes/origin/android-msm-hammerhead-3.4-lollipop-mr1.1
  remotes/origin/android-msm-hammerhead-3.4-lollipop-release
  remotes/origin/android-msm-hammerhead-3.4-m-preview
  remotes/origin/android-msm-hammerhead-3.4-marshmallow
  remotes/origin/android-msm-hammerhead-3.4-marshmallow-mr1
  remotes/origin/android-msm-hammerhead-3.4-marshmallow-mr2
  remotes/origin/android-msm-hammerhead-3.4-marshmallow-mr3
......

該檢出哪個分支呢?由於我不是特別熟悉git 命令操作,並不能根據git日誌詳細區分各個版本之間的區別。AOSP前技術領導人Jean-Baptiste Queru在給一位內核開發提交者的郵件中寫道,在安卓分支後綴中,mr = "maintenance release", fr = "factory rom".,分支的名字在開發中是不斷變化,最好以commid id進行提交。那麼我們就以commid id進行檢出。官方給出的實例是按分支名進行下載,但是我暫時確定不了分支,所以採用了commid id這種方式。
那麼我們怎麼獲得內核的版本信息與其中commid id呢?

官方給出了一條通用的命令,來獲得指定二進制內核文件的版本信息

dd if=kernel bs=1 skip=$(LC_ALL=C grep -a -b -o $'\x1f\x8b\x08\x00\x00\x00\x00\x00' kernel | cut -d ':' -f 1) | zgrep -a 'Linux version'

例:
這裏寫圖片描述

而Nexus 5 設備的內核名爲zImage-dtb,官方給出的針對該設備的命令是:

$ dd if=zImage-dtb bs=1 skip=$(LC_ALL=C od -Ad -x -w2 zImage-dtb | grep 8b1f | cut -d ' ' -f1 | head -1) | zgrep -a 'Linux version'

這裏寫圖片描述

事實上,我們可以在設置 > 關於手機 > 內核版本 中直接查看內核版本信息,也可以通過cat /proc/version 命令查看。內核版本信息的格式爲kernel version-gXXXXXXX,其中 XXXXXXX部分的值是git提交中 的short commit id的值(即kernel version-g<short commit id>),short commit id的值爲commit id值的前7位。Nexus 5 設備Adnroid 4.4.4_r1版本 AOSP自帶的內核值是`3.4.0-gd59db4e , 並且刷入手機能正常運行。
檢出帶代碼有兩種方式(推薦第二種):
一、直接 short commit id = d59db4e 來檢出分支。

$ git checkout d59db4e

這裏寫圖片描述

檢出代碼後的msm目錄:

這裏寫圖片描述

二、確定 short commit id 所在的分支,按分支進行檢出(推薦)

在本地 git clone msm 項目後,本地只有一個’master’ 分支,我們可以執行git branch -r --contains d59db4e 命令來查看包含 d59db4ecommit id 的分支
這裏寫圖片描述

然後我們可以在遠程分支的基礎上在本地分化出一個新的分支來

$ git checkout -b android-msm-hammerhead-3.4-kitkat-mr2  origin/android-msm-hammerhead-3.4-kitkat-mr2

我們輸入git log 命令,發現d59db4e 值就是android-msm-hammerhead-3.4-kitkat-mr2最後一次提交的 short commit id

這裏寫圖片描述

三、下載預編譯工具鏈,添加路徑到PATH中

1.下載 gcc交叉編譯工具鏈

之前下載過AOSP源碼樹的同學,就不用再下載預編譯工具鏈了,AOSP跟目錄中後該工具鏈。沒有下載AOSP源碼樹的同學,在AndroidKernel目錄下執行該執行進行下載:

$  git clone https://aosp.tuna.tsinghua.edu.cn/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6

這裏寫圖片描述

2.配置交叉工具鏈路徑到環境變量中

已經下載 AOSP源碼樹的同學,進入的源碼樹根目錄下 ,重新執行source build/envsetup.sh命令就會自動配置好環境變量。
沒有下載源樹的同學,在AndroidKernel目錄下執行export PATH=$(pwd)/arm-eabi-4.6/bin:$PATH就會配置到環境變量中。

這裏寫圖片描述

注意上述兩種方法都是在命令行中配置的,計算機重啓後會消失需重新配置,可將交叉編譯工具的的bin路徑寫到~/.bashrc文件中

四、配置編譯選項,進行編譯

編譯前,一定要確定交叉工具鏈的路徑在PATH 變量中。
在內核交叉編譯前,配置一下編譯選項


$ export ARCH=arm   //指明目標體系架構,arm、x86、arm64、
$ export CROSS_COMPILE=arm-eabi-  //指定使用的交叉編譯器的前綴

進入到msm 目錄,配置

$ cd msm
$ make hammerhead_defconfig

這裏寫圖片描述

執行 make 命令進行編譯

$ make

編譯成功後,會提示

這裏寫圖片描述

這時會在arch/arm/boot/ 目錄生成 ImagezImagezImage-dtb 三個文件 。其中zImage-dtb 就是之前使用的內核二進制文件。

五、對boot.img 文件進行重打包

一、準備bootimg-tools工具

bootimg-tools工具是一款基於mkbootimg開發的boot.img 解包重打包C語言工具,github地址:https://github.com/pbatard/bootimg-tools
在烏班圖上用下面的命令下載:

$ git clone https://github.com/pbatard/bootimg-tools.git 

下載後進入bootimg-tools目錄,執行make 命令編譯該項目,在 makebootimg目錄下生成了相應的二進制執行文件,將該二進制文件所在路徑添加到 PATH路徑中

$ make

這裏寫圖片描述

二、使用 unmkbootimg 二進制文件進行解包

$ unmkbootimg -i boot.img 

解包後生成 kernelramdisk.cpio.gz 兩個文件

這裏寫圖片描述

三、用unmkbootimg 將之前編譯生成的 zImage-dtb 替換kernel 進行重打包

$ mkbootimg --base 0 --pagesize 2048 --kernel_offset 0x00008000 --ramdisk_offset 0x02900000 --second_offset 0x00f00000 --tags_offset 0x02700000 --cmdline 'console=ttyHSL0,115200,n8 androidboot.hardware=hammerhead user_debug=31 maxcpus=2 msm_watchdog_v2.enable=1' --kernel zImage-dtb  --ramdisk ramdisk.cpio.gz -o bootnew.img

這裏寫圖片描述

六、將新生成的bootnew.img刷入設備

輸入下面的命令進入fastboot 模式,並解鎖

$ adb reboot bootloader
$ fastboot oem unlock

bootloader模式下輸入下面的命令將bootnew.img 刷入boot分區

$ fastboot flash boot bootnew.img

這裏寫圖片描述

七、修改內核源碼中的調試標誌位

如果我們用推薦的第二種方式下載內核源碼,輸入git branch命令可以查看當前已經切換到分支

這裏寫圖片描述

我們可用git 工具對修改的內核源碼進行版本控制。
下面修改相應的調試標誌位:
第一處 msm/fs/proc/base.c文件 273行 proc_pid_wchan 函數修改爲(主要對285行進行了修改)

static int proc_pid_wchan(struct task_struct *task, char *buffer)
{
    unsigned long wchan;
    char symname[KSYM_NAME_LEN];

    wchan = get_wchan(task);

    if (lookup_symbol_name(wchan, symname) < 0)
        if (!ptrace_may_access(task, PTRACE_MODE_READ))
            return 0;
        else
            return sprintf(buffer, "%lu", wchan);
    else{   
                if (strstr(symname, "trace")) {
                      return sprintf(buffer, "%s", "sys_epoll_wait");
                } 
        return sprintf(buffer, "%s", symname);
            }
}

第二處 msm/fs/proc/array.c 文件 134行

static const char * const task_state_array[] = {
    "R (running)",      /*   0 */
    "S (sleeping)",     /*   1 */
    "D (disk sleep)",   /*   2 */
    "S (sleeping)",     /*   4 */
    "S (sleeping)",         /*   8 */
    "Z (zombie)",       /*  16 */
    "X (dead)",     /*  32 */
    "x (dead)",     /*  64 */
    "K (wakekill)",     /* 128 */
    "W (waking)",       /* 256 */
};

第三處 msm/fs/proc/array.c 文件 180行

seq_printf(m,
        "State:\t%s\n"
        "Tgid:\t%d\n"
        "Pid:\t%d\n"
        "PPid:\t%d\n"
        "TracerPid:\t%d\n"
        "Uid:\t%d\t%d\t%d\t%d\n"
        "Gid:\t%d\t%d\t%d\t%d\n",
        get_task_state(p),
        task_tgid_nr_ns(p, ns),
        pid_nr_ns(pid, ns),
        ppid, /*tpid*/0,
        cred->uid, cred->euid, cred->suid, cred->fsuid,
        cred->gid, cred->egid, cred->sgid, cred->fsgid);

修改完成後,將修改後的base.carray.c文件提交到本地倉庫

$ git add array.c base.c
$ git commit  -m "change kernel anti flags"

再次按 上面的 三~ 六 步驟 編譯內核重新生成boot.timg刷入手機

這裏寫圖片描述

測了一下 TracerPid值爲0

這裏寫圖片描述

參考資料:
1.https://groups.google.com/forum/#!msg/android-building/5SKMilqvXys/LgbF576GF-YJ
2.https://softwarebakery.com/building-the-android-kernel-on-linux
3.http://marcin.jabrzyk.eu/posts/2014/05/building-and-booting-nexus-5-kernel
4.http://blog.csdn.net/qq1084283172/article/details/54880488

發佈了45 篇原創文章 · 獲贊 31 · 訪問量 12萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章