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.
196 lines
5.9 KiB
196 lines
5.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 pin tool domonstrate the difference between PIN_CallApplicationFunction() and
|
|
* PIN_CallApplicationFunctionNatively().
|
|
* It was designed to instrument the application call_function_natively_app and
|
|
* instrument the call from helloX() to world().
|
|
* Right before the main() function returns, this tool gain control and call
|
|
* the helloX() function using both PIN_CallApplicationFunction() and
|
|
* PIN_CallApplicationFunctionNatively().
|
|
* We expect that when calling helloX() using PIN_CallApplicationFunctionNatively()
|
|
* the instrumentation routines and the analysis routines that were instrumented
|
|
* ahead of time will not be call on the executed application code.
|
|
* But, when calling helloX() using PIN_CallApplicationFunction()
|
|
* The routines mentioned above should be called.
|
|
*/
|
|
#include "pin.H"
|
|
#include <iostream>
|
|
#include <fstream>
|
|
#include <cstdlib>
|
|
#include <cstring>
|
|
using std::ofstream;
|
|
using std::cerr;
|
|
using std::string;
|
|
using std::endl;
|
|
|
|
#ifdef TARGET_MAC
|
|
#define NAME(x) "_" x
|
|
#else
|
|
#define NAME(x) x
|
|
#endif
|
|
|
|
|
|
/* ===================================================================== */
|
|
/* Commandline Switches */
|
|
/* ===================================================================== */
|
|
|
|
KNOB<string> KnobOutputFile(KNOB_MODE_WRITEONCE, "pintool",
|
|
"o", "call_function_natively.out", "specify file name");
|
|
|
|
// Tool's output file
|
|
ofstream TraceFile;
|
|
/* ===================================================================== */
|
|
|
|
// address of helloX() function in the application
|
|
static ADDRINT helloXAddr = 0;
|
|
// address of helloX() function's end in the application
|
|
static ADDRINT helloXEndAddr = 0;
|
|
// address of world() function in the application
|
|
static ADDRINT worldAddr = 0;
|
|
|
|
// depth of the call to PIN_CallApplicationFunction*()
|
|
static int callingDepth = 0;
|
|
|
|
static INT32 Usage()
|
|
{
|
|
cerr <<
|
|
"This pin tool domonstrate the difference between PIN_CallApplicationFunction() and "
|
|
"PIN_CallApplicationFunctionNatively."
|
|
<< endl;
|
|
cerr << KNOB_BASE::StringKnobSummary();
|
|
cerr << endl;
|
|
return -1;
|
|
}
|
|
|
|
// Return the identation for text printing
|
|
// The identation is calculated according to the call depth
|
|
static string depthString()
|
|
{
|
|
string s;
|
|
for (int i = 0; i < callingDepth; i++)
|
|
s += "\t";
|
|
return s;
|
|
}
|
|
|
|
// A call to this function is instrumented in the app right before the call from helloX() to world()
|
|
static void HandleCallInHello(char* instType)
|
|
{
|
|
TraceFile << depthString() << "Calling world from helloX (instrumented " << instType << ")" << endl;
|
|
}
|
|
|
|
static void callApplicationFunction(THREADID tid, CONTEXT *ctxt, BOOL natively)
|
|
{
|
|
char buf[128] = {0};
|
|
char* ret;
|
|
|
|
TraceFile << depthString() << "Calling helloX from tool " << (natively?"natively":"regularly") << endl;
|
|
callingDepth++;
|
|
CALL_APPLICATION_FUNCTION_PARAM param;
|
|
memset(¶m, 0, sizeof(param));
|
|
param.native = natively;
|
|
|
|
PIN_CallApplicationFunction(ctxt, tid, CALLINGSTD_DEFAULT, AFUNPTR(helloXAddr), ¶m, PIN_PARG(char*), &ret, PIN_PARG(char*), buf, PIN_PARG_END());
|
|
|
|
callingDepth--;
|
|
TraceFile << depthString() << "Returned from helloX in tool with '" << ret << "'" << endl;
|
|
}
|
|
|
|
// This function should be called at the end of the application's main()
|
|
static void AfterMain(THREADID tid, CONTEXT *ctxt)
|
|
{
|
|
callApplicationFunction(tid, ctxt, TRUE);
|
|
callApplicationFunction(tid, ctxt, FALSE);
|
|
callApplicationFunction(tid, ctxt, TRUE);
|
|
}
|
|
|
|
// This is the instrumentation routine
|
|
// It Should locate the single instruction in the application which is
|
|
// the call from helloX() to world(), and instrument it
|
|
static void Instruction(INS ins, VOID *v)
|
|
{
|
|
ADDRINT addr = INS_Address(ins);
|
|
if (addr < helloXAddr && addr >= helloXEndAddr)
|
|
{
|
|
// We're not instrumenting the body of helloX()
|
|
return;
|
|
}
|
|
|
|
// Find the instruction which is the call to world()
|
|
if (INS_IsCall(ins)
|
|
&& INS_IsDirectControlFlow(ins)
|
|
&& INS_DirectControlFlowTargetAddress(ins) == worldAddr)
|
|
{
|
|
INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(HandleCallInHello), IARG_ADDRINT, v, IARG_END);
|
|
}
|
|
}
|
|
|
|
// Utility function to get the address of an RTN using its name
|
|
static ADDRINT FindAddressOfRtn(IMG img, const string& rtnName)
|
|
{
|
|
RTN r = RTN_FindByName(img, rtnName.c_str());
|
|
ASSERT(RTN_Valid(r), "Failed to find RTN " + rtnName);
|
|
return RTN_Address(r);
|
|
}
|
|
|
|
// Called opon new image load
|
|
static void Image(IMG img, VOID *v)
|
|
{
|
|
if (!IMG_IsMainExecutable(img))
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Find the relevant function addresses
|
|
helloXAddr = FindAddressOfRtn(img, NAME("helloX"));
|
|
worldAddr = FindAddressOfRtn(img, NAME("world"));
|
|
|
|
RTN r = RTN_FindByAddress(helloXAddr);
|
|
ASSERTX(RTN_Valid(r));
|
|
RTN_Open(r);
|
|
helloXEndAddr = helloXAddr + RTN_Size(r);
|
|
|
|
// Instrument helloX() ahead of time
|
|
for (INS i = RTN_InsHead(r); INS_Valid(i); i = INS_Next(i))
|
|
{
|
|
Instruction(i, (VOID*)"AOTI");
|
|
}
|
|
RTN_Close(r);
|
|
|
|
// Instrument our function to the end of the application's main()
|
|
RTN mainRtn = RTN_FindByName(img, NAME("main"));
|
|
ASSERTX(RTN_Valid(mainRtn));
|
|
|
|
RTN_Open(mainRtn);
|
|
RTN_InsertCall(mainRtn, IPOINT_AFTER, AFUNPTR(AfterMain), IARG_THREAD_ID, IARG_CONTEXT, IARG_END);
|
|
RTN_Close(mainRtn);
|
|
}
|
|
|
|
int main(int argc, CHAR *argv[])
|
|
{
|
|
if( PIN_Init(argc,argv) )
|
|
{
|
|
return Usage();
|
|
}
|
|
PIN_InitSymbols();
|
|
|
|
TraceFile.open(KnobOutputFile.Value().c_str());
|
|
|
|
IMG_AddInstrumentFunction(Image, 0);
|
|
|
|
INS_AddInstrumentFunction(Instruction, (VOID*)"JIT");
|
|
|
|
// Never return
|
|
PIN_StartProgram();
|
|
}
|