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.

171 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.
*/
/*! @file
* This test tool verifies that Pin on Windows correctly handles thread suspension
* and termination system calls. The tool must be run with the "suspend_app_win"
* application.
*/
#include <set>
#include "pin.H"
using std::set;
enum DOFLUSH_STATE
{
DOFLUSH_STATE_NONE,
DOFLUSH_STATE_INSTRUMENTATION,
DOFLUSH_STATE_ANALYSIS,
DOFLUSH_STATE_FLUSH_CALLED
};
static volatile DOFLUSH_STATE flushState = DOFLUSH_STATE_NONE;
static ADDRINT doFlushAddress = 0;
static volatile bool flushHappened = false;
/*!
* RTN analysis routines.
*/
static VOID OnIsToolPresent(ADDRINT addrIsTool)
{
volatile int * pIsTool = reinterpret_cast<volatile int *>(addrIsTool);
// Set the <isTool> flag in the application
*pIsTool = 1;
}
static VOID OnSleepInTool(ADDRINT addrInTool)
{
volatile int * pInTool = reinterpret_cast<volatile int *>(addrInTool);
// Set the <inTool> flag in the application while sleeping (1 second).
*pInTool = 1;
OS_Sleep(1000);
*pInTool = 0;
}
static VOID OnDoFlush()
{
static bool flushVerified = false;
switch (flushState)
{
case DOFLUSH_STATE_NONE:
ASSERTX(0);
break;
case DOFLUSH_STATE_INSTRUMENTATION:
flushState = DOFLUSH_STATE_ANALYSIS;
break;
case DOFLUSH_STATE_ANALYSIS:
flushState = DOFLUSH_STATE_FLUSH_CALLED;
flushVerified = false;
PIN_RemoveInstrumentation();
break;
case DOFLUSH_STATE_FLUSH_CALLED:
ASSERTX(!flushVerified);
ASSERTX(flushHappened);
flushVerified = true;
break;
}
}
static VOID OnCheckFlush(ADDRINT addrCodeCacheFlushed)
{
const unsigned int sleepLimit = 5 * 60 * 1000; // 5 minutes in milliseconds
const unsigned int microSleepDuration = 10;
const unsigned int numMicroSleeps = sleepLimit / microSleepDuration;
for (unsigned int i = 0; i < numMicroSleeps; ++i)
{
if (flushHappened)
{
*reinterpret_cast<volatile int *>(addrCodeCacheFlushed) = 1;
break;
}
OS_Sleep(microSleepDuration);
}
}
/*!
* RTN instrumentation routine.
*/
static VOID InstrumentRoutine(RTN rtn, VOID *)
{
if (RTN_Name(rtn) == "IsToolPresent")
{
RTN_Open(rtn);
RTN_InsertCall(rtn, IPOINT_BEFORE, AFUNPTR(OnIsToolPresent),
IARG_FUNCARG_ENTRYPOINT_VALUE, 0, IARG_END);
RTN_Close(rtn);
}
else if (RTN_Name(rtn) == "SleepInTool")
{
RTN_Open(rtn);
RTN_InsertCall(rtn, IPOINT_BEFORE, AFUNPTR(OnSleepInTool),
IARG_FUNCARG_ENTRYPOINT_VALUE, 0, IARG_END);
RTN_Close(rtn);
}
else if (RTN_Name(rtn) == "DoFlush")
{
RTN_Open(rtn);
RTN_InsertCall(rtn, IPOINT_BEFORE, AFUNPTR(OnDoFlush), IARG_END);
RTN_Close(rtn);
doFlushAddress = RTN_Address(rtn);
}
else if (RTN_Name(rtn) == "CheckFlush")
{
RTN_Open(rtn);
RTN_InsertCall(rtn, IPOINT_BEFORE, AFUNPTR(OnCheckFlush), IARG_FUNCARG_ENTRYPOINT_VALUE, 0, IARG_END);
RTN_Close(rtn);
}
}
static VOID Trace(TRACE trace, VOID *v)
{
if (TRACE_Address(trace) != doFlushAddress) return;
switch (flushState)
{
case DOFLUSH_STATE_NONE:
flushState = DOFLUSH_STATE_INSTRUMENTATION;
break;
case DOFLUSH_STATE_INSTRUMENTATION:
ASSERTX(0);
break;
case DOFLUSH_STATE_ANALYSIS:
flushState = DOFLUSH_STATE_INSTRUMENTATION;
break;
case DOFLUSH_STATE_FLUSH_CALLED:
flushHappened = true;
break;
}
}
/*!
* The main procedure of the tool.
*/
int main(int argc, char *argv[])
{
PIN_InitSymbols();
PIN_Init(argc, argv);
RTN_AddInstrumentFunction(InstrumentRoutine, 0);
TRACE_AddInstrumentFunction(Trace, 0);
PIN_StartProgram();
return 0;
}