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.
320 lines
9.5 KiB
320 lines
9.5 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 collects the dynamic counts of the behavior of the traces
|
|
// that are being generated by pin as the application executes.
|
|
|
|
#include "pin.H"
|
|
#include <iostream>
|
|
#include <iomanip>
|
|
#include <fstream>
|
|
#include <map>
|
|
#include <algorithm>
|
|
#include <assert.h>
|
|
using std::dec;
|
|
using std::setw;
|
|
using std::hex;
|
|
using std::endl;
|
|
using std::ofstream;
|
|
using std::map;
|
|
using std::multimap;
|
|
using std::make_pair;
|
|
using std::pair;
|
|
|
|
|
|
/* ================================================================== */
|
|
/* Global Data Structures */
|
|
/* ================================================================== */
|
|
|
|
/* ================================================================== */
|
|
/* Information on every branch in a trace */
|
|
typedef struct BBL_INFO_STRUCT
|
|
{
|
|
UINT32 ins_cnt;
|
|
UINT32 exec_cnt;
|
|
UINT32 code_size;
|
|
UINT32 accum_code_size;
|
|
UINT32 bbl_exit_cnt;
|
|
BBL_INFO_STRUCT() : ins_cnt(0), exec_cnt(0), code_size(0), accum_code_size(0), bbl_exit_cnt(0) {}
|
|
} BBL_INFO;
|
|
typedef map<ADDRINT, BBL_INFO> BBL_MAP;
|
|
|
|
/* ================================================================== */
|
|
/* Information on every trace produced by pin */
|
|
typedef struct TRACE_INFO_STRUCT
|
|
{
|
|
UINT32 exec_cnt;
|
|
UINT32 bbl_cnt;
|
|
UINT32 ins_cnt;
|
|
UINT32 fall_cnt;
|
|
|
|
BBL_MAP bbl_info;
|
|
TRACE_INFO_STRUCT() : exec_cnt(0), bbl_cnt(0), ins_cnt(0), fall_cnt(0) {}
|
|
} TRACE_INFO;
|
|
typedef multimap <ADDRINT, TRACE_INFO> TRACE_MAP;
|
|
|
|
/* ================================================================== */
|
|
TRACE_MAP Trace_Information;
|
|
ofstream OutFile ("traceusage.trace");
|
|
|
|
/* ================================================================== */
|
|
/*
|
|
Inc. the counter for a trace when the trace is short and results
|
|
in the program falling off the trace and into a new trace
|
|
*/
|
|
VOID TraceFall_Info(ADDRINT trace_addr)
|
|
{
|
|
TRACE_MAP::iterator tr_it = Trace_Information.find(trace_addr);
|
|
|
|
assert( tr_it == Trace_Information.end() );
|
|
|
|
TRACE_INFO& tr_info = tr_it->second;
|
|
tr_info.fall_cnt++;
|
|
}
|
|
|
|
/* ================================================================== */
|
|
/*
|
|
Insert a new bbl record into the trace record
|
|
*/
|
|
VOID Bbl_Info(ADDRINT bbl_addr, UINT32 ins_cnt, ADDRINT trace_addr, UINT32 code_size, UINT32 accum_code_size)
|
|
{
|
|
TRACE_MAP::iterator tr_it = Trace_Information.find(trace_addr);
|
|
|
|
assert( tr_it != Trace_Information.end() );
|
|
|
|
TRACE_INFO& tr_info = tr_it->second;
|
|
BBL_MAP& Bbl_Information = tr_info.bbl_info;
|
|
BBL_MAP::iterator bbl_it = Bbl_Information.find(bbl_addr);
|
|
|
|
if (bbl_it == Bbl_Information.end())
|
|
{
|
|
BBL_INFO bbl_info;
|
|
bbl_info.ins_cnt = ins_cnt;
|
|
bbl_info.code_size = code_size;
|
|
bbl_info.accum_code_size = accum_code_size;
|
|
bbl_info.exec_cnt = 0;
|
|
bbl_info.bbl_exit_cnt = 0;
|
|
|
|
Bbl_Information.insert(make_pair(bbl_addr, bbl_info));
|
|
}
|
|
}
|
|
|
|
/* ================================================================== */
|
|
/*
|
|
Insert/Inc. the usage of bbls and the exit status of a bbl
|
|
*/
|
|
VOID BblExit_Info(ADDRINT bbl_addr, ADDRINT trace_addr)
|
|
{
|
|
TRACE_MAP::iterator tr_it = Trace_Information.find(trace_addr);
|
|
|
|
assert( tr_it != Trace_Information.end() );
|
|
|
|
TRACE_INFO& tr_info = tr_it->second;
|
|
BBL_MAP& Bbl_Information = tr_info.bbl_info;
|
|
|
|
BBL_MAP::iterator bbl_it = Bbl_Information.begin();
|
|
for (; bbl_it != Bbl_Information.end(); bbl_it++)
|
|
{
|
|
BBL_INFO& bbl_info = bbl_it->second;
|
|
|
|
/* Inc usage of every bbl above the exit bbl for it is utilized */
|
|
bbl_info.exec_cnt++;
|
|
|
|
/* The exit bbl itself */
|
|
if (bbl_addr == bbl_it->first)
|
|
{
|
|
bbl_info.bbl_exit_cnt++;
|
|
return;
|
|
}
|
|
}
|
|
|
|
assert( bbl_it != Bbl_Information.end() );
|
|
}
|
|
|
|
/* ================================================================== */
|
|
/*
|
|
Insert/Inc. the usage of a trace
|
|
*/
|
|
VOID Trace_Info(ADDRINT trace_addr, UINT32 bbl_cnt, UINT32 ins_cnt)
|
|
{
|
|
TRACE_MAP::iterator it = Trace_Information.find(trace_addr);
|
|
|
|
// First visit
|
|
if (it == Trace_Information.end())
|
|
{
|
|
TRACE_INFO tr_info;
|
|
tr_info.bbl_cnt = bbl_cnt;
|
|
tr_info.ins_cnt = ins_cnt;
|
|
tr_info.exec_cnt = 0;
|
|
|
|
Trace_Information.insert( make_pair(trace_addr, tr_info) );
|
|
}
|
|
else
|
|
{
|
|
it->second.exec_cnt++;
|
|
}
|
|
}
|
|
|
|
/* ================================================================== */
|
|
/*
|
|
Instrumentation function;
|
|
Track the trace, the usage of the code in the bbls and the bbl exits
|
|
*/
|
|
VOID Trace(TRACE trace, VOID *v)
|
|
{
|
|
/* Add trace to db */
|
|
Trace_Info(TRACE_Address(trace),
|
|
TRACE_NumBbl(trace),
|
|
TRACE_NumIns(trace));
|
|
|
|
/* Inc. trace execution count */
|
|
TRACE_InsertCall(trace, IPOINT_BEFORE,
|
|
(AFUNPTR) Trace_Info,
|
|
IARG_ADDRINT, TRACE_Address(trace),
|
|
IARG_UINT32, TRACE_NumBbl(trace),
|
|
IARG_UINT32, TRACE_NumIns(trace),
|
|
IARG_END);
|
|
|
|
USIZE accum_code_size = 0;
|
|
for (BBL bbl = TRACE_BblHead(trace); BBL_Valid(bbl); bbl = BBL_Next(bbl))
|
|
{
|
|
accum_code_size += BBL_Size(bbl);
|
|
|
|
/* Add bbl to db */
|
|
Bbl_Info(BBL_Address(bbl),
|
|
BBL_NumIns(bbl),
|
|
TRACE_Address(trace),
|
|
BBL_Size(bbl),
|
|
accum_code_size);
|
|
|
|
INS ins = BBL_InsTail(bbl);
|
|
|
|
if (INS_IsValidForIpointTakenBranch(ins))
|
|
{
|
|
/* Inc. bbl exit count */
|
|
INS_InsertCall(ins, IPOINT_TAKEN_BRANCH,
|
|
(AFUNPTR) BblExit_Info,
|
|
IARG_ADDRINT, BBL_Address(bbl),
|
|
IARG_ADDRINT, TRACE_Address(trace),
|
|
IARG_END);
|
|
}
|
|
}
|
|
|
|
/* Trace falloff in the case the bbl is too big and does not
|
|
necessarily end with a bbl terminating op */
|
|
INS ins = BBL_InsTail(TRACE_BblTail(trace));
|
|
if (!INS_IsControlFlow(ins))
|
|
{
|
|
/* Inc. trace falloff exit count */
|
|
INS_InsertCall(ins, IPOINT_BEFORE,
|
|
(AFUNPTR) TraceFall_Info,
|
|
IARG_ADDRINT, TRACE_Address(trace),
|
|
IARG_END);
|
|
}
|
|
}
|
|
|
|
/* ================================================================== */
|
|
/*
|
|
Print bbl exit info
|
|
*/
|
|
VOID PrintBblExit(pair<const ADDRINT, BBL_INFO> bbl_info)
|
|
{
|
|
OutFile << hex << "0x" << bbl_info.first << "\t"
|
|
<< setw(5)
|
|
<< dec << bbl_info.second.exec_cnt << "\t"
|
|
<< setw(5)
|
|
<< dec << bbl_info.second.ins_cnt << "\t"
|
|
<< setw(5)
|
|
<< dec << bbl_info.second.bbl_exit_cnt << "\t"
|
|
<< setw(5)
|
|
<< dec << bbl_info.second.code_size << "\t"
|
|
<< setw(5)
|
|
<< dec << bbl_info.second.accum_code_size << "\t"
|
|
<< endl;
|
|
}
|
|
|
|
/* ================================================================== */
|
|
/*
|
|
Print a trace
|
|
*/
|
|
VOID PrintTrace(pair<const ADDRINT, TRACE_INFO> trace_info)
|
|
{
|
|
/* Trace information */
|
|
OutFile << "==================================================================" << endl;
|
|
OutFile << "Trace:" << "\t"
|
|
<< setw(10)
|
|
<< "# Exe"<< "\t"
|
|
<< setw(5)
|
|
<< "# Bbl"<< "\t"
|
|
<< setw(5)
|
|
<< "# Ins"<< "\t"
|
|
<< endl;
|
|
OutFile << "==================================================================" << endl;
|
|
|
|
OutFile << hex << "0x" << trace_info.first << "\t"
|
|
<< setw(5)
|
|
<< dec << trace_info.second.exec_cnt << "\t"
|
|
<< setw(5)
|
|
<< dec << trace_info.second.bbl_cnt << "\t"
|
|
<< setw(5)
|
|
<< dec << trace_info.second.ins_cnt << "\t"
|
|
<< endl << endl;
|
|
|
|
/* Bbl information */
|
|
OutFile << "------------------------------------------------------------------" << endl;
|
|
OutFile << "Bbl:" << "\t"
|
|
<< setw(10)
|
|
<< "# Exe" << "\t"
|
|
<< setw(5)
|
|
<< "# Ins" << "\t"
|
|
<< setw(5)
|
|
<< "Exit" << "\t"
|
|
<< setw(5)
|
|
<< "Size" << "\t"
|
|
<< setw(5)
|
|
<< "ASize" << "\t"
|
|
<< endl;
|
|
OutFile << "------------------------------------------------------------------" << endl;
|
|
|
|
BBL_MAP& Bbl_Information = trace_info.second.bbl_info;
|
|
|
|
/* Bbl exit information */
|
|
for_each(Bbl_Information.begin(), Bbl_Information.end(), PrintBblExit);
|
|
|
|
OutFile << endl << endl;
|
|
}
|
|
|
|
/* ================================================================== */
|
|
/*
|
|
Output the trace usage to a file
|
|
*/
|
|
VOID DumpTraceInfo(INT32 code, VOID *v)
|
|
{
|
|
for_each(Trace_Information.begin(), Trace_Information.end(), PrintTrace);
|
|
}
|
|
|
|
/* ================================================================== */
|
|
/*
|
|
Initialize and begin program execution under the control of Pin
|
|
*/
|
|
int main(INT32 argc, CHAR **argv)
|
|
{
|
|
PIN_Init(argc, argv);
|
|
|
|
TRACE_AddInstrumentFunction(Trace, 0);
|
|
|
|
PIN_AddFiniFunction(DumpTraceInfo, 0);
|
|
|
|
PIN_StartProgram();
|
|
|
|
return 0;
|
|
}
|