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

本文详细介绍了在Android平台上,使用Android NDK和GCC/Clang编译器生成ARM原生程序的过程。从预处理、编译、汇编到链接,逐一解析每个步骤,并提供了示例代码和命令,揭示了如何通过环境变量设置和编译选项生成不同架构的程序。同时,讨论了Clang在生成Bitcode字节码时的内部转换工作。
摘要由CSDN通过智能技术生成

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/include/sys/types.h" 2 3 4
# 1 "/root/android-ndk-r10e/toolchains/llvm-3.5/prebuilt/linux-x86_64/bin/../lib/clang/3.5/include/stdint.h" 1 3 4
# 63 "/root/android-ndk-r10e/toolchains/llvm-3.5/prebuilt/linux-x86_64/bin/../lib/clang/3.5/include/stdint.h" 3 4
# 1 "/root/android-ndk-r10e/platforms/android-21/arch-arm/
反汇编带符号表的32位/64位ELF目标文件,CPU类型:ARM PowerPC MIPS X86 操作菜单选择:文件解析 Alx+P ELF文件解析 Alt+E 另有文本比较等杂项功能。V1.26.00相对上一版本,增强EXE反汇编,增加dbx老邮件解析、二维码功能,;V1.25.07相对上一版本,增加二进制反汇编、IQ数据解析功能,完善MIPS反汇编,修复小BUG;V1.25.05相对上一版本,增加内存数据按数据类型解析功能;V1.25.04相对上一版本,完善X86反汇编,修复小BUG;V1.25.02相对上一版本,COREDUMP统计、匹配目标文件等相关功能优化,修复小BUG;V1.25.00相对上一版本,相关功能支持动态库文件,查询代码支持无符号目标文件+有符号目标文件,COREDUMP统计、与问题单关联、目标文件/CORE文件/问题单同步;V1.24.02相对上一版本,针对进程主动捕捉异常的信息定制处理进一步完善COREDUMP文件解析与应用,增强软件管理;V1.24.01相对上一版本,进一步完善COREDUMP文件解析与应用,提供部分ARM Thumb指令反汇编;V1.24.00相对上一版本,进一步完善COREDUMP文件解析与应用,提供堆栈调用关系分析;V1.23.03相对上一版本,提供32位X86反汇编;V1.23.02相对上一版本,提供源代码行查询指令地址,OBJ/COREDUMP文件解析,sprintf函数参数特定检查,完善文件拖放操作,修复小BUG;V1.23.01相对上一版本,提供ELF文件指令修改,修复ARM MLS指令反汇编错误等BUG;V1.23.00相对上一版本,提供程序地址对应源代码行查询,修复MIPS调试信息错误;V1.22相对上一版本,修复MIPS小端字节序反汇编错误,网上最新版本提示;V1.21相对上一版本,菜单调整,完善64位ELF文件解析,解析调试信息;另部分增强功能的菜单操作设有密码,如有兴趣欢迎咨询。欢迎大家反馈相关软件使用过程中的问题!
反汇编带符号表的32位/64位ELF目标文件,CPU类型:ARM PowerPC MIPS 操作菜单选择:文件解析 Alx+P ELF文件解析 Alt+E 另有文本比较等杂项功能。V1.25.00相对上一版本,相关功能支持动态库文件,查询代码支持无符号目标文件+有符号目标文件,COREDUMP统计、与问题单关联、目标文件/CORE文件/问题单同步;V1.24.02相对上一版本,针对进程主动捕捉异常的信息定制处理进一步完善COREDUMP文件解析与应用,增强软件管理;V1.24.01相对上一版本,进一步完善COREDUMP文件解析与应用,提供部分ARM Thumb指令反汇编;V1.24.00相对上一版本,进一步完善COREDUMP文件解析与应用,提供堆栈调用关系分析;V1.23.03相对上一版本,提供32位X86反汇编;V1.23.02相对上一版本,提供源代码行查询指令地址,OBJ/COREDUMP文件解析,sprintf函数参数特定检查,完善文件拖放操作,修复小BUG;V1.23.01相对上一版本,提供ELF文件指令修改,修复ARM MLS指令反汇编错误等BUG;V1.23.00相对上一版本,提供程序地址对应源代码行查询,修复MIPS调试信息错误;V1.22相对上一版本,修复MIPS小端字节序反汇编错误,网上最新版本提示;V1.21相对上一版本,菜单调整,完善64位ELF文件解析,解析调试信息;另部分增强功能的菜单操作设有密码,如有兴趣欢迎咨询。欢迎大家反馈相关软件使用过程中的问题!
反汇编带符号表的32位/64位ELF目标文件,CPU类型:ARM PowerPC MIPS 操作菜单选择:文件解析 Alx+P ELF文件解析 Alt+E 另有文本比较等杂项功能。V1.25.05相对上一版本,增加内存数据按数据类型解析功能;V1.25.04相对上一版本,完善X86反汇编,修复小BUG;V1.25.02相对上一版本,COREDUMP统计、匹配目标文件等相关功能优化,修复小BUG;V1.25.00相对上一版本,相关功能支持动态库文件,查询代码支持无符号目标文件+有符号目标文件,COREDUMP统计、与问题单关联、目标文件/CORE文件/问题单同步;V1.24.02相对上一版本,针对进程主动捕捉异常的信息定制处理进一步完善COREDUMP文件解析与应用,增强软件管理;V1.24.01相对上一版本,进一步完善COREDUMP文件解析与应用,提供部分ARM Thumb指令反汇编;V1.24.00相对上一版本,进一步完善COREDUMP文件解析与应用,提供堆栈调用关系分析;V1.23.03相对上一版本,提供32位X86反汇编;V1.23.02相对上一版本,提供源代码行查询指令地址,OBJ/COREDUMP文件解析,sprintf函数参数特定检查,完善文件拖放操作,修复小BUG;V1.23.01相对上一版本,提供ELF文件指令修改,修复ARM MLS指令反汇编错误等BUG;V1.23.00相对上一版本,提供程序地址对应源代码行查询,修复MIPS调试信息错误;V1.22相对上一版本,修复MIPS小端字节序反汇编错误,网上最新版本提示;另部分增强功能的菜单操作设有密码,如有兴趣欢迎咨询。欢迎大家反馈相关软件使用过程中的问题!
反汇编Linux/Windows OS运行的32位/64位程序/动态库文件,CPU类型:ARM PowerPC MIPS X86 操作菜单选择:文件解析 Alx+P ELF文件解析 Alt+E 另有CORE文件解调用栈、文本比较等功能。V2.0.3相对上一版本,完善ARM64、X8664、PPC64反汇编、ko反汇编,完善反汇编文本文件比较、IQ数据解析,修复小BUG;V2.0.2相对上一版本,完善ARM64、X8664反汇编ARM64位core文件调用栈,完善文本文件比较、增加高亮、查找功能,修复小BUG;V2.0.0相对上一版本,完善ARM64反汇编ARM64位core文件调用栈,完善C++符号名字解析,支持工具运行在英文版OS;V1.26.01相对上一版本,增加ARM64反汇编、64位core文件解析;V1.26.00相对上一版本,增强EXE反汇编,增加dbx老邮件解析、二维码功能;V1.25.07相对上一版本,增加二进制反汇编、IQ数据解析功能,完善MIPS反汇编,修复小BUG;V1.25.05相对上一版本,增加内存数据按数据类型解析功能;V1.25.04相对上一版本,完善X86反汇编,修复小BUG;V1.25.02相对上一版本,COREDUMP统计、匹配目标文件等相关功能优化,修复小BUG;V1.25.00相对上一版本,相关功能支持动态库文件,查询代码支持无符号目标文件+有符号目标文件,COREDUMP统计、与问题单关联、目标文件/CORE文件/问题单同步;V1.24.02相对上一版本,针对进程主动捕捉异常的信息定制处理进一步完善COREDUMP文件解析与应用,增强软件管理;V1.24.01相对上一版本,进一步完善COREDUMP文件解析与应用,提供部分ARM Thumb指令反汇编;V1.24.00相对上一版本,进一步完善COREDUMP文件解析与应用,提供堆栈调用关系分析;V1.23.03相对上一版本,提供32位X86反汇编;V1.23.02相对上一版本,提供源代码行查询指令地址,OBJ/COREDUMP文件解析,sprintf函数参数特定检查,完善文件拖放操作,修复小BUG;V1.23.01相对上一版本,提供ELF文件指令修改,修复ARM MLS指令反汇编错误等BUG;V1.23.00相对上一版本,提供程序地址对应源代码行查询,修复MIPS调试信息错误;V1.22相对上一版本,修复MIPS小端字节序反汇编错误,网上最新版本提示;V1.21相对上一版本,菜单调整,完善64位ELF文件解析,解析调试信息;另部分增强功能的菜单操作设有密码,如有兴趣欢迎咨询。欢迎大家反馈相关软件使用过程中的问题!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值