ARM汇编(IOS)中目标C选择器的偏移量

Loc*_*eyu 5 assembly arm objective-c ida ios

我试图了解如何在ARM汇编语言中实现IOS Objective-C消息调用.查看IDA反汇编输出,我可以看到在调用__obj_msgsend之前将类和选择器引用推送到寄存器中.这很有道理,但奇怪的是这些值有一个奇怪的偏移.

selector ref = (selRef_arrayWithObject_ - 0x29B0) 
class ref = (classRef_NSArray - 0x29BC)
Run Code Online (Sandbox Code Playgroud)

类ref中的0x29BC值似乎指向__obj_msgsend之后的指令,该指令具有某个逻辑,但0x29B0选择器ref指向随机MOVT指令.更糟糕的是,对于每个选择器调用,此偏移似乎是不同的.

有谁知道这些偏移来自哪里?为什么他们只是引用了指令+ 8的地址?

__text:00002998 E8 1F 01 E3                 MOV             R1, #(selRef_arrayWithObject_ - 0x29B0) ; selRef_arrayWithObject_
__text:0000299C 05 20 A0 E1                 MOV             R2, R5
__text:000029A0 00 10 40 E3                 MOVT            R1, #0
__text:000029A4 01 50 A0 E3                 MOV             R5, #1
__text:000029A8 01 10 9F E7                 LDR             R1, [PC,R1] ; selRef_arrayWithObject_ ; "arrayWithObject:"
__text:000029AC 74 00 02 E3                 MOV             R0, #(classRef_NSArray - 0x29BC) ; classRef_NSArray
__text:000029B0 00 00 40 E3                 MOVT            R0, #0
__text:000029B4 00 00 9F E7                 LDR             R0, [PC,R0] ;     _OBJC_CLASS_$_NSArray
__text:000029B8 8C 05 00 EB                 BL              _objc_msgSend
Run Code Online (Sandbox Code Playgroud)

更新:这是另一种情况:

__text:00002744 50 12 02 E3                 MOV             R1, #(selRef_view - 0x2758) ;    selRef_view
__text:00002748 00 10 40 E3                 MOVT            R1, #0
__text:0000274C 00 50 A0 E1                 MOV             R5, R0
__text:00002750 01 10 9F E7                 LDR             R1, [PC,R1] ; selRef_view ; "view"


__objc_selrefs:000049A8 1A 39 00 00 selRef_view     DCD sel_view            ; DATA XREF:     __text:000025F8o
Run Code Online (Sandbox Code Playgroud)

由于伊戈尔的解释,我明白了其中0x2758是从哪里来的,但数学已经不在这里工作了:selRef_view - 0x2758 = 0x49A8 - 0x2758 = 0x2250.但是第一条指令中的数据是50 12,转换为0x1250,比我预期的少0x1000.有任何想法吗???

Igo*_*sky 8

在ARM中,PC值指向前面的两个指令槽,即.ARM模式下+ 8.拇指模式下+ 4.这就是"随机"值来自的地方.例如:

__text:000029A8 LDR R1, [PC,R1]
Run Code Online (Sandbox Code Playgroud)

由于我们处于ARM模式,因此PC值为029A8 + 8 = 029B0.所以,这段代码相当于r1 = *(int*)(r1+0x29B0).IDA给出了一个提示,R1加载了值(selRef_arrayWithObject_ - 0x29B0),因此在简化之后我们得到r1 = *(int*)(selRef_arrayWithObject_),这可能解析为字符串(选择器)的地址"arrayWithObject:".