251 lines
4.8 KiB
C
251 lines
4.8 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1997 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
reftrace.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This module implements a reference count tracing facility.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Keith Moore (keithmo) 01-May-1997
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
|
|||
|
#include <nt.h>
|
|||
|
#include <ntrtl.h>
|
|||
|
#include <nturtl.h>
|
|||
|
#include <windows.h>
|
|||
|
#include <pudebug.h>
|
|||
|
#include <reftrace.h>
|
|||
|
#include <stktrace.h>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
PTRACE_LOG
|
|||
|
CreateRefTraceLog(
|
|||
|
IN LONG LogSize,
|
|||
|
IN LONG ExtraBytesInHeader
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Creates a new (empty) ref count trace log buffer.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
LogSize - The number of entries in the log.
|
|||
|
|
|||
|
ExtraBytesInHeader - The number of extra bytes to include in the
|
|||
|
log header. This is useful for adding application-specific
|
|||
|
data to the log.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
PTRACE_LOG - Pointer to the newly created log if successful,
|
|||
|
NULL otherwise.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
|
|||
|
return CreateTraceLog(
|
|||
|
LogSize,
|
|||
|
ExtraBytesInHeader,
|
|||
|
sizeof(REF_TRACE_LOG_ENTRY)
|
|||
|
);
|
|||
|
|
|||
|
} // CreateRefTraceLog
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
DestroyRefTraceLog(
|
|||
|
IN PTRACE_LOG Log
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Destroys a ref count trace log buffer created with CreateRefTraceLog().
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Log - The ref count trace log buffer to destroy.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
|
|||
|
DestroyTraceLog( Log );
|
|||
|
|
|||
|
} // DestroyRefTraceLog
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// N.B. For IISCaptureStackBackTrace() to work properly, the calling function
|
|||
|
// *must* be __cdecl, and must have a "normal" stack frame. So, we decorate
|
|||
|
// WriteRefTraceLog[Ex]() with the __cdecl modifier and disable the frame
|
|||
|
// pointer omission (FPO) optimization.
|
|||
|
//
|
|||
|
|
|||
|
#pragma optimize( "y", off ) // disable frame pointer omission (FPO)
|
|||
|
|
|||
|
LONG
|
|||
|
__cdecl
|
|||
|
WriteRefTraceLog(
|
|||
|
IN PTRACE_LOG Log,
|
|||
|
IN LONG NewRefCount,
|
|||
|
IN PVOID Context
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Writes a new entry to the specified ref count trace log. The entry
|
|||
|
written contains the updated reference count and a stack backtrace
|
|||
|
leading up to the current caller.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Log - The log to write to.
|
|||
|
|
|||
|
NewRefCount - The updated reference count.
|
|||
|
|
|||
|
Context - An uninterpreted context to associate with the log entry.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Index of entry in log.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
|
|||
|
return WriteRefTraceLogEx(
|
|||
|
Log,
|
|||
|
NewRefCount,
|
|||
|
Context,
|
|||
|
REF_TRACE_EMPTY_CONTEXT, // suppress use of optional extra contexts
|
|||
|
REF_TRACE_EMPTY_CONTEXT,
|
|||
|
REF_TRACE_EMPTY_CONTEXT
|
|||
|
);
|
|||
|
|
|||
|
} // WriteRefTraceLog
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
LONG
|
|||
|
__cdecl
|
|||
|
WriteRefTraceLogEx(
|
|||
|
IN PTRACE_LOG Log,
|
|||
|
IN LONG NewRefCount,
|
|||
|
IN PVOID Context,
|
|||
|
IN PVOID Context1, // optional extra context
|
|||
|
IN PVOID Context2, // optional extra context
|
|||
|
IN PVOID Context3 // optional extra context
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Writes a new "extended" entry to the specified ref count trace log.
|
|||
|
The entry written contains the updated reference count, stack backtrace
|
|||
|
leading up to the current caller and extra context information.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Log - The log to write to.
|
|||
|
|
|||
|
NewRefCount - The updated reference count.
|
|||
|
|
|||
|
Context - An uninterpreted context to associate with the log entry.
|
|||
|
Context1 - An uninterpreted context to associate with the log entry.
|
|||
|
Context2 - An uninterpreted context to associate with the log entry.
|
|||
|
Context3 - An uninterpreted context to associate with the log entry.
|
|||
|
|
|||
|
NOTE Context1/2/3 are "optional" in that the caller may suppress
|
|||
|
debug display of these values by passing REF_TRACE_EMPTY_CONTEXT
|
|||
|
for each of them.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Index of entry in log.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
|
|||
|
REF_TRACE_LOG_ENTRY entry;
|
|||
|
ULONG hash;
|
|||
|
DWORD cStackFramesSkipped;
|
|||
|
|
|||
|
//
|
|||
|
// Initialize the entry.
|
|||
|
//
|
|||
|
|
|||
|
RtlZeroMemory(
|
|||
|
&entry,
|
|||
|
sizeof(entry)
|
|||
|
);
|
|||
|
|
|||
|
//
|
|||
|
// Set log entry members.
|
|||
|
//
|
|||
|
|
|||
|
entry.NewRefCount = NewRefCount;
|
|||
|
entry.Context = Context;
|
|||
|
entry.Thread = GetCurrentThreadId();
|
|||
|
entry.Context1 = Context1;
|
|||
|
entry.Context2 = Context2;
|
|||
|
entry.Context3 = Context3;
|
|||
|
|
|||
|
//
|
|||
|
// Capture the stack backtrace. Normally, we skip two stack frames:
|
|||
|
// one for this routine, and one for IISCaptureStackBackTrace() itself.
|
|||
|
// For non-Ex callers who come in via WriteRefTraceLog,
|
|||
|
// we skip three stack frames.
|
|||
|
//
|
|||
|
|
|||
|
if ( entry.Context1 == REF_TRACE_EMPTY_CONTEXT
|
|||
|
&& entry.Context2 == REF_TRACE_EMPTY_CONTEXT
|
|||
|
&& entry.Context3 == REF_TRACE_EMPTY_CONTEXT
|
|||
|
) {
|
|||
|
|
|||
|
cStackFramesSkipped = 3;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
cStackFramesSkipped = 2;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
IISCaptureStackBackTrace(
|
|||
|
cStackFramesSkipped,
|
|||
|
REF_TRACE_LOG_STACK_DEPTH,
|
|||
|
entry.Stack,
|
|||
|
&hash
|
|||
|
);
|
|||
|
|
|||
|
//
|
|||
|
// Write it to the log.
|
|||
|
//
|
|||
|
|
|||
|
return WriteTraceLog(
|
|||
|
Log,
|
|||
|
&entry
|
|||
|
);
|
|||
|
|
|||
|
} // WriteRefTraceLogEx
|
|||
|
|
|||
|
#pragma optimize( "", on ) // restore frame pointer omission (FPO)
|
|||
|
|