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.
200 lines
6.0 KiB
200 lines
6.0 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 is meant to run on the application "pc-change-async.cpp".
|
|
*/
|
|
|
|
#include <iostream>
|
|
#include <cstdlib>
|
|
#include "pin.H"
|
|
|
|
BOOL FoundBreakpointFunction = FALSE;
|
|
BOOL FoundBreakpointLocation = FALSE;
|
|
BOOL FoundOneFunction = FALSE;
|
|
BOOL FoundTwoFunction = FALSE;
|
|
BOOL FoundOneRtn = FALSE;
|
|
BOOL AllowBreakpoint = FALSE;
|
|
|
|
ADDRINT BreakpointFunction;
|
|
ADDRINT BreakpointLocation;
|
|
ADDRINT OneFunction;
|
|
ADDRINT TwoFunction;
|
|
|
|
PIN_LOCK Lock;
|
|
|
|
|
|
static VOID OnImage(IMG, VOID *);
|
|
static VOID InstrumentRtn(RTN rtn, VOID *);
|
|
static VOID AtOne();
|
|
static BOOL Intercept(THREADID, DEBUGGING_EVENT, CONTEXT *, VOID *);
|
|
static VOID OnExit(INT32, VOID *);
|
|
|
|
|
|
int main(int argc, char * argv[])
|
|
{
|
|
PIN_Init(argc, argv);
|
|
PIN_InitSymbols();
|
|
PIN_InitLock(&Lock);
|
|
|
|
IMG_AddInstrumentFunction(OnImage, 0);
|
|
RTN_AddInstrumentFunction(InstrumentRtn, 0);
|
|
PIN_InterceptDebuggingEvent(DEBUGGING_EVENT_BREAKPOINT, Intercept, 0);
|
|
PIN_InterceptDebuggingEvent(DEBUGGING_EVENT_ASYNC_BREAK, Intercept, 0);
|
|
PIN_AddFiniFunction(OnExit, 0);
|
|
PIN_StartProgram();
|
|
return 0;
|
|
}
|
|
|
|
|
|
static VOID OnImage(IMG img, VOID *)
|
|
{
|
|
for (SYM sym = IMG_RegsymHead(img); SYM_Valid(sym); sym = SYM_Next(sym))
|
|
{
|
|
if (SYM_Name(sym) == "Breakpoint")
|
|
{
|
|
FoundBreakpointFunction = TRUE;
|
|
BreakpointFunction = SYM_Address(sym);
|
|
}
|
|
if (SYM_Name(sym) == "BreakpointLocation")
|
|
{
|
|
FoundBreakpointLocation = TRUE;
|
|
BreakpointLocation = SYM_Address(sym);
|
|
}
|
|
if (SYM_Name(sym) == "One")
|
|
{
|
|
FoundOneFunction = TRUE;
|
|
OneFunction = SYM_Address(sym);
|
|
}
|
|
if (SYM_Name(sym) == "Two")
|
|
{
|
|
FoundTwoFunction = TRUE;
|
|
TwoFunction = SYM_Address(sym);
|
|
}
|
|
}
|
|
}
|
|
|
|
static VOID InstrumentRtn(RTN rtn, VOID *)
|
|
{
|
|
if (RTN_Name(rtn) == "One")
|
|
{
|
|
RTN_Open(rtn);
|
|
RTN_InsertCall(rtn, IPOINT_BEFORE, AFUNPTR(AtOne), IARG_END);
|
|
FoundOneRtn = TRUE;
|
|
RTN_Close(rtn);
|
|
}
|
|
}
|
|
|
|
|
|
static VOID AtOne()
|
|
{
|
|
if (!AllowBreakpoint)
|
|
{
|
|
PIN_GetLock(&Lock, 1);
|
|
std::cout << "Breakpoint is allowed" << std::endl;
|
|
PIN_ReleaseLock(&Lock);
|
|
}
|
|
|
|
// When the main thread reaches the One() function, allow the child thread to trigger
|
|
// the breakpoint. The main thread will continue executing this instruction in a loop
|
|
// until we intercept the DEBUGGING_EVENT_ASYNC_BREAK event below.
|
|
//
|
|
AllowBreakpoint = TRUE;
|
|
}
|
|
|
|
|
|
static BOOL Intercept(THREADID tid, DEBUGGING_EVENT eventType, CONTEXT *ctxt, VOID *)
|
|
{
|
|
if (eventType == DEBUGGING_EVENT_BREAKPOINT)
|
|
{
|
|
// When the child thread reaches the breakpoint in Breakpoint(), wait for the main
|
|
// thread to reach the One() function. If the main thread is not there yet, squash the
|
|
// breakpoint and move the PC back to the start of the Breakpoint() function. This will
|
|
// delay a while and then re-trigger the breakpoint.
|
|
//
|
|
ADDRINT pc = PIN_GetContextReg(ctxt, REG_INST_PTR);
|
|
if (pc == BreakpointLocation && !AllowBreakpoint)
|
|
{
|
|
PIN_SetContextReg(ctxt, REG_INST_PTR, BreakpointFunction);
|
|
PIN_GetLock(&Lock, 1);
|
|
std::cout << "Squashing breakpoint at 0x" << std::hex << pc << " on thread " << std::dec << tid << std::endl;
|
|
PIN_ReleaseLock(&Lock);
|
|
return FALSE;
|
|
}
|
|
|
|
PIN_GetLock(&Lock, 1);
|
|
std::cout << "Stopping at breakpoint at 0x" << std::hex << pc << " on thread " << std::dec << tid << std::endl;
|
|
PIN_ReleaseLock(&Lock);
|
|
return TRUE;
|
|
}
|
|
|
|
if (eventType == DEBUGGING_EVENT_ASYNC_BREAK)
|
|
{
|
|
// When the child thread triggers the breakpoint, we should be at the One() function.
|
|
// Change the PC to the Two() function, which is the point of this test. We want to
|
|
// make sure Pin properly handles the change of PC in this case.
|
|
//
|
|
ADDRINT pc = PIN_GetContextReg(ctxt, REG_INST_PTR);
|
|
if (pc == OneFunction)
|
|
{
|
|
PIN_SetContextReg(ctxt, REG_INST_PTR, TwoFunction);
|
|
PIN_GetLock(&Lock, 1);
|
|
std::cout << "Changing ASYNC BREAK PC to Two() on thread " << std::dec << tid << std::endl;
|
|
PIN_ReleaseLock(&Lock);
|
|
return TRUE;
|
|
}
|
|
|
|
// If the PC is not at the One() function, the child thread has probably hit some breakpoint
|
|
// other than the one at Breakpoint(). (E.g. an internal breakpoint set by GDB.) Don't
|
|
// change the PC in such a case.
|
|
//
|
|
PIN_GetLock(&Lock, 1);
|
|
std::cout << "ASYNC_BREAK at 0x" << std::hex << pc << " on thread " << std::dec << tid << std::endl;
|
|
PIN_ReleaseLock(&Lock);
|
|
return TRUE;
|
|
}
|
|
|
|
PIN_GetLock(&Lock, 1);
|
|
std::cout << "FAILURE: Unexpected debugging event type" << std::endl;
|
|
PIN_ReleaseLock(&Lock);
|
|
std::exit(1);
|
|
}
|
|
|
|
|
|
static VOID OnExit(INT32, VOID *)
|
|
{
|
|
if (!FoundBreakpointFunction)
|
|
{
|
|
std::cout << "FAILURE: Did not find Breakpoint() SYM" << std::endl;
|
|
std::exit(1);
|
|
}
|
|
if (!FoundBreakpointLocation)
|
|
{
|
|
std::cout << "FAILURE: Did not find BreakpointLocation SYM" << std::endl;
|
|
std::exit(1);
|
|
}
|
|
if (!FoundOneFunction)
|
|
{
|
|
std::cout << "FAILURE: Did not find One() SYM" << std::endl;
|
|
std::exit(1);
|
|
}
|
|
if (!FoundTwoFunction)
|
|
{
|
|
std::cout << "FAILURE: Did not find Two() SYM" << std::endl;
|
|
std::exit(1);
|
|
}
|
|
if (!FoundOneRtn)
|
|
{
|
|
std::cout << "FAILURE: Did not find One() RTN" << std::endl;
|
|
std::exit(1);
|
|
}
|
|
}
|