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.
286 lines
7.8 KiB
286 lines
7.8 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 tests that THEN instrumentation is executed correctly.
|
|
*/
|
|
#include <cstdio>
|
|
#include <iostream>
|
|
#include <sstream>
|
|
#include <iomanip>
|
|
#include <fstream>
|
|
#include <cstdlib>
|
|
#include <map>
|
|
|
|
#if defined(TARGET_LINUX)
|
|
#include <unistd.h>
|
|
#include <sys/syscall.h>
|
|
#include <errno.h>
|
|
# ifdef TARGET_IA32E
|
|
# include <asm/prctl.h>
|
|
# include <sys/prctl.h>
|
|
# endif // TARGET_LINUX
|
|
#endif // TARGET_IA32E
|
|
|
|
#include "pin.H"
|
|
#include "instlib.H"
|
|
using std::map;
|
|
|
|
// windows.h must be included after pin.H
|
|
#ifdef TARGET_WINDOWS
|
|
namespace WIND
|
|
{
|
|
#include <windows.h>
|
|
}
|
|
#endif // TARGET_WINDOWS
|
|
|
|
// Knob for specifying if the test is for exception.
|
|
KNOB<int> KnobException(KNOB_MODE_WRITEONCE, "pintool",
|
|
"exception", "0", "specify if the test is for exception");
|
|
|
|
int isException = 0;
|
|
|
|
BOOL x = TRUE;
|
|
ADDRINT curIp = 0;
|
|
ADDRINT curIp2 = 0;
|
|
map<ADDRINT,BOOL> mem;
|
|
|
|
struct THENS_CALLED
|
|
{
|
|
BOOL contextInThenCalled;
|
|
BOOL noContextInThenCalled;
|
|
};
|
|
|
|
typedef std::map<ADDRINT, THENS_CALLED> THENS_CALLED_INFO;
|
|
THENS_CALLED_INFO thensCalledInfo;
|
|
|
|
|
|
const int numInstructionsToInstrument = 1000;
|
|
|
|
|
|
BOOL IfReturnTrue(ADDRINT ip)
|
|
{
|
|
curIp = ip;
|
|
return x;
|
|
}
|
|
|
|
BOOL IfReturnTrue2(ADDRINT ip)
|
|
{
|
|
curIp2 = ip;
|
|
return x;
|
|
}
|
|
|
|
VOID ContextInThen(
|
|
ADDRINT ip,
|
|
CONTEXT * context)
|
|
{
|
|
if (ip != curIp)
|
|
{
|
|
printf ("***Error ContextInThen got ip 0x%lx expected 0x%lx\n", static_cast<unsigned long>(ip), static_cast<unsigned long>(curIp));
|
|
exit(-1);
|
|
}
|
|
if (PIN_GetContextReg( context, REG_INST_PTR )!=ip)
|
|
{
|
|
printf ("***Error ContextInThen argument ip 0x%lx does not match ip in context (0x%lx)\n", static_cast<unsigned long>(ip),
|
|
static_cast<unsigned long>(PIN_GetContextReg( context, REG_INST_PTR )));
|
|
exit(-1);
|
|
}
|
|
THENS_CALLED_INFO::iterator it = thensCalledInfo.find(ip);
|
|
if (it == thensCalledInfo.end())
|
|
{
|
|
printf ("***Error ContextInThen with no record of instrumentation ip 0x%lx\n", static_cast<unsigned long>(ip));
|
|
}
|
|
THENS_CALLED thensCalled = it->second;
|
|
thensCalledInfo.erase(ip);
|
|
thensCalled.contextInThenCalled = TRUE;
|
|
thensCalledInfo.insert(std::make_pair(ip, thensCalled));
|
|
}
|
|
|
|
|
|
VOID NoContextInThen(
|
|
ADDRINT ip)
|
|
{
|
|
if (ip != curIp)
|
|
{
|
|
printf ("***Error NoContextInThen got ip 0x%lx expected curIp 0x%lx\n", static_cast<unsigned long>(ip), static_cast<unsigned long>(curIp));
|
|
exit(-1);
|
|
}
|
|
if (ip != curIp2)
|
|
{
|
|
printf ("***Error NoContextInThen got ip 0x%lx expected curIp2 0x%lx\n", static_cast<unsigned long>(ip), static_cast<unsigned long>(curIp2));
|
|
exit(-1);
|
|
}
|
|
curIp = 0;
|
|
curIp2 = 0;
|
|
THENS_CALLED_INFO::iterator it = thensCalledInfo.find(ip);
|
|
if (it == thensCalledInfo.end())
|
|
{
|
|
printf ("***Error NoContextInThen with no record of instrumentation ip 0x%lx\n", static_cast<unsigned long>(ip));
|
|
}
|
|
THENS_CALLED thensCalled = it->second;
|
|
thensCalledInfo.erase(ip);
|
|
thensCalled.noContextInThenCalled = TRUE;
|
|
thensCalledInfo.insert(std::make_pair(ip, thensCalled));
|
|
}
|
|
|
|
|
|
|
|
INT32 Usage()
|
|
{
|
|
cerr <<
|
|
"This is a test of moving the then sequence to the stub"
|
|
"\n";
|
|
|
|
cerr << endl;
|
|
|
|
return -1;
|
|
}
|
|
|
|
ADDRINT imgStartAdd;
|
|
USIZE imgSize;
|
|
|
|
VOID ImageLoad(IMG img, VOID *v)
|
|
{
|
|
if (IMG_IsMainExecutable(img))
|
|
{
|
|
imgStartAdd = IMG_StartAddress(img);
|
|
imgSize = IMG_SizeMapped(img);
|
|
}
|
|
}
|
|
|
|
|
|
int numInstructionsInstrumented = 0;
|
|
//intruction for noException tests
|
|
VOID Instruction(INS ins, VOID *v)
|
|
{
|
|
if (numInstructionsInstrumented >= numInstructionsToInstrument)
|
|
{
|
|
return;
|
|
}
|
|
THENS_CALLED_INFO::iterator it = thensCalledInfo.find(INS_Address(ins));
|
|
if (it != thensCalledInfo.end())
|
|
{
|
|
return;
|
|
}
|
|
//instrument if ins is app instruction, also not exception test
|
|
if (INS_Address(ins) >= imgStartAdd && INS_Address(ins) < (imgStartAdd + imgSize))
|
|
{
|
|
numInstructionsInstrumented++;
|
|
INS_InsertIfCall(ins, IPOINT_BEFORE, (AFUNPTR)IfReturnTrue,
|
|
IARG_INST_PTR,
|
|
IARG_END);
|
|
INS_InsertThenCall(ins, IPOINT_BEFORE, (AFUNPTR)ContextInThen,
|
|
IARG_INST_PTR,
|
|
IARG_CONTEXT,
|
|
IARG_END);
|
|
|
|
INS_InsertIfCall(ins, IPOINT_BEFORE, (AFUNPTR)IfReturnTrue2,
|
|
IARG_INST_PTR,
|
|
IARG_END);
|
|
INS_InsertThenCall(ins, IPOINT_BEFORE, (AFUNPTR)NoContextInThen,
|
|
IARG_INST_PTR,
|
|
IARG_END);
|
|
THENS_CALLED thensCalled;
|
|
thensCalled.contextInThenCalled = thensCalled.noContextInThenCalled = FALSE;
|
|
thensCalledInfo.insert(std::make_pair(INS_Address(ins), thensCalled));
|
|
}
|
|
}
|
|
|
|
//intruction for Exception tests
|
|
VOID InstructionEx(INS ins, VOID *v)
|
|
{
|
|
if (numInstructionsInstrumented >= numInstructionsToInstrument)
|
|
{
|
|
return;
|
|
}
|
|
THENS_CALLED_INFO::iterator it = thensCalledInfo.find(INS_Address(ins));
|
|
if (it != thensCalledInfo.end())
|
|
{
|
|
return;
|
|
}
|
|
|
|
numInstructionsInstrumented++;
|
|
INS_InsertIfCall(ins, IPOINT_BEFORE, (AFUNPTR)IfReturnTrue,
|
|
IARG_INST_PTR,
|
|
IARG_END);
|
|
INS_InsertThenCall(ins, IPOINT_BEFORE, (AFUNPTR)ContextInThen,
|
|
IARG_INST_PTR,
|
|
IARG_CONTEXT,
|
|
IARG_END);
|
|
|
|
INS_InsertIfCall(ins, IPOINT_BEFORE, (AFUNPTR)IfReturnTrue2,
|
|
IARG_INST_PTR,
|
|
IARG_END);
|
|
INS_InsertThenCall(ins, IPOINT_BEFORE, (AFUNPTR)NoContextInThen,
|
|
IARG_INST_PTR,
|
|
IARG_END);
|
|
THENS_CALLED thensCalled;
|
|
thensCalled.contextInThenCalled = thensCalled.noContextInThenCalled = FALSE;
|
|
thensCalledInfo.insert(std::make_pair(INS_Address(ins), thensCalled));
|
|
}
|
|
|
|
VOID Fini(INT32 code, VOID *v)
|
|
{
|
|
int numTested = 0;
|
|
for (THENS_CALLED_INFO::iterator it = thensCalledInfo.begin(); it != thensCalledInfo.end(); ++it)
|
|
{
|
|
numTested++;
|
|
if (it->second.contextInThenCalled != TRUE)
|
|
{
|
|
printf ("***Error ContextInThen NOT called for instruction at ip 0x%lx\n", static_cast<unsigned long>(it->first));
|
|
exit (-1);
|
|
}
|
|
if (it->second.noContextInThenCalled != TRUE)
|
|
{
|
|
printf ("***Error NoContextInThen NOT called for instruction at ip 0x%lx\n", static_cast<unsigned long>(it->first));
|
|
exit (-1);
|
|
}
|
|
}
|
|
if (numTested != numInstructionsInstrumented)
|
|
{
|
|
printf ("***Error numTested != numInstructionsToInstrument numTested %d numInstructionsToInstrument %d\n",
|
|
numTested, numInstructionsToInstrument);
|
|
exit (-1);
|
|
}
|
|
exit (0);
|
|
}
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
if( PIN_Init(argc,argv) )
|
|
{
|
|
return Usage();
|
|
}
|
|
|
|
isException = KnobException.Value();
|
|
|
|
if (isException)
|
|
{
|
|
INS_AddInstrumentFunction(InstructionEx, NULL);
|
|
}
|
|
else
|
|
{
|
|
INS_AddInstrumentFunction(Instruction, NULL);
|
|
}
|
|
PIN_AddFiniFunction(Fini, NULL);
|
|
|
|
IMG_AddInstrumentFunction(ImageLoad, NULL);
|
|
|
|
// Never returns
|
|
PIN_StartProgram();
|
|
|
|
return 1;
|
|
}
|
|
|
|
/* ===================================================================== */
|
|
/* eof */
|
|
/* ===================================================================== */
|