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.

293 lines
11 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 counts instructions instrumented and executed per-image in the process
//
#include <stdio.h>
#include <string.h>
#include "pin.H"
#include <map>
using std::make_pair;
using std::pair;
using std::map;
using std::string;
KNOB<string> KnobOutputFile(KNOB_MODE_WRITEONCE, "pintool",
"o", "inscount_per_image.out", "specify file name for inscount_per_image output");
KNOB<BOOL> KnobCountExecutedInstructions(KNOB_MODE_WRITEONCE, "pintool",
"count_exceuted_instructions", "1", "count executed instructions");
const UINT32 MaxNumThreads = 1024;
UINT32 numThreads = 0;
typedef struct {
MemRange memRange;
long long unsigned int numExecutedPerThread[MaxNumThreads];
UINT32 numInstrumented;
char moduleName[1024];
}LoadedModuleInfo;
LoadedModuleInfo unknownModuleInfo;
typedef map<ADDRINT, LoadedModuleInfo, std::less<ADDRINT> > LoadedModuleInfoMap;
LoadedModuleInfoMap loadedModulesInfoMap;
FILE * outFile;
LoadedModuleInfo *AddrInLoadedModules(ADDRINT addr)
{
// first range whose Base() is above the target
LoadedModuleInfoMap::iterator iter = loadedModulesInfoMap.upper_bound(addr);
if ( iter == loadedModulesInfoMap.begin())
{ // all ranges are above addr
return (NULL);
}
iter--;
if (iter->second.memRange.Contains(Addrint2VoidStar(addr)))
{
return (&(iter->second));
}
return (NULL);
}
// Pin calls this function every time a new img is loaded
// It can instrument the image, but this example does not
// Note that imgs (including shared libraries) are loaded lazily
int numTimesLoaded = 0;
VOID ImageLoad(IMG img, VOID *v)
{
fprintf (outFile, "Loading %s, Image id = %d %p %p\n", IMG_Name(img).c_str(), IMG_Id(img), (void *)(IMG_LowAddress(img)), (void *)(IMG_HighAddress(img)));
fflush (outFile);
// maintain record of loaded modules
LoadedModuleInfo loadedModuleInfo;
MemRange memRange((void *)(IMG_LowAddress(img)), (void *)(IMG_HighAddress(img)+1));
loadedModuleInfo.memRange = memRange;
for (UINT32 i=0; i<MaxNumThreads; i++)
{
loadedModuleInfo.numExecutedPerThread[i] = 0;
}
loadedModuleInfo.numInstrumented = 0;
strcpy (loadedModuleInfo.moduleName, IMG_Name(img).c_str());
const pair <const ADDRINT, LoadedModuleInfo>& newpair
= make_pair(IMG_LowAddress(img), loadedModuleInfo);
loadedModulesInfoMap.insert(newpair);
}
// Pin calls this function every time a new img is unloaded
// You can't instrument an image that is about to be unloaded
VOID ImageUnload(IMG img, VOID *v)
{
fprintf(outFile, "Unloading %s\n", IMG_Name(img).c_str());
fflush (outFile);
// Note - removing the image from the loadedModulesInfoMap is not implemented
}
VOID ExecutedBbl (long long unsigned int *ptrToPerThreadExecutionCounter, UINT32 insCountInBbl, THREADID tid)
{
ptrToPerThreadExecutionCounter[tid]+=insCountInBbl;
}
VOID Trace(TRACE trace, VOID *v)
{
long long unsigned int *ptrToPerThreadExecutionCounter;
BBL bblHead = TRACE_BblHead(trace);
INS ins = BBL_InsHead(bblHead);
// first range whose Base() is above the target
LoadedModuleInfoMap::iterator iter = loadedModulesInfoMap.upper_bound(INS_Address(ins));
if ( iter == loadedModulesInfoMap.begin())
{ // all ranges are above addr
unknownModuleInfo.numInstrumented+=BBL_NumIns(bblHead);
ptrToPerThreadExecutionCounter = (unknownModuleInfo.numExecutedPerThread);
}
else
{
iter--;
if (iter->second.memRange.Contains((void *)(INS_Address(ins))))
{
iter->second.numInstrumented+=BBL_NumIns(bblHead);
ptrToPerThreadExecutionCounter = (iter->second.numExecutedPerThread);
}
else
{
unknownModuleInfo.numInstrumented +=BBL_NumIns(bblHead);
ptrToPerThreadExecutionCounter = (unknownModuleInfo.numExecutedPerThread);
}
}
if (KnobCountExecutedInstructions)
{
// Visit every basic block in the trace
for (BBL bbl = TRACE_BblHead(trace); BBL_Valid(bbl); bbl = BBL_Next(bbl))
{
BBL_InsertCall(bbl, IPOINT_ANYWHERE, (AFUNPTR)ExecutedBbl, IARG_PTR, ptrToPerThreadExecutionCounter,
IARG_UINT32, BBL_NumIns(bbl), IARG_THREAD_ID, IARG_END);
}
}
}
// This function is called when the application exits
VOID Fini(INT32 code, VOID *v)
{
LoadedModuleInfoMap::const_iterator iter = loadedModulesInfoMap.begin();
if (KnobCountExecutedInstructions)
{
long long unsigned int totalExecuted = 0;
long long unsigned int totalExecutedInMainExe = 0;
long long unsigned int totalExecutedInSysModules = 0;
long long unsigned int totalExecutedInNonSysModules = 0;
long long unsigned int totalInstrumented = 0;
long long unsigned int totalInstrumentedInMainExe = 0;
long long unsigned int totalInstrumentedInSysModules = 0;
long long unsigned int totalInstrumentedInNonSysModules = 0;
while (iter!=loadedModulesInfoMap.end())
{
fprintf (outFile, "instrumented %d in module %s\n", iter->second.numInstrumented, iter->second.moduleName);
long long unsigned int totalExecutedInModule = 0;
for (UINT32 i=0; i<numThreads; i++)
{
if (iter->second.numExecutedPerThread[i])
{
fprintf (outFile, " executed %llu instructions in thread# %d\n", iter->second.numExecutedPerThread[i], i);
totalExecutedInModule += iter->second.numExecutedPerThread[i];
}
}
fprintf (outFile, " total executed instructions in module %llu\n", totalExecutedInModule);
totalExecuted += totalExecutedInModule;
totalInstrumented += iter->second.numInstrumented;
if (strcmp(".exe", &(iter->second.moduleName[strlen(iter->second.moduleName)-4]))==0)
{
ASSERTX(totalExecutedInMainExe == 0);
totalInstrumentedInMainExe = iter->second.numInstrumented;
totalExecutedInMainExe = totalExecutedInModule;
}
else if (!strstr(iter->second.moduleName, "C:\\Windows")
&& !strstr(iter->second.moduleName, "C:\\WINDOWS")
&& !strstr(iter->second.moduleName, "C:\\ProgramData")
&& !strstr (iter->second.moduleName, "Host Intrusion Prevention"))
{
totalExecutedInNonSysModules += totalExecutedInModule;
totalInstrumentedInNonSysModules += iter->second.numInstrumented;
}
else
{
totalExecutedInSysModules += totalExecutedInModule;
totalInstrumentedInSysModules += iter->second.numInstrumented;
}
iter++;
}
fprintf (outFile, "instrumented %d in module UNKNOWN\n", unknownModuleInfo.numInstrumented);
long long unsigned int totalExecutedInModule = 0;
for (UINT32 i=0; i<numThreads; i++)
{
if (unknownModuleInfo.numExecutedPerThread[i])
{
fprintf (outFile, " executed %llu instructions in thread# %d\n", unknownModuleInfo.numExecutedPerThread[i], i);
totalExecutedInModule += unknownModuleInfo.numExecutedPerThread[i];
}
}
fprintf (outFile, " total executed instructions in module %llu\n", totalExecutedInModule);
totalExecuted += totalExecutedInModule;
totalExecutedInNonSysModules += totalExecutedInModule;
totalInstrumentedInNonSysModules += unknownModuleInfo.numInstrumented;
fprintf (outFile, "\ntotal instrumented instructions %llu\n", totalInstrumented);
fprintf (outFile, " total instrumented instructions in MainExe %llu %3.2f\n", totalInstrumentedInMainExe
,((float)totalInstrumentedInMainExe*100)/(float)totalInstrumented);
fprintf (outFile, " total instrumented instructions in nonSys modules %llu %3.2f\n", totalInstrumentedInNonSysModules
,(float)(totalInstrumentedInNonSysModules*100)/(float)totalInstrumented);
fprintf (outFile, " total instrumented instructions in Sys modules %llu %3.2f\n", totalInstrumentedInSysModules
,((float)totalInstrumentedInSysModules*100)/(float)totalInstrumented);
fprintf (outFile, "\ntotal executed instructions %llu\n", totalExecuted);
fprintf (outFile, " total executed instructions in MainExe %llu %3.2f\n", totalExecutedInMainExe
,((float)totalExecutedInMainExe*100)/(float)totalExecuted);
fprintf (outFile, " total executed instructions in nonSys modules %llu %3.2f\n", totalExecutedInNonSysModules
,(float)(totalExecutedInNonSysModules*100)/(float)totalExecuted);
fprintf (outFile, " total executed instructions in Sys modules %llu %3.2f\n", totalExecutedInSysModules
,((float)totalExecutedInSysModules*100)/(float)totalExecuted);
}
else
{
while (iter!=loadedModulesInfoMap.end())
{
fprintf (outFile, "instrumented %d instructions in module %s\n", iter->second.numInstrumented, iter->second.moduleName);
iter++;
}
fprintf (outFile, "instrumented %d instructions in module UNKNOWN\n", unknownModuleInfo.numInstrumented);
}
fclose(outFile);
}
VOID ThreadStart(THREADID threadid, CONTEXT *ctxt, INT32 flags, VOID *v)
{
numThreads++;
ASSERT(numThreads <= MaxNumThreads, "Maximum number of threads exceeded\n");
}
/* ===================================================================== */
/* Main */
/* ===================================================================== */
int main(int argc, char * argv[])
{
for (UINT32 i=0; i<MaxNumThreads; i++)
{
unknownModuleInfo.numExecutedPerThread[i] = 0;
}
// Initialize symbol processing
PIN_InitSymbols();
// Initialize pin
PIN_Init(argc, argv);
// Initialize the output stream
outFile = fopen(KnobOutputFile.Value().c_str(), "w");
// Register ImageLoad to be called when an image is loaded
IMG_AddInstrumentFunction(ImageLoad, 0);
// Register ImageUnload to be called when an image is unloaded
IMG_AddUnloadFunction(ImageUnload, 0);
// Register Trace to be called to instrument Traces
TRACE_AddInstrumentFunction(Trace, 0);
PIN_AddThreadStartFunction(ThreadStart, 0);
// Register Fini to be called when the application exits
PIN_AddFiniFunction(Fini, 0);
// Start the program, never returns
PIN_StartProgram();
return 0;
}