步驟一:添加 Build Setting 設(shè)置
Target -> Build Setting -> Custom Complier Flags ->
Other C Flags?添加
-fsanitize-coverage=func,trace-pc-guard
Other Swift Flags?添加
-sanitize-coverage=func
-sanitize=undefined
步驟二:添加代碼
添加到啟動(dòng)最早的那個(gè)?ViewController?即可洒缀。
#import "dlfcn.h"
#import <libkern/OSAtomic.h>
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.
}
//初始化原子隊(duì)列
static OSQueueHead list = OS_ATOMIC_QUEUE_INIT;
//定義節(jié)點(diǎn)結(jié)構(gòu)體
typedef struct {
? ? void *pc;? //存下獲取到的PC
? ? void *next; //指向下一個(gè)節(jié)點(diǎn)
} 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() 計(jì)算出列尾坦敌,OSAtomicEnqueue() 把 node 加入 list 尾巴
? ? OSAtomicEnqueue(&list, node, offsetof(Node, next));
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
? ? NSMutableArray *arr = [NSMutableArray array];
? ? while(1){
? ? ? ? //有進(jìn)就有出隘擎,這個(gè)方法和 OSAtomicEnqueue() 類比使用
? ? ? ? Node *node = OSAtomicDequeue(&list, offsetof(Node, next));
? ? ? ? //退出機(jī)制
? ? ? ? if (node == NULL) {
? ? ? ? ? ? break;
? ? ? ? }
? ? ? ? //獲取函數(shù)信息
? ? ? ? Dl_info info;
? ? ? ? dladdr(node->pc, &info);
? ? ? ? NSString *sname = [NSString stringWithCString:info.dli_sname encoding:NSUTF8StringEncoding];
? ? ? ? printf("%s \n", info.dli_sname);
? ? ? ? //處理c函數(shù)及block前綴
? ? ? ? BOOL isObjc = [sname hasPrefix:@"+["] || [sname hasPrefix:@"-["];
? ? ? ? //c函數(shù)及block需要在開頭添加下劃線
? ? ? ? sname = isObjc ? sname: [@"_" stringByAppendingString:sname];
? ? ? ? //去重
? ? ? ? if (![arr containsObject:sname]) {
? ? ? ? ? ? //因?yàn)槿霔5臅r(shí)候是從上至下,取出的時(shí)候方向是從下至上柴钻,那么就需要倒序淮韭,直接插在數(shù)組頭部即可
? ? ? ? ? ? [arr insertObject:sname atIndex:0];
? ? ? ? }
? ? }
? ? //去掉 touchesBegan 方法 啟動(dòng)的時(shí)候不會(huì)用到這個(gè)
? ? [arr removeObject:[NSString stringWithFormat:@"%s",__FUNCTION__]];
? ? //數(shù)組合成字符串
? ? 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);?斷點(diǎn)
如果頁(yè)面無法觸發(fā)點(diǎn)擊,viewDidLoad里面調(diào)用touchesBegan:withEvent:也可以
運(yùn)行代碼后記錄?link.order?的路徑
Finder?前往路徑取出?order file
步驟四:設(shè)置 order file
把?link.order?的路徑放到工程根目錄
Target -> Build Setting -> Linking -> Order File?設(shè)置路徑
步驟五:編譯代碼
把步驟一?order file?的設(shè)置還原
把步驟二添加代碼刪除
clean?以后編譯代碼
參考鏈接:
https://juejin.im/post/6844904165773328392