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.
191 lines
4.9 KiB
191 lines
4.9 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 file contains an ISA-portable PIN tool for tracing instructions
|
|
*/
|
|
|
|
|
|
|
|
#include <iostream>
|
|
#include <iomanip>
|
|
#include <fstream>
|
|
#include <map>
|
|
#include <unistd.h>
|
|
#include "pin.H"
|
|
using std::setw;
|
|
using std::cerr;
|
|
using std::string;
|
|
using std::endl;
|
|
|
|
/* ===================================================================== */
|
|
/* Commandline Switches */
|
|
/* ===================================================================== */
|
|
|
|
KNOB<string> KnobOutputFile(KNOB_MODE_WRITEONCE, "pintool",
|
|
"o", "jumpmix.out", "specify profile file name");
|
|
|
|
KNOB<BOOL> KnobPid(KNOB_MODE_WRITEONCE, "pintool",
|
|
"i", "0", "append pid to output");
|
|
|
|
/* ===================================================================== */
|
|
/* Print Help Message */
|
|
/* ===================================================================== */
|
|
|
|
static INT32 Usage()
|
|
{
|
|
cerr << "This pin tool collects a profile of jump/branch/call instructions for an application\n";
|
|
|
|
cerr << KNOB_BASE::StringKnobSummary();
|
|
|
|
cerr << endl;
|
|
return -1;
|
|
}
|
|
|
|
/* ===================================================================== */
|
|
/* Global Variables */
|
|
/* ===================================================================== */
|
|
|
|
|
|
|
|
class COUNTER
|
|
{
|
|
public:
|
|
UINT64 _call;
|
|
UINT64 _call_indirect;
|
|
UINT64 _return;
|
|
UINT64 _syscall;
|
|
UINT64 _branch;
|
|
UINT64 _branch_indirect;
|
|
|
|
COUNTER() : _call(0),_call_indirect(0), _return(0), _branch(0), _branch_indirect(0) {}
|
|
|
|
UINT64 Total()
|
|
{
|
|
return _call + _call_indirect + _return + _syscall + _branch + _branch_indirect;
|
|
}
|
|
};
|
|
|
|
COUNTER CountSeen;
|
|
COUNTER CountTaken;
|
|
|
|
|
|
#define INC(what) VOID inc ## what (INT32 taken) { CountSeen. what ++; if( taken) CountTaken. what ++;}
|
|
|
|
INC(_call)
|
|
INC(_call_indirect)
|
|
INC(_branch)
|
|
INC(_branch_indirect)
|
|
INC(_syscall)
|
|
INC(_return)
|
|
|
|
|
|
|
|
|
|
/* ===================================================================== */
|
|
|
|
VOID Instruction(INS ins, void *v)
|
|
{
|
|
if( INS_IsRet(ins) )
|
|
{
|
|
INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR) inc_return, IARG_BRANCH_TAKEN, IARG_END);
|
|
}
|
|
else if( INS_IsSyscall(ins) )
|
|
{
|
|
INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR) inc_syscall, IARG_BRANCH_TAKEN, IARG_END);
|
|
}
|
|
else if (INS_IsDirectControlFlow(ins))
|
|
{
|
|
if( INS_IsCall(ins) )
|
|
INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR) inc_call, IARG_BRANCH_TAKEN, IARG_END);
|
|
else
|
|
INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR) inc_branch, IARG_BRANCH_TAKEN, IARG_END);
|
|
}
|
|
else if( INS_IsIndirectControlFlow(ins) )
|
|
{
|
|
if( INS_IsCall(ins) )
|
|
INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR) inc_call_indirect, IARG_BRANCH_TAKEN, IARG_END);
|
|
else
|
|
INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR) inc_branch_indirect, IARG_BRANCH_TAKEN, IARG_END);
|
|
}
|
|
|
|
}
|
|
|
|
/* ===================================================================== */
|
|
|
|
#define OUT(n, a, b) *out << n << " " << a << setw(16) << CountSeen. b << " " << setw(16) << CountTaken. b << endl
|
|
|
|
static std::ofstream* out = 0;
|
|
|
|
VOID Fini(int n, void *v)
|
|
{
|
|
SetAddress0x(1);
|
|
|
|
|
|
*out << "# JUMPMIX\n";
|
|
*out << "#\n";
|
|
*out << "# $dynamic-counts\n";
|
|
*out << "#\n";
|
|
|
|
|
|
|
|
*out << "4000 *total " << setw(16) << CountSeen.Total() << " " << setw(16) << CountTaken.Total() << endl;
|
|
|
|
|
|
OUT(4010, "call ",_call);
|
|
OUT(4011, "indirect-call ",_call_indirect);
|
|
OUT(4012, "branch ",_branch);
|
|
OUT(4013, "indirect-branch ",_branch_indirect);
|
|
OUT(4014, "syscall ",_syscall);
|
|
OUT(4015, "return ",_return);
|
|
|
|
*out << "#\n";
|
|
*out << "# eof\n";
|
|
out->close();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ===================================================================== */
|
|
/* Main */
|
|
/* ===================================================================== */
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
|
|
if( PIN_Init(argc,argv) )
|
|
{
|
|
return Usage();
|
|
}
|
|
|
|
string filename = KnobOutputFile.Value();
|
|
if (KnobPid)
|
|
{
|
|
filename += "." + decstr(getpid());
|
|
}
|
|
out = new std::ofstream(filename.c_str());
|
|
|
|
|
|
INS_AddInstrumentFunction(Instruction, 0);
|
|
PIN_AddFiniFunction(Fini, 0);
|
|
|
|
// Never returns
|
|
|
|
PIN_StartProgram();
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* ===================================================================== */
|
|
/* eof */
|
|
/* ===================================================================== */
|