Clang 原理
Clang文档 clang.llvm.org/docs/Saniti…
苹果提供的一个代码盯梢的功用, Tracing PCs
1、将-fsanitize-coverage=func,trace-pc-guard
添加到xcode中
留意这里的 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
这样 swift 的方法也就加进去了。