// 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