ART探险(1) - oatdump看到的世界
自从4.4加入Android大家庭,到5.0被正式扶正,ART对Android世界的影响越来越大。这么好玩儿的东西,我们当然要进去探险一番,看看这其中有哪些有趣的事情。
4.4至6.0的ART,都是将dex进行AOT的系统。也就是说,将java代码编译成本地代码。但是,这种编译,跟汇编和C的编译还有所不同。汇编和C的运行时支持基本没有,可以完全翻译成机器指令。而java就有比较重的运行时的负担,比如GC,CPU是没有这种指令集去支持它的。再比如反射,如果没有相应的结构来记录,在机器指令中哪知道该射到哪里去?
我们都知道,java是处理class格式的字节码,它是基于栈的指令。而Dalvik是处理dex格式的基于寄存器结构的字节码。经过dex2oat之后,oat变成了机器指令,我们第一步就来探险一下oat文件里都有什么。
我们前面的文章已经为这次探险提供了一些积累,比如我们前面讲过dex2oat工具的使用。借着这个由头,我们继续去探索OAT. 这次我们使用的工具是oatdump。
java源码
为了演示,我们先写个Empty3,它是一个空白应用,我们看下它的代码:
package com.yunos.system.empty3;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
public class MainActivity extends Activity {
private static final String TAG = "Empty3";
@Override
protected void onCreate(Bundle savedInstanceState) {
Log.d(TAG, "[Xulun]Enter Empty3 onCreate"
+ android.os.SystemClock.uptimeMillis());
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d(TAG, "[Xulun]Leave Empty3 onCreate"
+ android.os.SystemClock.uptimeMillis());
}
}
还有Android工具自动为我们生成的类,比如:
/**
* Automatically generated file. DO NOT MODIFY
*/
package com.yunos.system.empty3;
public final class BuildConfig {
public static final boolean DEBUG = Boolean.parseBoolean("true");
public static final String APPLICATION_ID = "com.yunos.system.empty3";
public static final String BUILD_TYPE = "debug";
public static final String FLAVOR = "";
public static final int VERSION_CODE = 1;
public static final String VERSION_NAME = "1.0";
}
我们先看看它编成apk之后的dex是什么样子,我们使用工具dexdump.
dexdump
我们用下面的命令行对apk进行反汇编,这还是传统的dex,与oat没有关系呢:
adb shell dexdump -d /data/app/com.yunos.system.empty3-1/base.apk
完整的dexdump的参数如下:
dexdump: [-c] [-d] [-f] [-h] [-i] [-l layout] [-m] [-t tempfile] dexfile...
-c : verify checksum and exit
-d : disassemble code sections
-f : display summary information from file header
-h : display file header details
-i : ignore checksum failures
-l : output layout, either 'plain' or 'xml'
-m : dump register maps (and nothing else)
-t : temp file name (defaults to /sdcard/dex-temp-*)
下面我们看看,我们的java代码编成dex之后的模样。
首先是源文件和dex的版本号:
Processing '/data/app/com.yunos.system.empty3-1/base.apk'...
Opened '/data/app/com.yunos.system.empty3-1/base.apk', DEX version '035'
BuildConfig类
先看类的域:
Class #0 -
Class descriptor : 'Lcom/yunos/system/empty3/BuildConfig;'
Access flags : 0x0011 (PUBLIC FINAL)
Superclass : 'Ljava/lang/Object;'
Interfaces -
Static fields -
#0 : (in Lcom/yunos/system/empty3/BuildConfig;)
name : 'APPLICATION_ID'
type : 'Ljava/lang/String;'
access : 0x0019 (PUBLIC STATIC FINAL)
#1 : (in Lcom/yunos/system/empty3/BuildConfig;)
name : 'BUILD_TYPE'
type : 'Ljava/lang/String;'
access : 0x0019 (PUBLIC STATIC FINAL)
#2 : (in Lcom/yunos/system/empty3/BuildConfig;)
name : 'DEBUG'
type : 'Z'
access : 0x0019 (PUBLIC STATIC FINAL)
#3 : (in Lcom/yunos/system/empty3/BuildConfig;)
name : 'FLAVOR'
type : 'Ljava/lang/String;'
access : 0x0019 (PUBLIC STATIC FINAL)
#4 : (in Lcom/yunos/system/empty3/BuildConfig;)
name : 'VERSION_CODE'
type : 'I'
access : 0x0019 (PUBLIC STATIC FINAL)
#5 : (in Lcom/yunos/system/empty3/BuildConfig;)
name : 'VERSION_NAME'
type : 'Ljava/lang/String;'
access : 0x0019 (PUBLIC STATIC FINAL)
Instance fields -
然后是方法:
我们从源码中可以看到,只有一条Boolean.parseBoolean的静态语句。其余就只剩默认的初始化方法<init>了。
Direct methods -
#0 : (in Lcom/yunos/system/empty3/BuildConfig;)
name : '<clinit>'
type : '()V'
access : 0x10008 (STATIC CONSTRUCTOR)
code -
registers : 1
ins : 0
outs : 1
insns size : 9 16-bit code units
000508: |[000508] com.yunos.system.empty3.BuildConfig.<clinit>:()V
000518: 1a00 4a00 |0000: const-string v0, "true" // string@004a
00051c: 7110 1000 0000 |0002: invoke-static {v0}, Ljava/lang/Boolean;.parseBoolean:(Ljava/lang/String;)Z // method@0010
000522: 0a00 |0005: move-result v0
000524: 6a00 0200 |0006: sput-boolean v0, Lcom/yunos/system/empty3/BuildConfig;.DEBUG:Z // field@0002
000528: 0e00 |0008: return-void
catches : (none)
positions :
0x0000 line=7
locals :
#1 : (in Lcom/yunos/system/empty3/BuildConfig;)
name : '<init>'
type : '()V'
access : 0x10001 (PUBLIC CONSTRUCTOR)
code -
registers : 1
ins : 1
outs : 1
insns size : 4 16-bit code units
00052c: |[00052c] com.yunos.system.empty3.BuildConfig.<init>:()V
00053c: 7010 1100 0000 |0000: invoke-direct {v0}, Ljava/lang/Object;.<init>:()V // method@0011
000542: 0e00 |0003: return-void
catches : (none)
positions :
0x0000 line=6
locals :
0x0000 - 0x0004 reg=0 this Lcom/yunos/system/empty3/BuildConfig;
Virtual methods -
source_file_idx : 7 (BuildConfig.java)
下面我们终于可以看看我们手工写的那个类了:
Class #1 -
Class descriptor : 'Lcom/yunos/system/empty3/MainActivity;'
Access flags : 0x0001 (PUBLIC)
Superclass : 'Landroid/app/Activity;'
Interfaces -
Static fields -
#0 : (in Lcom/yunos/system/empty3/MainActivity;)
name : 'TAG'
type : 'Ljava/lang/String;'
access : 0x001a (PRIVATE STATIC FINAL)
Instance fields -
Direct methods -
#0 : (in Lcom/yunos/system/empty3/MainActivity;)
name : '<init>'
type : '()V'
access : 0x10001 (PUBLIC CONSTRUCTOR)
code -
registers : 1
ins : 1
outs : 1
insns size : 4 16-bit code units
000544: |[000544] com.yunos.system.empty3.MainActivity.<init>:()V
000554: 7010 0000 0000 |0000: invoke-direct {v0}, Landroid/app/Activity;.<init>:()V // method@0000
00055a: 0e00 |0003: return-void
catches : (none)
positions :
0x0000 line=7
locals :
0x0000 - 0x0004 reg=0 this Lcom/yunos/system/empty3/MainActivity;
Virtual methods -
#0 : (in Lcom/yunos/system/empty3/MainActivity;)
name : 'onCreate'
type : '(Landroid/os/Bundle;)V'
access : 0x0004 (PROTECTED)
code -
registers : 6
ins : 2
outs : 3
insns size : 65 16-bit code units
00055c: |[00055c] com.yunos.system.empty3.MainActivity.onCreate:(Landroid/os/Bundle;)V
00056c: 1a00 0900 |0000: const-string v0, "Empty3" // string@0009
000570: 2201 1500 |0002: new-instance v1, Ljava/lang/StringBuilder; // type@0015
000574: 7010 1200 0100 |0004: invoke-direct {v1}, Ljava/lang/StringBuilder;.<init>:()V // method@0012
00057a: 1a02 2f00 |0007: const-string v2, "[Xulun]Enter Empty3 onCreate" // string@002f
00057e: 6e20 1400 2100 |0009: invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@0014
000584: 0c01 |000c: move-result-object v1
000586: 7100 0200 0000 |000d: invoke-static {}, Landroid/os/SystemClock;.uptimeMillis:()J // method@0002
00058c: 0b02 |0010: move-result-wide v2
00058e: 6e30 1300 2103 |0011: invoke-virtual {v1, v2, v3}, Ljava/lang/StringBuilder;.append:(J)Ljava/lang/StringBuilder; // method@0013
000594: 0c01 |0014: move-result-object v1
000596: 6e10 1500 0100 |0015: invoke-virtual {v1}, Ljava/lang/StringBuilder;.toString:()Ljava/lang/String; // method@0015
00059c: 0c01 |0018: move-result-object v1
00059e: 7120 0300 1000 |0019: invoke-static {v0, v1}, Landroid/util/Log;.d:(Ljava/lang/String;Ljava/lang/String;)I // method@0003
0005a4: 6f20 0100 5400 |001c: invoke-super {v4, v5}, Landroid/app/Activity;.onCreate:(Landroid/os/Bundle;)V // method@0001
0005aa: 1500 037f |001f: const/high16 v0, #int 2130903040 // #7f03
0005ae: 6e20 0800 0400 |0021: invoke-virtual {v4, v0}, Lcom/yunos/system/empty3/MainActivity;.setContentView:(I)V // method@0008
0005b4: 1a00 0900 |0024: const-string v0, "Empty3" // string@0009
0005b8: 2201 1500 |0026: new-instance v1, Ljava/lang/StringBuilder; // type@0015
0005bc: 7010 1200 0100 |0028: invoke-direct {v1}, Ljava/lang/StringBuilder;.<init>:()V // method@0012
0005c2: 1a02 3000 |002b: const-string v2, "[Xulun]Leave Empty3 onCreate" // string@0030
0005c6: 6e20 1400 2100 |002d: invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; // method@0014
0005cc: 0c01 |0030: move-result-object v1
0005ce: 7100 0200 0000 |0031: invoke-static {}, Landroid/os/SystemClock;.uptimeMillis:()J // method@0002
0005d4: 0b02 |0034: move-result-wide v2
0005d6: 6e30 1300 2103 |0035: invoke-virtual {v1, v2, v3}, Ljava/lang/StringBuilder;.append:(J)Ljava/lang/StringBuilder; // method@0013
0005dc: 0c01 |0038: move-result-object v1
0005de: 6e10 1500 0100 |0039: invoke-virtual {v1}, Ljava/lang/StringBuilder;.toString:()Ljava/lang/String; // method@0015
0005e4: 0c01 |003c: move-result-object v1
0005e6: 7120 0300 1000 |003d: invoke-static {v0, v1}, Landroid/util/Log;.d:(Ljava/lang/String;Ljava/lang/String;)I // method@0003
0005ec: 0e00 |0040: return-void
catches : (none)
positions :
0x0000 line=11
0x000d line=12
0x0019 line=11
0x001c line=13
0x001f line=14
0x0024 line=15
0x0031 line=16
0x003d line=15
0x0040 line=17
locals :
0x0000 - 0x0041 reg=4 this Lcom/yunos/system/empty3/MainActivity;
0x0000 - 0x0041 reg=5 savedInstanceState Landroid/os/Bundle;
source_file_idx : 37 (MainActivity.java)
oatdump
我们先来看看oatdump的命令行参数吧:
Usage: oatdump [options] ...
Example: oatdump --image=$ANDROID_PRODUCT_OUT/system/framework/boot.art
Example: adb shell oatdump --image=/system/framework/boot.art
--oat-file=<file.oat>: specifies an input oat filename.
Example: --oat-file=/system/framework/boot.oat
--image=<file.art>: specifies an input image location.
Example: --image=/system/framework/boot.art
--boot-image=<file.art>: provide the image location for the boot class path.
Do not include the arch as part of the name, it is added automatically.
Example: --boot-image=/system/framework/boot.art
--instruction-set=(arm|arm64|mips|mips64|x86|x86_64): for locating the image
file based on the image location set.
Example: --instruction-set=x86
Default: arm64
--output=<file> may be used to send the output to a file.
Example: --output=/tmp/oatdump.txt
--dump:raw_mapping_table enables dumping of the mapping table.
Example: --dump:raw_mapping_table
--dump:raw_gc_map enables dumping of the GC map.
Example: --dump:raw_gc_map
--no-dump:vmap may be used to disable vmap dumping.
Example: --no-dump:vmap
--no-disassemble may be used to disable disassembly.
Example: --no-disassemble
--list-classes may be used to list target file classes (can be used with filters).
Example: --list-classes
Example: --list-classes --class-filter=com.example.foo
--list-methods may be used to list target file methods (can be used with filters).
Example: --list-methods
Example: --list-methods --class-filter=com.example --method-filter=foo
--symbolize=<file.oat>: output a copy of file.oat with elf symbols included.
Example: --symbolize=/system/framework/boot.oat
--class-filter=<class name>: only dumps classes that contain the filter.
Example: --class-filter=com.example.foo
--method-filter=<method name>: only dumps methods that contain the filter.
Example: --method-filter=foo
--export-dex-to=<directory>: may be used to export oat embedded dex files.
Example: --export-dex-to=/data/local/tmp
--addr2instr=<address>: output matching method disassembled code from relative
address (e.g. PC from crash dump)
Example: --addr2instr=0x00001a3b
其实用法很简单,只要通过oat-file项给一个oat就可以了。我们可以在userdebug版的手机上做这个事情。
adb shell oatdump --oat-file=/data/app/com.yunos.system.empty3-1/oat/arm64/base.odex
文件头
标识和校验
MAGIC:
oat
064
CHECKSUM:
0x25f3d65d
指令集
说明我们这个是为64位的arm64指令集,针对Cortex-A53架构编译的。
INSTRUCTION SET:
Arm64
INSTRUCTION SET FEATURES:
smp,a53
文件位置相关
DEX FILE COUNT:
1
EXECUTABLE OFFSET:
0x00002000
INTERPRETER TO INTERPRETER BRIDGE OFFSET:
0x00000000
INTERPRETER TO COMPILED CODE BRIDGE OFFSET:
0x00000000
JNI DLSYM LOOKUP OFFSET:
0x00000000
QUICK GENERIC JNI TRAMPOLINE OFFSET:
0x00000000
QUICK IMT CONFLICT TRAMPOLINE OFFSET:
0x00000000
QUICK RESOLUTION TRAMPOLINE OFFSET:
0x00000000
QUICK TO INTERPRETER BRIDGE OFFSET:
0x00000000
IMAGE PATCH DELTA:
0 (0x00000000)
IMAGE FILE LOCATION OAT CHECKSUM:
0xfadcc32f
IMAGE FILE LOCATION OAT BEGIN:
0x71a77000
键值对
这里面最重要的信息就是编译这个oat所用的命令行。
以前的文章我们讲过了dex2oat的参数和用法,我们可以看到,这是通过手机上的dex2oat编译出来的。
KEY VALUE STORE:
classpath =
debuggable = true
dex2oat-cmdline = --zip-fd=7 --zip-location=base.apk --oat-fd=8 --oat-location=/data/app/vmdl248870519.tmp/oat/arm64/base.odex --instruction-set=arm64 --instruction-set-variant=cortex-a53 --instruction-set-features=default --runtime-arg -Xms64m --runtime-arg -Xmx512m --swap-fd=10 --debuggable
dex2oat-host = Arm
image-location = /data/dalvik-cache/arm64/system@framework@boot.art
pic = true
SIZE:
10388
BuildConfig类
OatDexFile:
location: base.apk
checksum: 0x160dd5b3
0: Lcom/yunos/system/empty3/BuildConfig; (offset=0x00001018) (type_idx=6) (StatusVerified) (OatClassSomeCompiled)
BuildConfig类构造
先看类的初始化,也就是那一条静态赋值的指令:
虽然有DEX指令,但是没有生成对应的本地code.
0: void com.yunos.system.empty3.BuildConfig.<clinit>() (dex_method_idx=4)
DEX CODE:
0x0000: 1a00 4a00 | const-string v0, "true" // string@74
0x0002: 7110 1000 0000 | invoke-static {v0}, boolean java.lang.Boolean.parseBoolean(java.lang.String) // method@16
0x0005: 0a00 | move-result v0
0x0006: 6a00 0200 | sput-boolean v0, Z com.yunos.system.empty3.BuildConfig.DEBUG // field@2
0x0008: 7300 | return-void-no-barrier
OatMethodOffsets (offset=0x00000000)
code_offset: 0x00000000
gc_map: (offset=0x00000000)
OatQuickMethodHeader (offset=0x00000000)
mapping_table: (offset=0x00000000)
vmap_table: (offset=0x00000000)
QuickMethodFrameInfo
frame_size_in_bytes: 0
core_spill_mask: 0x00000000
fp_spill_mask: 0x00000000
vr_stack_locations:
locals: v0[sp + #4294967288]
method*: v1[sp + #0]
outs: v0[sp + #8]
CODE: (code_offset=0x00000000 size_offset=0x00000000 size=0)
NO CODE!
BuildConfig的构造方法
因为没有重载,所以直接调用Object类的<init>方法就好了。
1: void com.yunos.system.empty3.BuildConfig.<init>() (dex_method_idx=5)
DEX CODE:
0x0000: 7010 1100 0000 | invoke-direct {v0}, void java.lang.Object.<init>() // method@17
0x0003: 0e00 | return-void
OatMethodOffsets (offset=0x00001024)
code_offset: 0x0000201c
gc_map: (offset=0x0000106c)
OatQuickMethodHeader (offset=0x00002000)
mapping_table: (offset=0x000010f4)
vmap_table: (offset=0x00001154)
v65535/r30
QuickMethodFrameInfo
frame_size_in_bytes: 32
core_spill_mask: 0x40000000 (r30)
fp_spill_mask: 0x00000000
vr_stack_locations:
ins: v0[sp + #40]
method*: v1[sp + #0]
outs: v0[sp + #8]
这个方法就对应生成了本地代码,我们看一下:
CODE: (code_offset=0x0000201c size_offset=0x00002018 size=88)...
0x0000201c: d1400bf0 sub x16, sp, #0x2000 (8192)
0x00002020: b940021f ldr wzr, [x16]
suspend point dex PC: 0x0000
GC map objects: v0 ([sp + #40])
0x00002024: f81e0fe0 str x0, [sp, #-32]!
0x00002028: f9000ffe str lr, [sp, #24]
0x0000202c: b9002be1 str w1, [sp, #40]
0x00002030: 79400250 ldrh w16, [tr] (state_and_flags)
0x00002034: 350001b0 cbnz w16, #+0x34 (addr 0x2068)
0x00002038: b9402be0 ldr w0, [sp, #40]
0x0000203c: b940001f ldr wzr, [x0]
suspend point dex PC: 0x0000
GC map objects: v0 ([sp + #40])
0x00002040: b90013e0 str w0, [sp, #16]
0x00002044: b94013e1 ldr w1, [sp, #16]
0x00002048: f94003e0 ldr x0, [sp]
0x0000204c: b9400400 ldr w0, [x0, #4]
0x00002050: f9404c00 ldr x0, [x0, #152]
0x00002054: f940181e ldr lr, [x0, #48]
0x00002058: d63f03c0 blr lr
suspend point dex PC: 0x0000
GC map objects: v0 ([sp + #40])
0x0000205c: f9400ffe ldr lr, [sp, #24]
0x00002060: 910083ff add sp, sp, #0x20 (32)
0x00002064: d65f03c0 ret
0x00002068: f9421e5e ldr lr, [tr, #1080] (pTestSuspend)
0x0000206c: d63f03c0 blr lr
suspend point dex PC: 0x0000
GC map objects: v0 ([sp + #40])
0x00002070: 17fffff2 b #-0x38 (addr 0x2038)
MainActivity类
MainActivity的构造
首先是类的构造方法,因为没有实现,还是调用父类Activity的。
1: Lcom/yunos/system/empty3/MainActivity; (offset=0x00001028) (type_idx=7) (StatusVerified) (OatClassAllCompiled)
0: void com.yunos.system.empty3.MainActivity.<init>() (dex_method_idx=6)
DEX CODE:
0x0000: 7010 0000 0000 | invoke-direct {v0}, void android.app.Activity.<init>() // method@0
0x0003: 0e00 | return-void
OatMethodOffsets (offset=0x0000102c)
code_offset: 0x0000209c
gc_map: (offset=0x0000106c)
OatQuickMethodHeader (offset=0x00002080)
mapping_table: (offset=0x000010f4)
vmap_table: (offset=0x00001154)
v65535/r30
QuickMethodFrameInfo
frame_size_in_bytes: 32
core_spill_mask: 0x40000000 (r30)
fp_spill_mask: 0x00000000
vr_stack_locations:
ins: v0[sp + #40]
method*: v1[sp + #0]
outs: v0[sp + #8]
生成的代码,跟BuildConfig的构造方法还真有点像:
CODE: (code_offset=0x0000209c size_offset=0x00002098 size=88)...
0x0000209c: d1400bf0 sub x16, sp, #0x2000 (8192)
0x000020a0: b940021f ldr wzr, [x16]
suspend point dex PC: 0x0000
GC map objects: v0 ([sp + #40])
0x000020a4: f81e0fe0 str x0, [sp, #-32]!
0x000020a8: f9000ffe str lr, [sp, #24]
0x000020ac: b9002be1 str w1, [sp, #40]
0x000020b0: 79400250 ldrh w16, [tr] (state_and_flags)
0x000020b4: 350001b0 cbnz w16, #+0x34 (addr 0x20e8)
0x000020b8: b9402be0 ldr w0, [sp, #40]
0x000020bc: b940001f ldr wzr, [x0]
suspend point dex PC: 0x0000
GC map objects: v0 ([sp + #40])
0x000020c0: b90013e0 str w0, [sp, #16]
0x000020c4: b94013e1 ldr w1, [sp, #16]
0x000020c8: f94003e0 ldr x0, [sp]
0x000020cc: b9400400 ldr w0, [x0, #4]
0x000020d0: f9400800 ldr x0, [x0, #16]
0x000020d4: f940181e ldr lr, [x0, #48]
0x000020d8: d63f03c0 blr lr
suspend point dex PC: 0x0000
GC map objects: v0 ([sp + #40])
0x000020dc: f9400ffe ldr lr, [sp, #24]
0x000020e0: 910083ff add sp, sp, #0x20 (32)
0x000020e4: d65f03c0 ret
0x000020e8: f9421e5e ldr lr, [tr, #1080] (pTestSuspend)
0x000020ec: d63f03c0 blr lr
suspend point dex PC: 0x0000
GC map objects: v0 ([sp + #40])
0x000020f0: 17fffff2 b #-0x38 (addr 0x20b8)
MainActivity.onCreate
我们没有写分支的逻辑,都是一系列调用的组合:
1: void com.yunos.system.empty3.MainActivity.onCreate(android.os.Bundle) (dex_method_idx=7)
DEX CODE:
0x0000: 1a00 0900 | const-string v0, "Empty3" // string@9
0x0002: 2201 1500 | new-instance v1, java.lang.StringBuilder // type@21
0x0004: 7010 1200 0100 | invoke-direct {v1}, void java.lang.StringBuilder.<init>() // method@18
0x0007: 1a02 2f00 | const-string v2, "[Xulun]Enter Empty3 onCreate" // string@47
0x0009: 6e20 1400 2100 | invoke-virtual {v1, v2}, java.lang.StringBuilder java.lang.StringBuilder.append(java.lang.String) // method@20
0x000c: 0c01 | move-result-object v1
0x000d: 7100 0200 0000 | invoke-static {}, long android.os.SystemClock.uptimeMillis() // method@2
0x0010: 0b02 | move-result-wide v2
0x0011: 6e30 1300 2103 | invoke-virtual {v1, v2, v3}, java.lang.StringBuilder java.lang.StringBuilder.append(long) // method@19
0x0014: 0c01 | move-result-object v1
0x0015: 6e10 1500 0100 | invoke-virtual {v1}, java.lang.String java.lang.StringBuilder.toString() // method@21
0x0018: 0c01 | move-result-object v1
0x0019: 7120 0300 1000 | invoke-static {v0, v1}, int android.util.Log.d(java.lang.String, java.lang.String) // method@3
0x001c: 6f20 0100 5400 | invoke-super {v4, v5}, void android.app.Activity.onCreate(android.os.Bundle) // method@1
0x001f: 1500 037f | const/high16 v0, #int +2130903040 // 0x7f030000
0x0021: 6e20 0800 0400 | invoke-virtual {v4, v0}, void com.yunos.system.empty3.MainActivity.setContentView(int) // method@8
0x0024: 1a00 0900 | const-string v0, "Empty3" // string@9
0x0026: 2201 1500 | new-instance v1, java.lang.StringBuilder // type@21
0x0028: 7010 1200 0100 | invoke-direct {v1}, void java.lang.StringBuilder.<init>() // method@18
0x002b: 1a02 3000 | const-string v2, "[Xulun]Leave Empty3 onCreate" // string@48
0x002d: 6e20 1400 2100 | invoke-virtual {v1, v2}, java.lang.StringBuilder java.lang.StringBuilder.append(java.lang.String) // method@20
0x0030: 0c01 | move-result-object v1
0x0031: 7100 0200 0000 | invoke-static {}, long android.os.SystemClock.uptimeMillis() // method@2
0x0034: 0b02 | move-result-wide v2
0x0035: 6e30 1300 2103 | invoke-virtual {v1, v2, v3}, java.lang.StringBuilder java.lang.StringBuilder.append(long) // method@19
0x0038: 0c01 | move-result-object v1
0x0039: 6e10 1500 0100 | invoke-virtual {v1}, java.lang.String java.lang.StringBuilder.toString() // method@21
0x003c: 0c01 | move-result-object v1
0x003d: 7120 0300 1000 | invoke-static {v0, v1}, int android.util.Log.d(java.lang.String, java.lang.String) // method@3
0x0040: 0e00 | return-void
OatMethodOffsets (offset=0x00001030)
code_offset: 0x0000211c
gc_map: (offset=0x00001078)
OatQuickMethodHeader (offset=0x00002100)
mapping_table: (offset=0x00001100)
vmap_table: (offset=0x00001154)
v65535/r30
QuickMethodFrameInfo
frame_size_in_bytes: 64
core_spill_mask: 0x40000000 (r30)
fp_spill_mask: 0x00000000
vr_stack_locations:
locals: v0[sp + #36] v1[sp + #40] v2[sp + #44] v3[sp + #48]
ins: v4[sp + #72] v5[sp + #76]
method*: v6[sp + #0]
outs: v0[sp + #8] v1[sp + #12] v2[sp + #16]
没想到,对应生成的代码还真不少!
不过,仔细看下来,大家是不是能从中看出来些规律啊?提示一下,像不像是根据某模板生成出来的?
本篇我们先不做解析,把全部的生成代码列在这里,大家先找找感觉。
CODE: (code_offset=0x0000211c size_offset=0x00002118 size=1028)...
0x0000211c: d1400bf0 sub x16, sp, #0x2000 (8192)
0x00002120: b940021f ldr wzr, [x16]
suspend point dex PC: 0x0000
GC map objects: v4 ([sp + #72]), v5 ([sp + #76])
0x00002124: f81c0fe0 str x0, [sp, #-64]!
0x00002128: f9001ffe str lr, [sp, #56]
0x0000212c: b9004be1 str w1, [sp, #72]
0x00002130: b9004fe2 str w2, [sp, #76]
0x00002134: 79400250 ldrh w16, [tr] (state_and_flags)
0x00002138: 350018f0 cbnz w16, #+0x31c (addr 0x2454)
0x0000213c: f94003e0 ldr x0, [sp]
0x00002140: b9400000 ldr w0, [x0]
0x00002144: b9401400 ldr w0, [x0, #20]
0x00002148: b9403000 ldr w0, [x0, #48]
0x0000214c: 340018a0 cbz w0, #+0x314 (addr 0x2460)
0x00002150: b90027e0 str w0, [sp, #36]
0x00002154: f94003e1 ldr x1, [sp]
0x00002158: 528002a0 mov w0, #0x15
0x0000215c: f940d65e ldr lr, [tr, #424] (pAllocObject)
0x00002160: d63f03c0 blr lr
suspend point dex PC: 0x0002
GC map objects: v0 ([sp + #36]), v4 ([sp + #72]), v5 ([sp + #76])
0x00002164: b9002be0 str w0, [sp, #40]
0x00002168: b9402be0 ldr w0, [sp, #40]
0x0000216c: b940001f ldr wzr, [x0]
suspend point dex PC: 0x0004
GC map objects: v0 ([sp + #36]), v1 ([sp + #40]), v4 ([sp + #72]), v5 ([sp + #76])
0x00002170: b90023e0 str w0, [sp, #32]
0x00002174: b94023e1 ldr w1, [sp, #32]
0x00002178: f94003e0 ldr x0, [sp]
0x0000217c: b9400400 ldr w0, [x0, #4]
0x00002180: f9405000 ldr x0, [x0, #160]
0x00002184: f940181e ldr lr, [x0, #48]
0x00002188: d63f03c0 blr lr
suspend point dex PC: 0x0004
GC map objects: v0 ([sp + #36]), v1 ([sp + #40]), v4 ([sp + #72]), v5 ([sp + #76])
0x0000218c: f94003e0 ldr x0, [sp]
0x00002190: b9400000 ldr w0, [x0]
0x00002194: b9401400 ldr w0, [x0, #20]
0x00002198: b940c800 ldr w0, [x0, #200]
0x0000219c: 340016a0 cbz w0, #+0x2d4 (addr 0x2470)
0x000021a0: b9002fe0 str w0, [sp, #44]
0x000021a4: b9402be0 ldr w0, [sp, #40]
0x000021a8: b940001f ldr wzr, [x0]
suspend point dex PC: 0x0009
GC map objects: v0 ([sp + #36]), v1 ([sp + #40]), v2 ([sp + #44]), v4 ([sp + #72]), v5 ([sp + #76])
0x000021ac: b90023e0 str w0, [sp, #32]
0x000021b0: b94023e1 ldr w1, [sp, #32]
0x000021b4: b9402fe2 ldr w2, [sp, #44]
0x000021b8: f94003e0 ldr x0, [sp]
0x000021bc: b9400400 ldr w0, [x0, #4]
0x000021c0: f9405800 ldr x0, [x0, #176]
0x000021c4: f940181e ldr lr, [x0, #48]
0x000021c8: d63f03c0 blr lr
suspend point dex PC: 0x0009
GC map objects: v0 ([sp + #36]), v1 ([sp + #40]), v2 ([sp + #44]), v4 ([sp + #72]), v5 ([sp + #76])
0x000021cc: b9002be0 str w0, [sp, #40]
0x000021d0: f94003e0 ldr x0, [sp]
0x000021d4: b9400800 ldr w0, [x0, #8]
0x000021d8: b9401c00 ldr w0, [x0, #28]
0x000021dc: 34001520 cbz w0, #+0x2a4 (addr 0x2480)
0x000021e0: 11021010 add w16, w0, #0x84 (132)
0x000021e4: 88dffe10 ldar w16, [x16]
0x000021e8: 71002a1f cmp w16, #0xa (10)
0x000021ec: 5400152b b.lt #+0x2a4 (addr 0x2490)
0x000021f0: f94003e0 ldr x0, [sp]
0x000021f4: b9400400 ldr w0, [x0, #4]
0x000021f8: f9401000 ldr x0, [x0, #32]
0x000021fc: f940181e ldr lr, [x0, #48]
0x00002200: d63f03c0 blr lr
suspend point dex PC: 0x000d
GC map objects: v0 ([sp + #36]), v1 ([sp + #40]), v2 ([sp + #44]), v4 ([sp + #72]), v5 ([sp + #76])
0x00002204: f802c3e0 stur x0, [sp, #44]
0x00002208: b9402be0 ldr w0, [sp, #40]
0x0000220c: b940001f ldr wzr, [x0]
suspend point dex PC: 0x0011
GC map objects: v0 ([sp + #36]), v1 ([sp + #40]), v4 ([sp + #72]), v5 ([sp + #76])
0x00002210: b90023e0 str w0, [sp, #32]
0x00002214: b94023e1 ldr w1, [sp, #32]
0x00002218: f842c3e2 ldur x2, [sp, #44]
0x0000221c: f94003e0 ldr x0, [sp]
0x00002220: b9400400 ldr w0, [x0, #4]
0x00002224: f9405400 ldr x0, [x0, #168]
0x00002228: f940181e ldr lr, [x0, #48]
0x0000222c: d63f03c0 blr lr
suspend point dex PC: 0x0011
GC map objects: v0 ([sp + #36]), v1 ([sp + #40]), v4 ([sp + #72]), v5 ([sp + #76])
0x00002230: b9002be0 str w0, [sp, #40]
0x00002234: b9402be0 ldr w0, [sp, #40]
0x00002238: b940001f ldr wzr, [x0]
suspend point dex PC: 0x0015
GC map objects: v0 ([sp + #36]), v1 ([sp + #40]), v4 ([sp + #72]), v5 ([sp + #76])
0x0000223c: b90023e0 str w0, [sp, #32]
0x00002240: b94023e1 ldr w1, [sp, #32]
0x00002244: f94003e0 ldr x0, [sp]
0x00002248: b9400400 ldr w0, [x0, #4]
0x0000224c: f9405c00 ldr x0, [x0, #184]
0x00002250: f940181e ldr lr, [x0, #48]
0x00002254: d63f03c0 blr lr
suspend point dex PC: 0x0015
GC map objects: v0 ([sp + #36]), v1 ([sp + #40]), v4 ([sp + #72]), v5 ([sp + #76])
0x00002258: b9002be0 str w0, [sp, #40]
0x0000225c: f94003e0 ldr x0, [sp]
0x00002260: b9400800 ldr w0, [x0, #8]
0x00002264: b9402000 ldr w0, [x0, #32]
0x00002268: 340011c0 cbz w0, #+0x238 (addr 0x24a0)
0x0000226c: 11021010 add w16, w0, #0x84 (132)
0x00002270: 88dffe10 ldar w16, [x16]
0x00002274: 71002a1f cmp w16, #0xa (10)
0x00002278: 540011cb b.lt #+0x238 (addr 0x24b0)
0x0000227c: b94027e1 ldr w1, [sp, #36]
0x00002280: b9402be2 ldr w2, [sp, #40]
0x00002284: f94003e0 ldr x0, [sp]
0x00002288: b9400400 ldr w0, [x0, #4]
0x0000228c: f9401400 ldr x0, [x0, #40]
0x00002290: f940181e ldr lr, [x0, #48]
0x00002294: d63f03c0 blr lr
suspend point dex PC: 0x0019
GC map objects: v0 ([sp + #36]), v1 ([sp + #40]), v4 ([sp + #72]), v5 ([sp + #76])
0x00002298: b9404be0 ldr w0, [sp, #72]
0x0000229c: b940001f ldr wzr, [x0]
suspend point dex PC: 0x001c
GC map objects: v0 ([sp + #36]), v1 ([sp + #40]), v4 ([sp + #72]), v5 ([sp + #76])
0x000022a0: b90023e0 str w0, [sp, #32]
0x000022a4: b94023e1 ldr w1, [sp, #32]
0x000022a8: b9404fe2 ldr w2, [sp, #76]
0x000022ac: f94003e0 ldr x0, [sp]
0x000022b0: b9400400 ldr w0, [x0, #4]
0x000022b4: f9400c00 ldr x0, [x0, #24]
0x000022b8: f940181e ldr lr, [x0, #48]
0x000022bc: d63f03c0 blr lr
suspend point dex PC: 0x001c
GC map objects: v0 ([sp + #36]), v1 ([sp + #40]), v4 ([sp + #72]), v5 ([sp + #76])
0x000022c0: 52afe070 mov w16, #0x7f030000
0x000022c4: b90027f0 str w16, [sp, #36]
0x000022c8: b9404be0 ldr w0, [sp, #72]
0x000022cc: b940001f ldr wzr, [x0]
suspend point dex PC: 0x0021
GC map objects: v1 ([sp + #40]), v4 ([sp + #72]), v5 ([sp + #76])
0x000022d0: b90023e0 str w0, [sp, #32]
0x000022d4: b94023e1 ldr w1, [sp, #32]
0x000022d8: b94027e2 ldr w2, [sp, #36]
0x000022dc: b9400020 ldr w0, [x1]
0x000022e0: f9469800 ldr x0, [x0, #3376]
0x000022e4: f940181e ldr lr, [x0, #48]
0x000022e8: d63f03c0 blr lr
suspend point dex PC: 0x0021
GC map objects: v1 ([sp + #40]), v4 ([sp + #72]), v5 ([sp + #76])
0x000022ec: f94003e0 ldr x0, [sp]
0x000022f0: b9400000 ldr w0, [x0]
0x000022f4: b9401400 ldr w0, [x0, #20]
0x000022f8: b9403000 ldr w0, [x0, #48]
0x000022fc: 34000e20 cbz w0, #+0x1c4 (addr 0x24c0)
0x00002300: b90027e0 str w0, [sp, #36]
0x00002304: f94003e1 ldr x1, [sp]
0x00002308: 528002a0 mov w0, #0x15
0x0000230c: f940d65e ldr lr, [tr, #424] (pAllocObject)
0x00002310: d63f03c0 blr lr
suspend point dex PC: 0x0026
GC map objects: v0 ([sp + #36]), v1 ([sp + #40]), v4 ([sp + #72]), v5 ([sp + #76])
0x00002314: b9002be0 str w0, [sp, #40]
0x00002318: b9402be0 ldr w0, [sp, #40]
0x0000231c: b940001f ldr wzr, [x0]
suspend point dex PC: 0x0028
GC map objects: v0 ([sp + #36]), v1 ([sp + #40]), v4 ([sp + #72]), v5 ([sp + #76])
0x00002320: b90023e0 str w0, [sp, #32]
0x00002324: b94023e1 ldr w1, [sp, #32]
0x00002328: f94003e0 ldr x0, [sp]
0x0000232c: b9400400 ldr w0, [x0, #4]
0x00002330: f9405000 ldr x0, [x0, #160]
0x00002334: f940181e ldr lr, [x0, #48]
0x00002338: d63f03c0 blr lr
suspend point dex PC: 0x0028
GC map objects: v0 ([sp + #36]), v1 ([sp + #40]), v4 ([sp + #72]), v5 ([sp + #76])
0x0000233c: f94003e0 ldr x0, [sp]
0x00002340: b9400000 ldr w0, [x0]
0x00002344: b9401400 ldr w0, [x0, #20]
0x00002348: b940cc00 ldr w0, [x0, #204]
0x0000234c: 34000c20 cbz w0, #+0x184 (addr 0x24d0)
0x00002350: b9002fe0 str w0, [sp, #44]
0x00002354: b9402be0 ldr w0, [sp, #40]
0x00002358: b940001f ldr wzr, [x0]
suspend point dex PC: 0x002d
GC map objects: v0 ([sp + #36]), v1 ([sp + #40]), v2 ([sp + #44]), v4 ([sp + #72]), v5 ([sp + #76])
0x0000235c: b90023e0 str w0, [sp, #32]
0x00002360: b94023e1 ldr w1, [sp, #32]
0x00002364: b9402fe2 ldr w2, [sp, #44]
0x00002368: f94003e0 ldr x0, [sp]
0x0000236c: b9400400 ldr w0, [x0, #4]
0x00002370: f9405800 ldr x0, [x0, #176]
0x00002374: f940181e ldr lr, [x0, #48]
0x00002378: d63f03c0 blr lr
suspend point dex PC: 0x002d
GC map objects: v0 ([sp + #36]), v1 ([sp + #40]), v2 ([sp + #44]), v4 ([sp + #72]), v5 ([sp + #76])
0x0000237c: b9002be0 str w0, [sp, #40]
0x00002380: f94003e0 ldr x0, [sp]
0x00002384: b9400800 ldr w0, [x0, #8]
0x00002388: b9401c00 ldr w0, [x0, #28]
0x0000238c: 34000aa0 cbz w0, #+0x154 (addr 0x24e0)
0x00002390: 11021010 add w16, w0, #0x84 (132)
0x00002394: 88dffe10 ldar w16, [x16]
0x00002398: 71002a1f cmp w16, #0xa (10)
0x0000239c: 54000aab b.lt #+0x154 (addr 0x24f0)
0x000023a0: f94003e0 ldr x0, [sp]
0x000023a4: b9400400 ldr w0, [x0, #4]
0x000023a8: f9401000 ldr x0, [x0, #32]
0x000023ac: f940181e ldr lr, [x0, #48]
0x000023b0: d63f03c0 blr lr
suspend point dex PC: 0x0031
GC map objects: v0 ([sp + #36]), v1 ([sp + #40]), v2 ([sp + #44]), v4 ([sp + #72]), v5 ([sp + #76])
0x000023b4: f802c3e0 stur x0, [sp, #44]
0x000023b8: b9402be0 ldr w0, [sp, #40]
0x000023bc: b940001f ldr wzr, [x0]
suspend point dex PC: 0x0035
GC map objects: v0 ([sp + #36]), v1 ([sp + #40]), v4 ([sp + #72]), v5 ([sp + #76])
0x000023c0: b90023e0 str w0, [sp, #32]
0x000023c4: b94023e1 ldr w1, [sp, #32]
0x000023c8: f842c3e2 ldur x2, [sp, #44]
0x000023cc: f94003e0 ldr x0, [sp]
0x000023d0: b9400400 ldr w0, [x0, #4]
0x000023d4: f9405400 ldr x0, [x0, #168]
0x000023d8: f940181e ldr lr, [x0, #48]
0x000023dc: d63f03c0 blr lr
suspend point dex PC: 0x0035
GC map objects: v0 ([sp + #36]), v1 ([sp + #40]), v4 ([sp + #72]), v5 ([sp + #76])
0x000023e0: b9002be0 str w0, [sp, #40]
0x000023e4: b9402be0 ldr w0, [sp, #40]
0x000023e8: b940001f ldr wzr, [x0]
suspend point dex PC: 0x0039
GC map objects: v0 ([sp + #36]), v1 ([sp + #40]), v4 ([sp + #72]), v5 ([sp + #76])
0x000023ec: b90023e0 str w0, [sp, #32]
0x000023f0: b94023e1 ldr w1, [sp, #32]
0x000023f4: f94003e0 ldr x0, [sp]
0x000023f8: b9400400 ldr w0, [x0, #4]
0x000023fc: f9405c00 ldr x0, [x0, #184]
0x00002400: f940181e ldr lr, [x0, #48]
0x00002404: d63f03c0 blr lr
suspend point dex PC: 0x0039
GC map objects: v0 ([sp + #36]), v1 ([sp + #40]), v4 ([sp + #72]), v5 ([sp + #76])
0x00002408: b9002be0 str w0, [sp, #40]
0x0000240c: f94003e0 ldr x0, [sp]
0x00002410: b9400800 ldr w0, [x0, #8]
0x00002414: b9402000 ldr w0, [x0, #32]
0x00002418: 34000740 cbz w0, #+0xe8 (addr 0x2500)
0x0000241c: 11021010 add w16, w0, #0x84 (132)
0x00002420: 88dffe10 ldar w16, [x16]
0x00002424: 71002a1f cmp w16, #0xa (10)
0x00002428: 5400074b b.lt #+0xe8 (addr 0x2510)
0x0000242c: b94027e1 ldr w1, [sp, #36]
0x00002430: b9402be2 ldr w2, [sp, #40]
0x00002434: f94003e0 ldr x0, [sp]
0x00002438: b9400400 ldr w0, [x0, #4]
0x0000243c: f9401400 ldr x0, [x0, #40]
0x00002440: f940181e ldr lr, [x0, #48]
0x00002444: d63f03c0 blr lr
suspend point dex PC: 0x003d
GC map objects: v0 ([sp + #36]), v1 ([sp + #40]), v4 ([sp + #72]), v5 ([sp + #76])
0x00002448: f9401ffe ldr lr, [sp, #56]
0x0000244c: 910103ff add sp, sp, #0x40 (64)
0x00002450: d65f03c0 ret
0x00002454: f9421e5e ldr lr, [tr, #1080] (pTestSuspend)
0x00002458: d63f03c0 blr lr
suspend point dex PC: 0x0000
GC map objects: v4 ([sp + #72]), v5 ([sp + #76])
0x0000245c: 17ffff38 b #-0x320 (addr 0x213c)
0x00002460: 52800120 mov w0, #0x9
0x00002464: f9410e5e ldr lr, [tr, #536] (pResolveString)
0x00002468: d63f03c0 blr lr
suspend point dex PC: 0x0000
GC map objects: v4 ([sp + #72]), v5 ([sp + #76])
0x0000246c: 17ffff39 b #-0x31c (addr 0x2150)
0x00002470: 528005e0 mov w0, #0x2f
0x00002474: f9410e5e ldr lr, [tr, #536] (pResolveString)
0x00002478: d63f03c0 blr lr
suspend point dex PC: 0x0007
GC map objects: v0 ([sp + #36]), v1 ([sp + #40]), v4 ([sp + #72]), v5 ([sp + #76])
0x0000247c: 17ffff49 b #-0x2dc (addr 0x21a0)
0x00002480: 52800080 mov w0, #0x4
0x00002484: f9410a5e ldr lr, [tr, #528] (pInitializeType)
0x00002488: d63f03c0 blr lr
suspend point dex PC: 0x000d
GC map objects: v0 ([sp + #36]), v1 ([sp + #40]), v2 ([sp + #44]), v4 ([sp + #72]), v5 ([sp + #76])
0x0000248c: 17ffff55 b #-0x2ac (addr 0x21e0)
0x00002490: 52800080 mov w0, #0x4
0x00002494: f941025e ldr lr, [tr, #512] (pInitializeStaticStorage)
0x00002498: d63f03c0 blr lr
suspend point dex PC: 0x000d
GC map objects: v0 ([sp + #36]), v1 ([sp + #40]), v2 ([sp + #44]), v4 ([sp + #72]), v5 ([sp + #76])
0x0000249c: 17ffff55 b #-0x2ac (addr 0x21f0)
0x000024a0: 528000a0 mov w0, #0x5
0x000024a4: f9410a5e ldr lr, [tr, #528] (pInitializeType)
0x000024a8: d63f03c0 blr lr
suspend point dex PC: 0x0019
GC map objects: v0 ([sp + #36]), v1 ([sp + #40]), v4 ([sp + #72]), v5 ([sp + #76])
0x000024ac: 17ffff70 b #-0x240 (addr 0x226c)
0x000024b0: 528000a0 mov w0, #0x5
0x000024b4: f941025e ldr lr, [tr, #512] (pInitializeStaticStorage)
0x000024b8: d63f03c0 blr lr
suspend point dex PC: 0x0019
GC map objects: v0 ([sp + #36]), v1 ([sp + #40]), v4 ([sp + #72]), v5 ([sp + #76])
0x000024bc: 17ffff70 b #-0x240 (addr 0x227c)
0x000024c0: 52800120 mov w0, #0x9
0x000024c4: f9410e5e ldr lr, [tr, #536] (pResolveString)
0x000024c8: d63f03c0 blr lr
suspend point dex PC: 0x0024
GC map objects: v1 ([sp + #40]), v4 ([sp + #72]), v5 ([sp + #76])
0x000024cc: 17ffff8d b #-0x1cc (addr 0x2300)
0x000024d0: 52800600 mov w0, #0x30
0x000024d4: f9410e5e ldr lr, [tr, #536] (pResolveString)
0x000024d8: d63f03c0 blr lr
suspend point dex PC: 0x002b
GC map objects: v0 ([sp + #36]), v1 ([sp + #40]), v4 ([sp + #72]), v5 ([sp + #76])
0x000024dc: 17ffff9d b #-0x18c (addr 0x2350)
0x000024e0: 52800080 mov w0, #0x4
0x000024e4: f9410a5e ldr lr, [tr, #528] (pInitializeType)
0x000024e8: d63f03c0 blr lr
suspend point dex PC: 0x0031
GC map objects: v0 ([sp + #36]), v1 ([sp + #40]), v2 ([sp + #44]), v4 ([sp + #72]), v5 ([sp + #76])
0x000024ec: 17ffffa9 b #-0x15c (addr 0x2390)
0x000024f0: 52800080 mov w0, #0x4
0x000024f4: f941025e ldr lr, [tr, #512] (pInitializeStaticStorage)
0x000024f8: d63f03c0 blr lr
suspend point dex PC: 0x0031
GC map objects: v0 ([sp + #36]), v1 ([sp + #40]), v2 ([sp + #44]), v4 ([sp + #72]), v5 ([sp + #76])
0x000024fc: 17ffffa9 b #-0x15c (addr 0x23a0)
0x00002500: 528000a0 mov w0, #0x5
0x00002504: f9410a5e ldr lr, [tr, #528] (pInitializeType)
0x00002508: d63f03c0 blr lr
suspend point dex PC: 0x003d
GC map objects: v0 ([sp + #36]), v1 ([sp + #40]), v4 ([sp + #72]), v5 ([sp + #76])
0x0000250c: 17ffffc4 b #-0xf0 (addr 0x241c)
0x00002510: 528000a0 mov w0, #0x5
0x00002514: f941025e ldr lr, [tr, #512] (pInitializeStaticStorage)
0x00002518: d63f03c0 blr lr
suspend point dex PC: 0x003d
GC map objects: v0 ([sp + #36]), v1 ([sp + #40]), v4 ([sp + #72]), v5 ([sp + #76])
0x0000251c: 17ffffc4 b #-0xf0 (addr 0x242c)