美文网首页
消息转发 反汇编伪代码____forwarding___

消息转发 反汇编伪代码____forwarding___

作者: 答案不止一个 | 来源:发表于2020-09-25 15:31 被阅读0次

消息转发流程

  1. 通过 Hooper 反汇编查找相关代码
  2. 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;
}

相关文章

网友评论

      本文标题:消息转发 反汇编伪代码____forwarding___

      本文链接:https://www.haomeiwen.com/subject/lwtfuktx.html