热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

iOS启动优化——Clang插桩

iOS启动优化——Clang插桩上文说到二进制重排可以减少缺页中断(pagefault)的次数而达到优化启动时间的效果,那么如何知道启动的


iOS启动优化 —— Clang插桩


上文说到二进制重排可以减少缺页中断(pagefault)的次数而达到优化启动时间的效果,那么如何知道启动的时候用到了哪些符号呢?这就要用到clang插桩了。

这里需要用到 Tracing PCs文档.根据文档里面的提示,在Build Settings 里面搜索 Other C Flags 添加 -fsanitize-coverage=trace-pc-guard
在这里插入图片描述
添加之后运行,发现报错,找不到符号___sanitizer_cov_trace_pc_guard_init___sanitizer_cov_trace_pc_guard。问题是程序中并没有调用这个函数,那么说明就是添加标记后的回调函数。
在这里插入图片描述
按照文档添加这两个方法。
在这里插入图片描述
运行后发现还是报错找不到符号__sanitizer_symbolize_pc,那么就将这个函数去掉得到:
在这里插入图片描述
去掉函数后运行,发现运行成功了,并且打印如下:
在这里插入图片描述
这里的0x104da93d0start0x104da9408stop,那么这里存的是什么数据呢?打印start 和stop得到下图的结果。这里的数字代表着符号的个数。而stop往前四位里面的就是符号总共的个数,这里就是14个符号
在这里插入图片描述

添加一个方法后重新运行,发现果然变成了f,也就是15个
在这里插入图片描述
添加一个block看看是否可以被检测到。运行后发现也+1了,变成了10,也就是16
在这里插入图片描述
到这里可以知道,___sanitizer_cov_trace_pc_guard_init里面可以得到符号的总个数,那么___sanitizer_cov_trace_pc_guard里面可以做什么呢?

___sanitizer_cov_trace_pc_guard里面加个断点后运行,发现进来了很多次,然后在点击屏幕触发touchesBegan后发现,___sanitizer_cov_trace_pc_guard也被调用了。并且发现是被touchesBegan调起的。
在这里插入图片描述
重新运行一下,发现___sanitizer_cov_trace_pc_guard依次被[ViewController load],main函数,[AppDelegate application:didFinishLaunchingWithOptions:]等方法调起,那么说明,这个就是启动的顺序(这里拦截的都是当前项目中的函数)。
在这里插入图片描述
这里可以知道,___sanitizer_cov_trace_pc_guard是hook一切的回调函数。那么___sanitizer_cov_trace_pc_guard是怎么做到的呢?
这里看到调用___sanitizer_cov_trace_pc_guard的方法的汇编代码 ,这里是touchesBegan。看到汇编代码这里当调用touchesBegan的时候,马上就调用了___sanitizer_cov_trace_pc_guard。那么也就是说只要添加了clang插桩的标记,那么编译器就会在所有方法,函数,block的代码的实现的边缘添加一句代码,也就是调用___sanitizer_cov_trace_pc_guard的代码。
在这里插入图片描述
那么应该如何获取符号以及顺序呢?
___sanitizer_cov_trace_pc_guard里面__builtin_return_address可以拿到上一个函数的地址,那么有了这个地址,就有机会拿到这个函数符号的名字。
在这里插入图片描述
importdlfcn
在这里插入图片描述
___sanitizer_cov_trace_pc_guard里面根据函数的地址调用dladdr函数来获得函数的基本信息。其中结构体Dl_info有以下成员变量:


  • dli_fname:路径名称
  • dli_fbase:路径地址
  • dli_sname:符号名称
  • dli_saddr:符号地址
    打印后信息如下。
    在这里插入图片描述
    那么这里可以通过dli_sname打印出符号调用的顺序。
    在这里插入图片描述

这个方法其实有个坑点。
___sanitizer_cov_trace_pc_guard里面打印线程,然后在viewDidLoad里面添加一个方法到子线程执行,

在这里插入图片描述
在这里插入图片描述

看到这里打印了线程number为6,那么就说明___sanitizer_cov_trace_pc_guard方法也会跑到子线程去执行,那么在存储数据的时候就会有多线程访问数据的情况,所以这里要用线程安全的方式去存储。

这里定义原子队列和定义符号结构体。
在这里插入图片描述
然后在___sanitizer_cov_trace_pc_guard里面创建结构体,并且使结构体入栈,这里会将node存入到symbolist的第一个地方,然后这个node的next属性会存下一个node的地址,形成一个链表。
在这里插入图片描述
接下来要将其取出来,就将node取出来,然后获得符号的名字。
在这里插入图片描述
运行后发现这里一直重复打印-[ViewController touchesBegan:withEvent:]。这是因为touchesBegan里面有循环,clang回对循环体进行拦截,拦截一次就添加一次,所以这里会一直重复打印-[ViewController touchesBegan:withEvent:]。
在这里插入图片描述
要解决这个问题,则需要将other c flag 里面-fsanitize-coverage=trace-pc-guard 改成 -fsanitize-coverage=func,trace-pc-guard
在这里插入图片描述
运行后发现不会死循环了,得到下面的结果。
在这里插入图片描述
由于是用栈来存储,所以列表是反的,这里要先把这个列表变成正的。还有就是这里的函数没有下划线,要给函数添加上下划线。
所以函数变成了这样:
在这里插入图片描述
这里看到有重复的符号,就要去重。
在这里插入图片描述
接下来写成文件。
在这里插入图片描述
生成文件后,点击 Add Additional Simulator,点开真机里面的Settings里面的 download console,放在想要的地方后选取生成的文件,右击选择显示包内容,点击AppData,点击tmp,看到 ls.order文件。
在这里插入图片描述
点击后可以看到这里符号表已经生成了。
在这里插入图片描述
到这里,就可以直接使用这个ls.order文件了。将这个文件拷贝到根目录下,然后打开 Write Link Map File后运行验证。
在这里插入图片描述
那么swift是否可以进行二进制重排呢?
创建一个swift文件并调用方法。
在这里插入图片描述
然后来到Build SettingsOther Swift Flags 添加 -sanitize=undefined-sanitize-coverage=func
在这里插入图片描述
运行后发现swift方法也打印了出来。
在这里插入图片描述


推荐阅读
  • Android Studio Bumblebee | 2021.1.1(大黄蜂版本使用介绍)
    本文介绍了Android Studio Bumblebee | 2021.1.1(大黄蜂版本)的使用方法和相关知识,包括Gradle的介绍、设备管理器的配置、无线调试、新版本问题等内容。同时还提供了更新版本的下载地址和启动页面截图。 ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • ihaveusedthedelphidatabindingwizardwithmyxmlfile,andeverythingcompilesandrunsfine. ... [详细]
  • 本文介绍了使用kotlin实现动画效果的方法,包括上下移动、放大缩小、旋转等功能。通过代码示例演示了如何使用ObjectAnimator和AnimatorSet来实现动画效果,并提供了实现抖动效果的代码。同时还介绍了如何使用translationY和translationX来实现上下和左右移动的效果。最后还提供了一个anim_small.xml文件的代码示例,可以用来实现放大缩小的效果。 ... [详细]
  • Nginx使用(server参数配置)
    本文介绍了Nginx的使用,重点讲解了server参数配置,包括端口号、主机名、根目录等内容。同时,还介绍了Nginx的反向代理功能。 ... [详细]
  • 基于layUI的图片上传前预览功能的2种实现方式
    本文介绍了基于layUI的图片上传前预览功能的两种实现方式:一种是使用blob+FileReader,另一种是使用layUI自带的参数。通过选择文件后点击文件名,在页面中间弹窗内预览图片。其中,layUI自带的参数实现了图片预览功能。该功能依赖于layUI的上传模块,并使用了blob和FileReader来读取本地文件并获取图像的base64编码。点击文件名时会执行See()函数。摘要长度为169字。 ... [详细]
  • IhaveconfiguredanactionforaremotenotificationwhenitarrivestomyiOsapp.Iwanttwodiff ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • HDU 2372 El Dorado(DP)的最长上升子序列长度求解方法
    本文介绍了解决HDU 2372 El Dorado问题的一种动态规划方法,通过循环k的方式求解最长上升子序列的长度。具体实现过程包括初始化dp数组、读取数列、计算最长上升子序列长度等步骤。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • 本文介绍了在Mac上安装Xamarin并使用Windows上的VS开发iOS app的方法,包括所需的安装环境和软件,以及使用Xamarin.iOS进行开发的步骤。通过这种方法,即使没有Mac或者安装苹果系统,程序员们也能轻松开发iOS app。 ... [详细]
  • 本文介绍了Sencha Touch的学习使用心得,主要包括搭建项目框架的过程。作者强调了使用MVC模式的重要性,并提供了一个干净的引用示例。文章还介绍了Index.html页面的作用,以及如何通过链接样式表来改变全局风格。 ... [详细]
  • 本文介绍了Cocos2dx学习笔记中的更新函数scheduleUpdate、进度计时器CCProgressTo和滚动视图CCScrollView的用法。详细介绍了scheduleUpdate函数的作用和使用方法,以及schedule函数的区别。同时,还提供了相关的代码示例。 ... [详细]
  • 本文介绍了iOS开发中检测和解决内存泄漏的方法,包括静态分析、使用instruments检查内存泄漏以及代码测试等。同时还介绍了最能挣钱的行业,包括互联网行业、娱乐行业、教育行业、智能行业和老年服务行业,并提供了选行业的技巧。 ... [详细]
author-avatar
无极圈颜汐
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有