消息转发流程
- 通过 Hooper 反汇编查找相关代码
- idea 查看汇编转换后的伪代码
int ___forwarding_prep_0___(int arg0, int arg1, int arg2, int arg3, int arg4, int arg5) {
...
rax = ____forwarding___(&stack[0], 0x0);
// 根据返回值判读,直接要走方法转发流程
// 当 forwardingTargetForSelector 返回有值的时候(不等于ins本身),走 消息发送历程
if (rax != 0x0) {
rax = *rax;
}
else {
rax = objc_msgSend(stack[0], stack[8]);
}
return rax;
}
____forwarding___
int ____forwarding___(int arg0, int arg1) {
// arg1 为 0x0
rsi = arg1;
// arg0 位ins
rdi = arg0;
r15 = rdi;
rcx = COND_BYTE_SET(NE);
if (rsi != 0x0) {
r12 = *_objc_msgSend_stret;
}
else { // 传入的是0x0
r12 = *_objc_msgSend;
}
rax = rcx;
// 根据流程下面内容 , rax = object_getClass(rbx);
// rbx 是对象指针
rbx = *(r15 + rax * 0x8);
rcx = *(r15 + rax * 0x8 + 0x8);
var_140 = rcx;
r13 = rax * 0x8;
// 判断 是否优化过的指针 taggedPonter 末尾是1
if ((rbx & 0x1) == 0x0) goto loc_64a2b;
loc_649fb:
rcx = **_objc_debug_taggedpointer_obfuscator;
rcx = rcx ^ rbx;
rax = rcx >> 0x1 & 0x7;
if (rax == 0x7) {
rcx = rcx >> 0x4;
rax = (rcx & 0xff) + 0x8;
}
if (rax == 0x0) goto loc_64db8;
loc_64a2b:
var_148 = r13;
// r12 是 *_objc_msgSend
var_138 = r12;
var_158 = rsi;
// rbx instance
rax = object_getClass(rbx);
r12 = rax; // 类
// class 名 char *
r13 = class_getName(rax);
// r12 Class 判断类的实例 是否有 forwardingTargetForSelector 方法
if (class_respondsToSelector(r12, @selector(forwardingTargetForSelector:)) == 0x0) goto loc_64ad7;
// 可以执行 forwardingTargetForSelector,去执行
loc_64a6c:
rdi = rbx;
// [ins forwardingTargetForSelector:sel] 返回新的 ins
rax = [rdi forwardingTargetForSelector:var_140];
// 如果执行之后的返回值位nil 或者 这个对象本身,也跳到 loc_64ad7 执行后续的消息转发 -> methodSignatureForSelector forwardInvocation 流程
if ((rax == 0x0) || (rax == rbx)) goto loc_64ad7;
// 如果 forwardingTargetForSelector 返回了对象 rax 是返回的对象
loc_64a89:
r12 = var_138;
r13 = var_148;
if ((rax & 0x1) == 0x0) goto loc_64acb; // taggedpointer 相关
loc_64a9b:
rdx = **_objc_debug_taggedpointer_obfuscator;
rdx = rdx ^ rax;
rcx = rdx >> 0x1 & 0x7;
if (rcx == 0x7) {
rcx = (rdx >> 0x4 & 0xff) + 0x8;
}
if (rcx == 0x0) goto loc_64db5;
loc_64acb:
*(r15 + r13) = rax;
r15 = 0x0;
goto loc_64df2;
// ??
loc_64df2:
if (**___stack_chk_guard == **___stack_chk_guard) {
rax = r15;
}
else {
rax = __stack_chk_fail();
}
return rax;
loc_64db5:
rbx = rax;
goto loc_64db8;
loc_64db8:
if ((*(int8_t *)__$e48aedf37b9edb179d065231b52a648b & 0x10) != 0x0) goto loc_64f41;
loc_64dc5:
*(r15 + r13) = _getAtomTarget(rbx);
___invoking___(r12, r15);
if (*r15 == rax) {
*r15 = rbx;
}
goto loc_64df2;
loc_64f41:
____forwarding___.cold.4();
rax = *(rdi + 0x8);
return rax;
// 当没有 forwardingTargetForSelector 是跳转到这里
// 判断是否是_NSZombie_,
loc_64ad7:
// 判断传入的是否是僵尸对象
var_138 = rbx;
if (strncmp(r13, "_NSZombie_", 0xa) == 0x0) goto loc_64e31;
loc_64afa:
// 再去执行methodSignatureForSelector
// 会返回true,NSObject 有该方法。Core Foundation 会替换掉NSObject的 methodSignatureForSelector方法。
rax = class_respondsToSelector(r12, @selector(methodSignatureForSelector:));
r14 = var_138;
var_148 = r15;
if (rax == 0x0) goto loc_64e47;
loc_64b22:
// 执行methodSignatureForSelector
rax = [r14 methodSignatureForSelector:var_140];
rbx = var_158;
// 如果返回的是nil,则会跳转到 loc_64eac。 执行 doesNotRecognizeSelector
if (rax == 0x0) goto loc_64eac;
// 如果 methodSignatureForSelector 有返回数据
// _forwardStackInvocation ??
loc_64b45:
r12 = rax;
rax = [rax _frameDescriptor];
r13 = rax;
if (((*(int16_t *)(*rax + 0x22) & 0xffff) >> 0x6 & 0x1) != rbx) {
rax = sel_getName(var_140);
rcx = "";
if ((*(int16_t *)(*r13 + 0x22) & 0xffff & 0x40) == 0x0) {
rcx = " not";
}
r8 = "";
if (rbx == 0x0) {
r8 = " not";
}
_CFLog(0x4, @"*** NSForwarding: warning: method signature and compiler disagree on struct-return-edness of '%s'. Signature thinks it does%s return a struct, and compiler thinks it does%s.", rax, rcx, r8, r9, stack[-360]);
}
rax = object_getClass(r14);
rax = class_respondsToSelector(rax, @selector(_forwardStackInvocation:));
var_150 = r13;
if (rax == 0x0) goto loc_64c89;
loc_64bdc:
if (*0x5c2700 != 0xffffffffffffffff) {
dispatch_once(0x5c2700, ^ {/* block implemented at ______forwarding____block_invoke */ } });
}
r15 = [NSInvocation requiredStackSizeForSignature:r12];
rsi = *0x5c26f8;
rsp = rsp - ___chkstk_darwin(@class(NSInvocation), rsi, r12, rcx);
r13 = &stack[-360];
__bzero(r13, rsi);
___chkstk_darwin(r13, rsi, r12, rcx);
rax = objc_constructInstance(*0x5c26f0, r13);
var_140 = r15;
[r13 _initWithMethodSignature:r12 frame:var_148 buffer:&stack[-360] size:r15];
[var_138 _forwardStackInvocation:r13];
r14 = 0x1;
goto loc_64ce6;
loc_64ce6:
if (*(int8_t *)(r13 + 0x34) != 0x0) {
rax = *var_150;
if (*(int8_t *)(rax + 0x22) < 0x0) {
rcx = *(int32_t *)(rax + 0x1c);
rdx = *(int8_t *)(rax + 0x20) & 0xff;
memmove(*(rdx + var_148 + rcx), *(rdx + rcx + *(r13 + 0x8)), *(int32_t *)(*rax + 0x10));
}
}
rax = [r12 methodReturnType];
rbx = rax;
rax = *(int8_t *)rax;
if ((rax != 0x76) && (((rax != 0x56) || (*(int8_t *)(rbx + 0x1) != 0x76)))) {
r15 = *(r13 + 0x10);
if (r14 != 0x0) {
r15 = [[NSData dataWithBytes:r15 length:var_140] bytes];
[r13 release];
rax = *(int8_t *)rbx;
}
if (rax == 0x44) {
asm { fld tword [r15] };
}
}
else {
r15 = ____forwarding___.placeholder;
if (r14 != 0x0) {
r15 = ____forwarding___.placeholder;
[r13 release];
}
}
goto loc_64df2;
loc_64c89:
if (class_respondsToSelector(object_getClass(r14), @selector(forwardInvocation:)) == 0x0) goto loc_64f32;
loc_64cab:
rax = [NSInvocation _invocationWithMethodSignature:r12 frame:var_148];
r13 = rax;
[r14 forwardInvocation:rax];
var_140 = 0x0;
r14 = 0x0;
goto loc_64ce6;
loc_64f32:
rdi = &var_130;
____forwarding___.cold.3(rdi, r14);
goto loc_64f41;
loc_64eac:
rax = sel_getName(var_140);
r14 = rax;
rax = sel_getUid(rax);
if (rax != var_140) {
_CFLog(0x4, @"*** NSForwarding: warning: selector (%p) for message '%s' does not match selector known to Objective C runtime (%p)-- abort", var_140, r14, rax, r9, stack[-360]);
}
if (class_respondsToSelector(object_getClass(var_138), @selector(doesNotRecognizeSelector:)) == 0x0) {
____forwarding___.cold.2(var_138);
}
(*_objc_msgSend)(var_138, @selector(doesNotRecognizeSelector:));
asm { ud2 };
rax = loc_64f32(rdi, rsi);
return rax;
//
loc_64e47:
rbx = class_getSuperclass(r12);
r14 = object_getClassName(r14);
if (rbx == 0x0) {
_CFLog(0x4, @"*** NSForwarding: warning: object %p of class '%s' does not implement methodSignatureForSelector: -- did you forget to declare the superclass of '%s'?", var_138, r14, object_getClassName(var_138), r9, stack[-360]);
}
else {
_CFLog(0x4, @"*** NSForwarding: warning: object %p of class '%s' does not implement methodSignatureForSelector: -- trouble ahead", var_138, r14, r8, r9, stack[-360]);
}
goto loc_64eac;
//
loc_64e31:
r14 = @selector(forwardingTargetForSelector:);
____forwarding___.cold.1(var_138, r13, var_140, rcx, r8);
goto loc_64e47;
}
msg_forward.png
在转发流程中,会判断有没有methodSignatureForSelector 方法,如果用户没有自定义,会执行汇编中的代码。
其中会有一个 ___methodDescriptionForSelector 然后 调用 class_getInstanceMethod 然后再调用
就会调用到 lookupimporforward behavor 为2 再次resolve一次
// Replaced by CF (returns an NSMethodSignature)
+ (NSMethodSignature *)instanceMethodSignatureForSelector:(SEL)sel {
_objc_fatal("+[NSObject instanceMethodSignatureForSelector:] "
"not available without CoreFoundation");
}
// Replaced by CF (returns an NSMethodSignature)
+ (NSMethodSignature *)methodSignatureForSelector:(SEL)sel {
_objc_fatal("+[NSObject methodSignatureForSelector:] "
"not available without CoreFoundation");
}
// Replaced by CF (returns an NSMethodSignature)
- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel {
_objc_fatal("-[NSObject methodSignatureForSelector:] "
"not available without CoreFoundation");
}
消息转发过程也会调用resolve
查看调用链
AC51DDE4A1EFDED5A5454FE1A6571D6C.png
反汇编查询的代码
-(void *)methodSignatureForSelector:(void *)arg2 {
rdx = arg2;
rdi = self;
if ((rdx != 0x0) && (___methodDescriptionForSelector([rdi class], rdx) != 0x0)) {
rax = [NSMethodSignature signatureWithObjCTypes:rdx];
}
else {
rax = 0x0;
}
return rax;
}
function ___methodDescriptionForSelector {
rbx = rsi; // sel
stack[-72] = rdi;// self ins
if (rdi == 0x0) goto loc_7c6fb;
loc_7c61c:
r12 = stack[-72]; // ins
stack[-88] = rbx; //
goto loc_7c624;
loc_7c624:
stack[-60] = 0x0; // 用来存储数量
rax = class_copyProtocolList(r12, &stack[-60]);
if (stack[-60] == 0x0) goto loc_7c6b2;
loc_7c63d:
r13 = 0x0;
// protocol list
stack[-80] = rax;
goto loc_7c644;
loc_7c644:
// 协议
r15 = *(rax + r13 * 0x8);
// cls
rdi = r12;
r14 = r12;
// protocol list
r12 = rax;
// ins 是否是metacls false
rax = class_isMetaClass(rdi);
// protocol sel isRequiredMethod
// protocol_getMethodDescription(proto, aSel, isRequiredMethod, isInstanceMethod)
rax = protocol_getMethodDescription(r15, rbx, 0x1, rax == 0x0 ? 0x1 : 0x0);
if (rax != 0x0) goto loc_7c6be;
loc_7c672:
r15 = *(r12 + r13 * 0x8);
rax = class_isMetaClass(r14);
rax = protocol_getMethodDescription(r15, rbx, 0x0, rax == 0x0 ? 0x1 : 0x0);
r12 = r14;
if (rax != 0x0) goto loc_7c6cc;
loc_7c69a:
r13 = r13 + 0x1;
rbx = stack[-88];
rax = stack[-80];
if (r13 < stack[-60]) goto loc_7c644;
loc_7c6ad:
r15 = 0x0;
goto loc_7c6d3;
loc_7c6d3:
rbx = 0x0;
goto loc_7c6d6;
loc_7c6d6:
free(rax);
if (r15 != 0x0) goto loc_7c722;
loc_7c6e3:
// ins
rax = class_getSuperclass(r12);
// cls 父类
r12 = rax;// cls
rbx = stack[-88];//
if (rax != 0x0) goto loc_7c624;
loc_7c6fb:
rax = class_getInstanceMethod(stack[-72], rbx);
if (rax != 0x0) {
rax = method_getDescription(rax);
r15 = *rax;
rbx = *(rax + 0x8);
}
else {
rbx = 0x0;
r15 = 0x0;
}
goto loc_7c722;
loc_7c722:
if (**___stack_chk_guard == **___stack_chk_guard) {
rax = r15;
}
else {
rax = __stack_chk_fail();
}
return rax;
loc_7c6cc:
r15 = rax;
rax = stack[-80];
goto loc_7c6d3;
loc_7c6be:
r15 = rax;
rbx = 0x1;
rax = r12;
r12 = r14;
goto loc_7c6d6;
loc_7c6b2:
if (rax == 0x0) goto loc_7c6e3;
loc_7c6b7:
r15 = 0x0;
rbx = 0x0;
goto loc_7c6d6;
}
网友评论