|
|
/*++
Copyright (c) 2001 Microsoft Corporation
Module Name:
critsect.c
Abstract:
Critical section debugger extension for both ntsd and kd.
Author:
Daniel Mihai (DMihai) 8-Feb-2001
Environment:
User Mode.
Revision History:
--*/
#include "precomp.h"
#pragma hdrstop
/////////////////////////////////////////////////////////////////////
BOOL ReadStructFieldVerbose( ULONG64 AddrStructBase, PCHAR StructTypeName, PCHAR StructFieldName, PVOID Buffer, ULONG BufferSize ) { ULONG FieldOffset; ULONG ErrorCode; BOOL Success;
Success = FALSE;
//
// Get the field offset
//
ErrorCode = GetFieldOffset (StructTypeName, StructFieldName, &FieldOffset );
if (ErrorCode == S_OK) {
//
// Read the data
//
Success = ReadMemory (AddrStructBase + FieldOffset, Buffer, BufferSize, NULL );
if (Success != TRUE) {
dprintf ("Cannot read structure field value at 0x%p, error %u\n", AddrStructBase + FieldOffset, ErrorCode ); } } else {
dprintf ("Cannot get field offset of %s in %s, error %u\n", StructFieldName, StructTypeName, ErrorCode ); }
return Success; }
/////////////////////////////////////////////////////////////////////
BOOL ReadPtrStructFieldVerbose( ULONG64 AddrStructBase, PCHAR StructTypeName, PCHAR StructFieldName, PULONG64 Buffer ) { ULONG FieldOffset; ULONG ErrorCode; BOOL Success;
Success = FALSE;
//
// Get the field offset inside the structure
//
ErrorCode = GetFieldOffset ( StructTypeName, StructFieldName, &FieldOffset );
if (ErrorCode == S_OK) {
//
// Read the data
//
if (ReadPointer(AddrStructBase + FieldOffset, Buffer) == FALSE) {
dprintf ("Cannot read structure field value at 0x%p\n", AddrStructBase + FieldOffset); } else {
Success = TRUE; } } else {
dprintf ("Cannot get field offset of %s in structure %s, error %u\n", StructFieldName, StructTypeName, ErrorCode ); }
return Success; }
/////////////////////////////////////////////////////////////////////////////
ULONG64 GetStackTraceAddress( ULONG StackTraceIndex, ULONG PointerSize ) { ULONG64 TraceDatabaseAddress; ULONG64 TraceDatabase; ULONG64 EntryIndexArray; ULONG64 StackTraceAddress; ULONG64 StackTraceToDump; ULONG NumberOfEntriesAdded; ULONG ErrorCode; BOOL Success;
StackTraceToDump = 0;
//
// Stack trace database address
//
TraceDatabaseAddress = GetExpression("&NTDLL!RtlpStackTraceDataBase"); if ( TraceDatabaseAddress == 0 ) { dprintf( "!cs: Unable to resolve NTDLL!RtlpStackTraceDataBase\n" "Please check your symbols\n" );
goto Done; }
if (ReadPointer (TraceDatabaseAddress, &TraceDatabase ) == FALSE) {
dprintf( "!cs: Cannot read pointer at NTDLL!RtlpStackTraceDataBase\n" ); goto Done; } else if (TraceDatabase == 0) {
dprintf( "NTDLL!RtlpStackTraceDataBase is NULL. Probably the stack traces are not enabled.\n" );
goto Done; }
//
// Read the number of entries in the database
//
Success = ReadStructFieldVerbose (TraceDatabase, "NTDLL!_STACK_TRACE_DATABASE", "NumberOfEntriesAdded", &NumberOfEntriesAdded, sizeof( NumberOfEntriesAdded ) );
if( Success == FALSE ) {
dprintf( "Cannot read the number of stack traces database entries\n" ); goto Done; } else if( StackTraceIndex == 0 ) {
dprintf( "No stack trace found.\n" ); goto Done; } else if( NumberOfEntriesAdded < StackTraceIndex ) {
dprintf( "Stack trace index 0x%X is invalid, current number of stack traces is 0x%X\n", StackTraceIndex, NumberOfEntriesAdded ); goto Done; }
//
// Find the array of stack traces
//
Success = ReadPtrStructFieldVerbose (TraceDatabase, "NTDLL!_STACK_TRACE_DATABASE", "EntryIndexArray", &EntryIndexArray );
if( Success == FALSE ) {
dprintf( "Cannot read the stack database array address\n" ); goto Done; } //
// Compute the address of our stack trace pointer
//
StackTraceAddress = EntryIndexArray - StackTraceIndex * PointerSize;
//
// Read the pointer to our trace entry in the array
//
if( ReadPointer (StackTraceAddress, &StackTraceToDump) == FALSE) {
dprintf( "Cannot read stack trace address at 0x%p\n", StackTraceAddress );
StackTraceToDump = 0; }
Done:
return StackTraceToDump; }
//////////////////////////////////////////////////////////////////////
VOID DumpStackTraceAtAddress (ULONG64 StackTraceAddress, ULONG PointerSize) { ULONG64 CrtTraceAddress; ULONG64 CodeAddress; ULONG64 Displacement; ULONG ErrorCode; ULONG BackTraceFieldOffset; USHORT Depth; USHORT CrtEntryIndex; BOOL Success; CHAR Symbol[ 1024 ];
//
// Read the stack trace depth
//
Success = ReadStructFieldVerbose (StackTraceAddress, "NTDLL!_RTL_STACK_TRACE_ENTRY", "Depth", &Depth, sizeof( Depth ));
if( Success == FALSE ) {
dprintf ("!cs: Cannot read depth for stack trace at 0x%p\n", StackTraceAddress);
goto Done; }
//
// Limit the depth to 20 to protect ourselves from corrupted data
//
Depth = __min( Depth, 20 );
//
// Get a pointer to the BackTrace array
//
ErrorCode = GetFieldOffset ("NTDLL!_RTL_STACK_TRACE_ENTRY", "BackTrace", &BackTraceFieldOffset);
if (ErrorCode != S_OK) {
dprintf ("!cs: Cannot get the BackTrace field offset\n"); goto Done; }
CrtTraceAddress = StackTraceAddress + BackTraceFieldOffset;
//
// Dump this stack trace
//
for( CrtEntryIndex = 0; CrtEntryIndex < Depth; CrtEntryIndex += 1 ) {
if (ReadPointer (CrtTraceAddress, &CodeAddress) == FALSE) {
dprintf ("!cs: Cannot read address at 0x%p\n", CrtTraceAddress ); }
GetSymbol( CodeAddress, Symbol, &Displacement);
dprintf ("0x%p: %s+0x%I64X\n", CodeAddress, Symbol, Displacement );
CrtTraceAddress += PointerSize; }
Done: NOTHING; }
//////////////////////////////////////////////////////////////////////
BOOL DumpCriticalSection ( ULONG64 AddrCritSec, ULONG64 AddrEndCritSect, ULONG64 AddrDebugInfo, ULONG PointerSize, BOOL DumpStackTrace ) { ULONG64 DebugInfo; ULONG64 OtherDebugInfo; ULONG64 CritSec; ULONG64 SpinCount; ULONG64 OwningThread; ULONG64 LockSemaphore; ULONG64 StackTraceAddress; ULONG64 Displacement; LONG LockCount; LONG RecursionCount; USHORT CreatorBackTraceIndex; ULONG DebugInfoFieldOffset; ULONG CriticalSectionFieldOffset; ULONG ErrorCode; BOOL HaveGoodSymbols; BOOL Success; CHAR Symbol[1024];
HaveGoodSymbols = FALSE;
//
// The caller must supply at least one of the
// critical section or debug information address.
//
if (AddrCritSec == 0 && AddrDebugInfo == 0) {
dprintf ("Internal debugger extension error: Both critical section and debug info are NULL\n"); goto Done; }
//
// Get the field offsets for various structures and check if we have
// good symbols, with type information.
//
ErrorCode = GetFieldOffset ("NTDLL!_RTL_CRITICAL_SECTION", "DebugInfo", &DebugInfoFieldOffset );
if (ErrorCode != S_OK) { dprintf( "Bad symbols for NTDLL (error %u). Aborting.\n", ErrorCode ); goto Done; }
ErrorCode = GetFieldOffset ("NTDLL!_RTL_CRITICAL_SECTION_DEBUG", "CriticalSection", &CriticalSectionFieldOffset );
if (ErrorCode != S_OK) { dprintf( "Bad symbols for NTDLL (error %u). Aborting.\n", ErrorCode ); goto Done; }
HaveGoodSymbols = TRUE;
//
// Read all the rest of the information we need
//
CritSec = AddrCritSec; DebugInfo = AddrDebugInfo;
if (AddrCritSec == 0 || (AddrEndCritSect != 0 && AddrDebugInfo != 0)) {
//
// Read the critical section address
//
if (ReadPointer (AddrDebugInfo + CriticalSectionFieldOffset, &CritSec) == FALSE ) {
dprintf ("Cannot read the critical section address at 0x%p.\n" "The memory is probably paged out or the active critical section list is corrupted.\n", AddrDebugInfo + CriticalSectionFieldOffset );
//
// We don't have any useful information to dump
// since we can't read the address of the critical section structure.
//
// Just display the stack trace since the active critical section list
// might be corrupted.
//
DumpStackTrace = TRUE;
goto DisplayStackTrace; }
if (AddrCritSec != 0 ) {
//
// We are dumpig all the critical sections in a range.
//
if (CritSec < AddrCritSec || CritSec > AddrEndCritSect) {
//
// We don't want to display this critical section
// because it is out of the range.
//
goto Done; } } //
// Read the the critical section address from the DebugInfo
//
dprintf( "-----------------------------------------\n" );
dprintf ("DebugInfo = 0x%p\n", AddrDebugInfo );
GetSymbol( CritSec, Symbol, &Displacement);
dprintf ("Critical section = 0x%p (%s+0x%I64X)\n", CritSec, Symbol, Displacement ); } else { //
// We have the critical section address from our caller
//
GetSymbol( CritSec, Symbol, &Displacement);
dprintf( "-----------------------------------------\n" );
dprintf ("Critical section = 0x%p (%s+0x%I64X)\n", AddrCritSec, Symbol, Displacement ); if (DebugInfo == 0) {
//
// Read the DebugInfo address from the critical section structure
//
if (ReadPointer (AddrCritSec + DebugInfoFieldOffset, &DebugInfo) == FALSE) {
dprintf ("Cannot read DebugInfo adddress at 0x%p. Possible causes:\n" "\t- The critical section is not initialized, deleted or corrupted\n" "\t- The critical section was a global variable in a DLL that was unloaded\n" "\t- The memory is paged out\n", AddrCritSec + DebugInfoFieldOffset ); } }
if (DebugInfo != 0) {
dprintf ("DebugInfo = 0x%p\n", DebugInfo ); } else {
dprintf ("Uninitialized or deleted.\n"); } }
//
// Read all the rest of the fields of this critical section
//
Success = ReadStructFieldVerbose (CritSec, "NTDLL!_RTL_CRITICAL_SECTION", "LockCount", &LockCount, sizeof( LockCount ) );
if( Success != TRUE ) { //
// Couldn't read the LockCount so we cannot say if it's
// locked or not. This can happen especially in stress where everything is
// paged out because of memory pressure.
//
dprintf ("Cannot determine if the critical section is locked or not.\n" );
goto DisplayStackTrace; } //
// Determine if the critical section is locked or not
//
if (LockCount == -1) {
//
// The critical section is not locked
//
dprintf ("NOT LOCKED\n"); } else {
//
// The critical section is currently locked
//
dprintf ("LOCKED\n" "LockCount = 0x%X\n", LockCount );
//
// OwningThread
//
Success = ReadPtrStructFieldVerbose( CritSec, "NTDLL!_RTL_CRITICAL_SECTION", "OwningThread", &OwningThread);
if (Success != FALSE) { dprintf ("OwningThread = 0x%p\n", OwningThread ); }
//
// RecursionCount
//
Success = ReadStructFieldVerbose( CritSec, "NTDLL!_RTL_CRITICAL_SECTION", "RecursionCount", &RecursionCount, sizeof( RecursionCount ) );
if (Success != FALSE) { dprintf ("RecursionCount = 0x%X\n", RecursionCount); } }
//
// LockSemaphore
//
Success = ReadStructFieldVerbose (CritSec, "NTDLL!_RTL_CRITICAL_SECTION", "LockSemaphore", &LockSemaphore, sizeof( LockSemaphore ));
if (Success != FALSE) { dprintf ("LockSemaphore = 0x%X\n", LockSemaphore ); }
//
// SpinCount
//
Success = ReadPtrStructFieldVerbose (CritSec, "NTDLL!_RTL_CRITICAL_SECTION", "SpinCount", &SpinCount);
if (Success != FALSE) { dprintf ("SpinCount = 0x%p\n", SpinCount ); }
//
// Simple checks for orphaned critical sections
//
if (AddrDebugInfo != 0) {
//
// AddrDebugInfo is a DebugInfo address from the active list.
// Verify that the critical section's DebugInfo is pointing
// back to AddrDebugInfo.
//
Success = ReadPtrStructFieldVerbose (CritSec, "NTDLL!_RTL_CRITICAL_SECTION", "DebugInfo", &OtherDebugInfo );
if (Success != FALSE && OtherDebugInfo != AddrDebugInfo) { dprintf ("\nWARNING: critical section DebugInfo = 0x%p doesn't point back\n" "to the DebugInfo found in the active critical sections list = 0x%p.\n" "The critical section was probably reused without calling DeleteCriticalSection.\n\n", OtherDebugInfo, AddrDebugInfo );
Success = ReadStructFieldVerbose (OtherDebugInfo, "NTDLL!_RTL_CRITICAL_SECTION_DEBUG", "CreatorBackTraceIndex", &CreatorBackTraceIndex, sizeof( CreatorBackTraceIndex ) );
StackTraceAddress = GetStackTraceAddress (CreatorBackTraceIndex, PointerSize );
if (StackTraceAddress != 0) { dprintf ("\nStack trace for DebugInfo = 0x%p:\n\n", OtherDebugInfo );
DumpStackTraceAtAddress (StackTraceAddress, PointerSize); }
//
// Dump the second stack trace too
//
DumpStackTrace = TRUE; } }
DisplayStackTrace:
if (!DumpStackTrace || DebugInfo == 0) {
goto Done; }
//
// Dump the initialization stack trace for this critical section
//
Success = ReadStructFieldVerbose (DebugInfo, "NTDLL!_RTL_CRITICAL_SECTION_DEBUG", "CreatorBackTraceIndex", &CreatorBackTraceIndex, sizeof (CreatorBackTraceIndex));
if (Success != FALSE) {
StackTraceAddress = GetStackTraceAddress (CreatorBackTraceIndex, PointerSize );
if (StackTraceAddress != 0) { dprintf ("\n\nStack trace for DebugInfo = 0x%p:\n\n", DebugInfo );
DumpStackTraceAtAddress (StackTraceAddress, PointerSize); } }
Done: return HaveGoodSymbols; }
/////////////////////////////////////////////////////////////////////////////
ULONG CriticalSectionFieldOffset; ULONG DebugInfoFieldOffset; ULONG LeftChildFieldOffset; ULONG RightChildFieldOffset;
ULONG EnterThreadFieldOffset; ULONG WaitThreadFieldOffset; ULONG TryEnterThreadFieldOffset; ULONG LeaveThreadFieldOffset;
BOOL DumpCSTreeRecursively (ULONG Level, ULONG64 TreeRoot) { ULONG64 CriticalSection; ULONG64 LeftChild; ULONG64 RightChild; ULONG64 DebugInfo; ULONG64 EnterThread; ULONG64 WaitThread; ULONG64 TryEnterThread; ULONG64 LeaveThread; ULONG64 ErrorCode; BOOL Continue = TRUE;
if (CheckControlC()) {
Continue = FALSE; goto Done; }
//
// Read the current CS address and dump information about it.
//
if (ReadPointer (TreeRoot + CriticalSectionFieldOffset, &CriticalSection) == FALSE) {
dprintf ("Cannot read CriticalSection address at %p\n", TreeRoot + CriticalSectionFieldOffset); goto Done; }
if (ReadPointer (TreeRoot + DebugInfoFieldOffset, &DebugInfo) == FALSE) {
dprintf ("Cannot read DebugInfo address at %p\n", TreeRoot + DebugInfoFieldOffset); goto Done; }
//
// Read the left child address.
//
if (ReadPointer (TreeRoot + LeftChildFieldOffset, &LeftChild) == FALSE) {
dprintf ("Cannot read left child address at %p\n", TreeRoot + LeftChildFieldOffset); goto Done; }
//
// Read the right child address.
//
if (ReadPointer (TreeRoot + RightChildFieldOffset, &RightChild) == FALSE) {
dprintf ("Cannot read right child address at %p\n", TreeRoot + RightChildFieldOffset); goto Done; }
//
// Dump the information about the current node.
//
dprintf ("%5u %p %p %p ", Level, TreeRoot, CriticalSection, DebugInfo);
if (EnterThreadFieldOffset != 0 ) {
//
// Read the EnterThread
//
if (ReadPointer (TreeRoot + EnterThreadFieldOffset, &EnterThread) == FALSE) {
dprintf ("Cannot read EnterThread at %p\n", TreeRoot + EnterThreadFieldOffset);
goto OlderThan3591; }
//
// Read the WaitThread
//
if (ReadPointer (TreeRoot + WaitThreadFieldOffset, &WaitThread) == FALSE) {
dprintf ("Cannot read WaitThread at %p\n", TreeRoot + WaitThreadFieldOffset);
goto OlderThan3591; }
//
// Read the TryEnterThread
//
if (ReadPointer (TreeRoot + TryEnterThreadFieldOffset, &TryEnterThread) == FALSE) {
dprintf ("Cannot read TryEnterThread at %p\n", TreeRoot + TryEnterThreadFieldOffset);
goto OlderThan3591; }
//
// Read the LeaveThread
//
if (ReadPointer (TreeRoot + LeaveThreadFieldOffset, &LeaveThread) == FALSE) {
dprintf ("Cannot read right LeaveThread at %p\n", TreeRoot + LeaveThreadFieldOffset);
goto OlderThan3591; }
dprintf ("%8p %8p %8p %8p\n", EnterThread, WaitThread, TryEnterThread, LeaveThread); } else {
dprintf ("\n"); }
OlderThan3591:
//
// Dump the left subtree.
//
if (LeftChild != 0) {
Continue = DumpCSTreeRecursively (Level + 1, LeftChild);
if (Continue == FALSE) { goto Done; } }
//
// Dump the right subtree.
//
if (RightChild != 0) {
Continue = DumpCSTreeRecursively (Level + 1, RightChild);
if (Continue == FALSE) { goto Done; } }
Done:
return Continue; }
/////////////////////////////////////////////////////////////////////////////
VOID DisplayHelp( VOID ) { dprintf( "!cs [-s] - dump all the active critical sections in the current process.\n" ); dprintf( "!cs [-s] address - dump critical section at this address.\n" ); dprintf( "!cs [-s] address1 address2 - dump all the active critical sections in this range.\n" ); dprintf( "!cs [-s] -d address - dump critical section corresponding to DebugInfo at this address.\n" ); dprintf( "\n\"-s\" will dump the critical section initialization stack trace if it's available.\n" ); }
/////////////////////////////////////////////////////////////////////////////
DECLARE_API( cs )
/*++
Routine Description:
Dump critical sections (both Kernel and User Debugger)
Arguments:
args - [address] [options]
Return Value:
None
--*/ { ULONG64 AddrCritSec; ULONG64 AddrEndCritSect; ULONG64 AddrDebugInfo; ULONG64 AddrListHead; ULONG64 ListHead; ULONG64 Next; ULONG64 AddrTreeRoot; ULONG64 TreeRoot = 0; LPCSTR Current; LPCSTR NextParam; BOOL StackTraces = FALSE; BOOL UseTree = FALSE; BOOL HaveGoodSymbols; ULONG ErrorCode; ULONG ProcessLocksListFieldOffset; ULONG Level; ULONG PointerSize;
INIT_API();
AddrDebugInfo = 0; AddrCritSec = 0; AddrEndCritSect = 0;
//
// Parse the command line arguments for:
//
// -s : dump initialization stack traces
// -d : find the critical section using a DebugInfo pointer
//
for (Current = args; *Current != '\0'; Current += 1) {
if (*Current == '-') {
Current += 1; switch (*Current) { case '?': case 'h': case 'H': //
// Need some help.
//
DisplayHelp(); goto Done;
case 's': case 'S': //
// Dump stack traces
//
StackTraces = TRUE;
if(*( Current + 1 ) != '\0') {
Current += 1; }
break;
case 't': case 'T': //
// Use the critical section tree
//
UseTree = TRUE;
if(*( Current + 1 ) != '\0') {
Current += 1; }
do {
Current += 1; } while (*Current == ' ');
if (*Current != '\0') {
TreeRoot = GetExpression(Current); }
break;
case 'd': case 'D':
//
// The next parameter should be the DebugInfo
//
do {
Current += 1; } while (*Current == ' ');
AddrDebugInfo = GetExpression(Current);
if (AddrDebugInfo == 0) {
dprintf("!cs: expected DebugInfo address after -d\n");
//
// Decrement Current since the for loop will increment it again.
// Otherwise, if this is the end of the string we will overrun
// the args buffer.
//
Current -= 1;
goto Done; } else {
goto DoneParsingArguments; }
break;
case ' ': Current += 1; break; default: dprintf ("!cs: invalid option flag '-%c'\n", *Current); break; } } else if(*Current == ' ') {
Current ++; } else {
break; } }
DoneParsingArguments:
//
// Get the size of a pointer
//
if (TargetMachine == IMAGE_FILE_MACHINE_I386) {
PointerSize = 4; } else {
PointerSize = 8; }
if( AddrDebugInfo == 0 && UseTree == FALSE ) { //
// If the user doesn't want us to use a DebugInfo
// then he might have asked us to dump a critical section
//
if (*Current != '\0') { AddrCritSec = GetExpression(Current);
if (AddrCritSec != 0) {
//
// We might have an additional argument if the user
// wants to dump all the active critical sections in
// an address range.
//
NextParam = strchr (Current, ' ' );
if (NextParam != NULL) {
AddrEndCritSect = GetExpression(NextParam); } } } }
//
// Start the real work
//
if ((AddrCritSec != 0 && AddrEndCritSect == 0) || AddrDebugInfo != 0) { //
// The user wants details only about this critical section
//
DumpCriticalSection (AddrCritSec, // critical section address
0, // end of address range if we are searching for critical sections
AddrDebugInfo, // debug info address
PointerSize, StackTraces ); // dump the stack trace
} else { if (UseTree == FALSE) {
//
// Parse all the critical sections list
//
//
// Get the offset of the list entry in the DebugInfo structure
//
ErrorCode = GetFieldOffset ("NTDLL!_RTL_CRITICAL_SECTION_DEBUG", "ProcessLocksList", &ProcessLocksListFieldOffset );
if (ErrorCode != S_OK) {
dprintf ("Bad symbols for NTDLL (error %u). Aborting.\n", ErrorCode ); goto Done; }
//
// Locate the address of the list head.
//
AddrListHead = GetExpression ("&NTDLL!RtlCriticalSectionList"); if (AddrListHead == 0 ) {
dprintf( "!cs: Unable to resolve NTDLL!RtlCriticalSectionList\n" "Please check your symbols\n" );
goto Done; }
//
// Read the list head
//
if (ReadPointer(AddrListHead, &ListHead) == FALSE) {
dprintf( "!cs: Unable to read memory at NTDLL!RtlCriticalSectionList\n" ); goto Done; }
Next = ListHead;
while (Next != AddrListHead) {
if (CheckControlC()) {
break; }
HaveGoodSymbols = DumpCriticalSection ( AddrCritSec, // critical section address
AddrEndCritSect, // end of address range if we are searching for critical sections
Next - ProcessLocksListFieldOffset, // debug info address
PointerSize, StackTraces ); // dump the stack trace
//
// Read the pointer to Next element from the list
//
if( HaveGoodSymbols == FALSE ) { break; }
if (ReadPointer (Next, &Next) == FALSE) {
dprintf ("!cs: Unable to read list entry at 0x%p - aborting.\n", Next); goto Done; } } } else {
//
// Parse all the critical section tree in verifier.dll.
//
if (TreeRoot == 0) {
AddrTreeRoot = GetExpression ("&verifier!CritSectSplayRoot"); if (AddrTreeRoot == 0 ) {
dprintf( "!cs: Unable to resolve verifier!CritSectSplayRoot\n" "Please check your symbols\n" );
goto Done; }
//
// Read the tree root.
//
if (ReadPointer(AddrTreeRoot, &TreeRoot) == FALSE) {
dprintf( "!cs: Unable to read memory at verifier!CritSectSplayRoot\n" ); goto Done; } }
dprintf ("Tree root %p\n", TreeRoot);
//
// Get the offset of the CriticalSection in the CRITICAL_SECTION_SPLAY_NODE structure.
//
ErrorCode = GetFieldOffset ("verifier!_CRITICAL_SECTION_SPLAY_NODE", "CriticalSection", &CriticalSectionFieldOffset );
if (ErrorCode != S_OK) {
dprintf ("Bad symbols for verifier.dll (error %u). Aborting.\n", ErrorCode ); goto Done; }
//
// Get the offset of the DebugInfo in the CRITICAL_SECTION_SPLAY_NODE structure.
//
ErrorCode = GetFieldOffset ("verifier!_CRITICAL_SECTION_SPLAY_NODE", "DebugInfo", &DebugInfoFieldOffset );
if (ErrorCode != S_OK) {
dprintf ("Bad symbols for verifier.dll (error %u). Aborting.\n", ErrorCode ); goto Done; }
//
// Get the offset of the LeftChild in the CRITICAL_SECTION_SPLAY_NODE structure.
//
ErrorCode = GetFieldOffset ("verifier!_RTL_SPLAY_LINKS", "LeftChild", &LeftChildFieldOffset );
if (ErrorCode != S_OK) {
dprintf ("Bad symbols for verifier.dll (error %u). Aborting.\n", ErrorCode ); goto Done; }
//
// Get the offset of the RightChild in the CRITICAL_SECTION_SPLAY_NODE structure.
//
ErrorCode = GetFieldOffset ("verifier!_RTL_SPLAY_LINKS", "RightChild", &RightChildFieldOffset );
if (ErrorCode != S_OK) {
dprintf ("Bad symbols for verifier.dll (error %u). Aborting.\n", ErrorCode ); goto Done; }
//
// Get the offset of the EnterThread, WaitThread, TryEnterThread, LeaveThread fields
// in the CRITICAL_SECTION_SPLAY_NODE structure.
// These fields were added after build 3590 (.NET Server Beta 3).
//
ErrorCode = GetFieldOffset ("verifier!_CRITICAL_SECTION_SPLAY_NODE", "EnterThread", &EnterThreadFieldOffset );
if (ErrorCode == S_OK) {
GetFieldOffset ("verifier!_CRITICAL_SECTION_SPLAY_NODE", "WaitThread", &WaitThreadFieldOffset );
GetFieldOffset ("verifier!_CRITICAL_SECTION_SPLAY_NODE", "TryEnterThread", &TryEnterThreadFieldOffset );
GetFieldOffset ("verifier!_CRITICAL_SECTION_SPLAY_NODE", "LeaveThread", &LeaveThreadFieldOffset ); } else {
//
// These fields are either not defined or we have a problem with ths symbols.
//
EnterThreadFieldOffset = 0; }
//
// Dump the tree recursively.
//
if (PointerSize == 4 ) {
dprintf ("Level %8s %8s %8s %8s %8s %8s %8s\n", "Node", "CS", "Debug", "Enter", "Wait", "TryEnter", "Leave");
dprintf ("--------------------------------------------------------------------\n"); } else {
dprintf ("Level %16s %16s %16s %8s %8s %8s %8s\n", "Node", "CS", "Debug", "Enter", "Wait", "TryEnter", "Leave"); dprintf ("--------------------------------------------------------------------------------------------\n"); } Level = 0;
DumpCSTreeRecursively (Level, TreeRoot); } }
Done:
EXIT_API();
return S_OK; }
|