TrampolineHook 是一个中心重定向框架。可以通过一个函数替换/拦截所有你想要函数的框架。
由于 TrampolineHook 进行过更新,本文先从最初的源码开始阅读分析。
预备知识
汇编语言
之前有文章简单总结了汇编语言。
虚拟内存
关于虚拟内存,特地做了一篇简述
初版
提交记录为 :commit => ‘eb2cb31243a86cd50760e8bb8f8e2145e18e4467’
代码例子
TrampolineHook 中提供了一个 demo ,展示了如何使用。
1 | /// 一个自定义函数,它会在拦截的目标方法前执行 |
直接替换掉目标方法的IMP,那么它是如何做到拦截方法的 ?
源码解析
新的 IMP 是在 THDynamicPageAllocator 中构建的
1 | - (IMP)allocateDynamicPageForFunction:(IMP)functionAdress |
fetchCandidiateDynamicPage 会调用 THCreateDynamicePage() 返回一个结构体。
THCreateDynamicePage() 方法中申请内存和映射的代码,将汇编映射到虚拟内存中
1 | static THDynamicPage *THCreateDynamicePage() |
我们来看看汇编和结构体的结构
汇编
1 | .text |
声明的结构体
1 |
|
我们用图对比这两个结构
可以看出,allocateDynamicPageForFunction 返回的索引,其实是汇编中的两条指令
1 | mov x13, lr |
通过 _th_entry 执行偏移地址执行原函数方法。
具体流程如下图
再版
针对可变参数函数方法,解决了栈污染问题,将寄存器的值存放在堆上。
申请堆空间保存寄存器数值
1 |
|
释放寄存器数值
1 |
|
这里用了,这个作用是为了让我们的函数不会额外的生成函数 prologue/epilogue 中的压栈消栈操作。1
__attribute__((__naked__))