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.
186 lines
5.8 KiB
186 lines
5.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.
|
|
*/
|
|
|
|
/*
|
|
* Check that things work OK with inlined instrumentation which is passed
|
|
* IARG_EXECUTING, IARG_FIRST_REP_ITERATION and IARG_BRANCH_TAKEN.
|
|
* The generation of those IARGs is non-trivial, and I have seen it cause problems...
|
|
*
|
|
* This checks firstly that Pin doesn't assert when we do this,
|
|
* and secondly that we get the same results when we pass the arguments
|
|
* and when we use them in if/then instrumentation.
|
|
*/
|
|
#include "pin.H"
|
|
#include <iostream>
|
|
#include <fstream>
|
|
#include <iomanip>
|
|
#include <stdlib.h>
|
|
using std::setw;
|
|
using std::ofstream;
|
|
using std::string;
|
|
using std::endl;
|
|
|
|
static KNOB<string> KnobOutput(KNOB_MODE_WRITEONCE, "pintool", "o", "checkinline.out", "output file");
|
|
|
|
static ofstream out;
|
|
|
|
static UINT64 predicatedTrueCount = 0;
|
|
static UINT64 firstRepCount = 0;
|
|
|
|
static UINT64 predicatedTrueCountArg = 0;
|
|
static UINT64 firstRepCountArg = 0;
|
|
|
|
struct branchCount_t
|
|
{
|
|
UINT64 taken;
|
|
UINT64 takenArg;
|
|
};
|
|
static branchCount_t branchCounts[XED_ICLASS_LAST];
|
|
|
|
THREADID myThread = INVALID_THREADID;
|
|
|
|
ADDRINT IfMyThread(THREADID threadId)
|
|
{
|
|
return threadId == myThread;
|
|
}
|
|
|
|
|
|
// Trivial analysis routine to pass its argument back in an IfCall so that we can use it
|
|
// to control the next piece of instrumentation.
|
|
// Simple enough to be inlined.
|
|
static ADDRINT returnArg (BOOL arg, THREADID threadId)
|
|
{
|
|
return arg && (threadId == myThread);
|
|
}
|
|
|
|
static VOID increment (UINT64 * counter)
|
|
{
|
|
(*counter)++;
|
|
}
|
|
|
|
static VOID add (UINT64 * counter, BOOL value)
|
|
{
|
|
(*counter) += (value ? 1 : 0);
|
|
}
|
|
|
|
static VOID InstrumentInstruction(INS ins, VOID *)
|
|
{
|
|
if (INS_IsPredicated(ins))
|
|
{
|
|
INS_InsertIfCall(ins, IPOINT_BEFORE, (AFUNPTR)returnArg, IARG_EXECUTING, IARG_THREAD_ID, IARG_END);
|
|
INS_InsertThenCall(ins, IPOINT_BEFORE, (AFUNPTR)increment, IARG_ADDRINT, ADDRINT(&predicatedTrueCount), IARG_END);
|
|
|
|
INS_InsertIfCall(ins, IPOINT_BEFORE, AFUNPTR(IfMyThread), IARG_THREAD_ID, IARG_END);
|
|
INS_InsertThenCall(ins, IPOINT_BEFORE, (AFUNPTR)add, IARG_ADDRINT, ADDRINT(&predicatedTrueCountArg),
|
|
IARG_EXECUTING, IARG_END);
|
|
// CountOp = TRUE;
|
|
}
|
|
|
|
if (INS_HasRealRep(ins))
|
|
{
|
|
INS_InsertIfCall(ins, IPOINT_BEFORE, (AFUNPTR)returnArg, IARG_FIRST_REP_ITERATION, IARG_THREAD_ID, IARG_END);
|
|
INS_InsertThenCall(ins, IPOINT_BEFORE, (AFUNPTR)increment, IARG_ADDRINT, ADDRINT(&firstRepCount), IARG_END);
|
|
|
|
INS_InsertIfCall(ins, IPOINT_BEFORE, AFUNPTR(IfMyThread), IARG_THREAD_ID, IARG_END);
|
|
INS_InsertThenCall(ins, IPOINT_BEFORE, (AFUNPTR)add, IARG_ADDRINT, ADDRINT(&firstRepCountArg),
|
|
IARG_FIRST_REP_ITERATION, IARG_END);
|
|
}
|
|
|
|
if (INS_IsBranch(ins))
|
|
{
|
|
UINT32 op = INS_Opcode(ins);
|
|
|
|
INS_InsertIfCall(ins, IPOINT_BEFORE, (AFUNPTR)returnArg, IARG_BRANCH_TAKEN, IARG_THREAD_ID, IARG_END);
|
|
INS_InsertThenCall(ins, IPOINT_BEFORE, (AFUNPTR)increment,
|
|
IARG_ADDRINT, ADDRINT(&(branchCounts[op].taken)),
|
|
IARG_END);
|
|
|
|
INS_InsertIfCall(ins, IPOINT_BEFORE, AFUNPTR(IfMyThread), IARG_THREAD_ID, IARG_END);
|
|
INS_InsertThenCall(ins, IPOINT_BEFORE, (AFUNPTR)add,
|
|
IARG_ADDRINT, ADDRINT(&(branchCounts[op].takenArg)),
|
|
IARG_BRANCH_TAKEN, IARG_END);
|
|
}
|
|
}
|
|
|
|
static VOID Fini(INT32,VOID *)
|
|
{
|
|
out << " If/Then Arg" << endl;
|
|
out << "True predicated: " << setw(16) << predicatedTrueCount << " " << setw(16) << predicatedTrueCountArg << endl;
|
|
out << "First Rep : " << setw(16) << firstRepCount << " " << setw(16) << firstRepCountArg << endl;
|
|
UINT64 takenTotal = 0;
|
|
UINT64 takenArgTotal = 0;
|
|
for (UINT32 i=0; i<(sizeof(branchCounts)/sizeof(branchCounts[0])); i++)
|
|
{
|
|
takenTotal = takenTotal + branchCounts[i].taken;
|
|
takenArgTotal = takenArgTotal + branchCounts[i].takenArg;
|
|
}
|
|
out << "Branch taken : " << setw(16) << takenTotal << " " << setw(16) << takenArgTotal << endl;
|
|
out << endl;
|
|
|
|
for (UINT32 i=0; i<(sizeof(branchCounts)/sizeof(branchCounts[0])); i++)
|
|
{
|
|
UINT64 taken = branchCounts[i].taken;
|
|
UINT64 takenArg = branchCounts[i].takenArg;
|
|
|
|
if (taken || takenArg)
|
|
{
|
|
string mnemonic = OPCODE_StringShort(i);
|
|
|
|
out << std::setw(20) << std::left << mnemonic << std::right <<
|
|
setw(13) << taken << " " << setw(16) << takenArg;
|
|
if (taken != takenArg)
|
|
out << " <==ERROR==";
|
|
out << endl;
|
|
}
|
|
}
|
|
|
|
if (predicatedTrueCount != predicatedTrueCountArg ||
|
|
firstRepCount != firstRepCountArg ||
|
|
takenTotal != takenArgTotal
|
|
)
|
|
{
|
|
out << "***MISMATCH***" << endl;
|
|
exit(1);
|
|
}
|
|
out.close();
|
|
exit(0);
|
|
}
|
|
|
|
static VOID CheckThreadCount(THREADID threadIndex, CONTEXT *, INT32, VOID *)
|
|
{
|
|
if (myThread == INVALID_THREADID)
|
|
{
|
|
myThread = threadIndex;
|
|
}
|
|
|
|
#ifndef _WIN32
|
|
ASSERT (threadIndex == myThread, "This tool does not handle multiple threads\n");
|
|
#endif
|
|
}
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
PIN_Init(argc, argv);
|
|
|
|
out.open(KnobOutput.Value().c_str());
|
|
|
|
INS_AddInstrumentFunction(InstrumentInstruction, 0);
|
|
|
|
// Fini prints the results.
|
|
PIN_AddFiniFunction(Fini, 0);
|
|
PIN_AddThreadStartFunction(CheckThreadCount, 0);
|
|
|
|
// Never returns
|
|
PIN_StartProgram();
|
|
|
|
return 0;
|
|
}
|