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.

160 lines
4.6 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
* A pin tool that intercepts exception and verifies the exception context.
* It works in pair with the win_exception_context application, that raises two
* exceptions. The context of the second exception should have a predefined FP
* state: all FPn and XMMn registers have value <n> in their first byte.
* This is verified by the tool.
*/
#include <stdio.h>
#include <string>
#include <fstream>
#include <iostream>
#include <memory.h>
#include "pin.H"
using std::ofstream;
using std::cerr;
using std::endl;
using std::string;
/*
* Verify the FP state of the exception context
*/
KNOB<BOOL> KnobCheckFp(KNOB_MODE_WRITEONCE, "pintool", "checkfp", "0", "Check FP state");
KNOB<string> KnobOutputFile(KNOB_MODE_WRITEONCE, "pintool",
"o", "exception_context_monitor_tool.out", "specify file name");
static ofstream* logFile = NULL;
ADDRINT appMainStart = 0;
ADDRINT appMainEnd = 0;
/*!
* Exit with the specified error message
*/
static void Abort(const char * msg)
{
cerr << "Tool: " << msg << endl;
PIN_ExitProcess(1);
}
/*!
* Check to see that FP/XMM registers in the specified context have predefined
* values assigned by the application: FPn and XMMn registers have value <n> in
* their first byte.
*/
static bool CheckMyFpContext(const CONTEXT * pContext)
{
unsigned char fpContextSpaceForXsave[sizeof (FPSTATE)+ FPSTATE_ALIGNMENT];
FPSTATE *fpState=
reinterpret_cast<FPSTATE *>
(( reinterpret_cast<ADDRINT>(fpContextSpaceForXsave) + (FPSTATE_ALIGNMENT - 1)) & (-1*FPSTATE_ALIGNMENT));
PIN_GetContextFPState(pContext, fpState);
for (unsigned i = 0; i < 8; ++i)
{
if (fpState->fxsave_legacy._sts[i]._raw._lo != i)
return false;
if (fpState->fxsave_legacy._sts[i]._raw._hi != 0)
return false;
}
unsigned numXmms = sizeof(fpState->fxsave_legacy._xmms) / sizeof(fpState->fxsave_legacy._xmms[0]);
for (unsigned i = 0; i < numXmms; ++i)
{
if (fpState->fxsave_legacy._xmms[i]._vec64[0] != i)
return false;
if (fpState->fxsave_legacy._xmms[i]._vec64[1] != 0)
return false;
}
return true;
}
static int hadException = FALSE;
static void OnException(THREADID threadIndex,
CONTEXT_CHANGE_REASON reason,
const CONTEXT *ctxtFrom,
CONTEXT *ctxtTo,
INT32 info,
VOID *v)
{
// check if this is an Exception from our app code
ADDRINT exceptionAddr = PIN_GetContextReg(ctxtFrom, REG_INST_PTR);
*logFile << "got exception at address " << hexstr(exceptionAddr) << " reason: " << hexstr(reason) << endl;
if (reason == CONTEXT_CHANGE_REASON_EXCEPTION)
{
if (exceptionAddr < appMainStart || exceptionAddr > appMainEnd) return;
*logFile << "handling exception" << endl;
hadException = TRUE;
static bool first = true;
if (first)
{
*logFile << "first time" << endl;
first = false;
}
else
{
if (KnobCheckFp)
{
*logFile << "tool: checking FP" << endl;
if (!CheckMyFpContext(ctxtFrom)) Abort("Mismatch in the FP context");
}
}
}
}
// Image load callback for the first Pin session
VOID ImageLoad(IMG img, VOID *v)
{
*logFile << "img load " << IMG_Name(img) << endl;
if (IMG_IsMainExecutable(img))
{
RTN mainRtn = RTN_FindByName(img, "main");
if (!RTN_Valid(mainRtn)) Abort("could not find main in application");
appMainStart = RTN_Address(mainRtn);
appMainEnd = RTN_Size(mainRtn) + appMainStart;
*logFile << "main exec range " << hexstr(appMainStart) << "-" << hexstr(appMainEnd) << endl;
}
}
VOID Fini(INT32 code, VOID *v)
{
if (!hadException) Abort("Did not detect exception");
}
int main(INT32 argc, CHAR **argv)
{
if (PIN_Init(argc, argv)) Abort("Invalid arguments");
PIN_InitSymbols();
logFile = new std::ofstream(KnobOutputFile.Value().c_str());
IMG_AddInstrumentFunction(ImageLoad, 0);
PIN_AddContextChangeFunction(OnException, 0);
PIN_AddFiniFunction(Fini, 0);
// Never returns
PIN_StartProgram();
return 0;
}