Intel Pin基礎


參考:http://software.intel.com/sites/landingpage/pintool/docs/62732/Pin/html/

http://blog.nruns.com/blog/2013/10/07/TracingExecutionWithPin-Carlos/

 

Pin is a tool for the instrumentation of programs. It supports the Android*, Linux*, OSX* and Windows* operating systems and executables for the IA-32, Intel(R) 64 and Intel(R) Many Integrated Core architectures.

Pin allows a tool to insert arbitrary code (written in C or C++) in arbitrary places in the executable. The code is added dynamically while the executable is running. This also makes it possible to attach Pin to an already running process.

Pin provides a rich API that abstracts away the underlying instruction set idiosyncracies and allows context information such as register contents to be passed to the injected code as parameters. Pin automatically saves and restores the registers that are overwritten by the injected code so the application continues to work. Limited access to symbol and debug information is available as well.

有點類似於Detours的意義,動態插樁。但是Detours的粒度是函數級別,而Pin的粒度是指令級別。

這也很好理解,Detours是Microsoft開發的,而Pin是Intel開發的。

 

1. 怎樣在Windows下編譯samples of Pintools

可以到http://software.intel.com/en-us/articles/pintool-downloads下載不同的Pin版本。

但是在Windows平台下,自版本56759以后,nmake被改成了make,但是內部仍然調用的cl.exe等工具進行生成,make問題不成功,沒辦法,只好退回49306版本。

 

cd .\source\tools\SimpleExamples
..\nmake TARGET=ia32 tools

 

然后,將

.\ia32\bin
.\source\tools\SimpleExamples\obj-ia32

目錄下的可執行文件拷貝到目標機器上,即可以按照documentation指示的方法來執行pintools了。

 

2. 怎樣編寫自己的pintools

首先需要了解一下回調函數:

Pin提供不同粒度的回調函數,大體上可以分為下面層次:

IMG: Image Object
INS: Instruction Object
SEC: Section Object
RTN: Routine Object
REG: Register Object
TRACE: Single entrance, multiple exit sequence of instructions
BBL: Single entrance, single exit sequence of instructions
SYM: Symbol Object

我們首先編寫一下IMG粒度的回調,用來捕獲加載image的事件。

在\source\tools下面新建一個目錄daniel

結構如下:

-- daniel
| 
 -- daniel.cpp
| 
 -- Nmakefile
|
 -- make.bat

 

1. daniel.cpp

#include "pin.H"
#include "portability.H"
#include <iostream>
#include <fstream>
 
using namespace std;
static std::ofstream* out = 0;
 
static INT32 Usage()
{
    cerr << "Daniel King's test module\n" << endl;
    return -1;
}
 
 
VOID ImageLoad(IMG img, void* v)
{
    *out << "loading image " << IMG_Name(img) << endl;
}
 
 
 
VOID Fini(int n, void *v)
{    
    *out << "## eof\n";
    out->close();
}
 
int main(int argc, char *argv[])
{
    
    if( PIN_Init(argc,argv) )
    {
        return Usage();
    }
    
        
    string filename =  "daniel.out";
    out = new std::ofstream(filename.c_str());
 
    IMG_AddInstrumentFunction(ImageLoad, 0);
    PIN_AddFiniFunction(Fini, 0);
 
    PIN_StartProgram();
    
    return 0;
}

2. Nmakefile

######################################################################################
# This is the NMAKE file for building and testing PIN toos contained in one of the
# subdirectories of the PinTool project or PIN kit. 
#
# For description of targets and options, see Nmakefile in the root directory.  
######################################################################################
 
!if "$(PIN_HOME)"==""
PIN_HOME=..
!endif
 
# Define tools to be buit and tested
######################################################################################
COMMON_TOOLS= daniel.dll
 
# Include building and testing rules from the root Nmakefile. 
######################################################################################
INCLUDE_SUB_RULES=1
!INCLUDE $(PIN_HOME)\Nmakefile 

3. make.bat

..\nmake target=ia32 tools

以后每次添加新的module時,在Nmakefile中添加生成目標,然后執行make.bat就會在obj-ia32目錄下生成目標文件。

測試時,將.\ia32\bin下的pin執行文件,以及剛剛生成的module文件一同拷貝到目標文件夾,編寫run.bat:

pin.exe -t %1 -- %2

 

3. MyPinTool模板

MyPinTool是一個Windows下項目的模板,通過該模板,可以方便地創建自己的項目,並且支持調試。

 

4. PinTool調試

參照第三步的模板建立的工程文件中,都會設置調試程序。

具體如下:

 
Command: .\ia32\bin\pin.exe
Command Arguments: -t $(TargetPath) -- target.exe
Working Directory: $(TargetDir)

在按下F5后,會彈出如下的提示窗口:

image

在Visual Studio IDE中選擇Debug->Attach to process菜單,按提示的pid選擇目標程序,附加到調試器;再到終端窗口下按下Enter鍵,就可以開啟調試了。

 

5. Pintool線程與Application線程

Pintool線程是各種Callback執行的線程,而Application線程是執行應用程序本身的指令,以及通過InsertXXX插入的Instrument指令的線程。

 

那么在Callback中的統計,與InsertXXX生成的Instrument函數中的統計有什么區別?

Callback針對同一位置的代碼塊只統計一次,而InsertXXX是調用了多少次,就統計多少次。

 

那么Callback是否能夠統計完全整個應用程序中的所有代碼塊嗎?估計不能,只是根據執行情況,動態地統計。

 

// Pin calls this function every time a new instruction is encountered
VOID Instruction(INS ins, VOID *v)
{
    RTN rtn = INS_Rtn(ins);
    if (!RTN_Valid(rtn))
    {
        ++insNoRtnDiscoveredCount;
        INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)InsNoRtnCount, IARG_END);
    }
    else if (RTN_IsDynamic(rtn))
    {
        ++insDynamicDiscoveredCount;
        INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)InsDynamicCount, IARG_END);
    }
    else
    {
        ++insNativeDiscoveredCount;
        INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)InsNativeCount, IARG_END);
    }
}

 

6. 粒度的理解

Trace instrumentation lets the Pintool inspect and instrument an executable one trace at a time. Traces usually begin at the target of a taken branch and end with an unconditional branch, including calls and returns. Pin guarantees that a trace is only entered at the top, but it may contain multiple exits. If a branch joins the middle of a trace, Pin constructs a new trace that begins with the branch target. Pin breaks the trace into basic blocks, BBLs. A BBL is a single entrance, single exit sequence of instructions. Branches to the middle of a bbl begin a new trace and hence a new BBL. It is often possible to insert a single analysis call for a BBL, instead of one analysis call for every instruction. Reducing the number of analysis calls makes instrumentation more efficient. Trace instrumentation utilizes the TRACE_AddInstrumentFunction API call.

trace是一個比函數小一級的代碼塊粒度。

trace有如下特征:

6.1 起始

trace由一個branch的目標代碼處起始

6.2 結束

遇到非條件的jmp指令,call指令,以及ret指令結束。

 

因此trace可以包含jcc指令,代表着一個trace可以有多個出口,即trace中的代碼可能會有多條執行路徑,即手冊中所說的“一個入口,多個出口”。

 

trace會在實際執行中不斷地划分,如果trace中包含了子trace,即有其他代碼跳轉到trace中的某個位置,這時需要細分trace.

 

BBL是比trace再小一個級別的代碼塊,它符合“一個入口,一個出口”的特點。

因此,我們可以在實際使用中,將BBL作為代碼塊的最小單位,以減少插樁的次數。

 

在靜態分析代碼方面

代碼段雖然在PE文件中有定義明確的范圍,但是在這個范圍內,仍然是一坨,可以通過export table entry,以及symbol table進行更細粒度的划分,但是許多release版本的可執行文件就不好更加詳細地划分了。

 

怎樣靜態地解析出比單條指令更加粗粒度的代碼塊,比如BBL級別,是一個需要解決的問題。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM