美文网首页Android源码编译
Android多版本源码及内核编译(Nexus5)

Android多版本源码及内核编译(Nexus5)

作者: PR老师 | 来源:发表于2017-08-29 20:22 被阅读652次

    因研究逆向工程需要编译多个Android源码和内核在Nexus5真机上运行。通过简书记录编译过程,所以不会针对单个功能做详细介绍,初次接触的同学可以按照下面流程一步一步来进行环境搭建,资源准备,真机编译。


    源码编译

    目标

    • 编译Android4.4.4-r1源码及内核
    • 编译Android6.0.1-r1源码及内核

    硬件环境

    • Ubuntu 14.0.4LTS
    • LG Nexus5 手机

    环境JDK搭建

    关于不同版本安卓源码对JDK版本的要求,如下是官方的文字描述:

    ....
    C. AOSP 中 Android 的 master 分支:Ubuntu - OpenJDK 8;Mac OS - jdk 8u45 或更高版本
    D. Android 5.x (Lollipop) - Android 6.0 (Marshmallow):Ubuntu - OpenJDK 7;Mac OS - jdk-7u71-macosx-x64.dmg
    E. Android 2.3.x (Gingerbread) - Android 4.4.x (KitKat):Ubuntu - Java JDK 6;Mac OS - Java JDK 6
    F. Android 1.5 (Cupcake) - Android 2.2.x (Froyo):Ubuntu - Java JDK 5
    ...

    所以编译Android 4.4.4需要 Java JDK 6, 编译Android6.0.1需要openJDK7

    Java JDK 6已经无法通过apt-get install方式安装, oracle官方下载地址

    Java JDK 6安装过程:

    1 把下载的文件放到自己定义的地方.
    2 修改权限
    $chmod 777 jdk-6u45-linux-x64.bin
    3 执行
    $./jdk-6u45-linux-x64.bin
    4 配置环境变量
    $sudo gedit /etc/profile

    ##添加到profile中保存
    JAVA_HOME=$jdk1.6自定目录/jdk1.6.0_45 
    JRE_HOME=$JAVA_HOME/jre
    CLASSPATH=$CLASSPATH:$JAVA_HOME/lib:$JRE_HOME/lib
    PATH=$PATH:$JAVA_HOME/bin:$JRE_HOME/bin:$JAVA_HOME/lib:$JAVA_HOME
    

    5 使/etc/profile生效
    $source /etc/profile
    6 查看是否生效
    $java –version

    openJDK7 安装过程

    终端上执行下面命令
    $sudo apt-get install openjdk-7-jdk
    正常情况下会安装到/usr/lib/jvm/java-7-openjdk-adm64/目录下

    安装基础软件

    $sudo apt-get install git-core gnupg flex bison gperf build-essential
        zip curl zlib1g-dev gcc-multilib g++-multilib libc6-dev-i386
         lib32ncurses5-dev x11proto-core-dev libx11-dev lib32z-dev ccache
         libgl1-mesa-dev libxml2-utils xsltproc unzip
    

    安装Repo

    1 创建目录

    $ mkdir ~/bin
    $ PATH=~/bin:$PATH
    

    2 下载 Repo 工具

    //使用了清华大学的镜像文件
    $curl https://mirrors.tuna.tsinghua.edu.cn/git/git-repo > ~/bin/repo
    $chmod a+x ~/bin/repo
    

    同步源码

    1 建立工作目录

    $mkdir WORKING_DIRECTORY
    $cd WORKING_DIRECTORY
    

    2 初始化仓库

    //WORKING_DIRECTORY 源码要放的目录
    $mkdir WORKING_DIRECTORY
    $cd WORKING_DIRECTORY
    

    初始化特定的 Android 版本列表文件,本文选择了两个支持Nexus 5的版本
    ,此处使用清华大学的镜像文件。

    //android-4.4.4_r1使用
    $repo init -u https://aosp.tuna.tsinghua.edu.cn/platform/manifest -b android-4.4.4_r1
    //android-6.0.1_r1使用
    $repo init -u https://aosp.tuna.tsinghua.edu.cn/platform/manifest -b android-6.0.1_r1
    

    如果提示无法连接到 gerrit.googlesource.com,参考链接

    3 同步源码
    $repo sync –j4
    同步时间看大家自己网络情况,我的网络比较好,大约花了2个小时同步一个版本

    4 下载驱动文件
    首先查看源码分支列表,确定源码分支代号

    Android4.4.4-r1分支代号KTU84P
    Android6.0.1-r1分支代号MMB29K

    5 下载驱动
    访问https://developers.google.com/android/nexus/drivers#hikey(暂时没发现国内有镜像,如果有需要的话加我QQ3231549366)中找到对应设备与源码分支的硬件驱动。

    KTU84P Nexus5驱动列表 MMB29 Nexus5驱动列表

    下载对应版本的渠道文件,依次解压三个文件,得到的三个shell脚本文件,将其置于源码根目录中再依次执行三个脚本,执行操作前,它会让你阅读相关协议,协议比较多有8项,最后输入I ACCEPT即可。执行完成以后会在源码的主目录生成一个vendor目录。注意执行shell的顺序,我第一次编译的时候没按照顺序执行,刷完机发现屏幕显示有问题,具体原因就没去研究,解决方法:删除了vendor目录,按照顺序又执行了一遍,重新编译后一切正常。

    初始化编译环境

    1 执行配置

    //终端执行
    $source build/envsetup.sh
    //输出信息
    including device/asus/deb/vendorsetup.sh
    including device/asus/flo/vendorsetup.sh
    including device/asus/fugu/vendorsetup.sh
    including device/generic/mini-emulator-arm64/vendorsetup.sh
    including device/generic/mini-emulator-armv7-a-neon/vendorsetup.sh
    including device/generic/mini-emulator-mips/vendorsetup.sh
    including device/generic/mini-emulator-x86_64/vendorsetup.sh
    including device/generic/mini-emulator-x86/vendorsetup.sh
    including device/htc/flounder/vendorsetup.sh
    including device/huawei/angler/vendorsetup.sh
    including device/lge/bullhead/vendorsetup.sh
    including device/lge/hammerhead/vendorsetup.sh
    including device/moto/shamu/vendorsetup.sh
    including sdk/bash_completion/adb.bash
    

    2 选择编译类型

    //终端执行
    $lunch
    //输出信息
    You're building on Linux
    
    Lunch menu... pick a combo:
         1. aosp_arm-eng
         2. aosp_x86-eng
         3. aosp_mips-eng
         4. vbox_x86-eng
         5. aosp_hammerhead-userdebug
         6. aosp_mako-userdebug
         7. aosp_deb-userdebug
         8. aosp_tilapia-userdebug
         9. aosp_grouper-userdebug
         10. aosp_flo-userdebug
         11. mini_armv7a_neon-userdebug
         12. mini_mips-userdebug
         13. mini_x86-userdebug
         14. aosp_manta-userdebug
    
    Which would you like? [aosp_arm-eng]
    //选择5, 因为Nexus5设备代号就是hammerhead,会出现下面的输出信息
    
    #### make completed successfully  ####
    ============================================
    PLATFORM_VERSION_CODENAME=REL
    PLATFORM_VERSION=4.4.4
    TARGET_PRODUCT=aosp_hammerhead
    TARGET_BUILD_VARIANT=userdebug
    TARGET_BUILD_TYPE=release
    TARGET_BUILD_APPS=
    TARGET_ARCH=arm
    TARGET_ARCH_VARIANT=armv7-a-neon
    TARGET_CPU_VARIANT=krait
    HOST_ARCH=x86
    HOST_OS=linux
    HOST_OS_EXTRA=Linux-4.2.0-27-generic-x86_64-with-Ubuntu-14.04-trusty
    HOST_BUILD_TYPE=release
    BUILD_ID=KTU84P
    OUT_DIR=out
    ============================================
    
    

    3 检查Java环境

    //终端执行
    $java –version 
    
    //Android 4.4.4 需要 Java JDK 6
    //Android 6.0.1需要open JDK7
        
    //有的时候大家通过update-alternatives命令切换当前JAVA环境。
    //sudo update-alternatives --config java
    //sudo update-alternatives --config javac
    //sudo update-alternatives --config javaws
    //envsetup.sh中会使用当前环境变量中JAVA_HOME指定的JDK,虽然Android 4.4.4有指定使用java6,最好还是通过修改/etc/profile中JAVA_HOME 指定jdk的版本,
    
    

    编译

    $make –j16
    //j后面的参数取决于你电脑处理器的核心数,j=核心数*2 
    大约2-3个小时。
    

    刷机

    1 进入recovery模式
    将Nexus5设备连接到电脑上,打开usb调试,输入$sudo adb reboot bootloader 手机就会进入recovery模式。
    2 刷机

    $fastboot flashall –w
    //或者fastboot -w flashall 刷机的过程大概在一至两分钟左右,刷机结束后会自动开机。
    

    内核编译

    下载内核

    当前工程目录下新建kernel目录,同步远程kernel代码仓库到本地

    $git clone https://aosp.tuna.tsinghua.edu.cn/kernel/msm.git
    //仓库文件大概有1.2G的大小,同步完成以后本地有文件夹msm
    

    确认分支

    $cd msm
    $git branch -a
    //终端会输出如下信息
        .
        .
        .
      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
        .
        .
        .
    

    1 Android4.4.4_r1分支

    remotes/origin/android-msm-hammerhead-3.4-kitkat-mr2

    2 Android6.0.1_r1分支
    按照设备代号,源码中的内核版本号,Android版本代号描述,有3个分支

    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

    理论上面这3个分支都可以使用,mr是"maintenance release"简写。因工作需要本文还是需要和源码中的kernel一致
    3 通过官方提供的命令行获取
    非 Nexus 5 (hammerhead)运行以下命令

    $ 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'
    //Kernel在源码out/target/product/hammerhead/目录下

    对于 Nexus 5 (hammerhead),请运行以下命令:

    $ 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'
    //zImage-dtb在源码/device/lge/hammerhead-kernel目录下

    //Android4.4.4-r1输出信息
    Linux version 3.4.0-gd59db4e (android-build@vpbs1.mtv.corp.google.com) (gcc version 4.7 (GCC) ) #1 SMP PREEMPT Mon Mar 17 15:16:36 PDT 2014
        Linux version CIFS VFS Client for Linux<7>%s: sess setup type %
    
    //Android6.0.1-r1输出信息
    Linux version 3.4.0-g7717f76 (android-build@kpfi6.cbf.corp.google.com) (gcc version 4.8 (GCC) ) #1 SMP PREEMPT Wed Nov 4 21:42:24 UTC 2015
        Linux version CIFS VFS Client for Linux<7>%s: sess setup type %d
    

    Linux version 3.4.0-gd59db4e 文本中d59db4e是git commit版本号信息
    Linux version 3.4.0-g7717f76 文本中7717f76是git commit版本号信息

    4 在关于手机内核版本信息查看
    5 在代码中或者adb中通过cat /proc/version信息查看

    内核源码下载

    //输入终端命令获取到对应的内核源码:
    //Android4.4.4-r
    $ git checkout d59db4e
    或者
    $ git checkout -b remotes/origin/android-msm-hammerhead-3.4-kitkat-mr2
    
    //Android6.0.1-r
    $ git checkout 7717f76
    
    

    内核源码编译

    设置环境变量

    //需要设置环境变量可以在kernel源码根目录下build.config文件中查看
    //Android6.0.1-r1
    $export ANDROID_SRC_PATH=源码根目录
    $export PATH=$ANDROID_SRC_PATH/prebuilts/gcc/linux-x86/arm/arm-eabi-4.8/bin:$PATH 
    $export ARCH=arm
    $export SUBARCH=arm
    $export CROSS_COMPILE=arm-eabi-
    
    //Android4.4.4-r1
    $export ANDROID_SRC_PATH=源码根目录
    $export PATH=$ANDROID_SRC_PATH/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin:$PATH 
    $export ARCH=arm
    $export SUBARCH=arm
    $export CROSS_COMPILE=arm-eabi-
    
    

    配置
    $make hammerhead_defconfig

    编译

    $make
    

    终端输出:Kernel: arch/arm/boot/zImage-dtb is ready 编译完成

    使用zImage-dtb替换/device/lge/hammerhead-kernel/zImage-dtb文件重新编译源码,编译后boot.img的内核就是我们编译的内核,可以在手机的关于界面内核信息可以看到。

    也可以通过如下文bootimg-tools针对当前编译后的boot.img重打包,毕竟重编译的时间太长了。

    Boot.img重打包

    bootimg-tools工具是一款基于mkbootimg开发的boot.img 解包重打包C语言工具,github地址:https://github.com/pbatard/bootimg-tools

    1 下载编译bootimg-tools

    //kernel/msm根目录终端命令行下执行
    $mkdir bootimg-tools
    $cd bootimg-tools
    $git clone https://github.com/pbatard/bootimg-tools.git
    $make 
    

    编译完成以后,在 makebootimg目录下生成了相应的二进制执行文件,将该二进制文件所在路径添加到 PATH路径中。

    2 终端上执行解包

    $cd 源码目录/out/target/product/hammerhead/
    $unmkbootimg –i boot.img
    
    //执行完毕输出信息
    /* 
    kernel written to 'kernel' (8451496 bytes)
    ramdisk written to 'ramdisk.cpio.gz' (923769 bytes)
    
    To rebuild this boot image, you can use the command:
      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 kernel --ramdisk ramdisk.cpio.gz -o boot.img
    */
    

    3 覆盖原来的kernel
    把内核源码目录下生成的arch/arm/boot目录下的zImage-dtb拷贝到Android源码目录out/target/product/hammerhead下。
    并改名为kernel(注意备份原始的kernel文件)

    4 重打包
    使用步骤2中输出的mkbootimg 命令

    //ramdisk.cpio.gz boot.img 可以在命令上指定目录,例子是在当前目录下执行,所以不需要全路径
    $cd 安卓源码目录/out/target/product/hammerhead/
    $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 kernel --ramdisk ramdisk.cpio.gz -o boot.img
    

    生成boot.img后,连接手机执行烧写

    5 烧写

    $ adb reboot bootloader
    $ fastboot flash boot boot.img
    

    总结

    本文介绍了2个版本源码和内核编译,其它版本源码和内核版本类似,主要是如何确认细节部分文中也做了说明。
    后续会写些逆向工程方面的学习资料,主要包含基础知识,相关工具介绍,逆向思维,主要是Android方面了。

    参考文档:
    1 https://source.android.com/source/requirements
    2 http://blog.csdn.net/liu1075538266/article/details/51272398
    3 https://mirrors.tuna.tsinghua.edu.cn/help/AOSP/

    相关文章

      网友评论

        本文标题:Android多版本源码及内核编译(Nexus5)

        本文链接:https://www.haomeiwen.com/subject/evladxtx.html