Intel Pin II - 编译与运行时环境
在我的上一篇介绍Pin的文章中使用的Pin还是3.4版本,而写本篇文章时已经是3.11版本了,这期间在使用Pin的时候也遇到了一些环境上的问题,在这里总结一下.
目前Intel Pin官网上的版本已经到3.11了,不过之前的一些版本还是可以下载的,只是找不到下载的入口。
Pin 2.x 与 3.x 的改动
目前Pin 2.x的最高版本是2.14,估计不会再更新了。2.x到3.x有较大的改动,这使得一些旧的在2.x上编译的项目可能不太好直接应用在3.x上。主要的变化有下面2点
kernel支持
理论上来说,Pin 2.x版本并不能支持4.x以上的linux kernel. 如果直接在高版本内核的系统中运行,会直接报下面的错误:
1 | E: 4.0 is not a supported linux release |
但pin居然有一个隐藏的开关 -ifeellucky
可以绕过这个检查,强制启动程序,真的是非常神奇……
加了这个开关之后也可能会出现问题,之前我在64位系统上对32位程序进行插桩时,就出现过报错的情形:
1 | A: Source/pin/vm_ia32_l/jit_region_ia32_linux.cpp: XlateSysCall: 33: Sysenter is supported on IA32 only and the expected location is inside Linux Gate |
这个错误可能是pin对于64位系统上sysenter
这种系统调用的方式不支持导致的,关于使用sysenter
进行系统调用的机制可以参考《深入理解Linux内核》这本书第十章”系统调用”的内容,之后可能会考虑总结一下。对于这种情况,也有一个workaround,就是禁用VDSO,使用native的int 0x80进行32位系统调用,方法是在内核启动时指定参数-vdso32=0
,不过这样的话系统调用的效率也会降低。
运行时库和CRT支持
3.x与2.x还有一个比较大的改动就是其使用了自己实现的CRT,相关内容可以参考文末给出的文档链接。主要的影响有:
- 必须链接Pin自身的CRT,这在文档中有比较详细的说明,但对于一般项目来说,使用Pin的Makefile Infrastructure就可以省去自己添加编译选项的过程了。
- 无法链接第三方的动态链接库,即使在link的时候指定了
-l
选项,之后也是不会链接到指定的library的,目前还没有找到好的解决方案。但静态链接第三方的库是可以的。 - C++ STL的一些模板类被port过来,但仅有比较少的一些功能,大部分的模板类都没有,例如
std::array
.
所以如果自己的Pintool需要第三方动态库的支持的话,可以考虑用回2.14版本,或者将代码静态编译到Pintool当中。
Intel Pin 的 Makefile Infrastructure
如果手动编译3.x的Pintool,需要手动添加很多编译链接选项,不仅繁琐而且容易出错,所以推荐使用Pin自身的Makefile功能。参考一下 User Guide 中 makefile 的部分,应该很容易就能够理解了。
文件结构
首先需要指定一下pin自身的目录位置 PIN_ROOT
makefile会自动去这个目录查找默认的makefile. 参考 ./source/tools/MyPinTool
目录下makefile
和makefile.rules
的配置。makefile
不需要修改,主要的配置都是在makefile.rules
中进行的。
如果是在Linux下编译pintool,主makefile会依次包含makefile.config
, makefile.unix.config
, unix.vars
, makefile.rules
, makefile.default.rules
. 其中前3个文件包含了一些flags和系统相关的定义,makefile.rules
是我们自己定义的build target和一些规则,makefile.default.rules
是默认的编译规则。
指定自己的编译目标
将./source/tools/MyPinTool
目录下的makefile
和makefile.rules
拷贝到自定义的目录下,新建一个自己的pintool文件test_pintool.cpp
,然后修改makefile.rules
里面的TOOL_ROOTS
变量。
1 | TOOL_ROOTS := test_pintool |
然后直接运行make
,默认的编译规则会自动寻找test_pintool.cpp
文件,并将编译好的pintool test_pintool.so
放置在obj-intel64
目录下. 如果编译32位的,就指定make TARGET=ida32
即可,pintool会被放置在obj-ia32
目录。
除了TOOL_ROOTS
还有APP_ROOTS
和TEST_ROOTS
,分别对应非Pintool的app和相关测试程序。
自定义编译选项和编译命令
在makefile.rules
中的Build rules
这一节我们可以定义一些自己的编译命令,例如通过修改TOOL_CXXFLAGS
来改变编译pintool时候的选项,修改TOOL_LIBS
能够改变链接时候的选项,例如我们想链接一个静态库,就可以这样
1 | TOOL_LIBS += -lxxx |
类似地,我们可以定义自己的编译规则,在user guide中有这样一个例子
1 | # Build the intermediate object file. |
这是将多个.cpp文件编译成.o然后链接成一个pintool的例子,对于大型的项目来说很有用。OBJDIR
也是可以更改的。
Reference
Pin 3.11 User Guide
Intel Pin Tool on Linux 4.0
PinCRT Overview