iOSの基礎となる最適化(33)-スタートアップの最適化のためのclangインストルメンテーション

Clangの原則

Clangドキュメントclang.llvm.org/docs/Saniti…

Appleが提供するコードトレース機能、PCのトレース

-fsanitize-coverage=func,trace-pc-guard1.xcodeに追加されます

image.png

ここでfunc、はインターセプトメソッドのみを表すことに注意してください。

2.まだ定義されていないメソッドが2つあるため、実行時にエラーが報告されます

__sanitizer_cov_trace_pc_guard_init
__sanitizer_cov_trace_pc_guard
复制代码

これはコールバックであり、ドキュメントで要求されているようにプロジェクトで定義する必要があります。

メモリを表示するコマンド:x 0x100000

以下、メソッド、ブロック、関数などを総称してメソッドと呼びます。

__sanitizer_cov_trace_pc_guard_init

すべてのメソッドの数を取得できます。

__sanitizer_cov_trace_pc_guard

すべてのメソッドをフックして、これらすべてのメソッドの呼び出し順序を取得します。

各メソッドの実装部分にコード行を追加することであり、このメソッドを呼び出すことは、バイナリファイルを変更することと同じです。

この方法は、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);
}

复制代码

迅速なシンボルオーバーライド

1.迅速なファイルを作成します

2.追加Other Swift Flags

image.png

このようにして、swiftメソッドも追加されます。

おすすめ

転載: juejin.im/post/7085638984126169095
おすすめ