/* * 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 * Insert a call before and after a stdcall function in probe mode. */ /* ===================================================================== */ #include "pin.H" #if defined (TARGET_WINDOWS) namespace WINDOWS { #include } #endif #include #include "probe_stdcall_fastcall.h" using std::string; /* ===================================================================== */ typedef int ( __stdcall * FuncType)( int, int, int, int, int, int, int, int, int, int ); class EXECUTION_CHECKER{ public: EXECUTION_CHECKER () { _instrumentedFunc1 = FALSE; _instrumentedFunc2 = FALSE; _instrumentedFunc3 = FALSE; _instrumentedFunc4 = FALSE; _instrumentedFunc5 = FALSE; _numBeforeExecutions = 0; _numBeforeWithParamsExecutions = 0; _numAfterExecutions = 0; _numAfterWithParamsExecutions = 0; } ~EXECUTION_CHECKER () { if (!_instrumentedFunc1) { printf ("did not instrument func1\n"); exit(1); } if (!_instrumentedFunc2) { printf ("did not instrument func2\n"); exit(1); } if (!_instrumentedFunc3) { printf ("did not instrument func3\n"); exit(1); } if (!_instrumentedFunc4) { printf ("did not instrument func4\n"); exit(1); } if (!_instrumentedFunc5) { printf ("did not instrument func5\n"); exit(1); } if (_numBeforeExecutions != 2) { printf ("did not execute expected # of BeforeExecutions\n"); exit(1); } if (_numBeforeWithParamsExecutions != 2) { printf ("did not execute expected # of BeforeWithParamsExecutions\n"); exit(1); } if (_numAfterWithParamsExecutions != 1) { printf ("did not execute expected # of AfterWithParamsExecutions\n"); exit(1); } if (_numAfterExecutions != 4) { printf ("did not execute expected # of AfterExecutions\n"); exit(1); } } BOOL _instrumentedFunc1; BOOL _instrumentedFunc2; BOOL _instrumentedFunc3; BOOL _instrumentedFunc4; BOOL _instrumentedFunc5; int _numBeforeExecutions; int _numBeforeWithParamsExecutions; int _numAfterExecutions; int _numAfterWithParamsExecutions; } ; EXECUTION_CHECKER executionChecker; /* ===================================================================== */ /* Analysis routines */ /* ===================================================================== */ VOID Before() { executionChecker._numBeforeExecutions++; } VOID BeforeWithParams(char c1, int num1, char c2, int num2, char c3) { executionChecker._numBeforeWithParamsExecutions++; if (c1 != CHAR_VAL1) { printf ("TOOL ERROR: BeforeWithParams was not passed in c1 as expected, actual c1 %c\n", c1); exit(1); } if (c2 != CHAR_VAL2) { printf ("TOOL ERROR: BeforeWithParams was not passed in c2 as expected, actual c2 %c\n", c2); exit(1); } if (c3 != CHAR_VAL3) { printf ("TOOL ERROR: BeforeWithParams was not passed in c3 as expected, actual c3 %c %x\n", c3, c3); exit(1); } if (num1 != INT_VAL1) { printf ("TOOL ERROR: BeforeWithParams was not passed in num1 as expected, actual num1 %d\n", num1); exit(1); } if (num2 != INT_VAL2) { printf ("TOOL ERROR: BeforeWithParams was not passed in num2 as expected, actual num2 %d\n", num2); exit(1); } } VOID After( ) { executionChecker._numAfterExecutions++; } VOID AfterWithParams(int retValFromStdCallFunction5ToBeReplacedByPinAppFun ) { executionChecker._numAfterWithParamsExecutions++; if (retValFromStdCallFunction5ToBeReplacedByPinAppFun != RETVAL5) { printf ("TOOL ERROR: AfterWithParams was not passed in retValFromStdCallFunction5ToBeReplacedByPinAppFun as expected, actual retValFromStdCallFunction5ToBeReplacedByPinAppFun %d\n", retValFromStdCallFunction5ToBeReplacedByPinAppFun); exit(1); } } /* ===================================================================== */ /* Instrumentation routines */ /* ===================================================================== */ VOID Sanity(IMG img, RTN rtn) { if ( PIN_IsProbeMode() && ! RTN_IsSafeForProbedInsertion( rtn ) ) { printf ("Cannot insert calls around %s() in %s\n", RTN_Name(rtn).c_str(), IMG_Name(img).c_str()); exit(1); } } /* ===================================================================== */ VOID ImageLoad(IMG img, VOID *v) { // Walk through the symbols in the symbol table. // for (SYM sym = IMG_RegsymHead(img); SYM_Valid(sym); sym = SYM_Next(sym)) { string undFuncName = PIN_UndecorateSymbolName(SYM_Name(sym), UNDECORATION_NAME_ONLY); // Find the LocalAlloc function. if (undFuncName == "StdCallFunctionToBeReplacedByPin") { RTN rtn = RTN_FindByAddress(IMG_LowAddress(img) + SYM_Value(sym)); if (RTN_Valid(rtn)) { Sanity(img, rtn); printf ( "Inserting calls before/after StdCallFunctionToBeReplacedByPin() in %s at address %x\n", IMG_Name(img).c_str(), RTN_Address(rtn)); PROTO protoOfStdCallFunction1ToBeReplacedByPin = PROTO_Allocate( PIN_PARG(int ), CALLINGSTD_STDCALL, "protoOfStdCallFunction1ToBeReplacedByPin", PIN_PARG(char), PIN_PARG(int), PIN_PARG(char), PIN_PARG(int), PIN_PARG(char), PIN_PARG_END() ); RTN_InsertCallProbed( rtn, IPOINT_AFTER, AFUNPTR( After ), IARG_PROTOTYPE, protoOfStdCallFunction1ToBeReplacedByPin, IARG_END ); RTN_InsertCallProbed( rtn, IPOINT_BEFORE, AFUNPTR( Before ), IARG_PROTOTYPE, protoOfStdCallFunction1ToBeReplacedByPin, IARG_END); PROTO_Free( protoOfStdCallFunction1ToBeReplacedByPin ); executionChecker._instrumentedFunc1 = TRUE; } } else if (undFuncName == "StdCallFunction2ToBeReplacedByPin") { RTN rtn = RTN_FindByAddress(IMG_LowAddress(img) + SYM_Value(sym)); if (RTN_Valid(rtn)) { Sanity(img, rtn); printf ( "Inserting call before StdCallFunction2ToBeReplacedByPin() in %s at address %x\n", IMG_Name(img).c_str(), RTN_Address(rtn)); PROTO protoOfStdCallFunction2ToBeReplacedByPin = PROTO_Allocate( PIN_PARG(int ), CALLINGSTD_STDCALL, "protoOfStdCallFunction2ToBeReplacedByPin", PIN_PARG(char), PIN_PARG(int), PIN_PARG(char), PIN_PARG(int), PIN_PARG(char), PIN_PARG_END() ); RTN_InsertCallProbed( rtn, IPOINT_BEFORE, AFUNPTR( Before ), IARG_PROTOTYPE, protoOfStdCallFunction2ToBeReplacedByPin, IARG_END); RTN_InsertCallProbed( rtn, IPOINT_AFTER, AFUNPTR( After ), IARG_PROTOTYPE, protoOfStdCallFunction2ToBeReplacedByPin, IARG_END ); PROTO_Free( protoOfStdCallFunction2ToBeReplacedByPin ); executionChecker._instrumentedFunc2 = TRUE; } } else if (undFuncName == "StdCallFunction3ToBeReplacedByPin") { RTN rtn = RTN_FindByAddress(IMG_LowAddress(img) + SYM_Value(sym)); if (RTN_Valid(rtn)) { Sanity(img, rtn); printf ( "Inserting call after StdCallFunction3ToBeReplacedByPin() in %s at address %x\n", IMG_Name(img).c_str(), RTN_Address(rtn)); PROTO protoOfStdCallFunction3ToBeReplacedByPin = PROTO_Allocate( PIN_PARG(int ), CALLINGSTD_STDCALL, "protoOfStdCallFunction3ToBeReplacedByPin", PIN_PARG(char), PIN_PARG(int), PIN_PARG(char), PIN_PARG(int), PIN_PARG(char), PIN_PARG_END() ); RTN_InsertCallProbed( rtn, IPOINT_AFTER, AFUNPTR( After ), IARG_PROTOTYPE, protoOfStdCallFunction3ToBeReplacedByPin, IARG_END); PROTO_Free( protoOfStdCallFunction3ToBeReplacedByPin ); executionChecker._instrumentedFunc3 = TRUE; } } else if (undFuncName == "StdCallFunction4ToBeReplacedByPin") { RTN rtn = RTN_FindByAddress(IMG_LowAddress(img) + SYM_Value(sym)); if (RTN_Valid(rtn)) { Sanity(img, rtn); printf ( "Inserting call after StdCallFunction4ToBeReplacedByPin() in %s at address %x\n", IMG_Name(img).c_str(), RTN_Address(rtn)); PROTO protoOfStdCallFunction4ToBeReplacedByPin = PROTO_Allocate( PIN_PARG(int ), CALLINGSTD_STDCALL, "protoOfStdCallFunction4ToBeReplacedByPin", PIN_PARG(char), PIN_PARG(int), PIN_PARG(char), PIN_PARG(int), PIN_PARG(char), PIN_PARG_END() ); RTN_InsertCallProbed( rtn, IPOINT_AFTER, AFUNPTR( After ), IARG_PROTOTYPE, protoOfStdCallFunction4ToBeReplacedByPin, IARG_END); RTN_InsertCallProbed( rtn, IPOINT_BEFORE, AFUNPTR( BeforeWithParams ), IARG_PROTOTYPE, protoOfStdCallFunction4ToBeReplacedByPin, IARG_FUNCARG_ENTRYPOINT_VALUE, 0, IARG_FUNCARG_ENTRYPOINT_VALUE, 1, IARG_FUNCARG_ENTRYPOINT_VALUE, 2, IARG_FUNCARG_ENTRYPOINT_VALUE, 3, IARG_FUNCARG_ENTRYPOINT_VALUE, 4, IARG_END); PROTO_Free( protoOfStdCallFunction4ToBeReplacedByPin ); executionChecker._instrumentedFunc4 = TRUE; } } else if (undFuncName == "StdCallFunction5ToBeReplacedByPin") { RTN rtn = RTN_FindByAddress(IMG_LowAddress(img) + SYM_Value(sym)); if (RTN_Valid(rtn)) { Sanity(img, rtn); printf ( "Inserting call after StdCallFunction5ToBeReplacedByPin() in %s at address %x\n", IMG_Name(img).c_str(), RTN_Address(rtn)); PROTO protoOfStdCallFunction5ToBeReplacedByPin = PROTO_Allocate( PIN_PARG(int), CALLINGSTD_STDCALL, "protoOfStdCallFunction5ToBeReplacedByPin", PIN_PARG(char), PIN_PARG(int), PIN_PARG(char), PIN_PARG(int), PIN_PARG(char), PIN_PARG_END() ); RTN_InsertCallProbed( rtn, IPOINT_AFTER, AFUNPTR( AfterWithParams ), IARG_PROTOTYPE, protoOfStdCallFunction5ToBeReplacedByPin, IARG_REG_VALUE, REG_GAX, IARG_END); RTN_InsertCallProbed( rtn, IPOINT_BEFORE, AFUNPTR( BeforeWithParams ), IARG_PROTOTYPE, protoOfStdCallFunction5ToBeReplacedByPin, IARG_FUNCARG_ENTRYPOINT_VALUE, 0, IARG_FUNCARG_ENTRYPOINT_VALUE, 1, IARG_FUNCARG_ENTRYPOINT_VALUE, 2, IARG_FUNCARG_ENTRYPOINT_VALUE, 3, IARG_FUNCARG_ENTRYPOINT_VALUE, 4, IARG_END); PROTO_Free( protoOfStdCallFunction5ToBeReplacedByPin ); executionChecker._instrumentedFunc5 = TRUE; } } } } /* ===================================================================== */ int main(INT32 argc, CHAR *argv[]) { PIN_InitSymbols(); PIN_Init(argc, argv); IMG_AddInstrumentFunction(ImageLoad, 0); PIN_StartProgramProbed(); return 0; } /* ===================================================================== */ /* eof */ /* ===================================================================== */