本文已参与[新人创作礼]活动,一起开启掘金创作之路。
clang 插桩
配置clang 插装参数 oc 项目去targets - build settings - other c flags 配置
-fsanitize-coverage=func,trace-pc-guard
swift 项目去targets - build settings - other swift flags 配置
-sanitize-coverage=func
-sanitize=undefined
运行项目报如下错误
undefined symbol: "___sanitizer_cov_trace_pc_guard_init",
undefined symbol: "___sanitizer_cov_trace_pc_guard",
此时需要去llvm 官方文档实现以上两个方法,直到运行成功。
__sanitizer_cov_trace_pc_guard_init 方法里面会打印出符号化的个数__sanitizer_cov_trace_pc_guard 方法会打印出符号化的列表
**void** __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) {
**static** uint64_t N;
**if** (start == stop || *start) **return**;
printf("INIT: %p %p\n", start, stop);
**for** (uint32_t *x = start; x < stop; x++)
*x = ++N;
NSLog(@"%d",N);
}
**void** __sanitizer_cov_trace_pc_guard(uint32_t *guard) {
// NSLog(@"%s",__func__);
**if** (!*guard) **return**;
**void** *PC = __builtin_return_address(0);
SYNode *node = malloc(**sizeof**(SYNode));
*node = (SYNode){PC,0};
//插入结构体
OSAtomicEnqueue(&symbolList, node, offsetof(SYNode, abc));
// printf("%s\n",info.dli_sname);
}
最后一步输出符号化列表表并写入文件
//创建数组
NSMutableArray *symbleNames = [NSMutableArray array];
**while** (**YES**) {
SYNode *node = OSAtomicDequeue(&symbolList, offsetof(SYNode, abc));
**if** (node == **NULL**) {
**break**;
}
Dl_info info;
dladdr(node->pc, &info);
//转为OC字符串方便操作
NSString *name = @(info.dli_sname);
//OC方法 直接添加到数组
// if ([name hasPrefix:@"+["] || [name hasPrefix:@"-["]) {
// [symbleNames addObject:name];
// continue;
// }
// [symbleNames addObject:];
**BOOL** isObjc = [name hasPrefix:@"+["] || [name hasPrefix:@"-["];
NSString * symbleName = isObjc ? name : [@"_" stringByAppendingString:name];
[symbleNames addObject:symbleName];
}
// symbleNames = (NSMutableArray *)[[symbleNames reverseObjectEnumerator] allObjects];
NSEnumerator *em = [symbleNames reverseObjectEnumerator];
//新数组存储
NSMutableArray *funcs = [NSMutableArray arrayWithCapacity:symbleNames.count];
NSString *name;
**while** (name = [em nextObject]) {
**if** (![funcs containsObject:name]) {
[funcs addObject:name];
}
}
//数组转为字符串
NSString *funcStr = [funcs componentsJoinedByString:@"\n"];
//文件路径
NSString *filePath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"ll.order"];
//文件内容
NSData *file = [funcStr dataUsingEncoding:NSUTF8StringEncoding];
//写入文件
[[NSFileManager defaultManager] createFileAtPath:filePath contents:file attributes:**nil**];
//获取沙盒主目录路径
NSLog(@"%@",NSHomeDirectory());
NSLog(@"%@",funcStr);
配置输出的order 文件:targets - buildsettings - order file
./ll.order
再次启动时,APP加载page进入内存时,启动所需要的符号都放在了前几页page,减少page加载的个数,也就减少了page fault 次数。
检测启动时间是否减少:通过工具instrument工具,system trace ,查看启动时间。
swift 项目符号化之后的方法都是混淆过的。