[转组第10天] | Android6.0.0_r1源码编译和POC程序的编译

Posted nww-570

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[转组第10天] | Android6.0.0_r1源码编译和POC程序的编译相关的知识,希望对你有一定的参考价值。

2018-05-23

android6.0.0_r1源码编译

简要说明:android源码编译的四个流程:1.源码下载;2.构建编译环境;3.编译源码;4运行.下文也将按照该流程讲述。

 

主机环境

Ubuntu 16.04 LTS

Android 6.0.0_r1

Open JDK 7

 

源码下载

由于某墙的原因,这里我们采用国内的镜像源进行下载.
目前,可用的镜像源一般是科大和清华的,具体使用差不多,这里我选择清华大学镜像进行说明.(参考:科大源,清华源)

Google采用Repo管理Android源码,所以要先下载Repo工具.

通过执行以下命令实现repo工具的下载和安装:

1 mkdir ~/bin
2 PATH=~/bin:$PATH
3 curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo
4 chmod a+x ~/bin/repo

 

建立源码文件夹 

熟悉Git的同学都应该知道,我们需要为项目在本地创建对应的仓库.同样,这里为了方便对代码进行管理,我们为其创建一个文件夹.这里我在当前用户目录下创建了source文件夹,后面所有的下载的源码和编译出的产物也都放在这里,命令如下:

1 mkdir source
2 cd source


初始化仓库
 

我们将上面的source文件夹作为仓库,现在需要来初始化这个仓库了.通过执行初始化仓库命令可以获取AOSP项目master上最新的代码并初始化该仓库,命令如下:

1 repo init -u https://aosp.tuna.tsinghua.edu.cn/platform/manifest -b android-6.0.0_r1

(AOSP项目当前所有的分支列表参看:分支列表)-b参数表示指定获取某个特定的Android版本,这里我们指定android-6.0.0_r1.

 

同步源码到本地

初始化仓库之后,就可以开始正式同步代码到本地了,命令如下:

1 repo sync

将该文件保存在源码目录下,也就是我们的source目录,然后执行该脚本即可,安心的等待源码下载完成,预计花费3小时左右就可下载完成。由于网络原因,在使用repo sync同步代码的过程中会多次出错,这里我们采用一个shell脚本使其同步失败时自动重试:

1 #!/bin/bash  
2 echo "======start repo sync======"  
3         repo sync  # 第一次下载android源代码
4         while [ $? != 0 ]; do
5         echo "======sync failed, re-sync again======"  
6         sleep 2
7         repo sync  #  如果出错,隔2秒后回继续调用repo sync下载android源代码
8         done

 

注意:由于 .repo 目录是隐藏目录,因此在下载完成之前你是不看到啥东西的。

 

构建编译环境

硬件要求:

64位的操作系统只能编译2.3.x以上的版本,如果你想要编译2.3.x以下的,那么需要32位的操作系统.

 

软件要求:

操作系统,在AOSP开源中,主分支使用Ubuntu长期版本开发和测试的,因此也建议你使用Ubuntu进行编译,下面我们列出不同版本的的Ubuntu能够编译那些android版本:

Android版本

编译要求的Ubuntu最低版本

Android 6.0至AOSP master

Ubuntu 14.04

Android 2.3.x至Android 5.x

Ubuntu 12.04

Android 1.5至Android 2.2.x

Ubuntu 10.04

JDK版本,

Android版本

编译要求的JDK版本

AOSP的Android主线

OpenJDK 8

Android 5.x至android 6.0

OpenJDK 7

Android 2.3.x至Android 4.4.x

Oracle JDK 6

Android 1.5至Android 2.2.x

Oracle JDK 5

更具体的可以参看:Google源码编译要求

 

安装JDK

由于我们安装的是android6.0,我们需要采用OpenJDK7,而但是在Ubuntu 15.04及之后的版本的在线安装库中只支持openjdk8和openjdk9的安装,因此在Ubuntu16.04上安装OpenJDK7需要执行下面命令:

1 sudo add-apt-repository ppa:openjdk-r/ppa
2 sudo apt-get update
3 sudo apt-get install openjdk-7-jdk

配置OpenJDK,打开/etc/profile文件:

1 sudo gedit /etc/profile

在末尾追加下面代码:

1 # jdk path config
2 export JAVA_HOME=/usr/lib/jvm/java-7-openjdk-amd64
3 export JRE_HOME=${JAVA_HOME}/jre
4 export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib
5 export PATH=${JAVA_HOME}/bin:$PATH

修改/etc/profile文件重启生效:

1 source /etc/profile

检查OpenJDK配置是否正确:

1 java -version

 配置成功如下图:

 技术分享图片

 

安装环境依赖:(16.04环境依赖)

 1 sudo apt-get install libx11-dev:i386 libreadline6-dev:i386 libgl1-mesa-dev g++-multilib
 2 sudo apt-get install -y git flex bison gperf build-essential libncurses5-dev:i386
 3 sudo apt-get install tofrodos python-markdown libxml2-utils xsltproc zlib1g-dev:i386
 4 sudo apt-get install dpkg-dev libsdl1.2-dev libesd0-dev
 5 sudo apt-get install git-core gnupg flex bison gperf build-essential
 6 sudo apt-get install zip curl zlib1g-dev gcc-multilib g++-multilib
 7 sudo apt-get install libc6-dev-i386
 8 sudo apt-get install lib32ncurses5-dev x11proto-core-dev libx11-dev
 9 sudo apt-get install libgl1-mesa-dev libxml2-utils xsltproc unzip m4
10 sudo apt-get install lib32z-dev ccache

 注意:不同Ubuntu所需要的依赖不同,一定要安装正确。

 

修改源码:

修改source/art/build/Android.common_build.mk文件,定位到75行,将下面代码:

1 ifneq ($(WITHOUT_HOST_CLANG),true)

改为:

1 ifeq ($(WITHOUT_HOST_CLANG),false)

修改的目的是把CLANG编译选项关闭。

 

上面的工作完成后,基本的预准备工作就已经完成。下面是正式的编译步骤。

 

初始化编译环境:

(当前目录在包含Android源码的source目录下)

确保上述过程完成后,接下来我们需要初始化编译环境

1)在.bashrc文件末尾添加:export USER_CCACHE = 1

1 echo export USER_CCACHE=1 >> ~/.bashrc

2)为了提高编译效率,设置编译器高速缓存:

1 prebuilts/misc/linux-x86/ccache/ccache -M 50G

3)接着导入编译Android源码所欲要得环境变量和其他参数:

1 source build/envsetup.h

 执行命令结果如下:

技术分享图片

不难发现该命令只是引入了其他执行脚本,至于这些脚本做什么,目前不在本文中细说.
该命令执行成功后,我们会得到了一些有用的命令,比如最下面要用到的lunch命令.

 

编译源码

执行lunch命令

1 lunch

 控制台会列出所有的编译目标,如下:

技术分享图片

这里选择aosp_arm-eng,表示生成arm架构的工程师版本,拥有最大权限(root),此外还附带了许多debug工具。

这里输入1之后,会输出一些环境变量信息:

技术分享图片

 

开始编译

通过make指令进行代码编译,该指令通过-j参数来设置参与编译的线程数量,以提高编译速度.比如这里我们设置8个线程同时编译:

1 make -j8

如果一切顺利的话,在几个小时之后,便可以编译完成.看到### make completed successfully (01:18:45(hh:mm:ss)) ###表示你编译成功了.需要注意的是,参与编译的线程并不是越多越好,通常是根据你机器cup的核心来确定:core*2,即当前cpu的核心的2倍.比如,我现在的笔记本是双核四线程的,因此根据公式,最快速的编译可以make -j8.
(通过cat /proc/cpuinfo查看相关cpu信息)

 

运行模拟器

编译完成之后,就可以通过下面命令运行Android虚拟机了,命令如下:

1 source build/envsetup.sh
2 lunch(选择刚才你设置的目标版本,比如这里了我选择的是1)
3 emulator

不出意外,稍作等待,会看到运行界面:像lunch,emulator这些命令是属于envsetup.sh的,如果你没有离开刚编译完源码的终端,直接输入emulator也是可以的。

 技术分享图片

Android源码的编译到此就完成了,我在编译过程中遇到了一些问题,多半是依赖没有装全,上网查16.04装Android6的文章,对着重新过一遍依赖就可以了。

 

POC源码编译

这里针对的是对Android源码有所依赖的程序的编译,因为要编译的POC程序大多要模拟客户端的底层与系统服务通信,需要调用一些客户端底层的函数,如下:

 技术分享图片

 

如果在Android.mk里面配置头文件和库文件路径的话,会很麻烦,而且头文件还有嵌套,不太好配置,我也没找到配置库文件路径的参数,最终选择了源码编译环境中的mmm指令进行编译。

下面是编译步骤:

1)创建一个目录里面存放poc.cpp和Android.mk.

Android.mk中的内容是:

1 LOCAL_PATH  :=  $(call  my-dir)
2 include  $(CLEAR_VARS)
3 LOCAL_MODULE  :=  poc
4 LOCAL_MODULE_TAGS  :=  optional
5 LOCAL_SRC_FILES  :=  poc.cpp
6 LOCAL_CFLAGS  +=  -march=armv4
7 LOCAL_SHARED_LIBRARIES  :=  libbinder  libutils  libmedia  libstagefright_foundation
8 include  $(BUILD_EXECUTABLE)

这些大部分参数在官方NDK入门指南都有介绍,说两个:

LOCAL_MODULE_TAGS :=optional,表示在任何版本(usr,debug,eng)下都编译。

include  $(BUILD_EXECUTABLE),表示生成可执行文件。

LOCAL_CFLAGS += -march=armv4,相当于在编译时指定了-march参数,gcc将不会再用兼容的指令去编译,而是根据指定的CPU结构,采用其特定的指令集去生成二进制代码。因此,当你确定所编译的程序只会在特定的环境中运行时,可以使用-march参数来指定CPU架构,这样编译器就可以根据你的CPU架构进行指令上的优化,而这个指定带来的后果就是,如果你将程序放在其他机器上运行,有可能得到Illegal instruction的运行错误。

 

2)进入Android源码目录,初始化源码编译环境

1 cd source(android源码目录)
2 source build/envsetup.sh
3 lunch 1

mmm属于envsetup.sh的指令,作用是编译指定目录下的所有模块。

 

3)利用mmm进行编译

1 mmm AndroidWP/jni(poc.cpp目录)

 使用mmm的好处是,它会自动寻找头文件和库文件路径,把要编译的模块作为android的一个内部模块进行编译,输出到out里。所以只需要在Android.mk中指定共享库的名字就可以了。

 

注意:在使用mmm编译的前几次,它会默认执行make clean操作,会把你之前编译安装的android源码的输出全部remove,目前我就是只能再重新编译一遍android源码,不过这就很快了,更多的是copy和install的操作,不要惊慌。

 

具体的mmm指令细节没有深究,有兴趣可以上网看源码分析。

 

编译完之后,利用adb把程序push到android机上,运行即可。

 

 参考:

https://blog.csdn.net/dd864140130/article/details/51718187

https://blog.csdn.net/fuchaosz/article/details/51487585

 





以上是关于[转组第10天] | Android6.0.0_r1源码编译和POC程序的编译的主要内容,如果未能解决你的问题,请参考以下文章

[转组第5天] | 天枢分享Reverse入门

[转组第3天] | 黑盒测试

[转组第9天] | 数组和指针的寻址

[转组第8天] | 变量在内存中的位置和访问方式

[转组第2天] | baby_mips和android xss的调研

数学方法模拟(洛谷1017 进制转换NOIp2000提高组第一题)