美文网首页
将启动函数信息放在Mach-O文件的section里

将启动函数信息放在Mach-O文件的section里

作者: 蓝天白云_Sam | 来源:发表于2020-12-01 15:35 被阅读0次
    • WSGlobalCallbackMgr.h
    //
    //  WSGlobalCallbackMgr.h
    //  OCTest
    //
    //  Created by Sammy Lan on 2020/12/1.
    //  Copyright © 2020 Sammy Lan. All rights reserved.
    //
    
    #import <Foundation/Foundation.h>
    
    typedef void (*WSCallbackT)(void *arg);
    
    #define WSTaskPriorityDefault (long)(-1)
    struct WSTaskInfo {
        char * key;
        unsigned long priority;  //优先级,值越小优先级越高,用于确定任务的执行先后顺序,如果不需要确定的顺序执行,可以使用WSTaskPriorityDefault
        WSCallbackT callback;
    };
    
    #define SECTION_KEY(key) "__" #key ".ws"
    
    #define RUN_FUNCTION_ON_STAY_WITH_PRIORITY(key,priority)                                                                                                                                                    \
    static void _ram##key(void *);                                                                                                                                                          \
    __attribute__((used, section("__DATA," SECTION_KEY(key)))) static const struct WSTaskInfo __F##key = (struct WSTaskInfo){(char *)(&#key), priority, (void *)(&_ram##key)}; \
    static void _ram##key(void *arg)
    
    #define RUN_FUNCTION_ON_STAY(key) RUN_FUNCTION_ON_STAY_WITH_PRIORITY(key,WSTaskPriorityDefault)
    
    //kMain: 在main函数开始执行
    //kStartup: 在application:didFinishLaunchingWithOptions: 执行
    //kAppeared: 在首页渲染完毕后执行
    //kLogin: 在登录完成后执行
    //kLoginEx: 在登录完成后且首页渲染完毕后执行
    
    
    NS_ASSUME_NONNULL_BEGIN
    
    
    @interface WSGlobalCallbackMgr : NSObject
    + (instancetype)sharedInstance;
    - (void)runFunctionOnState:(char const *)state arg:(nullable void *)arg;
    @end
    
    NS_ASSUME_NONNULL_END
    
    
    • WSGlobalCallbackMgr.mm
    //
    //  WSGlobalCallbackMgr.m
    //  OCTest
    //
    //  Created by Sammy Lan on 2020/12/1.
    //  Copyright © 2020 Sammy Lan. All rights reserved.
    //
    
    #import "WSGlobalCallbackMgr.h"
    #import <dlfcn.h>
    #include <mach-o/loader.h>
    #include <mach-o/getsect.h>
    #include<mach-o/dyld.h>
    #include<mach/mach.h>
    
    
    #ifndef IMPL_SINGLETON
    #define IMPL_SINGLETON(className)                      \
        +(instancetype)sharedInstance                      \
        {                                                  \
            static className *sharedInstance = nil;        \
            static dispatch_once_t onceToken;              \
            dispatch_once(&onceToken, ^{                   \
                sharedInstance = [[className alloc] init]; \
            });                                            \
            return sharedInstance;                         \
        }
    #endif
    
    
    static NSString *configuration = @"";
    
    
    @interface WSGlobalCallbackMgr ()
    {
       
    }
    
    @end
    
    
    @implementation WSGlobalCallbackMgr
    
    IMPL_SINGLETON(WSGlobalCallbackMgr);
    
    
    - (void)runFunctionOnState:(char const *)state arg:(nullable void *)arg;
    {
        int *ptr = nullptr;
        if (sizeof(ptr) == 8) {
            [self loadSectionData64:state arg:arg];
        } else {
            [self loadSectionData32:state arg:arg];
        }
    }
    - (void)loadSectionData64:(char const *)state arg:(nullable void *)arg;
    {
        static mach_header_64 * s_machHeader;
        if (s_machHeader == nullptr) {
            Dl_info info;
            dladdr((__bridge const void *)(configuration), &info);
            s_machHeader = (struct mach_header_64 *)info.dli_fbase;
        }
    
        intptr_t  slide = _dyld_get_image_vmaddr_slide(1);
        UInt64 byteCount = 0;
        WSTaskInfo *taskInfo = (WSTaskInfo *)(WSTaskInfo *) (getsectdatafromheader_64(s_machHeader, "__DATA",state , &byteCount) + slide);;
        auto counter = byteCount / sizeof(WSTaskInfo);
        for (NSUInteger idx = 0; idx < counter; ++idx) {
            WSTaskInfo &item = taskInfo[idx];
            item.callback(arg);
        }
    }
    
    - (void)loadSectionData32:(char const *)state arg:(nullable void *)arg;
    {
        static mach_header * s_machHeader;
        if (s_machHeader == nullptr) {
            Dl_info info;
            dladdr((__bridge const void *)(configuration), &info);
            s_machHeader = (struct mach_header *)info.dli_fbase;
        }
    
        intptr_t  slide = _dyld_get_image_vmaddr_slide(1);
        uint32_t byteCount = 0;
        WSTaskInfo *taskInfo = (WSTaskInfo *)(WSTaskInfo *) (getsectdatafromheader(s_machHeader, "__DATA",state , &byteCount) + slide);;
        auto counter = byteCount / sizeof(WSTaskInfo);
        for (NSUInteger idx = 0; idx < counter; ++idx) {
            WSTaskInfo &item = taskInfo[idx];
            item.callback(arg);
        }
    }
    
    
    @end
    
    • 添加特定阶段运行的函数
    RUN_FUNCTION_ON_STAY(kStartup)
    {
        NSLog(@"File: %s,Line: %d",__FILE__,__LINE__);
    }
    

    https://blog.csdn.net/ios8988/article/details/89510599

    相关文章

      网友评论

          本文标题:将启动函数信息放在Mach-O文件的section里

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