Aspcet

作者: bigCatloveFish | 来源:发表于2019-01-10 20:01 被阅读5次

    Aspect

    tips:

    • 未识别消息转发流程:

    1.resolveInstanceMethod (给类动态添加方法)
    2.forwardingTargetForSelector(寻找其他的实例去处理方法)
    3.forwardInvocation(完整的invocation 可以转发)

    • NSInvovation:

    NSInvocation文档 。包含objectiveC的消息的所有元素。目标对象,方法,参数,和返回值。

    • NSMethodSignature:

    通过一个字符串数组记录方法的返回值和参数
    Type Encodings

    • Block 获取方法签名

    苹果并没有提供一个开放的接口,供开发者获取 Block 的方法签名。不过根据 LLVM 对 Block 结构的描述,我们可以通过操作指针获取签名字符串。以下是 Block 的结构:

    // Block internals.
    typedef NS_OPTIONS(int, AspectBlockFlags) {
        AspectBlockFlagsHasCopyDisposeHelpers = (1 << 25),
        AspectBlockFlagsHasSignature          = (1 << 30)
    };
    typedef struct _AspectBlock {
        __unused Class isa;
        AspectBlockFlags flags;
        __unused int reserved;
        void (__unused *invoke)(struct _AspectBlock *block, ...);
        struct {
            unsigned long int reserved;
            unsigned long int size;
            // requires AspectBlockFlagsHasCopyDisposeHelpers
            void (*copy)(void *dst, const void *src);
            void (*dispose)(const void *);
            // requires AspectBlockFlagsHasSignature
            const char *signature;
            const char *layout;
        } *descriptor;
        // imported variables
    } *AspectBlockRef;
    

    获取descriptor拿到signature。

    static NSMethodSignature *aspect_blockMethodSignature(id block, NSError **error) {
        //通过layout获取对应的block签名
        AspectBlockRef layout = (__bridge void *)block;
        //无签名
        if (!(layout->flags & AspectBlockFlagsHasSignature)) {
            NSString *description = [NSString stringWithFormat:@"The block %@ doesn't contain a type signature.", block];
            AspectError(AspectErrorMissingBlockSignature, description);
            return nil;
        }
        //desc
        void *desc = layout->descriptor;
        //跳过
        //        unsigned long int reserved;
        //        unsigned long int size;
        desc += 2 * sizeof(unsigned long int);
        // 跳过
        if (layout->flags & AspectBlockFlagsHasCopyDisposeHelpers) {
            desc += 2 * sizeof(void *);
        }
        if (!desc) {
            NSString *description = [NSString stringWithFormat:@"The block %@ doesn't has a type signature.", block];
            AspectError(AspectErrorMissingBlockSignature, description);
            return nil;
        }
        const char *signature = (*(const char **)desc);
        return [NSMethodSignature signatureWithObjCTypes:signature];
    }
    

    基本原理

    1,生成要hook方法的自己的方法的NSInVocation 的相关参数。
    2,将要hook的方法指向objc_msgForward/_objc_msgForward_stret。并保存原有的执行函数。
    3,hook对象的forwardInvocation方法指向自己的方法。
    4,当系统调用hook的方法。会调用自己的forwardInvocation。然后执行里面的相关方法。

    引用

    面向切面编程之 Aspects 源码解析及应用

    相关文章

      网友评论

          本文标题:Aspcet

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