iOS App启动优化二进制重排

步骤一:添加 Build Setting 设置

Target -> Build Setting -> Custom Complier Flags ->

Other C Flags 添加

-fsanitize-coverage=func,trace-pc-guard

Other Swift Flags 添加

-sanitize-coverage=func

-sanitize=undefined

步骤二:添加代码

添加到启动最早的那个 ViewController 即可。

#import "dlfcn.h"

#import


void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) {

    static uint64_t N;  // Counter for the guards.

    if (start == stop || *start) return;  // Initialize only once.

    printf("INIT: %p %p\n", start, stop);

    for (uint32_t *x = start; x < stop; x++)

      *x = ++N;  // Guards should start from 1.

}

//初始化原子队列

static OSQueueHead list = OS_ATOMIC_QUEUE_INIT;

//定义节点结构体

typedef struct {

    void *pc;  //存下获取到的PC

    void *next; //指向下一个节点

} Node;

void __sanitizer_cov_trace_pc_guard(uint32_t *guard) {

    void *PC = __builtin_return_address(0);

    Node *node = malloc(sizeof(Node));

    *node = (Node){PC, NULL};

    // offsetof() 计算出列尾,OSAtomicEnqueue() 把 node 加入 list 尾巴

    OSAtomicEnqueue(&list, node, offsetof(Node, next));

}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

    NSMutableArray *arr = [NSMutableArray array];

    while(1){

        //有进就有出,这个方法和 OSAtomicEnqueue() 类比使用

        Node *node = OSAtomicDequeue(&list, offsetof(Node, next));

        //退出机制

        if (node == NULL) {

            break;

        }

        //获取函数信息

        Dl_info info;

        dladdr(node->pc, &info);

        NSString *sname = [NSString stringWithCString:info.dli_sname encoding:NSUTF8StringEncoding];

        printf("%s \n", info.dli_sname);

        //处理c函数及block前缀

        BOOL isObjc = [sname hasPrefix:@"+["] || [sname hasPrefix:@"-["];

        //c函数及block需要在开头添加下划线

        sname = isObjc ? sname: [@"_" stringByAppendingString:sname];


        //去重

        if (![arr containsObject:sname]) {

            //因为入栈的时候是从上至下,取出的时候方向是从下至上,那么就需要倒序,直接插在数组头部即可

            [arr insertObject:sname atIndex:0];

        }

    }


    //去掉 touchesBegan 方法 启动的时候不会用到这个

    [arr removeObject:[NSString stringWithFormat:@"%s",__FUNCTION__]];

    //数组合成字符串

    NSString * funcStr = [arr  componentsJoinedByString:@"\n"];

    //写入文件

    NSString * filePath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"link.order"];

    NSData * fileContents = [funcStr dataUsingEncoding:NSUTF8StringEncoding];

    NSLog(@"%@", filePath);

    [[NSFileManager defaultManager] createFileAtPath:filePath contents:fileContents attributes:nil];

}

步骤三:取出 order file

在步骤二的代码NSLog(@"%@", filePath); 断点

如果页面无法触发点击,viewDidLoad里面调用touchesBegan:withEvent:也可以

运行代码后记录 link.order 的路径

Finder 前往路径取出 order file

步骤四:设置 order file

把 link.order 的路径放到工程根目录

Target -> Build Setting -> Linking -> Order File 设置路径


步骤五:编译代码

把步骤一 order file 的设置还原

把步骤二添加代码删除

clean 以后编译代码


参考链接:

https://juejin.im/post/6844904165773328392

你可能感兴趣的:(iOS App启动优化二进制重排)