traceDebug

/*BEGIN_LEGAL 
Intel Open Source License 


Copyright (c) 2002-2012 Intel Corporation. All rights reserved.
 
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:


Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.  Redistributions
in binary form must reproduce the above copyright notice, this list of
conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.  Neither the name of
the Intel Corporation nor the names of its contributors may be used to
endorse or promote products derived from this software without
specific prior written permission.
 
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE INTEL OR
ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
END_LEGAL */


/* ===================================================================== */
/*
  @ORIGINAL_AUTHOR: Robert Cohn
*/


/* ===================================================================== */
/*! @file
 *  This file contains a tool that generates instructions traces with values.
 *  It is designed to help debugging.
 */






#include "pin.H"
#include "instlib.H"
#include "portability.H"
#include <vector>
#include <iostream>
#include <iomanip>
#include <fstream>


using namespace INSTLIB;


/* ===================================================================== */
/* Commandline Switches */
/* ===================================================================== */


KNOB<string> KnobOutputFile(KNOB_MODE_WRITEONCE,         "pintool",
    "o", "debugtrace.out", "trace file");
KNOB<BOOL>   KnobPid(KNOB_MODE_WRITEONCE,                "pintool",
    "i", "0", "append pid to output");
KNOB<THREADID>   KnobWatchThread(KNOB_MODE_WRITEONCE,                "pintool",
    "watch_thread", "-1", "thread to watch, -1 for all");
KNOB<BOOL>   KnobFlush(KNOB_MODE_WRITEONCE,                "pintool",
    "flush", "0", "Flush output after every instruction");
KNOB<BOOL>   KnobSymbols(KNOB_MODE_WRITEONCE,       "pintool",
    "symbols", "1", "Include symbol information");
KNOB<BOOL>   KnobLines(KNOB_MODE_WRITEONCE,       "pintool",
    "lines", "1", "Include line number information");
KNOB<BOOL>   KnobTraceInstructions(KNOB_MODE_WRITEONCE,       "pintool",
    "instruction", "1", "Trace instructions");
KNOB<BOOL>   KnobTraceCalls(KNOB_MODE_WRITEONCE,       "pintool",
    "call", "1", "Trace calls");
KNOB<BOOL>   KnobTraceMemory(KNOB_MODE_WRITEONCE,       "pintool",
    "memory", "1", "Trace memory");
KNOB<BOOL>   KnobSilent(KNOB_MODE_WRITEONCE,       "pintool",
    "silent", "0", "Do everything but write file (for debugging).");
KNOB<BOOL> KnobEarlyOut(KNOB_MODE_WRITEONCE, "pintool", "early_out", "0" , "Exit after tracing the first region.");




/* ===================================================================== */


INT32 Usage()
{
    cerr <<
        "This pin tool collects an instruction trace for debugging\n"
        "\n";


    cerr << KNOB_BASE::StringKnobSummary();


    cerr << endl;


    return -1;
}


/* ===================================================================== */
/* Global Variables */
/* ===================================================================== */


typedef UINT64 COUNTER;


LOCALVAR std::ofstream out;


LOCALVAR INT32 enabled = 0;


LOCALVAR FILTER filter;


LOCALVAR ICOUNT icount;


LOCALFUN BOOL Emit(THREADID threadid)
{
    if (!enabled || 
        KnobSilent || 
        (KnobWatchThread != static_cast<THREADID>(-1) && KnobWatchThread != threadid))
        return false;
    return true;
}


LOCALFUN VOID Flush()
{
    if (KnobFlush)
        out << flush;
}


/* ===================================================================== */


LOCALFUN VOID Fini(int, VOID * v);


LOCALFUN VOID Handler(CONTROL_EVENT ev, VOID *, CONTEXT * ctxt, VOID *, THREADID)
{
    switch(ev)
    {
      case CONTROL_START:
        enabled = 1;
        PIN_RemoveInstrumentation();
#if defined(TARGET_IA32) || defined(TARGET_IA32E)
    // So that the rest of the current trace is re-instrumented.
    if (ctxt) PIN_ExecuteAt (ctxt);
#endif   
        break;


      case CONTROL_STOP:
        enabled = 0;
        PIN_RemoveInstrumentation();
        if (KnobEarlyOut)
        {
            cerr << "Exiting due to -early_out" << endl;
            Fini(0, NULL);
            exit(0);
        }
#if defined(TARGET_IA32) || defined(TARGET_IA32E)
    // So that the rest of the current trace is re-instrumented.
    if (ctxt) PIN_ExecuteAt (ctxt);
#endif   
        break;


      default:
        ASSERTX(false);
    }
}




/* ===================================================================== */


VOID EmitNoValues(THREADID threadid, string * str)
{
    if (!Emit(threadid))
        return;
    
    out
        << *str
        << endl;


    Flush();
}


VOID Emit1Values(THREADID threadid, string * str, string * reg1str, ADDRINT reg1val)
{
    if (!Emit(threadid))
        return;
    
    out
        << *str << " | "
        << *reg1str << " = " << reg1val
        << endl;


    Flush();
}


VOID Emit2Values(THREADID threadid, string * str, string * reg1str, ADDRINT reg1val, string * reg2str, ADDRINT reg2val)
{
    if (!Emit(threadid))
        return;
    
    out
        << *str << " | "
        << *reg1str << " = " << reg1val
        << ", " << *reg2str << " = " << reg2val
        << endl;
    
    Flush();
}


VOID Emit3Values(THREADID threadid, string * str, string * reg1str, ADDRINT reg1val, string * reg2str, ADDRINT reg2val, string * reg3str, ADDRINT reg3val)
{
    if (!Emit(threadid))
        return;
    
    out
        << *str << " | "
        << *reg1str << " = " << reg1val
        << ", " << *reg2str << " = " << reg2val
        << ", " << *reg3str << " = " << reg3val
        << endl;
    
    Flush();
}




VOID Emit4Values(THREADID threadid, string * str, string * reg1str, ADDRINT reg1val, string * reg2str, ADDRINT reg2val, string * reg3str, ADDRINT reg3val, string * reg4str, ADDRINT reg4val)
{
    if (!Emit(threadid))
        return;
    
    out
        << *str << " | "
        << *reg1str << " = " << reg1val
        << ", " << *reg2str << " = " << reg2val
        << ", " << *reg3str << " = " << reg3val
        << ", " << *reg4str << " = " << reg4val
        << endl;
    
    Flush();
}




const UINT32 MaxEmitArgs = 4;


AFUNPTR emitFuns[] = 
{
    AFUNPTR(EmitNoValues), AFUNPTR(Emit1Values), AFUNPTR(Emit2Values), AFUNPTR(Emit3Values), AFUNPTR(Emit4Values)
}; // INS_InsertFunction的插入功能函数,共有四个


/* ===================================================================== */


VOID EmitXMM(THREADID threadid, UINT32 regno, PIN_REGISTER* xmm)
{
    if (!Emit(threadid))
        return;
    out << "\t\t\tXMM" << dec << regno << " := " << setfill('0') << hex;
    out.unsetf(ios::showbase);
    for(int i=0;i<16;i++) {
        if (i==4 || i==8 || i==12)
            out << "_";
        out << setw(2) << (int)xmm->byte[15-i]; // msb on the left as in registers
    }
    out  << setfill(' ') << endl;
    out.setf(ios::showbase);
    Flush();
}


VOID AddXMMEmit(INS ins, IPOINT point, REG xmm_dst) 
{
    INS_InsertCall(ins, point, AFUNPTR(EmitXMM), IARG_THREAD_ID,
                   IARG_UINT32, xmm_dst - REG_XMM0,
                   IARG_REG_CONST_REFERENCE, xmm_dst,
                   IARG_END);
}


VOID AddEmit(INS ins, IPOINT point, string & traceString, UINT32 regCount, REG regs[])   //自定义函数
{
    if (regCount > MaxEmitArgs)  //如果指令改变的通用寄存器和标志寄存器个数大于最大提交参数个数,将寄存器个数改为最大提交参数个数
        regCount = MaxEmitArgs;
    
    IARGLIST args = IARGLIST_Alloc();
    // allocate a container to hold instrumentation arguments.
    for (UINT32 i = 0; i < regCount; i++)
    {
        IARGLIST_AddArguments(args, IARG_PTR, new string(REG_StringShort(regs[i])), IARG_REG_VALUE, regs[i], IARG_END);
//add an argument to an IARGLIST
    }


    INS_InsertCall(ins, point, emitFuns[regCount], IARG_THREAD_ID,
                   IARG_PTR, new string(traceString),
                   IARG_IARGLIST, args,
                   IARG_END);
    // ins, action, funptr
    IARGLIST_Free(args);
}


LOCALVAR VOID *WriteEa[PIN_MAX_THREADS];


VOID CaptureWriteEa(THREADID threadid, VOID * addr)
{
    WriteEa[threadid] = addr;
}


VOID ShowN(UINT32 n, VOID *ea)
{
    out.unsetf(ios::showbase);
    // Print out the bytes in "big endian even though they are in memory little endian.
    // This is most natural for 8B and 16B quantities that show up most frequently.
    // The address pointed to 
    out << std::setfill('0');
    UINT8 b[512];
    UINT8* x;
    if (n > 512)
        x = new UINT8[n];
    else
        x = b;
    PIN_SafeCopy(x,static_cast<UINT8*>(ea),n);    
    for (UINT32 i = 0; i < n; i++)
    {
        out << std::setw(2) <<  static_cast<UINT32>(x[n-i-1]);
        if (((reinterpret_cast<ADDRINT>(ea)+n-i-1)&0x3)==0 && i<n-1)
            out << "_";
    }
    out << std::setfill(' ');
    out.setf(ios::showbase);
    if (n>512)
        delete [] x;
}




VOID EmitWrite(THREADID threadid, UINT32 size)
{
    if (!Emit(threadid))
        return;
    
    out << "                                 Write ";
    
    VOID * ea = WriteEa[threadid];
    
    switch(size)
    {
      case 0:
        out << "0 repeat count" << endl;
        break;
        
      case 1:
        {
            UINT8 x;
            PIN_SafeCopy(&x, static_cast<UINT8*>(ea), 1);
            out << "*(UINT8*)" << ea << " = " << static_cast<UINT32>(x) << endl;
        }
        break;
        
      case 2:
        {
            UINT16 x;
            PIN_SafeCopy(&x, static_cast<UINT16*>(ea), 2);
            out << "*(UINT16*)" << ea << " = " << x << endl;
        }
        break;
        
      case 4:
        {
            UINT32 x;
            PIN_SafeCopy(&x, static_cast<UINT32*>(ea), 4);
            out << "*(UINT32*)" << ea << " = " << x << endl;
        }
        break;
        
      case 8:
        {
            UINT64 x;
            PIN_SafeCopy(&x, static_cast<UINT64*>(ea), 8);
            out << "*(UINT64*)" << ea << " = " << x << endl;
        }
        break;
        
      default:
        out << "*(UINT" << dec << size * 8 << hex << ")" << ea << " = ";
        ShowN(size,ea);
        out << endl;
        break;
    }


    Flush();
}


VOID EmitRead(THREADID threadid, VOID * ea, UINT32 size)
{
    if (!Emit(threadid))
        return;
    
    out << "                                 Read ";


    switch(size)
    {
      case 0:
        out << "0 repeat count" << endl;
        break;
        
      case 1:
        {
            UINT8 x;
            PIN_SafeCopy(&x,static_cast<UINT8*>(ea),1);
            out << static_cast<UINT32>(x) << " = *(UINT8*)" << ea << endl;
        }
        break;
        
      case 2:
        {
            UINT16 x;
            PIN_SafeCopy(&x,static_cast<UINT16*>(ea),2);
            out << x << " = *(UINT16*)" << ea << endl;
        }
        break;
        
      case 4:
        {
            UINT32 x;
            PIN_SafeCopy(&x,static_cast<UINT32*>(ea),4);
            out << x << " = *(UINT32*)" << ea << endl;
        }
        break;
        
      case 8:
        {
            UINT64 x;
            PIN_SafeCopy(&x,static_cast<UINT64*>(ea),8);
            out << x << " = *(UINT64*)" << ea << endl;
        }
        break;
        
      default:
        ShowN(size,ea);
        out << " = *(UINT" << dec << size * 8 << hex << ")" << ea << endl;
        break;
    }


    Flush();
}




LOCALVAR INT32 indent = 0;


VOID Indent()
{
    for (INT32 i = 0; i < indent; i++)
    {
        out << "| ";
    }
}


VOID EmitICount()
{
    out << setw(10) << dec << icount.Count() << hex << " ";
}


VOID EmitDirectCall(THREADID threadid, string * str, INT32 tailCall, ADDRINT arg0, ADDRINT arg1, ADDRINT arg2)
{
    if (!Emit(threadid))
        return;
    
    EmitICount();


    if (tailCall)
    {
        // A tail call is like an implicit return followed by an immediate call
        indent--;
    }
    
    Indent();
    out << *str << "(" << arg0 << ", " << arg1 <<", "<<arg2 << ", ...)" << endl;


    indent++;


    Flush();
}


string FormatAddress(ADDRINT address, RTN rtn)       //参数一个地址,一个trace中第一条指令所在rtn
{
    string s = StringFromAddrint(address); //将int类型地址转化为字符串类型地址
    
    if (KnobSymbols && RTN_Valid(rtn))   // include symbol information , pin -t *.dll -symbol 1,默认值为1
    {
        s += " " + IMG_Name(SEC_Img(RTN_Sec(rtn))) + ":";
//RTN_Sec(rtn)返回routine(rtn是其缩写)所在section
//SEC_Img()   返回section所在img
//IMG_Name    返回img名字
        s += RTN_Name(rtn);
//RTN_Name(rtn):返回routine的名字


        ADDRINT delta = address - RTN_Address(rtn);
//RTN_Address(rtn)返回routine在内存的地址
//指令地址-routine内存地址=delta
        if (delta != 0)
        {
            s += "+" + hexstr(delta, 4);
   //hexstr返回string
        }
    }


    if (KnobLines)  //pin -t *.dll -lines 0:lines的参数,默认为0,即不包含行号信息
    {
        INT32 line;
        string file;
        
        PIN_GetSourceLocation(address, NULL, &line, &file);
// Find the line number, file, column number corresponding(相当,一致的,符合) to a memory address
// windows: Executable/dll has to have program data base(.pdb) file in order to support this API
/*而微软最新的调试信息格式就是PDB(Program Data Base)了。这种调试信息和可执行文件是完全分离的。他记录了很多丰富的信息,同时还提供了调试并继续、增量链接的功能。不过这种调试信息的格式并没有官方的公开文档,要操作它一般只有通过debughelp或者DIA。PDB又分为两种格式,一种是vc6使用的PDB2.0,后来的版本则全是PDB7.0。PDB7.0是不能向下兼容的
*/
        if (file != "")
        {
            s += " (" + file + ":" + decstr(line) + ")"; //将十进制数字转化为对应的string
        }
    }
    return s;
}


VOID EmitIndirectCall(THREADID threadid, string * str, ADDRINT target, ADDRINT arg0, ADDRINT arg1 , ADDRINT arg2)   //不直接call
{
    if (!Emit(threadid))
        return;
    
    EmitICount();
    Indent();
    out << *str;


    PIN_LockClient();
    
    string s = FormatAddress(target, RTN_FindByAddress(target));
    
    PIN_UnlockClient();
    
    out << s << "(" << arg0 << ", " << arg1 << ","<<arg2<<", ...)" << endl;
    indent++;


    Flush();
}


VOID EmitReturn(THREADID threadid, string * str, ADDRINT ret0)
{
    if (!Emit(threadid))
        return;
    
    EmitICount();
    indent--;
    if (indent < 0)
    {
        out << "@@@ return underflow\n";
        indent = 0;
    }
    
    Indent();
    out << *str << " returns: " << ret0 << endl;


    Flush();
}


        
VOID CallTrace(TRACE trace, INS ins)  //instructiontrace的下一个处理函数
{
    if (!KnobTraceCalls) //pin -t *.dll -call 1:参数之一,默认值为1
        return;


    if (INS_IsCall(ins) && !INS_IsDirectBranchOrCall(ins)) //INS_IsCall如果ins为call指令则为真. 
   // INS_IsDirectBranchOrCall(in),如果目标地址是当前地址的偏移或者是立即数,则为真
   // 大致是说call指令如果目标地址不是当前地址的偏移或者立即数,则该指令执行之前调用======EmitIndirectCall()
    {
        // Indirect call
        string s = "Call " + FormatAddress(INS_Address(ins), TRACE_Rtn(trace));
        s += " -> ";


        INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(EmitIndirectCall), IARG_THREAD_ID,  //EmitIndirectCall()
                       IARG_PTR, new string(s), IARG_BRANCH_TARGET_ADDR,
                       IARG_G_ARG0_CALLER, IARG_G_ARG1_CALLER, IARG_G_ARG2_CALLER, IARG_END);    //修改一下下,添加几个参数看看
    }
    else if (INS_IsDirectBranchOrCall(ins))
   //INS_IsDirectBranchOrCall(in),如果目标地址是当前地址的偏移或者是立即数,则为真
    {
        // Is this a tail call?
        RTN sourceRtn = TRACE_Rtn(trace); // return rtn that contains first instruction of trace
        RTN destRtn = RTN_FindByAddress(INS_DirectBranchOrCallTargetAddress(ins));
// return: for direct branches or calls, the target address
// RTN_FindByAddress returns: handle to the found


        if (INS_IsCall(ins)         // conventional call
            || sourceRtn != destRtn // tail call
        )
        {
            BOOL tailcall = !INS_IsCall(ins);
            
            string s = "";
            if (tailcall)
            {
                s += "Tailcall ";
            }
            else
            {
                if( INS_IsProcedureCall(ins) ) //INS_IsProcedureCall: true if ins is a procedure call. This filters out call instructions that are (ab)used for other purposes
                    s += "Call ";
                else
                {
                    s += "PcMaterialization ";
                    tailcall=1;
                }
                
            }


            //s += INS_Mnemonic(ins) + " ";
            
            s += FormatAddress(INS_Address(ins), TRACE_Rtn(trace));
            s += " -> ";


            ADDRINT target = INS_DirectBranchOrCallTargetAddress(ins);
        
            s += FormatAddress(target, RTN_FindByAddress(target));


            INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(EmitDirectCall),    //  EmitDirectCall:
                           IARG_THREAD_ID, IARG_PTR, new string(s), IARG_BOOL, tailcall,
                           IARG_G_ARG0_CALLER, IARG_G_ARG1_CALLER, IARG_G_ARG2_CALLER,IARG_END);
        }
    }
    else if (INS_IsRet(ins))
    {
        RTN rtn =  TRACE_Rtn(trace); //rtn that contains the first instruction of trace
        
#if defined(TARGET_LINUX) && defined(TARGET_IA32)
//        if( RTN_Name(rtn) ==  "_dl_debug_state") return;
        if( RTN_Valid(rtn) && RTN_Name(rtn) ==  "_dl_runtime_resolve") return;
#endif
        string tracestring = "Return " + FormatAddress(INS_Address(ins), rtn);
        INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(EmitReturn),
                       IARG_THREAD_ID, IARG_PTR, new string(tracestring), IARG_G_RESULT0, IARG_END);
    }
}
        


VOID InstructionTrace(TRACE trace, INS ins)   //循环trace每一个bbl,循环bbl每一个ins,对每一个ins进行处理的第一个函数(总共有三个)
{
    if (!KnobTraceInstructions)  //pin -t *.dll -instruction 的输入值,默认为0,如果改为1,则继续执行InstructionTrace函数
        return;
    
    ADDRINT addr = INS_Address(ins); //取出ins指令地址
    ASSERTX(addr);
            
    // Format the string at instrumentation time
    string traceString = "";
    string astring = FormatAddress(INS_Address(ins), TRACE_Rtn(trace));  //从函数名来看,是格式化地址,参数一个为指令地址,一个为:RTN that contains first instruction of trace
    // trace中第一条指令所在RTN
    // what is RTN ????????????????????????????
    // RTN: routine object
    // A RTN represents the functions/routines/procedures typically produced by a compiler for a procedural programming language such as C.
    // instrumentation time and analysis time ?????????????????????????????? 
    for (INT32 length = astring.length(); length < 30; length++)  //该循环应该是调整输出文件格式
    {
        traceString += " ";
    }
    traceString = astring + traceString;
    
    traceString += " " + INS_Disassemble(ins); //机器指令汇编指令


    for (INT32 length = traceString.length(); length < 80; length++)  //应该是调整格式
    {
        traceString += " ";
    }


    INT32 regCount = 0;        //寄存器计数?
    REG regs[20];     //REG: register object
    REG xmm_dst = REG_INVALID(); //返回无效寄存器   
      
    for (UINT32 i = 0; i < INS_MaxNumWRegs(ins); i++)  //INS_MaxNumWRegs返回 maximum number of write operands
    {
        REG x = REG_FullRegName(INS_RegW(ins, i));
// INS_RegW(INS ins, UINT32 n) returns kth write register of instruction x, including implicit(不言明的) writes. eg: stack pointer is written by push on IA-32 architectures.
// REG_FullRegName: 返回reg寄存器全称
        
        if (REG_is_gr(x) // true if reg is a full width general purpose register(通用寄存器)
#if defined(TARGET_IA32)
            || x == REG_EFLAGS  //或者是标志寄存器
#elif defined(TARGET_IA32E)
            || x == REG_RFLAGS
#endif
        )
        {
            regs[regCount] = x;
            regCount++;
        }


        if (REG_is_xmm(x)) // true if reg is a sse register
      //what is sse register ?????????????????????
            xmm_dst = x;
    }


    if (INS_HasFallThrough(ins)) // true: the instruction may execute the "natural" instruction(ie: the one which starts immediately after this one)
 //true for instructions which do not change the control flow(most of ins), or for conditional branches (which may change the control flow, may not) 
 //false: the instruction following the one tested will not be executed next.  
 //false for unconditional branches and calls(where the next instruction to be executed always explicitly specified)
    {
        AddEmit(ins, IPOINT_AFTER, traceString, regCount, regs);
//如果指令流基本不变(或者不变,或者条件跳转不确定),执行上述函数。
    }
    if (INS_IsBranchOrCall(ins)) // true if ins is a Branch or call instruction, includes both direct and indirect instruction types.
    {
        AddEmit(ins, IPOINT_TAKEN_BRANCH, traceString, regCount, regs);
    }


    if (xmm_dst != REG_INVALID()) //REG_INVALID:返回无效寄存器 
    {
        if (INS_HasFallThrough(ins))
            AddXMMEmit(ins, IPOINT_AFTER, xmm_dst);
        if (INS_IsBranchOrCall(ins))
            AddXMMEmit(ins, IPOINT_TAKEN_BRANCH, xmm_dst);
    }   
}


VOID MemoryTrace(INS ins)  //trace函数的第三个功能函数
{
    if (!KnobTraceMemory)  //pin -t *.dll -参数
        return;
    
    if (INS_IsMemoryWrite(ins))  //是否内存写
    {
        INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(CaptureWriteEa), IARG_THREAD_ID, IARG_MEMORYWRITE_EA, IARG_END);


        if (INS_HasFallThrough(ins))
        {
            INS_InsertPredicatedCall(ins, IPOINT_AFTER, AFUNPTR(EmitWrite), IARG_THREAD_ID, IARG_MEMORYWRITE_SIZE, IARG_END);
        }
        if (INS_IsBranchOrCall(ins))
        {
            INS_InsertPredicatedCall(ins, IPOINT_TAKEN_BRANCH, AFUNPTR(EmitWrite), IARG_THREAD_ID, IARG_MEMORYWRITE_SIZE, IARG_END);
        }
    }


    if (INS_HasMemoryRead2(ins))
    {
        INS_InsertPredicatedCall(ins, IPOINT_BEFORE, AFUNPTR(EmitRead), IARG_THREAD_ID, IARG_MEMORYREAD2_EA, IARG_MEMORYREAD_SIZE, IARG_END);
    }


    if (INS_IsMemoryRead(ins) && !INS_IsPrefetch(ins))
    {
        INS_InsertPredicatedCall(ins, IPOINT_BEFORE, AFUNPTR(EmitRead), IARG_THREAD_ID, IARG_MEMORYREAD_EA, IARG_MEMORYREAD_SIZE, IARG_END);
    }
}




/* ===================================================================== */


VOID Trace(TRACE trace, VOID *v)          //TRACE_AddInstrumentFunction参数
{
    if (!filter.SelectTrace(trace))
        return;
    
    if (enabled)
    {
        for (BBL bbl = TRACE_BblHead(trace); BBL_Valid(bbl); bbl = BBL_Next(bbl)) //将trace的每个bbl块进行循环处理
        {
            for (INS ins = BBL_InsHead(bbl); INS_Valid(ins); ins = INS_Next(ins)) //将bbl块的每一条ins进行循环处理
            {
                InstructionTrace(trace, ins);         
    
                CallTrace(trace, ins);
    
                MemoryTrace(ins);
            }
        }
    }
}




/* ===================================================================== */


VOID Fini(int, VOID * v)
{
    out << "# $eof" <<  endl;


    out.close();
}




    
/* ===================================================================== */


static void OnSig(THREADID threadIndex, 
                  CONTEXT_CHANGE_REASON reason, 
                  const CONTEXT *ctxtFrom,
                  CONTEXT *ctxtTo,
                  INT32 sig, 
                  VOID *v)
{
    if (ctxtFrom != 0)
    {
        ADDRINT address = PIN_GetContextReg(ctxtFrom, REG_INST_PTR); 
/*
Get the value of the integer register or fp status/control register in the specified context. Note that fp registers such as fp-stack regs, xmm regs, ymm regs (when running with AVX support), can only read thru the FPSTATE * parameter of the PIN_GetContextFPState function


Parameters:
[in] ctxt context whose register value is requested
[in] reg register whose value is requested. This could be an integer register or a floating point register with integer values, like FP status/control register.
Returns:
value of the register in the specified context
*/
        out << "SIG signal=" << sig << " on thread " << threadIndex
            << " at address " << hex << address << dec << " ";
    }


    switch (reason)
    {
      case CONTEXT_CHANGE_REASON_FATALSIGNAL:
        out << "FATALSIG" << sig;
        break;
      case CONTEXT_CHANGE_REASON_SIGNAL:
        out << "SIGNAL " << sig;
        break;
      case CONTEXT_CHANGE_REASON_SIGRETURN:
        out << "SIGRET";
        break;
   
      case CONTEXT_CHANGE_REASON_APC:
        out << "APC";
        break;


      case CONTEXT_CHANGE_REASON_EXCEPTION:
        out << "EXCEPTION";
        break;


      case CONTEXT_CHANGE_REASON_CALLBACK:
        out << "CALLBACK";
        break;


      default: 
        break;
    }
    out << std::endl;
}


/* ===================================================================== */


LOCALVAR CONTROL control;
LOCALVAR SKIPPER skipper;


/* ===================================================================== */


int main(int argc, CHAR *argv[])
{
    PIN_InitSymbols();


    if( PIN_Init(argc,argv) )
    {
        return Usage();
    }
    
    string filename =  KnobOutputFile.Value();


    if( KnobPid )
    {
        filename += "." + decstr( getpid_portable() );
    }


    // Do this before we activate controllers
    out.open(filename.c_str());
    out << hex << right;
    out.setf(ios::showbase);


    control.CheckKnobs(Handler, 0);
    skipper.CheckKnobs(0);
    
    TRACE_AddInstrumentFunction(Trace, 0);        //重点
    PIN_AddContextChangeFunction(OnSig, 0);       //重点
    //Register a notification function that is called immediately before the application changes context due to receipt of an asynchronous event such as Unix signal or Windows APC.


    PIN_AddFiniFunction(Fini, 0);


    filter.Activate();
    icount.Activate();
    
    // Never returns


    PIN_StartProgram();
    
    return 0;
}


/* ===================================================================== */
/* eof */
/* ===================================================================== */
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值