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.
158 lines
4.6 KiB
158 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.
|
|
*/
|
|
|
|
#include <fstream>
|
|
#include <assert.h>
|
|
#include "pin.H"
|
|
using std::ofstream;
|
|
using std::string;
|
|
using std::endl;
|
|
|
|
/*
|
|
* Demonstrate the multiversioning of traces to support specialization of instrumentation
|
|
*
|
|
* We instrument a procedure with 2 entry points: red and blue. See
|
|
* redblue.s in the same directory. When we enter from red, we create the
|
|
* red version of instrumentation. When we enter from blue, we create the
|
|
* blue version of instrumentation. The procedure has common code that
|
|
* should be instrumented differently depending on whether we are red or
|
|
* blue.
|
|
*
|
|
* When we see the entry point for red, set the versioning so all targets
|
|
* of this trace to red. When we see blue, we set the versioning of targets
|
|
* to blue. When we see a ret, we clear the versioning.
|
|
*
|
|
* At the entry of a trace, we check the versioning and instrument it
|
|
* appropriately.
|
|
*/
|
|
|
|
// A knob for defining the output file name
|
|
KNOB<string> KnobOutputFile(KNOB_MODE_WRITEONCE, "pintool", "o", "special.out",
|
|
"specify file name for special case output");
|
|
|
|
// ofstream object for handling the output.
|
|
ofstream outstream;
|
|
|
|
|
|
ADDRINT redEnter;
|
|
ADDRINT blueEnter;
|
|
ADDRINT commonEnter;
|
|
|
|
char const * redVersion = "red version";
|
|
char const * red2Version = "red2 version";
|
|
char const * blueVersion = "blue version";
|
|
|
|
VOID Emit(char * string)
|
|
{
|
|
outstream << string << endl;
|
|
}
|
|
|
|
VOID Trace(TRACE trace, VOID *v)
|
|
{
|
|
char * version = reinterpret_cast<char*>(TRACE_Version(trace));
|
|
|
|
if (TRACE_Address(trace) == redEnter)
|
|
{
|
|
TRACE_InsertCall(trace, IPOINT_BEFORE, AFUNPTR(Emit), IARG_PTR, "Enter red", IARG_END);
|
|
|
|
// Targets of this trace will have red instrumentation
|
|
BBL_SetTargetVersion(TRACE_BblHead(trace), reinterpret_cast<ADDRINT>(redVersion));
|
|
|
|
// Setting for the 2nd bbl should override previous values
|
|
BBL bbl2 = BBL_Next(TRACE_BblHead(trace));
|
|
ASSERTX(BBL_Valid(bbl2));
|
|
BBL_SetTargetVersion(bbl2, reinterpret_cast<ADDRINT>(red2Version));
|
|
}
|
|
|
|
if (TRACE_Address(trace) == blueEnter)
|
|
{
|
|
TRACE_InsertCall(trace, IPOINT_BEFORE, AFUNPTR(Emit), IARG_PTR, "Enter blue", IARG_END);
|
|
|
|
// Target of this trace will have blue instrumentation
|
|
BBL_SetTargetVersion(TRACE_BblHead(trace), reinterpret_cast<ADDRINT>(blueVersion));
|
|
}
|
|
|
|
if (TRACE_Address(trace) == commonEnter)
|
|
TRACE_InsertCall(trace, IPOINT_BEFORE, AFUNPTR(Emit), IARG_PTR, "Enter common", IARG_END);
|
|
|
|
// A ret from a trace will clear the versioning
|
|
if (version != 0)
|
|
{
|
|
for (BBL bbl = TRACE_BblHead(trace); BBL_Valid(bbl); bbl = BBL_Next(bbl))
|
|
{
|
|
INS tail = BBL_InsTail(bbl);
|
|
if (INS_Valid(tail) && INS_IsRet(tail))
|
|
{
|
|
BBL_SetTargetVersion(bbl, 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
// print the versioning of the trace at runtime
|
|
if (version != 0)
|
|
TRACE_InsertCall(trace, IPOINT_BEFORE, AFUNPTR(Emit), IARG_PTR, version, IARG_END);
|
|
}
|
|
|
|
VOID Fini(INT32 code, VOID *v)
|
|
{
|
|
outstream.close();
|
|
}
|
|
|
|
#if defined(TARGET_MAC)
|
|
const char* red_rtn = "_red";
|
|
const char* blue_rtn = "_blue";
|
|
const char* common_rtn = "_common";
|
|
#else
|
|
const char* red_rtn = "red";
|
|
const char* blue_rtn = "blue";
|
|
const char* common_rtn = "common";
|
|
#endif
|
|
|
|
// Find the entries points
|
|
VOID ImageLoad(IMG img, VOID *v)
|
|
{
|
|
RTN redRtn = RTN_FindByName(img, red_rtn);
|
|
if (RTN_Valid(redRtn))
|
|
redEnter = RTN_Address(redRtn);
|
|
|
|
RTN blueRtn = RTN_FindByName(img, blue_rtn);
|
|
if (RTN_Valid(blueRtn))
|
|
blueEnter = RTN_Address(blueRtn);
|
|
|
|
RTN commonRtn = RTN_FindByName(img, common_rtn);
|
|
if (RTN_Valid(commonRtn))
|
|
commonEnter = RTN_Address(commonRtn);
|
|
}
|
|
|
|
|
|
int main(int argc, char * argv[])
|
|
{
|
|
PIN_InitSymbolsAlt(EXPORT_SYMBOLS);
|
|
|
|
// Initialize pin
|
|
PIN_Init(argc, argv);
|
|
|
|
outstream.open(KnobOutputFile.Value().c_str());
|
|
|
|
// Register Instruction to be called to instrument instructions
|
|
TRACE_AddInstrumentFunction(Trace, 0);
|
|
|
|
// Register Fini to be called when the application exits
|
|
PIN_AddFiniFunction(Fini, 0);
|
|
|
|
IMG_AddInstrumentFunction(ImageLoad, 0);
|
|
|
|
// Start the program, never returns
|
|
PIN_StartProgram();
|
|
|
|
return 0;
|
|
}
|