You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

140 lines
4.2 KiB

/*
* Copyright 2002-2019 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.
*/
/*
* This tool only runs with the application "intercept-app.cpp". It's part
* of a test for PIN_InterceptDebuggingEvent().
*/
#include <iostream>
#include <cstdlib>
#include "pin.H"
#include "memlog.hpp"
using std::string;
static void InstrumentRtn(RTN, VOID *);
static VOID InstrumentIns(INS, VOID *);
static void OnCheckpoint(CONTEXT *);
static void OnMemWrite(ADDRINT, ADDRINT);
static BOOL InterceptBreakpoint(THREADID, DEBUGGING_EVENT, CONTEXT *, VOID *);
static void OnExit(INT32, VOID *);
static BOOL FoundCheckpoint = FALSE;
static BOOL IsCheckpointing = FALSE;
static CONTEXT SavedContext;
static MEMLOG MemLog;
int main(int argc, char * argv[])
{
PIN_Init(argc, argv);
PIN_InitSymbols();
RTN_AddInstrumentFunction(InstrumentRtn, 0);
INS_AddInstrumentFunction(InstrumentIns, 0);
PIN_InterceptDebuggingEvent(DEBUGGING_EVENT_BREAKPOINT, InterceptBreakpoint, 0);
PIN_AddFiniFunction(OnExit, 0);
PIN_StartProgram();
return 0;
}
// When the application executes the Checkpoint() function, we take a snapshot of the
// registers and start recording changes to memory. This allows us to roll the application
// back to the Checkpoint() call later.
//
static void InstrumentRtn(RTN rtn, VOID *)
{
if (RTN_Name(rtn) == "Checkpoint")
{
RTN_Open(rtn);
RTN_InsertCall(rtn, IPOINT_AFTER, AFUNPTR(OnCheckpoint), IARG_CONTEXT, IARG_END);
FoundCheckpoint = TRUE;
RTN_Close(rtn);
}
}
static void InstrumentIns(INS ins, VOID *)
{
if (INS_IsMemoryWrite(ins))
{
INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)OnMemWrite,
IARG_MEMORYWRITE_EA, IARG_MEMORYWRITE_SIZE, IARG_END);
}
}
static void OnCheckpoint(CONTEXT *ctxt)
{
PIN_SaveContext(ctxt, &SavedContext);
IsCheckpointing = TRUE;
}
static VOID OnMemWrite(ADDRINT addr, ADDRINT size)
{
if (IsCheckpointing)
MemLog.Record(addr, size);
}
// This function is called whenever Pin wants to report a breakpoint event to the
// debugger.
//
static BOOL InterceptBreakpoint(THREADID tid, DEBUGGING_EVENT eventType, CONTEXT *ctxt, VOID *)
{
if (eventType != DEBUGGING_EVENT_BREAKPOINT)
{
std::cout << "FAILURE: Wrong event type in InterceptBreakpoint()" << std::endl;
std::exit(1);
}
ADDRINT pc = PIN_GetContextReg(ctxt, REG_INST_PTR);
RTN rtn = RTN_FindByAddress(pc);
string rtnName = RTN_Valid(rtn) ? RTN_Name(rtn) : "<N/A>";
// When the application triggers the breakpoint in Breakpoint1(), squash the breakpoint
// and roll the application back to the Checkpoint() call. The application will NOT stop
// at the breakpoint, and it will immediately resume from Checkpoint().
//
if (rtnName == "Breakpoint1")
{
std::cout << "Intercepting breakpoint #1 at 0x" << std::hex << pc << std::endl;
PIN_SaveContext(&SavedContext, ctxt);
PIN_SetContextReg(ctxt, REG_GAX, 1);
MemLog.Restore();
IsCheckpointing = FALSE;
return FALSE;
}
// When the application triggers the breakpoint in Breakpoint2(), do not squash the
// breakpoint, but change the return value from Breakpoint2(). The application will stop
// in the debugger, and the debugger should see the modified return value.
//
if (rtnName == "Breakpoint2" || rtnName == "Breakpoint2Label")
{
std::cout << "Intercepting breakpoint #2 at 0x" << std::hex << pc << std::endl;
std::cout << "RTN=" << rtnName << std::endl;
PIN_SetContextReg(ctxt, REG_GAX, 1);
return TRUE;
}
std::cout << "Skipping breakpoint at 0x" << std::hex << pc << ", RTN=" << rtnName << std::endl;
return TRUE;
}
static void OnExit(INT32, VOID *)
{
if (!FoundCheckpoint)
{
std::cout << "FAILURE: Couldn't add instrumentation routines" << std::endl;
std::exit(1);
}
}