随笔 - 48  文章 - 0  评论 - 0  阅读 - 11784

iOS启动优化之编译器插桩

一、什么是编译器插桩

编译器插桩是指在编译期间修改已有的代码或者生成新的代码。

二、准备知识

Tracing PCs是用来跟踪CPU将要执行的指令代码;我们可以借此拿到程序启动时需要的用到的函数,然后减少缺页中断的产生,从而达到启动优化的效果。如何配置如下面这个图所示:

工程中配置使用它-fsanitized-coverage=trace-pc-guard,编译器会在每个代码边缘插入以下代码: __sanitizer_cov_trace_pc_guard(&guard_variable)。

在工程上配置了-fsanitized-coverage=trace-pc-guard后再编译工程就会报错,需要定义两个函数__sanitizer_cov_trace_pc_guard_init和__sanitizer_cov_trace_pc_guard。

三 、具体举例

1. 新建一个空的过程,然后添加配置:

Target -> Build Setting -> Custom Complier Flags -> Other C Flags 添加 fsanitize-coverage=func,trace-pc-guard

2.在Viewcontroller.m的文件中添加代码

复制代码
#include <stdint.h>
#include <stdio.h>
#include <sanitizer/coverage_interface.h>

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.
  printf("INIT: %p %p\n", start, stop);
  for (uint32_t *x = start; x < stop; x++)
    *x = ++N;  // Guards should start from 1.
}

void __sanitizer_cov_trace_pc_guard(uint32_t *guard) {
  if (!*guard) return;
  void *PC = __builtin_return_address(0);
  char PcDescr[1024];
  printf("guard: %p %x PC %s\n", guard, *guard, PcDescr);
}
复制代码

3.跑代码看输出结果

__sanitizer_cov_trace_pc_guard_init:获取整个工程中所有函数/方法的数量;start stop是存储的是工程中符号的个数

__sanitizer_cov_trace_pc_guard:拿到工程中这些函数/方法的地址;系统每调用一个方法,都会回调这个__sanitizer_cov_trace_pc_guard;在汇编中,编译器会在每一个方法之前插入__sanitizer_cov_trace_pc_guard;

由此可以知道app启动的程序,方便二进制重排

四 获取工程启动时需要用到的函数(三种方式)

复制代码
void __sanitizer_cov_trace_pc_guard(uint32_t *guard) {
    //第一种方式
   NSLog(@"%s",__func__);
    //第二种方式
    if (!*guard) return;
    //调用__sanitizer_cov_trace_pc_guard的函数的函数地址
    void *PC = __builtin_return_address(0);
    //可以获得一个函数的名称以及地址
    Dl_info info;
    dladdr(PC, &info);
    NSLog(@"dil_fname %s",info.dli_fname);//文件的路径
    NSLog(@"dil_fname %p",info.dli_fbase);//文件的地址
    NSLog(@"dil_fname %s",info.dli_sname);//符号的名字,这个是我们需要的
    NSLog(@"dil_fname %p",info.dli_saddr);//符号的地址
    
    //第三种方式
//    typedef struct {
//        void * pc;
//        int abc;
//    } SYNode;
    SYNode *node = malloc(sizeof(SYNode));
    *node = (SYNode){PC,0};
复制代码

五、生成的APP启动函数顺序的order文件

复制代码
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    //创建数组
    NSMutableArray *symbleNames = [NSMutableArray array];
    while (YES) {
        SYNode *node = OSAtomicDequeue(&symbolList, offsetof(SYNode, abc));
        if (node == NULL) {
            break;;
        }
        Dl_info info;
        dladdr(node->pc, &info);
//        printf("%s\n",info.dli_sname);
        //转为OC字符串方便操作
        NSString *name = @(info.dli_sname);
        //写法一 添加
        //OC方法 直接添加到数组
        //hasPrefix 表示以+[开头
//        if ([name hasPrefix:@"+["] || [name hasPrefix:@"-["]) {
//            [symbleNames addObject:name];
//            continue;
//        }
//        [symbleNames addObject:[@"_" stringByAppendingString:name]];
        //写法二
        BOOL isObjc = [name hasPrefix:@"+["] || [name hasPrefix:@"-["];
        NSString * symbleName = isObjc ? name : [@"_" stringByAppendingString:name];
        //取反
        [symbleNames addObject:symbleName];
            symbleNames = (NSMutableArray *)[[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];
        }
    }
    NSLog(@"%@",funcs);
    //数组转为字符串
    NSString *funcStr = [funcs componentsJoinedByString:@"\n"];
    //文件路径  写文件
    NSString *filePath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"lg.order"];
    //文件内容
    NSData *file = [funcStr dataUsingEncoding:NSUTF8StringEncoding];
    //写入文件
    [[NSFileManager defaultManager] createFileAtPath:filePath contents:file attributes:nil];
    //获取沙盒主目录路径
    NSLog(@"%@",NSHomeDirectory());
    
    NSLog(@"%@",funcStr);
}
复制代码
posted on   suanningmeng98  阅读(285)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

点击右上角即可分享
微信分享提示