// Copyright (c) 1998 John Panzer. Permission is granted to // use, copy, modify, distribute, and sell this source code as // long as this copyright notice appears in all source files. #include <windows.h> #include <imagehlp.h> #include <stdio.h> #include "CallMon.h" using namespace std; typedef CallMonitor::ADDR ADDR; // Processor-specific offset from // _penter return address to start of // caller. static const unsigned OFFSET_CALL_BYTES=5; // Start of MSVC-specific code // _pexit is called upon return from // an instrumented function. static void _pexit() { CallMonitor::TICKS endTime; CallMonitor::queryTicks(&endTime); ADDR framePtr,parentFramePtr; // Retrieve parent stack frame to pass // to exitProcedure __asm mov DWORD PTR [framePtr], ebp parentFramePtr = ((ADDR *)framePtr)[0]; CallMonitor::threadObj().exitProcedure( parentFramePtr, &((ADDR*)framePtr)[3],endTime); } // An entry point to which all instrumented // function returns are redirected. static void __declspec(naked) _pexitThunk() { // Push placeholder return address __asm push 0 // Protect original return value __asm push eax _pexit(); // Restore original return value __asm pop eax // Return using new address set by _pexit __asm ret } // _penter is called on entry to each client function extern "C" __declspec(dllexport) void _penter() { CallMonitor::TICKS entryTime; CallMonitor::queryTicks(&entryTime); // Track entry time ADDR framePtr; __asm mov DWORD PTR [framePtr], ebp CallMonitor::threadObj().enterProcedure( (ADDR)((unsigned *)framePtr)[0], (ADDR)((unsigned *)framePtr)[1]-OFFSET_CALL_BYTES, (ADDR*)&((unsigned *)framePtr)[2], entryTime); } // End of MSVC-specific code //End of File