iOS underlying optimization (33) - clang instrumentation for startup optimization

Clang Principles

Clang documentation clang.llvm.org/docs/Saniti…

A code tracing feature provided by Apple, Tracing PCs

1. will be -fsanitize-coverage=func,trace-pc-guardadded to xcode

image.png

Note that here func, represents only intercepting methods.

2. An error will be reported when running, because there are two methods that have not yet been defined

__sanitizer_cov_trace_pc_guard_init
__sanitizer_cov_trace_pc_guard
复制代码

This is the callback, which needs to be defined in the project as required by the documentation.

Command to view memory:x 0x100000

Hereinafter, methods, blocks, functions, etc. are collectively referred to as methods.

__sanitizer_cov_trace_pc_guard_init

You can get the number of all methods.

__sanitizer_cov_trace_pc_guard

Hook all methods and get the calling order of all these methods.

It is to add a line of code to the implementation part of each method, and calling this method is equivalent to modifying the binary file.

This method is also the principle of Clang instrumentation.

get symbol and store

Print all symbols by:

void __sanitizer_cov_trace_pc_guard(uint32_t *guard) {
    void *PC = __builtin_return_address(0);
    Dl_info info;
    dladdr(PC,&info);
    printf(@"%s\n",info.dli_sname);
}
复制代码

The above callback method is multi-threaded, that is to say, the function in the child thread, this method will be executed in the child thread.

Therefore, a thread-safe way to store symbols is required, that is, in a thread-safe atomic queue.

#include <stdint.h>
#include <stdio.h>
#include <sanitizer/coverage_interface.h>
#import <dlfcn.h>
#import <libkern/OSAtomic.h>


void __sanitizer_cov_trace_pc_guard(uint32_t *guard) {
    void *PC = __builtin_return_address(0);
    Dl_info info;
    dladdr(PC,&info);
    printf(@"%s\n",info.dli_sname);
    //创建结构体
    SYNode * node = malloc(sizeof(SYNode));
    *node = (SYNode){PC,NULL};
    //结构体入栈
    OSAtomicEnqueue(&symbolList, node, offsetof(SYNode, next));
    
}


//生成order文件!!
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    //定义数组
    NSMutableArray<NSString *> * symbleNames = [NSMutableArray array];
    
    while (YES) {//循环体内!进行了拦截!!
        SYNode * node = OSAtomicDequeue(&symbolList, offsetof(SYNode,next));
        
        if (node == NULL) {
            break;
        }
        
        Dl_info info;
        dladdr(node->pc, &info);
        NSString * name = @(info.dli_sname);//转字符串
        //给函数名称添加 _
        BOOL isObjc = [name hasPrefix:@"+["] || [name hasPrefix:@"-["];
        NSString * symbolName = isObjc ? name : [@"_" stringByAppendingString:name];
        [symbleNames addObject:symbolName];
    }
    
    //反向遍历数组
//    symbleNames = (NSMutableArray<NSString *> *)[[symbleNames reverseObjectEnumerator] allObjects];
//    NSLog(@"%@",symbleNames);
    NSEnumerator * em = [symbleNames reverseObjectEnumerator];
    NSMutableArray * funcs = [NSMutableArray arrayWithCapacity:symbleNames.count];
    NSString * name;
    //去重
    while (name = [em nextObject]) {
        if (![funcs containsObject:name]) {
            [funcs addObject:name];
        }
    }
    //去掉自己!touchesBegan
    [funcs removeObject:[NSString stringWithFormat:@"%s",__func__]];
    
    //写入文件
    //1.编程字符串
    NSString * funcStr = [funcs componentsJoinedByString:@"\n"];
    NSString * filePath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"dd.order"];
    NSData * file = [funcStr dataUsingEncoding:NSUTF8StringEncoding];
    
    [[NSFileManager defaultManager] createFileAtPath:filePath contents:file attributes:nil];
    
    NSLog(@"%@",funcStr);
}

复制代码

swift symbol override

1. Create a swift file

2. AddOther Swift Flags

image.png

In this way, the swift method is also added.

Guess you like

Origin juejin.im/post/7085638984126169095