第七章 ARM 反汇编基础(三)(ARM 原生程序的生成过程)

ARM 原生程序的生成过程

  • Android 平台上的 ARM 原生程序是用 Android NDK 开发的,整个原生程序的编译生成工作由 Android NDK 提供的编译工具链完成
  • Android NDK 目前提供了两套 ARM 编译器,分别是基于 GNU GCC 编译器的 gcc 编译器和基于LLVM 编译套件的 Clang 编译器
  • Android NDK 打算从 r17 版本开始移除对 gcc 的支持,只提供 Clang 编译开发 Android 原生程序,但实际却是仍可用 gcc 开发
  • 现在用 Android NDK 写一个 ARM 原生程序,然后分析编译器执行的每一步操作,从而了解原生程序的整个生成过程。代码如下:
    在这里插入图片描述
  • 系统:Ubuntu 18.04
  • Android NDK 版本:r10e
  • 用传统的 gcc 工具编译这段代码,只要执行 gcc hello.c -o hello 命令;用 Android NDK 要麻烦一些
  • 在命令行下指定 CC 环境变量,用 arm-linux-androideabi-gcc 编译器单独编译代码时要指定 --sysroot 选项(官方解释
  • 执行如下命令,可在命令行下编译 hello.c 代码:
    在这里插入图片描述
    • 第一行:指定 Android NDK 的根目录,方便在下面的命令中引用
    • 第二行:指定 SYSROOT 环境变量,arm-linux-androideabi-gcc 编译器在编译代码时会到此目录下查找头文件和库。此处使用的是 android-21,表示系统版本是 Android 5.0(这是第一个引入 arm64-v8a 架构的系统版本)
    • 第三行:指定 CC 环境变量,指向具体的编译器路径
    • 第四行:使用由 CC 环境变量指定的编译器编译代码。后面的 -fPIE -pie 参数,作用是生成与位置无关的代码,在 Android 5.0 及以上版本的系统中必须设置此参数,不然程序运行时会产生异常,提示信息为“error: only position independent executables (PIE) are supported”。编译成功后,会生成 hello 可执行文件
    • 若是编译 C++ 代码,第四行命令可改为 export CXX="$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-g++ --sysroot=$SYSROOT"
  • 直接执行 hello 程序会提示“该文件无法执行”
    在这里插入图片描述
  • 可将文件传入 Android 手机或模拟器执行,命令和输出如下:
    在这里插入图片描述
  • 上面用 $CC 编译的 Android 原生程序没指定 -march 参数,故默认的是 ARM 架构,对应的处理器是 armeabi,采用的指令集是 ARMv5TE
  • 若想生成其他 ARM 架构的程序,如 ARMv7-A,可执行如下命令:
    $CC -march=armv7-a hello.c -o hello
  • 除了用 arm-linux-androideabi-gcc 编译器,还可用 Android NDK 提供的 Clang 编译器生成程序,二者只在指定编译工具链的环境变量设置上有所不同
  • (本书成书时)Android NDK 提供的 LLVM 编译套件中虽有 Clang 前端,但没用于处理代码的后端工具,如汇编器 as 和链接器 ld。用 Clang 只能完成编译工作,要想完成汇编和链接工作,还得借助 gcc 的 arm-linux-androideabi-as 和 arm-linux-androideabi-ld。在设置 CC 环境变量时,指定 -gcc-toolchain 即可将后端部分传给 gcc。除此之外,用 Clang 编译器编译不同架构的代码应通过 -target 参数指定,而不应通过 gcc 的 -march。指定 -target 的值为“armv7-linux-androideabi”,表示生成 ARMv7-A 架构的程序。若没指定 -target 的值,默认情况下其值为当前编译系统平台架构的名称
  • CC 环境变量的设置和 hello.c 的编译可执行如下命令:
    在这里插入图片描述
  • 无论 gcc 或 Clang,执行一次完整的编译工作通常分为预处理、编译、汇编、链接四个步骤,各步骤的工作细节有所不同

预处理

  • 在预处理阶段,编译器将处理代码中的预处理指令。如,#include 中包含的头文件会全部被编译出来,#define 预定义、#if 预条件处理等也都会被编译器处理。详细的输出信息可通过向编译器传递 -E 选项查看。以 hello.c 为例,gcc 和 Clang 都可执行 $CC -E -fPIE -pie hello.c -o hello.i 命令完成代码的预处理
  • hello.i 内容如下:
# 1 "hello.c"
# 1 "<built-in>" 1
# 1 "<built-in>" 3
# 325 "<built-in>" 3
# 1 "<command line>" 1
# 1 "<built-in>" 2
# 1 "hello.c" 2
# 1 "/root/android-ndk-r10e/platforms/android-21/arch-arm/usr/include/stdio.h" 1 3 4
# 49 "/root/android-ndk-r10e/platforms/android-21/arch-arm/usr/include/stdio.h" 3 4
# 1 "/root/android-ndk-r10e/platforms/android-21/arch-arm/usr/include/sys/cdefs.h" 1 3 4
# 77 "/root/android-ndk-r10e/platforms/android-21/arch-arm/usr/include/sys/cdefs.h" 3 4
# 1 "/root/android-ndk-r10e/platforms/android-21/arch-arm/usr/include/sys/cdefs_elf.h" 1 3 4
# 78 "/root/android-ndk-r10e/platforms/android-21/arch-arm/usr/include/sys/cdefs.h" 2 3 4
# 547 "/root/android-ndk-r10e/platforms/android-21/arch-arm/usr/include/sys/cdefs.h" 3 4
# 1 "/root/android-ndk-r10e/platforms/android-21/arch-arm/usr/include/android/api-level.h" 1 3 4
# 548 "/root/android-ndk-r10e/platforms/android-21/arch-arm/usr/include/sys/cdefs.h" 2 3 4
# 50 "/root/android-ndk-r10e/platforms/android-21/arch-arm/usr/include/stdio.h" 2 3 4
# 1 "/root/android-ndk-r10e/platforms/android-21/arch-arm/usr/include/sys/types.h" 1 3 4
# 31 "/root/android-ndk-r10e/platforms/android-21/arch-arm/usr/include/sys/types.h" 3 4
# 1 "/root/android-ndk-r10e/toolchains/llvm-3.5/prebuilt/linux-x86_64/bin/../lib/clang/3.5/include/stddef.h" 1 3 4
# 47 "/root/android-ndk-r10e/toolchains/llvm-3.5/prebuilt/linux-x86_64/bin/../lib/clang/3.5/include/stddef.h" 3 4
typedef int ptrdiff_t;
# 58 "/root/android-ndk-r10e/toolchains/llvm-3.5/prebuilt/linux-x86_64/bin/../lib/clang/3.5/include/stddef.h" 3 4
typedef unsigned int size_t;
# 86 "/root/android-ndk-r10e/toolchains/llvm-3.5/prebuilt/linux-x86_64/bin/../lib/clang/3.5/include/stddef.h" 3 4
typedef unsigned int wchar_t;
# 32 "/root/android-ndk-r10e/platforms/android-21/arch-arm/usr/inclu
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值