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.
202 lines
6.1 KiB
202 lines
6.1 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 is an example of the PIN tool that demonstrates some basic PIN APIs
|
|
* and could serve as the starting point for developing your first PIN tool
|
|
*/
|
|
|
|
#include "pin.H"
|
|
#include <iostream>
|
|
#include <fstream>
|
|
#include <stdio.h>
|
|
#include <sched.h>
|
|
|
|
using std::string;
|
|
using std::cout;
|
|
using std::endl;
|
|
using std::cerr;
|
|
/* ================================================================== */
|
|
// Global variables
|
|
/* ================================================================== */
|
|
|
|
UINT64 threadStartCount = 0; //total number of started threads, including main thread
|
|
UINT64 threadCreateCount = 0; //total number of create threads, including main thread
|
|
UINT64 threadFiniCount = 0; //total number of finished threads, including main thread
|
|
|
|
std::ostream * out = &cerr;
|
|
|
|
|
|
#if defined(TARGET_IA32)
|
|
#define SC_clone 120
|
|
#else
|
|
#define SC_clone 56
|
|
#endif
|
|
|
|
/* ===================================================================== */
|
|
// Command line switches
|
|
/* ===================================================================== */
|
|
KNOB<string> KnobOutputFile(KNOB_MODE_WRITEONCE, "pintool",
|
|
"o", "", "specify file name for cpp11Threads output");
|
|
|
|
|
|
/*!
|
|
* Increase counter of threads in the application.
|
|
* This function is called for every thread created by the application when it is
|
|
* about to start running (including the root thread).
|
|
* @param[in] threadIndex ID assigned by PIN to the new thread
|
|
* @param[in] ctxt initial register state for the new thread
|
|
* @param[in] flags thread creation flags (OS specific)
|
|
* @param[in] v value specified by the tool in the
|
|
* PIN_AddThreadStartFunction function call
|
|
*/
|
|
VOID ThreadStart(THREADID threadIndex, CONTEXT *ctxt, INT32 flags, VOID *v)
|
|
{
|
|
threadStartCount++;
|
|
}
|
|
|
|
|
|
VOID ThreadFini(THREADID threadIndex, const CONTEXT *ctxt, INT32 flags, VOID *v)
|
|
{
|
|
threadFiniCount++;
|
|
}
|
|
|
|
enum SYSCALL_SEMANTIC
|
|
{
|
|
SCS_UNKNOWN,
|
|
SCS_EXIT,
|
|
SCS_THREADEXIT,
|
|
SCS_THREADCREATE,
|
|
SCS_EXCEPTIONRETURN /* Signal return on Linux, APC/Callback/Exception on Windows */
|
|
};
|
|
|
|
|
|
BOOL IsVForkOrFork(ADDRINT arg)
|
|
{
|
|
return !(arg & ADDRINT(CLONE_VM|CLONE_THREAD));
|
|
}
|
|
|
|
// Map system calls from pre-system call machine state to semantic.
|
|
// Slightly more general than just using the call number, because the semantic
|
|
// can depend on the arguments too.
|
|
SYSCALL_SEMANTIC GetSyscallSemantic(CONTEXT *ctx, SYSCALL_STANDARD std)
|
|
{
|
|
SYSCALL_SEMANTIC res = SCS_UNKNOWN;
|
|
|
|
switch (PIN_GetSyscallNumber(ctx, std))
|
|
{
|
|
case SC_clone:
|
|
// Check if this is a fork or a thread creation.
|
|
{
|
|
ADDRINT arg0 = PIN_GetSyscallArgument(ctx, std, 0);
|
|
if (IsVForkOrFork(arg0))
|
|
res = SCS_UNKNOWN;
|
|
else
|
|
res = SCS_THREADCREATE;
|
|
break;
|
|
}
|
|
|
|
default: res = SCS_UNKNOWN;
|
|
break;
|
|
}
|
|
return res;
|
|
}
|
|
|
|
VOID SyscallEntry(THREADID pin_tid, CONTEXT *ctxt, SYSCALL_STANDARD std, VOID *v)
|
|
{
|
|
|
|
SYSCALL_SEMANTIC s = GetSyscallSemantic(ctxt, std);
|
|
if (s == SCS_THREADCREATE)
|
|
{
|
|
threadCreateCount++;
|
|
}
|
|
}
|
|
|
|
/*!
|
|
* Print out analysis results.
|
|
* This function is called when the application exits.
|
|
* @param[in] code exit code of the application
|
|
* @param[in] v value specified by the tool in the
|
|
* PIN_AddFiniFunction function call
|
|
*/
|
|
VOID Fini(INT32 code, VOID *v)
|
|
{
|
|
*out << "===============================================" << endl;
|
|
*out << "cpp11Threads analysis results: " << endl;
|
|
*out << "Number of threads started: " << threadStartCount << endl;
|
|
*out << "Number of threads created: " << threadCreateCount << endl;
|
|
*out << "Number of threads finish: " << threadFiniCount << endl;
|
|
*out << "===============================================" << endl;
|
|
}
|
|
|
|
INT32 Usage()
|
|
{
|
|
cerr <<
|
|
"This pin tool counts predicated instructions selected by the\n"
|
|
"following filter options\n"
|
|
"\n";
|
|
|
|
cerr << KNOB_BASE::StringKnobSummary() << endl;
|
|
return -1;
|
|
}
|
|
|
|
/*!
|
|
* The main procedure of the tool.
|
|
* This function is called when the application image is loaded but not yet started.
|
|
* @param[in] argc total number of elements in the argv array
|
|
* @param[in] argv array of command line arguments,
|
|
* including pin -t <toolname> -- ...
|
|
*/
|
|
int main(int argc, char *argv[])
|
|
{
|
|
// Initialize PIN library. Print help message if -h(elp) is specified
|
|
// in the command line or the command line is invalid
|
|
if( PIN_Init(argc,argv) )
|
|
{
|
|
return Usage();
|
|
}
|
|
|
|
threadStartCount = 0;
|
|
threadCreateCount = 0;
|
|
threadFiniCount = 0;
|
|
|
|
string fileName = KnobOutputFile.Value();
|
|
|
|
if (!fileName.empty()) { out = new std::ofstream(fileName.c_str());}
|
|
|
|
// Register function to be called for every thread before it starts running
|
|
PIN_AddThreadStartFunction(ThreadStart, 0);
|
|
PIN_AddThreadFiniFunction(ThreadFini, 0);
|
|
|
|
PIN_AddSyscallEntryFunction(SyscallEntry, NULL);
|
|
|
|
|
|
// Register function to be called when the application exits
|
|
PIN_AddFiniFunction(Fini, 0);
|
|
|
|
cerr << "===============================================" << endl;
|
|
if (!KnobOutputFile.Value().empty())
|
|
{
|
|
cerr << "See file " << KnobOutputFile.Value() << " for analysis results" << endl;
|
|
}
|
|
cerr << "===============================================" << endl;
|
|
|
|
// Start the program, never returns
|
|
PIN_StartProgram();
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* ===================================================================== */
|
|
/* eof */
|
|
/* ===================================================================== */
|