Skip to content

Commit

Permalink
feature:clang插桩用于启动优化
Browse files Browse the repository at this point in the history
  • Loading branch information
wangluyuan committed Mar 5, 2021
1 parent 1d888d1 commit 2e1b57a
Show file tree
Hide file tree
Showing 4 changed files with 168 additions and 0 deletions.
6 changes: 6 additions & 0 deletions TRCommonTools.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
02E687CE21ABF44400C9D68C /* UIViewController+Swizzling.m in Sources */ = {isa = PBXBuildFile; fileRef = 02E687CC21ABF44400C9D68C /* UIViewController+Swizzling.m */; };
02E687D121ABF53E00C9D68C /* TRPrintJsonLog.m in Sources */ = {isa = PBXBuildFile; fileRef = 02E687D021ABF53E00C9D68C /* TRPrintJsonLog.m */; };
0E754CC1C6CF9AFE54D81E75 /* libPods-TRCommonTools.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 25E011084E6EFE789B24557D /* libPods-TRCommonTools.a */; };
BA504D8625F20865000D9327 /* TRClangTrance.m in Sources */ = {isa = PBXBuildFile; fileRef = BA504D8425F20865000D9327 /* TRClangTrance.m */; };
FD02A67C20FCA41400E9F1C3 /* FirstViewController+Config.m in Sources */ = {isa = PBXBuildFile; fileRef = FD02A67B20FCA41400E9F1C3 /* FirstViewController+Config.m */; };
FD4E8B5820EDF3BA00738E1A /* FirstViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = FD4E8B5720EDF3BA00738E1A /* FirstViewController.m */; };
FD4E8B5B20EDF88D00738E1A /* UITextField+TRBackward.m in Sources */ = {isa = PBXBuildFile; fileRef = FD4E8B5A20EDF88D00738E1A /* UITextField+TRBackward.m */; };
Expand Down Expand Up @@ -59,6 +60,8 @@
25E011084E6EFE789B24557D /* libPods-TRCommonTools.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-TRCommonTools.a"; sourceTree = BUILT_PRODUCTS_DIR; };
2E123FFCE8603E9A31373231 /* Pods-TRCommonTools.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-TRCommonTools.debug.xcconfig"; path = "Pods/Target Support Files/Pods-TRCommonTools/Pods-TRCommonTools.debug.xcconfig"; sourceTree = "<group>"; };
B0B99ED09189721CDB732B7E /* Pods-TRCommonTools.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-TRCommonTools.release.xcconfig"; path = "Pods/Target Support Files/Pods-TRCommonTools/Pods-TRCommonTools.release.xcconfig"; sourceTree = "<group>"; };
BA504D8425F20865000D9327 /* TRClangTrance.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TRClangTrance.m; sourceTree = "<group>"; };
BA504D8525F20865000D9327 /* TRClangTrance.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TRClangTrance.h; sourceTree = "<group>"; };
FD02A67A20FCA41400E9F1C3 /* FirstViewController+Config.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "FirstViewController+Config.h"; sourceTree = "<group>"; };
FD02A67B20FCA41400E9F1C3 /* FirstViewController+Config.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "FirstViewController+Config.m"; sourceTree = "<group>"; };
FD4E8B5620EDF3BA00738E1A /* FirstViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FirstViewController.h; sourceTree = "<group>"; };
Expand Down Expand Up @@ -214,6 +217,8 @@
FD52387420E5D6AB00F35119 /* TRAlert */,
FD52387920E5D6AB00F35119 /* TRAnimationHelper.h */,
FD52387A20E5D6AB00F35119 /* TRAnimationHelper.m */,
BA504D8525F20865000D9327 /* TRClangTrance.h */,
BA504D8425F20865000D9327 /* TRClangTrance.m */,
FD52387B20E5D6AB00F35119 /* TRAttributeDictionary.h */,
FD52387C20E5D6AB00F35119 /* TRAttributeDictionary.m */,
FD52387D20E5D6AB00F35119 /* TRCommonFunction.h */,
Expand Down Expand Up @@ -403,6 +408,7 @@
FD5238A520E5D6AB00F35119 /* ZFModalTransitionAnimator.m in Sources */,
FD52389B20E5D6AB00F35119 /* TRCommonFunction.m in Sources */,
02E687D121ABF53E00C9D68C /* TRPrintJsonLog.m in Sources */,
BA504D8625F20865000D9327 /* TRClangTrance.m in Sources */,
FD52389F20E5D6AB00F35119 /* TRTimeUtility.m in Sources */,
FD5238A320E5D6AB00F35119 /* UIView+TRFrame.m in Sources */,
FD52389C20E5D6AB00F35119 /* TRFileManager.m in Sources */,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
21 changes: 21 additions & 0 deletions TRCommonTools/TRCommonTools/TRClangTrance.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//
// TRClangTrance.h
// Runner
//
// Created by 控客 on 2021/3/5.
//

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface TRClangTrance : NSObject

/// -fsanitize-coverage=func,trace-pc-guard
/// 生成trace.order文件
/// 一般我们要检测启动前执行的函数,所以放到首页的viewDidAppear中调用该函数
+ (void)generateOrderFile;

@end

NS_ASSUME_NONNULL_END
133 changes: 133 additions & 0 deletions TRCommonTools/TRCommonTools/TRClangTrance.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
//
// TRClangTrance.m
// Runner
//
// Created by 控客 on 2021/3/5.
//

#import "TRClangTrance.h"
#import <dlfcn.h>
//用于定义原子队列
#import <libkern/OSAtomic.h>

@implementation TRClangTrance

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.
for (uint32_t *x = start; x < stop; x++)

*x = ++N;
// Guards should start from 1.
}

//定义原子队列
static OSQueueHead symbolList = OS_ATOMIC_QUEUE_INIT;

//定义符号结构体
typedef struct {
void *pc;
void *next;

} SymbolNode;

void __sanitizer_cov_trace_pc_guard(uint32_t *guard) {
//排除load方法
//if (!*guard) return;

//当前函数返回到上一个方法继续执行的地址
void *PC = __builtin_return_address(0);


Dl_info info;
dladdr(PC, &info);
printf("fname:%s \nfbase:%p \nsname:%s \nsaddr:%p\n\n\n",info.dli_fname,info.dli_fbase,info.dli_sname,info.dli_saddr);

char PcDescr[1024];
//__sanitizer_symbolize_pc(PC, "%p %F %L", PcDescr, sizeof(PcDescr));
printf("guard: %p %x PC %s\n", guard, *guard, PcDescr);



SymbolNode *node = malloc(sizeof(SymbolNode));
*node = (SymbolNode){PC, NULL};
OSAtomicEnqueue(&symbolList, node, offsetof(SymbolNode, next));
}

+ (void)generateOrderFile {

NSMutableArray <NSString *> *symbolNames = [NSMutableArray array];

while (YES) {
//一次循环!也会被HOOK一次!!(Tracing PCs只要有跳转(汇编中b/bl指令)就会被HOOK)

SymbolNode * node = OSAtomicDequeue(&symbolList, offsetof(SymbolNode, next));
if (node == NULL) {
break;
}

Dl_info info = {0};
dladdr(node->pc, &info);
printf("%s \n",info.dli_sname);

NSString *name = @(info.dli_sname);
free(node);

// 判断是不是oc方法,是的话直接加入符号数组 C函数前需加 _
BOOL isInstanceMethod = [name hasPrefix:@"-["];
BOOL isClassMethod = [name hasPrefix:@"+["];

BOOL isObjc = isInstanceMethod || isClassMethod;

NSString * symbolName = isObjc ? name: [@"_" stringByAppendingString:name];
if (![symbolNames containsObject:symbolName]) {
[symbolNames addObject:symbolName];
}
}

// 取反:将先调用的函数放到前面
NSEnumerator * emt = [symbolNames reverseObjectEnumerator];


// 去重:由于一个函数可能执行多次,__sanitizer_cov_trace_pc_guard会执行多次,就加了重复的了,所以去重一下

//反向数组
NSMutableArray<NSString *> *funcs = [NSMutableArray arrayWithCapacity:symbolNames.count];
NSString *name;
while (name = [emt nextObject]) {
if (![funcs containsObject:name]) {
[funcs addObject:name];
}
}

// 由于trace了所有执行的函数,这里我们就把本函数移除掉 去掉当前方法
[funcs removeObject:[NSString stringWithFormat:@"%s",__FUNCTION__]];

// 写order文件
//数组转成字符串
NSString *funcStr = [funcs componentsJoinedByString:@"\n"];
//字符串写入文件
NSString *filePath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"trclangtrace.order"];
//文件内容
NSData *fileContents = [funcStr dataUsingEncoding:NSUTF8StringEncoding];

[[NSFileManager defaultManager] createFileAtPath:filePath contents:fileContents attributes:nil];

if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]){
NSLog(@"orderPath:%@",filePath);
}else{
NSLog(@"生成orderPath失败");
}
}

#pragma mark - Util
+ (BOOL)isObjcMethodBySymbolName:(NSString *)symbolName {

BOOL isInstanceMethod = [symbolName hasPrefix:@"-["];
BOOL isClassMethod = [symbolName hasPrefix:@"+["];
return isInstanceMethod || isClassMethod;
}

@end

0 comments on commit 2e1b57a

Please sign in to comment.