有时 gcc 在编译 arm abi 的 C++ 代码时会将第一个参数放入 R1 寄存器?
Sometimes gcc would put the first argument into R1 register when compiling the C++ code for arm abi?
从 ARM 到 C 的调用约定,我知道参数是从寄存器 r0-r4 开始按顺序传递的,然后对于其他参数使用堆栈。 Return 值传递给 r0-r1。
但是在libart.so(AndroidM,/system/lib/libart.so,32bit)中,有一个方法好像不符合规则。
//https://android.googlesource.com/platform/art/+/android-6.0.0_r5/runtime/oat_file.cc
std::unique_ptr<const DexFile> OatFile::OatDexFile::OpenDexFile(std::string* error_msg) const {
return DexFile::Open(dex_file_pointer_, FileSize(), dex_file_location_,
dex_file_location_checksum_, this, error_msg);
}
//https://android.googlesource.com/platform/art/+/android-6.0.0_r5/runtime/dex_file.h
static std::unique_ptr<const DexFile> DexFile::Open(const uint8_t* base, size_t size,
const std::string& location,
uint32_t location_checksum,
const OatDexFile* oat_dex_file,
std::string* error_msg) {
return OpenMemory(base, size, location, location_checksum, nullptr, oat_dex_file, error_msg);
}
OpenDexfile 是 OatDexFile class 的一个成员函数,它是 OatFile class 的内部 class。所以 OpenDexFile 实际上有 2 个参数,因为第一个参数是 "this"。
但在 IDA Pro 中,OpenDexFile 如下所示:
.text:002E9718 var_14 = -0x14
.text:002E9718 var_4 = -4
.text:002E9718
.text:002E9718 STR.W R4, [SP,#var_14]!
.text:002E971C MOV R4, R1 ;<<--After analysing, I can assure that R1 is the "this" pointer
.text:002E971E LDR R1, [R1,#0x20] ;<<---dex_file_pointer
.text:002E9720 STRD.W R5, R6, [SP,#4]
.text:002E9724 ADDS R3, R4, #4
.text:002E9726 MOV R5, R0 ;<<---It seems like that r0 is added but not for the "this" pointer
.text:002E9728 STRD.W R7, LR, [SP,#0xC]
.text:002E972C LDR.W LR, [R4,#0x1C]
.text:002E9730 SUB SP, SP, #0x14
.text:002E9732 MOVS R7, #0
.text:002E9734 LDR R6, [R1,#0x20]
.text:002E9736 STRD.W R4, R2, [SP,#8] ;<<--R2 represent the arg "error_msg"
.text:002E973A STRD.W LR, R7, [SP]
.text:002E973E MOV R2, R6
.text:002E9740 BL DexFile::OpenMemory ;<<---DexFile::Open is a inline function. When executing this instruction, r0 equals r5.
.text:002E9744 MOV R0, R5;<<--OpenMemory is also a bit weird. It looks like that OpenMemory also adds r0 for the return value, because r0 equals r5 before calling OpenMemory
.text:002E9746 ADD SP, SP, #0x14
.text:002E9748 LDRD.W R4, R5, [SP]
.text:002E974C LDRD.W R6, R7, [SP,#8]
.text:002E9750 ADD SP, SP, #0x10
.text:002E9752 LDR.W PC, [SP+4+var_4],#4
我只是想知道是否存在一种特殊情况,其中 "this" 指针将被放入 R1 而不是 R0,并且参数从寄存器 r1 开始按顺序传递。
如果你能帮助我,我将不胜感激。
检查 arm ABI 第 5.5 章
R0:对于 return 值
R1-R3加栈:用于传递参数
If the subroutine is a function that returns a result in memory, then
the address for the result is placed in r0 and the NCRN is set to r1.
OpenDexFile
是(可能)返回一个 DexFile 对象,该对象需要放置内存,因此 r0
和 r1
变为 this
.
这个之前已经讲过:the order of C++ implicit arguments: this and the returned object, which goes first?
一般注意事项是 ARM ABI 与 Itanium ABI 类似。如果您在查看 ARM ABI 后找不到要研究的资源,您也可以查看那个。
从 ARM 到 C 的调用约定,我知道参数是从寄存器 r0-r4 开始按顺序传递的,然后对于其他参数使用堆栈。 Return 值传递给 r0-r1。
但是在libart.so(AndroidM,/system/lib/libart.so,32bit)中,有一个方法好像不符合规则。
//https://android.googlesource.com/platform/art/+/android-6.0.0_r5/runtime/oat_file.cc
std::unique_ptr<const DexFile> OatFile::OatDexFile::OpenDexFile(std::string* error_msg) const {
return DexFile::Open(dex_file_pointer_, FileSize(), dex_file_location_,
dex_file_location_checksum_, this, error_msg);
}
//https://android.googlesource.com/platform/art/+/android-6.0.0_r5/runtime/dex_file.h
static std::unique_ptr<const DexFile> DexFile::Open(const uint8_t* base, size_t size,
const std::string& location,
uint32_t location_checksum,
const OatDexFile* oat_dex_file,
std::string* error_msg) {
return OpenMemory(base, size, location, location_checksum, nullptr, oat_dex_file, error_msg);
}
OpenDexfile 是 OatDexFile class 的一个成员函数,它是 OatFile class 的内部 class。所以 OpenDexFile 实际上有 2 个参数,因为第一个参数是 "this"。 但在 IDA Pro 中,OpenDexFile 如下所示:
.text:002E9718 var_14 = -0x14
.text:002E9718 var_4 = -4
.text:002E9718
.text:002E9718 STR.W R4, [SP,#var_14]!
.text:002E971C MOV R4, R1 ;<<--After analysing, I can assure that R1 is the "this" pointer
.text:002E971E LDR R1, [R1,#0x20] ;<<---dex_file_pointer
.text:002E9720 STRD.W R5, R6, [SP,#4]
.text:002E9724 ADDS R3, R4, #4
.text:002E9726 MOV R5, R0 ;<<---It seems like that r0 is added but not for the "this" pointer
.text:002E9728 STRD.W R7, LR, [SP,#0xC]
.text:002E972C LDR.W LR, [R4,#0x1C]
.text:002E9730 SUB SP, SP, #0x14
.text:002E9732 MOVS R7, #0
.text:002E9734 LDR R6, [R1,#0x20]
.text:002E9736 STRD.W R4, R2, [SP,#8] ;<<--R2 represent the arg "error_msg"
.text:002E973A STRD.W LR, R7, [SP]
.text:002E973E MOV R2, R6
.text:002E9740 BL DexFile::OpenMemory ;<<---DexFile::Open is a inline function. When executing this instruction, r0 equals r5.
.text:002E9744 MOV R0, R5;<<--OpenMemory is also a bit weird. It looks like that OpenMemory also adds r0 for the return value, because r0 equals r5 before calling OpenMemory
.text:002E9746 ADD SP, SP, #0x14
.text:002E9748 LDRD.W R4, R5, [SP]
.text:002E974C LDRD.W R6, R7, [SP,#8]
.text:002E9750 ADD SP, SP, #0x10
.text:002E9752 LDR.W PC, [SP+4+var_4],#4
我只是想知道是否存在一种特殊情况,其中 "this" 指针将被放入 R1 而不是 R0,并且参数从寄存器 r1 开始按顺序传递。 如果你能帮助我,我将不胜感激。
检查 arm ABI 第 5.5 章
R0:对于 return 值
R1-R3加栈:用于传递参数
If the subroutine is a function that returns a result in memory, then the address for the result is placed in r0 and the NCRN is set to r1.
OpenDexFile
是(可能)返回一个 DexFile 对象,该对象需要放置内存,因此 r0
和 r1
变为 this
.
这个之前已经讲过:the order of C++ implicit arguments: this and the returned object, which goes first?
一般注意事项是 ARM ABI 与 Itanium ABI 类似。如果您在查看 ARM ABI 后找不到要研究的资源,您也可以查看那个。