IDA 分析 _objc_msgSend 的时候,如何知道,这个函数的具体执?


#1

Objective-C消息机制的原理在Objective-C中,message与方法的真正实现是在执行阶段绑定的,而非编译阶段。编译器会将消息发送转换成对objc_msgSend方法的调用。
objc_msgSend方法含两个必要参数:receiver、方法名(即:selector),如:
[receiver message]; 将被转换为:objc_msgSend(receiver, selector);
问题:通过IDA静态分析,如何快速定位到 selector 的真正代码实现(方法的真正实现)

__text:0001D76A MOV R0, #(selRef_HTTPMethod - 0x1C776) ; selRef_HTTPMethod
__text:0001D772 ADD R0, PC ; selRef_HTTPMethod
__text:0001D774 LDR R1, [R0] ; “HTTPMethod”
__text:0001D776 MOV R0, R10
__text:0001D778 STR R1, [SP,#0xAC+var_A0]
__text:0001D77A BLX _objc_msgSend
__text:0001D77E MOV R7, R7
__text:0001D780 BLX _objc_retainAutoreleasedReturnValue
__text:0001D784 MOV R4, R0
text:0001D786 MOV R0, #(selRef_setRequestMethod - 0x1C794) ; selRef_setRequestMethod
__text:0001D78E MOV R2, R4
_text:0001D790 ADD R0, PC ; selRef_setRequestMethod
__text:0001D792 LDR R1, [R0] ; “setRequestMethod:”
__text:0001D794 MOV R0, R6
__text:0001D796 BLX _objc_msgSend
__text:0001D79A MOV R0, R4
__text:0001D79C BLX _objc_release
__text:0001D7A0 MOVW R0, #(:lower16:(selRef_allHTTPHeaderFields - 0x1C7B8))
__text:0001D7A4 ADD.W R8, SP, #0xAC+var_3C
__text:0001D7A8 MOVT.W R0, #(:upper16:(selRef_allHTTPHeaderFields - 0x1C7B8))
__text:0001D7AC VMOV.I32 Q8, #0
__text:0001D7B0 ADD.W R1, R8, #0x10
__text:0001D7B4 ADD R0, PC ; selRef_allHTTPHeaderFields
__text:0001D7B6 VST1.32 {D16-D17}, [R1]
__text:0001D7BA LDR R1, [R0] ; “allHTTPHeaderFields”
__text:0001D7BC MOV R0, R10
__text:0001D7BE VST1.32 {D16-D17}, [R8]
__text:0001D7C2 STR R1, [SP,#0xAC+var_84]
__text:0001D7C4 BLX _objc_msgSend


#2

就举你贴出的代码为例,0001D77A处的objc_msgSend其selector为HTTPMethod,你在functions window里搜这个HTTPMethod就可以找到它的实现了


#3

续问:
这两天也在琢磨objc_msgSend的问题
最开始理解汇编码的时候,我以为
LDR R1, [R0] ; “HTTPMethod”
这样,就会执行HTTPMethod的函数,并且把结果存在R1里,这两天查资料,才确切的知道函数的调用会被转换成objc_msgSend(receiver, selector); 由此,我个人得出的结论是:
函数在:
BLX _objc_msgSend
这个地方才会被执行,并且函数的返回值会被存储在R0里。
也就是说在
BLX _objc_msgSend
之后,R0的值就会更新,不知道这样的理解对否?是否还有什么错误或者遗漏的地方?


#4

你这样理解是没错的。
_objc_msgSend 就是一个发送消息的函数,里面就有要调用的方法名。如HTTPMethod这个。如果这个方法有参数的话,那在这个msgSend之前会在设置一些参数,你看 LDR R1, [R0]; "HTTPMethod"就是将这个方法名放到R1中,然后R0是赋值为R10,此处R10为HTTPMethod这个方法所归属的类的指针之类。所以这里,这两个参数的目的是确认调用的函数。
调用完方法,如果方法有一个返回值,那会更新在R0,大于一个返回值,就会通过栈来返回值。具体你可以看看书里,书里还是讲得很清楚的。


#5

我的理解是在 执行完毕 HTTPMethod 这时候 R0肯定改变,但是执行完毕HTTPMethod之后到回到BLX _objc_msgSend 的下一条指令期间有可能做了一些其他操作,这个R0有可能会改变。

不知道我这样的理解对否,请明白人指教。


#6

这个地方书上写得非常非常清楚了,函数执行前的调用对象存在R0里,执行完的返回值也是存在R0里的,所以R0在objc_msgSend前后是有可能变化的(取决于函数有没有返回值)。你好好看看书吧,书上这部分是重点,我用了很大篇幅来解释


#7

看哪本书呢?


#8

。。。。。。你是怎么找过来的


#9

小黄书:)