Pintool

1. 基本介绍

1.1 Pin

pin 是 Intel 开发的一个动态二进制插桩工具,提供了丰富的 API 接口,可以监控一些程序运行状态,也可以模拟一些现有处理器不支持的指令。

Pin is a dynamic binary instrumentation framework for the IA-32, x86-64 and MIC instruction-set architectures that enables the creation of dynamic program analysis tools. Some tools built with Pin are Intel® VTune™ Amplifier, Intel® Inspector, Intel® Advisor and Intel® Software Development Emulator (Intel® SDE).

在这里插入图片描述

1.2 Pintool

The tools created using Pin, called Pintools, can be used to perform program analysis on user space applications on Linux*, Windows* and macOS*. As a dynamic binary instrumentation tool, instrumentation is performed at run time on the compiled binary files. Thus, it requires no recompiling of source code and can support instrumenting programs that dynamically generate code.

Pintool 是指经过 Pin 框架开发后的工具,可以用来完成具体的程序分析和仿真验证。
一般来讲,插桩需要两个基本功能:

  1. 插桩代码 —— A mechanism that decides where and what code is inserted
  2. 分析代码 —— The code to execute at insertion points

Pin 提供的 API 的粒度包括:

  1. Trace 粒度:表示一个单入口,多出口指令序列。Pin 经 Trace 分为若干个基本块 BBL,其中一个 BBL 是一个单入口、单出口的指令序列。
TRACE_ADDInstrumentFunction(TRACE_INSTRUMENT_CALLBACK fun, VOID *val);
  1. IMG 粒度:
IMG_AddInstrumentFunction(IMAGECALLBACK fun, VOID *v)
IMG_AddUnloadFunction(IMAGECALLBACK fun, VOID *v)
  1. RTN 粒度:
RTN_AddInstrumentFunction(RTN_INSTRUMENT_CALLBACK fun, VOID *val)
  1. INS 粒度:
INS_AddInstrumentFunction(INS_INSTRUMENT_CALLBACK fun, VOID *val)

2 Pintool 的编写流程

  1. Pin 初始化
  2. 注册回调函数
  3. 启动

2.1 例子

#include <iostream>
#include <fstream>
#include "pin.H"

ofstream OutFile;

KNOB<string> KnobOutputFile(KNOB_MODE_WRITEONCE, "pintool",
    "o", "inscountmt.out", "specify output file name");

PIN_LOCK lock;

INT32 numThreads = 0;
const INT32 MaxNumThreads = 10000;

// The running count of instructions is kept here
// We let each thread's count be in its own data cache line so that
// multiple threads do not contend for the same data cache line.
// This has shown to improve the performance of inscount2_mt by up to 6X
// on SPECOMP2001.
#define PADSIZE 56  // 64byte linesize : 64 - 8
struct THREAD_DATA
{
    UINT64 _count;
    UINT8 _pad[PADSIZE];
};

THREAD_DATA icount[MaxNumThreads];


// This function is called before every block
VOID PIN_FAST_ANALYSIS_CALL docount(ADDRINT c, THREADID tid) { icount[tid]._count += c; }

VOID ThreadStart(THREADID threadid, CONTEXT *ctxt, INT32 flags, VOID *v)
{
    PIN_InitLock(&lock);
    PIN_GetLock(&lock, threadid+1);
    numThreads++;
    PIN_ReleaseLock(&lock);
    
    ASSERT(numThreads <= MaxNumThreads, "Maximum number of threads exceeded\n");
}

// Pin calls this function every time a new basic block is encountered
// It inserts a call to docount
VOID Trace(TRACE trace, VOID *v)
{
    // Visit every basic block  in the trace
    for (BBL bbl = TRACE_BblHead(trace); BBL_Valid(bbl); bbl = BBL_Next(bbl))
    {
        // Insert a call to docount for every bbl, passing the number of instructions.
        // IPOINT_ANYWHERE allows Pin to schedule the call anywhere in the bbl to obtain best performance.
        
        BBL_InsertCall(bbl, IPOINT_ANYWHERE, (AFUNPTR)docount, IARG_FAST_ANALYSIS_CALL, IARG_UINT32, 
                       BBL_NumIns(bbl), IARG_THREAD_ID, IARG_END);
    }
}

// This function is called when the application exits
VOID Fini(INT32 code, VOID *v)
{
    // Write to a file since cout and cerr maybe closed by the application
    OutFile << "Number of threads ever exist = " << numThreads << endl;
    
    for (INT32 t=0; t<numThreads; t++)
    {
        OutFile << "Count[" << decstr(t) << "]= " << icount[t]._count << endl;
    }

    OutFile.close();
}
/* ===================================================================== */
/* Print Help Message                                                    */
/* ===================================================================== */

INT32 Usage()
{
    cerr << "This Pintool counts the number of dynamic instructions executed" << endl;
    cerr << endl << KNOB_BASE::StringKnobSummary() << endl;
    return -1;
}

/* ===================================================================== */
/* Main                                                                  */
/* ===================================================================== */

// argc, argv are the entire command line, including pin -t <toolname> -- ...
int main(int argc, char * argv[])
{
    // Initialize pin
    if (PIN_Init(argc, argv)) return Usage();

    OutFile.open(KnobOutputFile.Value().c_str());

    // Initialize icount[]
    for (INT32 t=0; t<MaxNumThreads; t++)
        icount[t]._count = 0;

    PIN_InitLock(&lock);
    PIN_AddThreadStartFunction(ThreadStart, 0);

    // Register Instruction to be called to instrument instructions
    TRACE_AddInstrumentFunction(Trace, 0);

    // Register Fini to be called when the application exits
    PIN_AddFiniFunction(Fini, 0);

    // Start the program, never returns
    PIN_StartProgram();
    
    return 0;
}

Reference

  1. Pin
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值