Search code examples
c++instrumentationintel-pin

Cannot use IARG_MEMORYREAD_SIZE on non-standard memory access of instruction at 0x7ffbdcbe4e88: xsave ptr [rsp+0x40]


I'm trying to use Intel Pin for investigating memory activity of an executable. And I tried to use IARG_MEMORYREAD_SIZE parameter. Here is the source code.

#include <iostream>
#include <zlib.h>
#include <set>
#include <stdio.h>
#include <stdlib.h>
#include "pin.H"

using namespace std;

#define LINE_SIZE 50


/* Traces generation parameters*/  
#define WARMUP_WINDOW 100E6
#define RUNNING_WINDOW 200E9
#define REST_WINDOW 3E9

#define NUMBER_OF_WINDOWS 2
#define PREFIX_TRACE "memory_trace_"


enum State
{
    outROI,
    warming,
    running,
    resting,
};


State state;
int nb_windows;
uint64_t cpt_time;
uint64_t accessPhase;
char buffer[LINE_SIZE];

set<int> idThreads;

PIN_LOCK lock;
gzFile trace;

using namespace std;

VOID access(uint64_t pc , uint64_t addr, int type, int size, int id_thread)
{
    PIN_GetLock(&lock, id_thread);

    idThreads.insert(id_thread);

    if(state != outROI)
    {
        if(nb_windows < NUMBER_OF_WINDOWS)
        {

            if(state == resting && accessPhase == REST_WINDOW)
            {
                cout << "PINTOOLS:BEGIN OF INSTRUMENTATION" << endl;
                accessPhase = 0;        
                state = warming;
                std::string trace_str = string(PREFIX_TRACE) + to_string(nb_windows) + ".out";              
                trace = gzopen(trace_str.c_str(), "wb8");
            }
            else if(state == warming && accessPhase == WARMUP_WINDOW)
            {
                cout << "PINTOOLS:END OF WARMUP" << endl;
                state = running;
                accessPhase = 0;
            }
            else if(state == running && accessPhase == RUNNING_WINDOW)
            {
                state = resting;
                accessPhase = 0;

                nb_windows++;
                gzclose(trace);
                cout << "PINTOOLS:END OF INSTRUMENTATION" << endl;
            }


            if(state == running || state == warming)
            {
                sprintf(buffer, "#!0x%lx %d %d %d 0x%lx" , addr , type , size , id_thread, pc);
                gzwrite(trace, buffer, LINE_SIZE);
            }
            accessPhase++;  
        }
        else
        {
            PIN_ExitApplication(0);
        }
        cpt_time++;
    }
    PIN_ReleaseLock(&lock);
}



/* Record Instruction Fetch */
VOID RecordMemInst(VOID* pc, int size, int id_thread)
{
    uint64_t convert_pc = reinterpret_cast<uint64_t>(pc);   
    access(convert_pc , convert_pc , 0 , size , id_thread);
}


/* Record Data Read Fetch */
VOID RecordMemRead(VOID* pc , VOID* addr, int size, int id_thread)
{
    uint64_t convert_pc = reinterpret_cast<uint64_t>(pc);
    uint64_t convert_addr = reinterpret_cast<uint64_t>(addr);
    access(convert_pc , convert_addr , 1 , size , id_thread);
}


/* Record Data Write Fetch */
VOID RecordMemWrite(VOID * pc, VOID * addr, int size, int id_thread)
{
    uint64_t convert_pc = reinterpret_cast<uint64_t>(pc);
    uint64_t convert_addr = reinterpret_cast<uint64_t>(addr);
    access(convert_pc , convert_addr , 2 , size , id_thread);
}

VOID Routine(RTN rtn, VOID *v)
{           
    RTN_Open(rtn);

    for (INS ins = RTN_InsHead(rtn); INS_Valid(ins); ins = INS_Next(ins)){

        INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)RecordMemInst,
            IARG_INST_PTR,
            IARG_UINT32,
            INS_Size(ins),
            IARG_THREAD_ID,
            IARG_END);

            UINT32 memOperands = INS_MemoryOperandCount(ins);   

        for (UINT32 memOp = 0; memOp < memOperands; memOp++){
            if (INS_MemoryOperandIsRead(ins, INS_InsertPredicatedCallmemOp))
            {
                (
                ins, IPOINT_BEFORE, (AFUNPTR)RecordMemRead,
                IARG_INST_PTR,
                IARG_MEMORYOP_EA, memOp,
                IARG_MEMORYREAD_SIZE,
                IARG_THREAD_ID,
                IARG_END);
            }



            if (INS_MemoryOperandIsWritten(ins, memOp))
            {
                INS_InsertPredicatedCall(
                ins, IPOINT_BEFORE, (AFUNPTR)RecordMemWrite,
                IARG_INST_PTR,
                IARG_MEMORYOP_EA, memOp,

/**************************wrong happend here*************************/

                IARG_MEMORYREAD_SIZE,
                IARG_THREAD_ID,
                IARG_END);
            }
        }
    }
    RTN_Close(rtn);
}


VOID Fini(INT32 code, VOID *v)
{
    cout << "PINTOOLS:NB Access " << cpt_time << endl;
    cout << "PINTOOLS:NB Threads " << idThreads.size() << endl;
//  cout << ""
//  if(state != outROI)
//  {
    gzclose(trace); 
//  }

}

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

INT32 Usage()
{
    return -1;
}

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

int main(int argc, char *argv[])
{



    PIN_InitLock(&lock);

    nb_windows=0;
    cpt_time =0;
    accessPhase = 0;

    RTN_AddInstrumentFunction(Routine, 0);

    PIN_AddFiniFunction(Fini, 0);

    state = running;


    PIN_StartProgram();

    return 0;
}

After compilation I am trying to run it by Pin like this:

/home/kolin/cache/pin-2.14-71313-gcc.4.4.7-linux/pin -ifeellucky -injection child -follow-execv -t /home/kolin/cache-simulator-master/utils/pintools-trace-gen/obj-intel64/trace-gen.so -- ../run_base_test_gcc41-64bit.0000/gcc_base.gcc41-64bit cccp.in -o cccp.s

But I received this error:

E: src/trace-gen.cc:161: Cannot use IARG_MEMORYREAD_SIZE on non-standard memory access of instruction at 0x7ffbdcbe4e88: xsave ptr [rsp+0x40].

I've never meet this error before, does anybody have any idea about what am I doing wrong?

(This program is from https://github.com/gvaumour/cache-simulator)


Solution

  • This might fall under the case where you need to use IARG_MULTI_MEMORYACCESS_EA (see the documentation).

    Basically, according to the XSAVE documentation the number of bytes written to the memory pointed by the instruction is not constant and depends on the following factors:

    • The requested-feature bitmap (RFBM)
    • The logical-AND of EDX:EAX
    • The logical-OR of XCR0 with the IA32_XSS MSR

    You can check if you can use IARG_MEMORYREAD_SIZE (constant memory sized instruction) or not with INS_hasKnownMemorySize.

                if (INS_MemoryOperandIsWritten(ins, memOp))
                {
                    // known memory size (standard behavior)
                    if(INS_hasKnownMemorySize(ins)) {
                        INS_InsertPredicatedCall(
                        ins, IPOINT_BEFORE, (AFUNPTR)RecordMemWrite,
                        IARG_INST_PTR,
                        IARG_MEMORYOP_EA, memOp,
                        IARG_MEMORYREAD_SIZE,
                        IARG_THREAD_ID,
                        IARG_END);
                    } else {
                    // multi memory access
                        INS_InsertPredicatedCall(
                        ins, IPOINT_BEFORE, (AFUNPTR)RecordMemWriteMulti, // use another analysis routine
                        IARG_INST_PTR,
                        IARG_MEMORYOP_EA, memOp,
                        IARG_MULTI_MEMORYACCESS_EA, // the analysis routine gets a PIN_MULTI_MEM_ACCESS_INFO*
                        IARG_THREAD_ID,
                        IARG_END);
                    }
                }
    

    The PIN_MULTI_MEM_ACCESS_INFO structure is documented here.