前言
最近遇到一个 native crash 问题,如下所示:(Android 8.1)
Revision: '0'
ABI: 'arm64'
pid: 1863, tid: 3348, name: Binder:1863_F >>> system_server <<<
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x8
Cause: null pointer dereference
x0 c200007682ae00c0 x1 0000000070556938 x2 0000000000000001 x3 000000761afa89d8
x4 00000000137c0248 x5 0000000000000010 x6 0000000000000001 x7 0000000000000008
x8 0000000000000000 x9 238e9a517469cba9 x10 000000761afa89d4 x11 000000764e6e47b8
x12 0000000000000006 x13 0000000000000019 x14 0000000000000229 x15 0000000000000007
x16 000000761afa89d8 x17 0000000000000020 x18 0000000000000008 x19 0000000070556938
x20 0000000000000001 x21 000000761afa9588 x22 000000764eaa9300 x23 000000764eaa93f8
x24 000000764e623e73 x25 000000764e623e7b x26 0000000000000043 x27 000000761afa9588
x28 0000000000000059 x29 000000761afa88a0 x30 000000764e2dde4c
sp 000000761afa8860 pc 000000764e2cae80 pstate 0000000080000000
v0 0000000000000000ffffffffffffffff v1 000000761afa90a0000000761afa9110
v2 000000000000000075636553636e7953 v3 00000000000000000000000000000000
v4 00000000000000000000000000000000 v5 00000000000000004000000000000000
v6 00000000000000000000000000000000 v7 00000000000000008020080280200802
v8 00000000000000000000000000000000 v9 00000000000000000000000000000000
v10 00000000000000000000000000000000 v11 00000000000000000000000000000000
v12 00000000000000000000000000000000 v13 00000000000000000000000000000000
v14 00000000000000000000000000000000 v15 00000000000000000000000000000000
v16 40100401401004014010040140100401 v17 80080000000000008800000000404000
v18 80000800000000000000000000000000 v19 0000000000000000d362ff28f3dabbdf
v20 000000000000000000000000ebad8084 v21 000000000000000000000000ebad8085
v22 000000000000000000000000ebad8086 v23 000000000000000000000000ebad8087
v24 000000000000000000000000ebad8088 v25 000000000000000000000000ebad8089
v26 000000000000000000000000ebad808a v27 000000000000000000000000ebad808b
v28 000000000000000000000000ebad808c v29 000000000000000000000000ebad808d
v30 000000000000000000000000ebad808e v31 000000000000000000000000133c7810
fpsr 00000013 fpcr 00000000
backtrace:
#00 pc 0000000000215e80 /system/lib64/libart.so (art::gc::Heap::FindContinuousSpaceFromObject(art::ObjPtr<art::mirror::Object>, bool) const+68)
#01 pc 0000000000228e48 /system/lib64/libart.so (art::gc::Heap::IsMovableObject(art::ObjPtr<art::mirror::Object>) const+12)
#02 pc 0000000000382f04 /system/lib64/libart.so (art::JNI::GetStringCritical(_JNIEnv*, _jstring*, unsigned char*)+596)
#03 pc 000000000011342c /system/lib64/libandroid_runtime.so (android::android_os_Parcel_enforceInterface(_JNIEnv*, _jclass*, long, _jstring*)+76)
#04 pc 0000000000cc9254 /system/framework/arm64/boot-framework.oat (offset 0x9bd000) (android.app.admin.SecurityLog.readEventsOnWrapping [DEDUPED]+180)
#05 pc 000000000177afc8 /system/framework/arm64/boot-framework.oat (offset 0x9bd000) (android.os.Parcel.enforceInterface+56)
#06 pc 00000000014f05ec /system/framework/arm64/boot-framework.oat (offset 0x9bd000) (android.net.IConnectivityManager$Stub.onTransact+17724)
#07 pc 00000000009c017c /system/framework/arm64/boot-framework.oat (offset 0x9bd000) (android.os.Binder.execTransact+524)
#08 pc 0000000000549588 /system/lib64/libart.so (art_quick_invoke_stub+584)
#09 pc 00000000000dd178 /system/lib64/libart.so (art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)+200)
#10 pc 000000000046d290 /system/lib64/libart.so (art::InvokeWithArgArray(art::ScopedObjectAccessAlreadyRunnable const&, art::ArtMethod*, art::ArgArray*, art::JValue*, char const*)+100)
#11 pc 000000000046e718 /system/lib64/libart.so (art::InvokeVirtualOrInterfaceWithVarArgs(art::ScopedObjectAccessAlreadyRunnable const&, _jobject*, _jmethodID*, std::__va_list)+440)
#12 pc 0000000000347ed8 /system/lib64/libart.so (art::JNI::CallBooleanMethodV(_JNIEnv*, _jobject*, _jmethodID*, std::__va_list)+624)
#13 pc 00000000000bba88 /system/lib64/libandroid_runtime.so (_JNIEnv::CallBooleanMethod(_jobject*, _jmethodID*, ...)+120)
#14 pc 000000000011f2cc /system/lib64/libandroid_runtime.so (JavaBBinder::onTransact(unsigned int, android::Parcel const&, android::Parcel*, unsigned int)+156)
#15 pc 000000000004ae38 /system/lib64/libbinder.so (android::BBinder::transact(unsigned int, android::Parcel const&, android::Parcel*, unsigned int)+136)
#16 pc 0000000000054e04 /system/lib64/libbinder.so (android::IPCThreadState::executeCommand(int)+532)
#17 pc 0000000000054b40 /system/lib64/libbinder.so (android::IPCThreadState::getAndExecuteCommand()+156)
#18 pc 0000000000055178 /system/lib64/libbinder.so (android::IPCThreadState::joinThreadPool(bool)+60)
#19 pc 00000000000761f8 /system/lib64/libbinder.so (android::PoolThread::threadLoop()+24)
#20 pc 0000000000011460 /system/lib64/libutils.so (android::Thread::_threadLoop(void*)+280)
#21 pc 00000000000ab6a0 /system/lib64/libandroid_runtime.so (android::AndroidRuntime::javaThreadShell(void*)+140)
#22 pc 0000000000067e3c /system/lib64/libc.so (__pthread_start(void*)+36)
#23 pc 000000000001f280 /system/lib64/libc.so (__start_thread+68)
在反汇编 FindContinuousSpaceFromObject 方法的时候,始终理解的不太清楚,因此,使用 gdb 来辅助理解一下。因为 gdb 调试过程当中,使用了一些 gdb 分析的常用技巧,并且新了解到了一些汇编知识,因此,将自己的一些收获总结下来。(注:因为手头的机器恰好是 Android 7.0 的,所以 gdb 调试分析过程基于 Android 7.0,与上面的 log 略有不同)
一、FindContinuousSpaceFromObject
首先看一下 FindContinuousSpaceFromObject 方法的实现,基于 Android 7.0:
art/runtime/gc/heap.cc
space::ContinuousSpace* Heap::FindContinuousSpaceFromObject(const mirror::Object* obj,
bool fail_ok) const {
for (const auto& space : continuous_spaces_) {
if (space->Contains(obj)) {
return space;
}
}
if (!fail_ok) {
LOG(FATAL) << "object " << reinterpret_cast<const void*>(obj) << " not inside any spaces!";
}
return nullptr;
}
二、gdb 分析过程
首先,我们需要将断点设置在 FindContinuousSpaceFromObject 方法处,通过:
nm libart.so | grep -i FindContinuousSpaceFromObject
我们可以知道 FindContinuousSpaceFromObject 对应的 symbol 为:
_ZNK3art2gc4Heap29FindContinuousSpaceFromObjectEPKNS_6mirror6ObjectEb
通过 b 来设置断点,continue 使程序继续运行:
通过 disass 查看其对应的汇编代码:
Dump of assembler code for function art::gc::Heap::FindContinuousSpaceFromObject(art::mirror::Object const*, bool) const:
0x0000007fa15dd42c <+0>: stp x24, x23, [sp,#-64]!
0x0000007fa15dd430 <+4>: stp x22, x21, [sp,#16]
0x0000007fa15dd434 <+8>: stp x20, x19, [sp,#32]
0x0000007fa15dd438 <+12>: stp x29, x30, [sp,#48]
0x0000007fa15dd43c <+16>: add x29, sp, #0x30
0x0000007fa15dd440 <+20>: sub sp, sp, #0x10
0x0000007fa15dd444 <+24>: adrp x22, 0x7fa19f8000 <_ZTVN3art5arm6412Arm64ContextE+32>
0x0000007fa15dd448 <+28>: ldr x22, [x22,#1368]
0x0000007fa15dd44c <+32>: mov w20, w2
0x0000007fa15dd450 <+36>: mov x19, x1
0x0000007fa15dd454 <+40>: ldr x22, [x22]
0x0000007fa15dd458 <+44>: str x22, [sp,#8]
=> 0x0000007fa15dd45c <+48>: ldp x23, x21, [x0]
0x0000007fa15dd460 <+52>: cmp x23, x21
0x0000007fa15dd464 <+56>: b.eq 0x7fa15dd494 <art::gc::Heap::FindContinuousSpaceFromObject(art::mirror::Object const*, bool) const+104>
0x0000007fa15dd468 <+60>: mov x24, x23
0x0000007fa15dd46c <+64>: ldr x0, [x24],#8
0x0000007fa15dd470 <+68>: mov x1, x19
0x0000007fa15dd474 <+72>: ldr x8, [x0]
0x0000007fa15dd478 <+76>: ldr x8, [x8,#8]
0x0000007fa15dd47c <+80>: blr x8
0x0000007fa15dd480 <+84>: and w8, w0, #0x1
0x0000007fa15dd484 <+88>: tbnz w8, #0, 0x7fa15dd530 <art::gc::Heap::FindContinuousSpaceFromObject(art::mirror::Object const*, bool) const+260>
0x0000007fa15dd488 <+92>: cmp x21, x24
0x0000007fa15dd48c <+96>: mov x23, x24
0x0000007fa15dd490 <+100>: b.ne 0x7fa15dd468 <art::gc::Heap::FindContinuousSpaceFromObject(art::mirror::Object const*, bool) const+60>
0x0000007fa15dd494 <+104>: and w8, w20, #0x1
0x0000007fa15dd498 <+108>: tbz w8, #0, 0x7fa15dd4a4 <art::gc::Heap::FindContinuousSpaceFromObject(art::mirror::Object const*, bool) const+120>
0x0000007fa15dd49c <+112>: mov x0, xzr
0x0000007fa15dd4a0 <+116>: b 0x7fa15dd534 <art::gc::Heap::FindContinuousSpaceFromObject(art::mirror::Object const*, bool) const+264>
0x0000007fa15dd4a4 <+120>: adrp x1, 0x7fa195e000
0x0000007fa15dd4a8 <+124>: add x1, x1, #0xb83
0x0000007fa15dd4ac <+128>: mov x0, sp
0x0000007fa15dd4b0 <+132>: mov w2, #0x515 // #1301
0x0000007fa15dd4b4 <+136>: orr w3, wzr, #0x6
0x0000007fa15dd4b8 <+140>: mov w4, #0xffffffff // #-1
0x0000007fa15dd4bc <+144>: bl 0x7fa14be818 <art::LogMessage::LogMessage(char const*, unsigned int, art::LogSeverity, int)>
0x0000007fa15dd4c0 <+148>: mov x0, sp
0x0000007fa15dd4c4 <+152>: bl 0x7fa14be810 <art::LogMessage::stream()>
0x0000007fa15dd4c8 <+156>: adrp x21, 0x7fa195f000
0x0000007fa15dd4cc <+160>: add x21, x21, #0x806
0x0000007fa15dd4d0 <+164>: mov x20, x0
0x0000007fa15dd4d4 <+168>: orr w1, wzr, #0x8
0x0000007fa15dd4d8 <+172>: mov x0, x21
0x0000007fa15dd4dc <+176>: bl 0x7fa1497b00 <__strlen_chk@plt>
0x0000007fa15dd4e0 <+180>: mov x2, x0
0x0000007fa15dd4e4 <+184>: mov x0, x20
0x0000007fa15dd4e8 <+188>: mov x1, x21
0x0000007fa15dd4ec <+192>: bl 0x7fa14b5c74 <std::__1::__put_character_sequence<char, std::__1::char_traits<char> >(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, char const*, unsigned long)>
0x0000007fa15dd4f0 <+196>: mov x1, x19
0x0000007fa15dd4f4 <+200>: bl 0x7fa14b5abc <std::__1::basic_ostream<char, std::__1::char_traits<char> >::operator<<(void const*)>
0x0000007fa15dd4f8 <+204>: adrp x20, 0x7fa195f000
0x0000007fa15dd4fc <+208>: add x20, x20, #0x80e
0x0000007fa15dd500 <+212>: mov x19, x0
0x0000007fa15dd504 <+216>: orr w1, wzr, #0x18
0x0000007fa15dd508 <+220>: mov x0, x20
0x0000007fa15dd50c <+224>: bl 0x7fa1497b00 <__strlen_chk@plt>
0x0000007fa15dd510 <+228>: mov x2, x0
0x0000007fa15dd514 <+232>: mov x0, x19
0x0000007fa15dd518 <+236>: mov x1, x20
0x0000007fa15dd51c <+240>: bl 0x7fa14b5c74 <std::__1::__put_character_sequence<char, std::__1::char_traits<char> >(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, char const*, unsigned long)>
0x0000007fa15dd520 <+244>: mov x0, sp
0x0000007fa15dd524 <+248>: bl 0x7fa14be964 <art::LogMessage::~LogMessage()>
0x0000007fa15dd528 <+252>: mov x0, xzr
0x0000007fa15dd52c <+256>: b 0x7fa15dd534 <art::gc::Heap::FindContinuousSpaceFromObject(art::mirror::Object const*, bool) const+264>
0x0000007fa15dd530 <+260>: ldr x0, [x23]
0x0000007fa15dd534 <+264>: ldr x8, [sp,#8]
0x0000007fa15dd538 <+268>: sub x8, x22, x8
0x0000007fa15dd53c <+272>: cbnz x8, 0x7fa15dd558 <art::gc::Heap::FindContinuousSpaceFromObject(art::mirror::Object const*, bool) const+300>
0x0000007fa15dd540 <+276>: sub sp, x29, #0x30
0x0000007fa15dd544 <+280>: ldp x29, x30, [sp,#48]
0x0000007fa15dd548 <+284>: ldp x20, x19, [sp,#32]
0x0000007fa15dd54c <+288>: ldp x22, x21, [sp,#16]
0x0000007fa15dd550 <+292>: ldp x24, x23, [sp],#64
0x0000007fa15dd554 <+296>: ret
0x0000007fa15dd558 <+300>: bl 0x7fa1497af0 <__stack_chk_fail@plt>
End of assembler dump.
我们主要关注一下:
Dump of assembler code for function art::gc::Heap::FindContinuousSpaceFromObject(art::mirror::Object const*, bool) const:
0x0000007fa15dd42c <+0>: stp x24, x23, [sp,#-64]!
0x0000007fa15dd430 <+4>: stp x22, x21, [sp,#16]
0x0000007fa15dd434 <+8>: stp x20, x19, [sp,#32]
0x0000007fa15dd438 <+12>: stp x29, x30, [sp,#48]
0x0000007fa15dd43c <+16>: add x29, sp, #0x30
0x0000007fa15dd440 <+20>: sub sp, sp, #0x10
0x0000007fa15dd444 <+24>: adrp x22, 0x7fa19f8000 <_ZTVN3art5arm6412Arm64ContextE+32>
0x0000007fa15dd448 <+28>: ldr x22, [x22,#1368]
// 此处开始主要部分
0x0000007fa15dd44c <+32>: mov w20, w2 // 参数2,bool fail_ok
0x0000007fa15dd450 <+36>: mov x19, x1 // 参数1,const mirror::Object* obj
0x0000007fa15dd454 <+40>: ldr x22, [x22]
0x0000007fa15dd458 <+44>: str x22, [sp,#8]
=> 0x0000007fa15dd45c <+48>: ldp x23, x21, [x0] // x0 中是 this 指针,即指向 Heap 对象的指针
0x0000007fa15dd460 <+52>: cmp x23, x21
0x0000007fa15dd464 <+56>: b.eq 0x7fa15dd494 <art::gc::Heap::FindContinuousSpaceFromObject(art::mirror::Object const*, bool) const+104>
// b.ne 0x7fa15dd468 会跳转到此处
0x0000007fa15dd468 <+60>: mov x24, x23
0x0000007fa15dd46c <+64>: ldr x0, [x24],#8
0x0000007fa15dd470 <+68>: mov x1, x19
0x0000007fa15dd474 <+72>: ldr x8, [x0]
0x0000007fa15dd478 <+76>: ldr x8, [x8,#8]
0x0000007fa15dd47c <+80>: blr x8
0x0000007fa15dd480 <+84>: and w8, w0, #0x1
0x0000007fa15dd484 <+88>: tbnz w8, #0, 0x7fa15dd530 <art::gc::Heap::FindContinuousSpaceFromObject(art::mirror::Object const*, bool) const+260>
0x0000007fa15dd488 <+92>: cmp x21, x24
0x0000007fa15dd48c <+96>: mov x23, x24
0x0000007fa15dd490 <+100>: b.ne 0x7fa15dd468 <art::gc::Heap::FindContinuousSpaceFromObject(art::mirror::Object const*, bool) const+60>
这一段是循环的主要内容,如下所示:
for (const auto& space : continuous_spaces_) {
if (space->Contains(obj)) {
return space;
}
}
从上面的注释来看,我们可以知道,x0 中是 this 指针,即指向 Heap 对象的指针,那么
0x0000007fa15dd45c <+48>: ldp x23, x21, [x0]
是在干什么呢?我们可以通过
b *0x0000007fa15dd460
把断点打在
0x0000007fa15dd460 <+52>: cmp x23, x21
处,然后看一下各个寄存器的值来加以分析。
// x0 即为 0x7fa1a4c700
(gdb) p /x $x0
$1 = 0x7fa1a4c700
// 因为 x0 中是指向 ‘art::gc::Heap’ 类型的指针,所以 print 一下其对应的对象
(gdb) p ('art::gc::Heap')*0x7fa1a4c700
$2 = {
static kDefaultStartingSize = 4096,
static kDefaultInitialSize = 2097152,
...
continuous_spaces_ = {
<std::__1::__vector_base<art::gc::space::ContinuousSpace*, std::__1::allocator<art::gc::space::ContinuousSpace*> >> = {
<std::__1::__vector_base_common<true>> = {<No data fields>},
members of std::__1::__vector_base<art::gc::space::ContinuousSpace*, std::__1::allocator<art::gc::space::ContinuousSpace*> >:
__begin_ = 0x7fa1a80200,
__end_ = 0x7fa1a802c0,
__end_cap_ = {
...
}
// 所以可知 Heap 对象的第一个成员即为 continuous_spaces_,
// 其类型为 'std::__1::__vector_base<art::gc::space::ContinuousSpace*, std::__1::allocator<art::gc::space::ContinuousSpace*> >'
// 所以 ldp x23, x21, [x0] 对应的就是分别把 __begin_ 和 __end_ 放在了 x23、x21 中
// 可以验证一下
(gdb) p /x $x23
$5 = 0x7fa1a80200
(gdb) p /x $x21
$6 = 0x7fa1a802c0
// 所以 cmp x23, x21 就是比较 __begin_(或当前指针)和 __end_ 两个指针
// 从而我们可以确定 continuous_spaces_ 中是否还有元素
接下来调整断点到
0x0000007fa15dd47c <+80>: blr x8
// x24 = x23,即 x24 现在为 __begin_
0x0000007fa15dd468 <+60>: mov x24, x23
0x0000007fa15dd46c <+64>: ldr x0, [x24],#8
// x23 即 __begin_
(gdb) p /x $x23
$7 = 0x7fa1a80200
// x24 比 __begin_ 多 8,可知 ldr x0, [x24],#8 会使 x24 = x24 + 8
// 即指针增加一个元素单位长度
(gdb) p /x $x24
$8 = 0x7fa1a80208
// 因为 x0 中的值等于地址 0x7fa1a80200 中的值,此时 x24 还没加 8
// 所以 ldr x0, [x24],#8 可以看作
// 先 ldr x0, [x24]
// 再 x24 = x24 + 8
(gdb) p /x $x0
$9 = 0x7fa1aa3380
(gdb) x/1xg 0x7fa1a80200
0x7fa1a80200: 0x0000007fa1aa3380
(gdb) x/1xg 0x7fa1a80208
0x7fa1a80208: 0x0000007fa1a26300
// x1 为参数1,即 const mirror::Object* obj
0x0000007fa15dd470 <+68>: mov x1, x19
// x0 中是一个 art::gc::space::ContinuousSpace* 指针
// 所以 x8 中赋值的是一个 art::gc::space::ContinuousSpace 对象的数据
0x0000007fa15dd474 <+72>: ldr x8, [x0]
// 即应该为 0x7fa19ef428
(gdb) p ('art::gc::space::ContinuousSpace')*0x7fa1aa3380
$12 = {
<art::gc::space::Space> = {
_vptr$Space = 0x7fa19ef428 <vtable for art::gc::space::RosAllocSpace+16>,
name_ = {
...
}
// 所以 load 之后 x8 中应该为地址 0x7fa19ef428+8 上的值
0x0000007fa15dd478 <+76>: ldr x8, [x8,#8]
// 验证一下:
(gdb) p /x $x8
$13 = 0x7fa15f4f78
(gdb) p /x 0x7fa19ef428 + 8
$14 = 0x7fa19ef430
(gdb) x/1xg 0x7fa19ef430
0x7fa19ef430 <_ZTVN3art2gc5space13RosAllocSpaceE+24>: 0x0000007fa15f4f78
// 验证没问题
=> 0x0000007fa15dd47c <+80>: blr x8
0x0000007fa15dd480 <+84>: and w8, w0, #0x1
0x0000007fa15dd484 <+88>: tbnz w8, #0, 0x7fa15dd530 <art::gc::Heap::FindContinuousSpaceFromObject(art::mirror::Object const*, bool) const+260>
0x0000007fa15dd488 <+92>: cmp x21, x24
0x0000007fa15dd48c <+96>: mov x23, x24
0x0000007fa15dd490 <+100>: b.ne 0x7fa15dd468 <art::gc::Heap::FindContinuousSpaceFromObject(art::mirror::Object const*, bool) const+60>
上面解释了各个汇编指令大体的意思,并结合 gdb 做了一些测试;那么
_vptr$Space = 0x7fa19ef428 <vtable for art::gc::space::RosAllocSpace+16>
是什么呢?为什么 blr x8 就相当于调用 Contains() 方法了呢?
原因是 art::gc::space::ContinuousSpace 的父类为 class art::gc::space::Space,查看其结构:
(gdb) ptype 'art::gc::space::Space'
type = class art::gc::space::Space {
protected:
std::__1::string name_;
art::gc::space::GcRetentionPolicy gc_retention_policy_;
public:
virtual void Dump(std::__1::ostream &) const;
const char * GetName(void) const;
art::gc::space::GcRetentionPolicy GetGcRetentionPolicy(void) const;
virtual bool Contains(const art::mirror::Object *) const;
virtual art::gc::space::SpaceType GetType(void) const;
bool IsImageSpace(void) const;
art::gc::space::ImageSpace * AsImageSpace(void);
bool IsMallocSpace(void) const;
art::gc::space::MallocSpace * AsMallocSpace(void);
virtual bool IsDlMallocSpace(void) const;
virtual art::gc::space::DlMallocSpace * AsDlMallocSpace(void);
virtual bool IsRosAllocSpace(void) const;
virtual art::gc::space::RosAllocSpace * AsRosAllocSpace(void);
bool IsZygoteSpace(void) const;
virtual art::gc::space::ZygoteSpace * AsZygoteSpace(void);
bool IsBumpPointerSpace(void) const;
virtual art::gc::space::BumpPointerSpace * AsBumpPointerSpace(void);
bool IsRegionSpace(void) const;
virtual art::gc::space::RegionSpace * AsRegionSpace(void);
bool IsLargeObjectSpace(void) const;
art::gc::space::LargeObjectSpace * AsLargeObjectSpace(void);
virtual bool IsContinuousSpace(void) const;
art::gc::space::ContinuousSpace * AsContinuousSpace(void);
virtual bool IsDiscontinuousSpace(void) const;
art::gc::space::DiscontinuousSpace * AsDiscontinuousSpace(void);
virtual bool IsAllocSpace(void) const;
virtual art::gc::space::AllocSpace * AsAllocSpace(void);
virtual bool IsContinuousMemMapAllocSpace(void) const;
virtual art::gc::space::ContinuousMemMapAllocSpace * AsContinuousMemMapAllocSpace(void);
virtual bool CanMoveObjects(void) const;
virtual ~Space(void);
protected:
Space(const std::__1::string &, art::gc::space::GcRetentionPolicy);
private:
Space(void);
Space(const art::gc::space::Space &);
protected:
void SetGcRetentionPolicy(art::gc::space::GcRetentionPolicy);
private:
void operator=(const art::gc::space::Space &);
}
其中存在虚函数,0x7fa19ef428 即为 art::gc::space::ContinuousSpace 实例的自动生成的 vtable 的地址,用于查找对应的虚函数的调用地址,因为 Contains() 方法为第二个虚函数,所以 0x7fa19ef428+8 中的值才为 Contains() 方法的跳转地址。
三、总结
需要注意的点:
- ldr x8, [x0]:假设 x0 中为 num_ptr,这里就为取地址 num_ptr 中的值放到 x8 中
- ldr x8, [x8,#8]:假设 x8 中为 num_ptr,这里就为取地址(num_ptr+8)中的值放到 x8 中
- ldr x0, [x24],#8:假设 x24 中为 num_ptr,这里就为取地址 num_ptr 中的值放到 x0 中,并且将 (num_ptr+8)放到 x24 中
- 注意 vtable
- for (const auto& space : continuous_spaces_) 依据 std::__1::__vector_base 的 _begin、_end 指针以及指向当前元素的指针来判断是否结束循环