5

There are four levels of granularity in Pin: routine, instruction and image, trace. Can i specify an limits/area to start and stop inserting instrumentation code. may by like directive like ( # start instrumentation , # end instrumentation ) or some thing like that,

An example:
for( int i=0; i< x; i++) { #startInstrumentation for( ....;.....;.....) { // some code // function call, conditions , loops, .... } #endInstrumentation }
Is there are any way to do this ?

Mos Moh
  • 317
  • 3
  • 15

2 Answers2

5

You can use trace-based instrumentation to do what you want. At the beginning of each trace, check its start address and if it is not in range of interest, avoid adding analysis functions and return immediately from the routine.

It's possible that a trace will begin outside a region of interest but end inside it, or the other way around. If this can happen, you will need to perform more fine grained choice about what to instrument. I would check if this is a real concern before investing an effort.

If you're interested in instrumenting specific routines or images, consider using filter.cpp from InstLib in the kit. An example for use can be found in InstLibExamples.

Now, as for how to target these regions of interest, you have several options. If you have no control over the target binary, you can specify the region in a command line parameter, as a pair of offsets into the image of interest.

If you have control of the binary, you can insert two symbols, that specify the start and end of the rgion of interest, and then iterate over image symbols using the SYM interface.

nitzanms
  • 1,786
  • 12
  • 35
  • But how can i specify the range of interest in a binary file( ofcourse i can specify in high level, but how can i find it in binary file), like how can i find a specific loop (it's start and end )in binary file. – Mos Moh Aug 16 '15 at 07:45
  • Is the issue locating the area of interest in the file or specifying it to pin? – nitzanms Aug 16 '15 at 08:00
  • i want the both, i want from pin to select an area in the application. – Mos Moh Aug 16 '15 at 08:25
  • 1
    See if the paragraphs I added answer your question – nitzanms Aug 16 '15 at 09:44
2

My solution would be:

1) Insert Region Of Interest (ROI) begin and end functions in code

2) Set a flag after ROI begin is executed and unset it before ROI end is executed

3) Return immediately from instrumenting calls if the flat is unset

Here you have an example where I have modified the memory reference trace to trace only a ROI.

#include <stdio.h>
#include "pin.H"
#include <string>

const CHAR * ROI_BEGIN = "__parsec_roi_begin";
const CHAR * ROI_END = "__parsec_roi_end";

FILE * trace;
bool isROI = false;

// Print a memory read record
VOID RecordMemRead(VOID * ip, VOID * addr, CHAR * rtn)
{
    // Return if not in ROI
    if(!isROI)
    {
        return;
    }

    // Log memory access in CSV
    fprintf(trace,"%p,R,%p,%s\n", ip, addr, rtn);
}

// Print a memory write record
VOID RecordMemWrite(VOID * ip, VOID * addr, CHAR * rtn)
{
    // Return if not in ROI
    if(!isROI)
    {
        return;
    }

    // Log memory access in CSV
    fprintf(trace,"%p,W,%p,%s\n", ip, addr, rtn);
}

// Set ROI flag
VOID StartROI()
{
    isROI = true;
}

// Set ROI flag
VOID StopROI()
{
    isROI = false;
}

// Is called for every instruction and instruments reads and writes
VOID Instruction(INS ins, VOID *v)
{
    // Instruments memory accesses using a predicated call, i.e.
    // the instrumentation is called iff the instruction will actually be executed.
    //
    // On the IA-32 and Intel(R) 64 architectures conditional moves and REP 
    // prefixed instructions appear as predicated instructions in Pin.
    UINT32 memOperands = INS_MemoryOperandCount(ins);

    // Iterate over each memory operand of the instruction.
    for (UINT32 memOp = 0; memOp < memOperands; memOp++)
    {
        // Get routine name if valid
        const CHAR * name = "invalid";
        if(RTN_Valid(INS_Rtn(ins))) 
        {
            name = RTN_Name(INS_Rtn(ins)).c_str();
        }

        if (INS_MemoryOperandIsRead(ins, memOp))
        {
            INS_InsertPredicatedCall(
                ins, IPOINT_BEFORE, (AFUNPTR)RecordMemRead,
                IARG_INST_PTR,
                IARG_MEMORYOP_EA, memOp,
                IARG_ADDRINT, name,
                IARG_END);
        }
        // Note that in some architectures a single memory operand can be 
        // both read and written (for instance incl (%eax) on IA-32)
        // In that case we instrument it once for read and once for write.
        if (INS_MemoryOperandIsWritten(ins, memOp))
        {
            INS_InsertPredicatedCall(
                ins, IPOINT_BEFORE, (AFUNPTR)RecordMemWrite,
                IARG_INST_PTR,
                IARG_MEMORYOP_EA, memOp,
                IARG_ADDRINT, name,
                IARG_END);
        }
    }
}

// Pin calls this function every time a new rtn is executed
VOID Routine(RTN rtn, VOID *v)
{
    // Get routine name
    const CHAR * name = RTN_Name(rtn).c_str();

    if(strcmp(name,ROI_BEGIN) == 0) {
        // Start tracing after ROI begin exec
        RTN_Open(rtn);
        RTN_InsertCall(rtn, IPOINT_AFTER, (AFUNPTR)StartROI, IARG_END);
        RTN_Close(rtn);
    } else if (strcmp(name,ROI_END) == 0) {
        // Stop tracing before ROI end exec
        RTN_Open(rtn);
        RTN_InsertCall(rtn, IPOINT_BEFORE, (AFUNPTR)StopROI, IARG_END);
        RTN_Close(rtn);
    }
}

// Pin calls this function at the end
VOID Fini(INT32 code, VOID *v)
{
    fclose(trace);
}

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

INT32 Usage()
{
    PIN_ERROR( "This Pintool prints a trace of memory addresses\n" 
              + KNOB_BASE::StringKnobSummary() + "\n");
    return -1;
}

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

int main(int argc, char *argv[])
{
    // Initialize symbol table code, needed for rtn instrumentation
    PIN_InitSymbols();

    // Usage
    if (PIN_Init(argc, argv)) return Usage();

    // Open trace file and write header
    trace = fopen("roitrace.csv", "w");
    fprintf(trace,"pc,rw,addr,rtn\n");

    // Add instrument functions
    RTN_AddInstrumentFunction(Routine, 0);
    INS_AddInstrumentFunction(Instruction, 0);
    PIN_AddFiniFunction(Fini, 0);

    // Never returns
    PIN_StartProgram();

    return 0;
}