一、首先获取 重排后方法执行顺序
.h 文件
import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface SymbolTools : NSObject
///写入启动完成时 调用的符号表
- (void)writeSymobol;
@end
NS_ASSUME_NONNULL_END
.m 文件
import "SymbolTools.h"
include <stdint.h>
include <stdio.h>
include <sanitizer/coverage_interface.h>
import <dlfcn.h>
import <libkern/OSAtomicQueue.h>
@implementation SymbolTools
//原子队列
static OSQueueHead symbolist = OS_ATOMIC_QUEUE_INIT;
//存放符号表的结构体
typedef struct {
void *pc; //当前函数栈信息
void *next; //下个函数栈信息
}SYNode;
//根据stop 地址偏移可以算出调用函数个数 ---暂时用不到,但是必须实现该函数,因为clang 会调用
void __sanitizer_cov_trace_pc_guard_init(uint32_t *start,
uint32_t *stop) {
if (start == stop || *start) return; // Initialize only once.
printf("INIT: %p %p\n", start, stop);
}
//返回函数调用地址 ->寄存器即将调用的下个函数地址
void __sanitizer_cov_trace_pc_guard(uint32_t *guard) {
void *PC = __builtin_return_address(0);
SYNode *node = malloc(sizeof(SYNode));
*node = (SYNode){PC,NULL};
//进入
OSAtomicEnqueue(&symbolist, node, offsetof(SYNode,next));
}
pragma 文件写入
- (void)writeSymobol{
NSMutableArray <NSString *> *symbolAry = [NSMutableArray array];
while (YES) {
SYNode *node = OSAtomicDequeue(&symbolist, 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]; //非oc符号 缺少''
[symbolAry addObject:symbolName];
}
//字符串颠倒顺序,因为结构体加入的时候 类似栈的形式先进后出
NSArray *resultAry = [[symbolAry reverseObjectEnumerator] allObjects];
//由于方法会被多次调用,需要去重
[symbolAry removeAllObjects];
for (NSString *symbolName in resultAry) {
if (![symbolAry containsObject:symbolName]) {
[symbolAry addObject:symbolName];
}
}
[symbolAry removeObject:[NSString stringWithFormat:@"%s",FUNCTION]]; //移除本方法
//写入文件
NSString *symbols = [symbolAry componentsJoinedByString:@"\n"];
NSString *filePath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"pdmi.order"];
NSData *fileConten = [symbols dataUsingEncoding:NSUTF8StringEncoding];
[[NSFileManager defaultManager] createFileAtPath:filePath contents:fileConten attributes:nil];
NSLog(@"filePath == %@",filePath);
}
@end
二、配置顺序方法执行条件 -fsanitize-coverage=func,trace-pc-guard
三、按路径取到文件 放到工程目录中 然后配置参数