Intel PinTools使用笔记——INS_InsertCall()

14 篇文章 0 订阅
4 篇文章 0 订阅

最近想采集某程序访存相关的trace,打算用PinTools。
Pin的使用很多博文已经进行了介绍,本文介绍关于VOID INS_InsertCall (INS ins, IPOINT action, AFUNPTR funptr,...)的相关内容。

以</pin directory>/source/tools/ManualExamples/inscount0为例,该实例生成的.so可用来记录程序运行过程中指令的数量。

/*
 * Copyright 2002-2020 Intel Corporation.
 * 
 * This software is provided to you as Sample Source Code as defined in the accompanying
 * End User License Agreement for the Intel(R) Software Development Products ("Agreement")
 * section 1.L.
 * 
 * This software and the related documents are provided as is, with no express or implied
 * warranties, other than those that are expressly stated in the License.
 */

#include <iostream>
#include <fstream>
#include "pin.H"
using std::cerr;
using std::ofstream;
using std::ios;
using std::string;
using std::endl;

ofstream OutFile;

// The running count of instructions is kept here
// make it static to help the compiler optimize docount
static UINT64 icount = 0;

// This function is called before every instruction is executed
VOID docount() { icount++; }
    
// Pin calls this function every time a new instruction is encountered
VOID Instruction(INS ins, VOID *v)
{
    // Insert a call to docount before every instruction, no arguments are passed
    INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)docount, IARG_END);
}

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

// 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.setf(ios::showbase);
    OutFile << "Count " << icount << endl;
    OutFile.close();
}

/* ===================================================================== */
/* Print Help Message                                                    */
/* ===================================================================== */

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

/* ===================================================================== */
/* Main                                                                  */
/* ===================================================================== */
/*   argc, argv are the entire command line: pin -t <toolname> -- ...    */
/* ===================================================================== */

int main(int argc, char * argv[])
{
    // Initialize pin
    if (PIN_Init(argc, argv)) return Usage();

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

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

    // Register Fini to be called when the application exits
    PIN_AddFiniFunction(Fini, 0);
    
    // Start the program, never returns
    PIN_StartProgram();
    
    return 0;
}

main函数中,PIN_Init是对Pin工具进行了初始化,INS_AddInstrumentFunction(Instruction, 0);调用了函数Instruction,也就按照指令逐条进行,如下

// Pin calls this function every time a new instruction is encountered
VOID Instruction(INS ins, VOID *v)
{
    // Insert a call to docount before every instruction, no arguments are passed
    INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)docount, IARG_END);
}

其中调用了INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)docount, IARG_END);

INS_InsertCall:

VOID INS_InsertCall	(	INS 	ins,
IPOINT 	action,
AFUNPTR 	funptr,
 	... 
)	

该函数的作用是“Insert a call to funptr relative to instruction ins.”
其中的参数

ins: Instruction to instrument(将ins数据结构传入)
action: Specifies before, after, etc.(确定操作发生的时间点)

  • IPOINT_BEFORE is always valid for all instructions.
  • IPOINT_AFTER is valid only when a fall-through exists (i.e. Calls and unconditional branches will fail). It is only allowed when INS_IsValidForIpointAfter(ins) is true.
  • IPOINT_TAKEN_BRANCH is invalid for non-branches. It is only allowed when INS_IsValidForIpointTakenBranch is true.

funptr: Insert a call to funptr
: List of arguments to pass funptr. See IARG_TYPE, terminated with IARG_END。

函数具体使用的方法就是action确定一个操作发生时间例如 IPOINT_BEFORE,下一个参数action是一个自定义的函数,每次INS_InsertCall执行的时候都会触发action的自定义函数例如示例的VOID docount() { icount++; },这个自定义函数还可以传递参数,具体传递的内容由自定义函数后面的IARG_TYPE决定。 如下的例子

VOID printip(VOID *ip) { fprintf(trace, "%p\n", ip); }

// Pin calls this function every time a new instruction is encountered
VOID Instruction(INS ins, VOID *v)
{
    // Insert a call to printip before every instruction, and pass it the IP
    INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)printip, IARG_INST_PTR, IARG_END);
}

该例子添加了参数IARG_INST_PTR,就是返回指令的pc,通过printip的*ip传入。

常用的参数如下:更多参数详见Intel tools官网

IARG_INST_PTR 程序的pcType: ADDRINT. The address of the instrumented instruction. This value does not change at IPOINT_AFTER. This is simply shorthan
IARG_REG_VALUE 寄存器的值Type: ADDRINT for integer registers.
IARG_MEMORYREAD_EA 读内存操作的地址Type: ADDRINT. Effective address of a memory read, only valid if INS_IsMemoryRead is true and at IPOINT_BEFORE.
IARG_MEMORYWRITE_EA 写内存操作的地址Type: ADDRINT. Effective address of a memory write, only valid at IPOINT_BEFORE.
IARG_MEMORYREAD_SIZEType: UINT32. Size in bytes of memory read.
IARG_BRANCH_TAKEN 分支与否Type: BOOL. Non zero if a branch is taken. Argument is invalid for XBEGIN and XEND instructions.
IARG_BRANCH_TARGET_ADDR 分支地址Type: ADDRINT. Target address of branch instruction.
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值