在我的上一篇介绍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 目录下makefilemakefile.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目录下的makefilemakefile.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_ROOTSTEST_ROOTS,分别对应非Pintool的app和相关测试程序。

自定义编译选项和编译命令

makefile.rules中的Build rules这一节我们可以定义一些自己的编译命令,例如通过修改TOOL_CXXFLAGS来改变编译pintool时候的选项,修改TOOL_LIBS能够改变链接时候的选项,例如我们想链接一个静态库,就可以这样

1
TOOL_LIBS += -lxxx

类似地,我们可以定义自己的编译规则,在user guide中有这样一个例子

1
2
3
4
5
6
7
8
9
10
11
# Build the intermediate object file.
$(OBJDIR)Source1$(OBJ_SUFFIX): Source1.cpp
$(CXX) $(TOOL_CXXFLAGS) $(COMP_OBJ)$@ $<

# Build the intermediate object file.
$(OBJDIR)Source2$(OBJ_SUFFIX): Source2.c Source2.h
$(CC) $(TOOL_CXXFLAGS) $(COMP_OBJ)$@ $<

# Build the tool as a dll (shared object).
$(OBJDIR)YourTool$(PINTOOL_SUFFIX): $(OBJDIR)Source1$(OBJ_SUFFIX) $(OBJDIR)Source2$(OBJ_SUFFIX) Source2.h
$(LINKER) $(TOOL_LDFLAGS_NOOPT) $(LINK_EXE)$@ $(^:%.h=) $(TOOL_LPATHS) $(TOOL_LIBS)

这是将多个.cpp文件编译成.o然后链接成一个pintool的例子,对于大型的项目来说很有用。OBJDIR也是可以更改的。

Reference

Pin 3.11 User Guide
Intel Pin Tool on Linux 4.0
PinCRT Overview

Pin系列索引

Intel Pin基本用法