Pin
pin可以被认为是一个JIT编译器,这个编译器的输入不是字节码而是普通的可执行文件。pin截获这个可执行文件的第一条指令,产生新的代码序列。
在JIT模式,执行的代码都是pin生成的代码,原始代码仅仅是用来参考。当生成代码时,pin给用户提供了插入自己代码的机会
‘PIn的桩代码都会被执行的,不论他们位于哪里。大体上,对于分支存在一些异常,比如,如果一个指令从不执行,它将不会插入桩函数
Pintools
pintools包含两个组件:
桩:决定在哪里插入什么代码
分析代码:插入点执行的代码
两个组件都在一个独立的可执行体中(windows:.dll; linux: .so);即pintool。pintool可以认为是pin中的插件,能够修改生成代码的流程。
pintool在pin中注册一些桩回调函数,每当pin生成新的代码时就调用回调函数。这些回调函数代表了桩组件。它可以检查将要生成的代码,得到它的静态属性,并且决定是否需要以及在哪里插入分析函数。
分析函数手机关于程序的数据。pin保证整数和浮点指针寄存器状态在必要时会被保存和回复,允许床底参数给(分析)函数
pintools也可以注册一些事件通知类回调函数,比如线程创建和fork,这些回调大体上用于数据收集或者初始化与清理
由于pintools像插件一样的工作,所以它必须处于pin与被插桩的可执行文件的地址空间以便访问可执行文件的所有数据,它也跟可执行文件共享文件描述符和进程等其他信息。
pin和pintool从第一条指令开始控制程序,对于与共享库一起编译的可执行文件,这意味着动态加载器和共享库将会对pintool可见。
插桩粒度:
1 踪迹插桩(TRACE_AddInstrumentFunction)
2 指令插桩(INS_AddInstrumentFunction)
3 镜像插桩(IMG_AddInstrumentFunction)
镜像插桩依靠符号信息判断函数边界,因此需要在PIN_Init之前调用PIN_InitSymbols
4 函数插桩(RTN_AddInstrumentFunction)
注意:镜像插桩和函数插桩中,不可能知道一个(分析)函数会被执行(因为这些插桩发生在镜像载入时)。在Trace和Instruction中只有被执行的代码才会被遍历。
参考:
https://huirongis.me/2015/12/30/Intel-Pin-Introduction/