Clang 原理

Clang文档 clang.llvm.org/docs/Saniti…

苹果提供的一个代码盯梢的功用, Tracing PCs

1、将-fsanitize-coverage=func,trace-pc-guard添加到xcode中

iOS底层优化(33) - 发动优化之clang插桩

留意这里的 func,代表仅阻拦方法。

2、工作的时分会报错,因为有两个方法还未定义

__sanitizer_cov_trace_pc_guard_init
__sanitizer_cov_trace_pc_guard

这是回调,,需要按照文档的要求在项目中定义。

查看内存的指令:x 0x100000

以下将方法、block、函数等总称方法。

__sanitizer_cov_trace_pc_guard_init

可以获取全部方法的个数。

__sanitizer_cov_trace_pc_guard

hook全部的方法,而且可以得到全部这些方法的调用次序。

就是在每一个方法的完成的部分添加了一句代码,调用该方法,相当于修改了二进制文件。

这个方法也就是Clang插桩的原理。

获取符号并存储

经过下面的方法打印全部符号:

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);
}

上述回调方法是多线程的,也就是说子线程里边的函数,这个方法就会在子线程履行。

因此,需要用一种线程安全的方法,来存储符号,也就是放在一个线程安全的原子行列中。

#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符号掩盖

1、创立一个swift文件

2、添加 Other Swift Flags

iOS底层优化(33) - 发动优化之clang插桩

这样 swift 的方法也就加进去了。