细说dex2oat(3)

细说dex2oat(3)

dex2oat是如何在makefile中落地的

在Android的mk系统中,调用dex2oat中有几处,但是真正被调用来生成目标系统上的oat的是下面这个,位于/build/core/dex_preopt_libart.mk中:

 # For a single jar or APK

 # $(1): the input .jar or .apk file
 # $(2): the output .odex file
define dex2oat-one-file
$(hide) rm -f $(2)
$(hide) mkdir -p $(dir $(2))
$(hide) $(DEX2OAT) \
    --runtime-arg -Xms$(DEX2OAT_XMS) --runtime-arg -Xmx$(DEX2OAT_XMX) \
    --boot-image=$(PRIVATE_DEX_PREOPT_IMAGE_LOCATION) \
    --dex-file=$(1) \
    --dex-location=$(PRIVATE_DEX_LOCATION) \
    --oat-file=$(2) \
    --android-root=$(PRODUCT_OUT)/system \
    --instruction-set=$($(PRIVATE_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_ARCH) \
    --instruction-set-variant=$($(PRIVATE_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_CPU_VARIANT) \
    --instruction-set-features=$($(PRIVATE_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_INSTRUCTION_SET_FEATURES) \
    --include-patch-information --runtime-arg -Xnorelocate --no-generate-debug-info \
    --abort-on-hard-verifier-error \
    $(PRIVATE_DEX_PREOPT_FLAGS)
endef

这个dex2oat-one-file,是被dexpreopt-one-file调用,位于/build/core/dex_preopt.mk中:

include $(BUILD_SYSTEM)/dex_preopt_libart.mk

 # Define dexpreopt-one-file based on current default runtime.
 # $(1): the input .jar or .apk file
 # $(2): the output .odex file
define dexpreopt-one-file
$(call dex2oat-one-file,$(1),$(2))
endef

以下根据生成的类型不同,包、库、预先编译好的应用有不同的路径。

Build package中的odex生成

/build/core/package_internal.mk

 ###############################
 ## Rule to build the odex file
ifdef LOCAL_DEX_PREOPT
$(built_odex): PRIVATE_DEX_FILE := $(built_dex)
 # Use pattern rule - we may have multiple built odex files.
$(built_odex) : $(dir $(LOCAL_BUILT_MODULE))% : $(built_dex)
    $(hide) mkdir -p $(dir $@) && rm -f $@
    $(add-dex-to-package)
    $(hide) mv $@ $@.input
    $(call dexpreopt-one-file,$@.input,$@)
    $(hide) rm $@.input
endif

Build java library中的odex生成

/build/core/java_library.mk

$(built_odex): PRIVATE_MODULE := $(LOCAL_MODULE)
 # Use pattern rule - we may have multiple built odex files.
$(built_odex) : $(dir $(LOCAL_BUILT_MODULE))% : $(common_javalib.jar)
    @echo "Dexpreopt Jar: $(PRIVATE_MODULE) ($@)"
    $(call dexpreopt-one-file,$<,$@)

Prebuild的odex生成

 ###############################
 ## Rule to build the odex file
ifdef LOCAL_DEX_PREOPT
$(built_odex) : $(my_prebuilt_src_file)
    $(call dexpreopt-one-file,$<,$@)
endif

install odex

我们再来看看,odex是如何被install到system分区下面的。

 # Use pattern rule - we may have multiple installed odex files.
 # Ugly syntax - See the definition get-odex-file-path.
$(installed_odex) : $(dir $(LOCAL_INSTALLED_MODULE))%$(notdir $(word 1,$(installed_odex))) \
                  : $(dir $(LOCAL_BUILT_MODULE))%$(notdir $(word 1,$(built_odex))) \
    | $(ACP)
    @echo "Install: $@"
    $(copy-file-to-target)
endif

我们看一个实际的例子:

Install: out/target/product/6753_64_m/system/app/Note/oat/arm64/Note.odex
mkdir -p out/target/product/6753_64_m/system/app/Note/oat/arm64/
out/host/linux-x86/bin/acp -fp out/target/product/6753_64_m/obj/APPS/Note_intermediates/oat/arm64/package.odex out/target/product/6753_64_m/system/app/Note/oat/arm64/Note.odex

Install: out/target/product/6753_64_m/system/priv-app/Settings/oat/arm64/Settings.odex
mkdir -p out/target/product/6753_64_m/system/priv-app/Settings/oat/arm64/
out/host/linux-x86/bin/acp -fp out/target/product/6753_64_m/obj/APPS/Settings_intermediates/oat/arm64/package.odex out/target/product/6753_64_m/system/priv-app/Settings/oat/arm64/Settings.odex

definitions.mk中预定义的一些函数

除了编译之外,我们得先看一些预先定义好的函数。它们定义于/build/core/definitions.mk中。

add-dex-to-package

将class文件压缩成classes*.dex

define add-dex-to-package
$(hide) zip -qj $@ $(dir $(PRIVATE_DEX_FILE))classes*.dex
endef
copy-file-to-target

将依赖文件复制到目标文件

define copy-file-to-target
@mkdir -p $(dir $@)
$(hide) $(ACP) -fp $< $@
endef
<think>首先,用户的问题是:"我想了解或解决与dex2oat相关的问题 请问dex2oat 是什么以及如何使用"。这基于系统级指令,我需要遵循那些规则:所有行内数学表达式用$...$,独立公式用$$...$$,使用中文回答,生成相关问题,并在引用段落末尾添加引用标识。 系统指令还包括:"回答中引用的段落末尾自然地添加引用标识,例如:[^1]"。参考的引用是来自一个博客:"引用[1]:在 【Android 逆向】ART 脱壳 ( DexClassLoader 脱壳 | exec_utils.cc 中执行 Dex 编译为 Oat 文件的 Exec 和 ExecAndReturnC函数 ) 博客中 , 将 dex 文件编译为 oat 文件 , 编译过程是由 dex2oat 可执行程序完成的 , 这是一个有 main 函数的可执行程序 ; 一、搜索 dex2oat 源码 [^1]" 用户的问题是询问dex2oat是什么以及如何使用,所以我需要基于这个引用提供信息。引用中提到dex2oat是将dex文件编译为oat文件的可执行程序,有main函数,是编译过程的一部分。 我的回答需要结构清晰,帮助用户逐步解决问题。内容应真实可靠,基于Android开发的知识。 分解问题: 1. **什么是dex2oat?** - dex2oatAndroid运行时(ART)的一个工具,用于将DEX字节码编译成本地机器码(OAT文件),以提高应用执行效率。ART是Android的运行时环境,取代了Dalvik虚拟机。 2. **如何使用dex2oat?** - 通常,在Android设备上,dex2oat是系统自动运行的,例如在应用安装时。但开发者也可以手动使用它。 - 手动使用方式:通过adb shell命令在设备上执行dex2oat。命令格式如:`dex2oat --dex-file=/path/to/dex --oat-file=/path/to/output.oat` - 参数包括指定输入dex文件和输出oat文件。 从引用中,我可以提取信息:dex2oat是一个可执行程序,有main函数,用于编译dex到oat。 在回答中,我需要自然地添加引用标识。既然引用是[^1],我应该在相关部分末尾添加[^1]。 系统指令说:"生成相关问题",所以我需要在回答结束时生成相关问题。 回答结构: - 先解释什么是dex2oat。 - 然后解释如何使用它。 - 确保语言是中文。 - 使用行内数学表达式如果有必要,但在这个上下文中可能不需要,因为dex2oat是编程相关,不是数学。除非有数学表达式,否则可以省略。 - 独立公式如果有,但这里可能不适用。 - 最后,生成相关问题。 可能的回答大纲: 1. 介绍dex2oat:解释其作用、在Android系统中的地位。 2. 如何使用:包括手动使用命令。 3. 引用部分:基于提供的引用,添加[^1]。 4. 生成相关问题。 相关问题示例: - dex2oat的优化选项有哪些? - 如何调试dex2oat编译过程? - dex2oat在ART中的作用是什么? - 等等。 确保回答真实可靠:基于Android文档或常识。 最终回答: - 开头:直接回答用户问题。 - 主体:分步骤解释。 - 结尾:生成相关问题。</think>### dex2oat 是什么以及如何使用 dex2oatAndroid 运行时(ART)环境中的一个关键工具,用于将 DEX 字节码文件编译为 OAT(Optimized Android 可执行文件)文件。OAT 文件包含本地机器码,能显著提升 Android 应用的执行效率和启动速度,因为 ART 在应用安装或运行时使用这种编译方式来优化性能(取代了旧版 Dalvik 虚拟机的即时编译)。dex2oat 本身是一个命令行可执行程序,通常位于 Android 设备的 `/system/bin/` 目录下,它基于 C++ 实现,并包含一个 `main` 函数作为入口点[^1]。在 Android 系统中,dex2oat 通常在以下场景自动运行: - 应用安装时:系统自动调用 dex2oat 将 APK 中的 DEX 文件编译为 OAT 文件。 - 系统更新时:对预装应用进行优化。 - 开发者模式下:用于手动编译和测试。 #### 如何使用 dex2oat 虽然 dex2oat 在大多数情况下由系统自动调用,但开发者或逆向工程师可以手动使用它来编译 DEX 文件,例如在调试或优化过程中。以下是基本使用步骤(基于 Android 设备或模拟器): 1. **准备工作**: - 确保设备已 root 或具有 ADB 调试权限(通过 `adb root` 或 `adb shell`)。 - 获取 DEX 文件:可以从 APK 中提取(例如使用 `unzip` 命令),或直接使用设备上的 DEX 文件(如 `/data/app/.../base.dex`)。 2. **基本命令格式**: dex2oat 通过命令行参数执行,核心语法如下: ```bash dex2oat --dex-file=<输入DEX文件路径> --oat-file=<输出OAT文件路径> [其他选项] ``` - `--dex-file`:指定输入 DEX 文件的路径(支持多个文件,用逗号分隔)。 - `--oat-file`:指定编译后 OAT 文件的输出路径。 - 常用选项: - `--instruction-set`:指定目标 CPU 架构(如 arm, arm64, x86),默认为设备当前架构。 - `--compiler-filter`:控制编译优化级别(如 `speed` 为最高优化,`verify` 仅验证)。 - `--app-image-file`:生成应用镜像文件以加速启动。 - `--runtime-arg`:传递运行时参数(如堆大小)。 3. **示例操作**: - **编译单个 DEX 文件**: 假设设备上有一个 DEX 文件 `/sdcard/test.dex`,将其编译为 OAT 文件: ```bash adb shell dex2oat --dex-file=/sdcard/test.dex --oat-file=/sdcard/output.oat ``` 编译完成后,OAT 文件将保存在 `/sdcard/output.oat`。 - **编译 APK 中的多个 DEX 文件**: 如果 APK 包含多个 DEX(如 `classes.dex`, `classes2.dex`),先提取它们,然后编译: ```bash adb shell dex2oat --dex-file=/sdcard/classes.dex,/sdcard/classes2.dex --oat-file=/sdcard/app.oat ``` - **添加优化选项**: 使用 `--compiler-filter=speed` 进行全速优化: ```bash adb shell dex2oat --dex-file=/sdcard/test.dex --oat-file=/sdcard/optimized.oat --compiler-filter=speed ``` 4. **注意事项**: - **权限问题**:手动执行时,需确保设备有足够权限(通常需要 root)。否则,使用 `adb shell run-as <包名>` 访问应用私有目录。 - **输出验证**:编译后,使用 `file /sdcard/output.oat` 检查文件类型(应为 ELF 格式)。 - **性能影响**:dex2oat 编译可能消耗较多 CPU 和内存,在低端设备上谨慎使用。 - **错误处理**:常见错误如文件路径错误或权限不足,可通过 `adb logcat | grep dex2oat` 查看日志。 在 Android 逆向工程中,dex2oat 常用于脱壳操作,例如通过修改编译过程来提取优化后的代码[^1]。但请注意,dex2oat 的使用依赖于 Android 版本(例如 Android 5.0+ 支持 ART),且不同版本命令参数可能略有差异。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jtag特工

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值