/*++ Copyright (c) 1997 Microsoft Corporation Module Name: context.c Abstract: Dumps the AML Context Structure in Human-Readable-Form (HRF) Author: Stephane Plante (splante) 21-Mar-1997 Environment: User Mode. Revision History: --*/ #include "pch.h" VOID dumpAccessFieldObject( IN ULONG_PTR AccessFieldAddress, IN ULONG Verbose, IN ULONG IndentLevel ) { ACCFIELDOBJ fieldObj; BOOL result; UCHAR buffer[80]; ULONG returnLength; // // Initialize the indent buffer // IndentLevel = (IndentLevel > 79 ? 79 : IndentLevel); memset( buffer, ' ', IndentLevel ); buffer[IndentLevel] = '\0'; result = ReadMemory( AccessFieldAddress, &fieldObj, sizeof(ACCFIELDOBJ), &returnLength ); if (result != TRUE || returnLength != sizeof(ACCFIELDOBJ) || fieldObj.FrameHdr.dwSig != SIG_ACCFIELDOBJ) { dprintf( "%sdumpAccessFieldUnit: Coult not read ACCFIELDOBJ %08lx\n", buffer, AccessFieldAddress ); return; } dprintf( "%sAccess Field Object - %08lx\n" "%s Field Data Object: %08lx\n", buffer, AccessFieldAddress, buffer, fieldObj.pdataObj ); if (fieldObj.pdataObj != NULL && (Verbose & VERBOSE_CONTEXT)) { dumpPObject( (ULONG_PTR) fieldObj.pdataObj, Verbose, IndentLevel + 4 ); } dprintf( "%s Target Buffer: %08lx - %08lx\n" "%s Access Size: %08lx\n" "%s # of Accesses: %08lx\n" "%s Data Mask: %08lx\n" "%s # of Left Bits: %08lx\n" "%s # of Right Bits: %08lx\n" "%s Index to #/Accesses: %08lx\n" "%s Temp Data: %08lx\n", buffer, fieldObj.pbBuff, fieldObj.pbBuffEnd, buffer, fieldObj.dwAccSize, buffer, fieldObj.dwcAccesses, buffer, fieldObj.dwDataMask, buffer, fieldObj.iLBits, buffer, fieldObj.iRBits, buffer, fieldObj.iAccess, buffer, fieldObj.dwData ); dprintf( "%s Field Descriptor: %p\n", buffer, ( (ULONG_PTR) &(fieldObj.fd) - (ULONG_PTR) &fieldObj + AccessFieldAddress ) ); dumpFieldAddress( ( (ULONG_PTR) &(fieldObj.fd) - (ULONG_PTR) &fieldObj + AccessFieldAddress ), Verbose, IndentLevel + 4 ); } VOID dumpAccessFieldUnit( IN ULONG_PTR AccessFieldAddress, IN ULONG Verbose, IN ULONG IndentLevel ) { ACCFIELDUNIT fieldUnit; BOOL result; UCHAR buffer[80]; ULONG returnLength; // // Initialize the indent buffer // IndentLevel = (IndentLevel > 79 ? 79 : IndentLevel); memset( buffer, ' ', IndentLevel ); buffer[IndentLevel] = '\0'; result = ReadMemory( AccessFieldAddress, &fieldUnit, sizeof(ACCFIELDUNIT), &returnLength ); if (result != TRUE || returnLength != sizeof(ACCFIELDUNIT) || fieldUnit.FrameHdr.dwSig != SIG_ACCFIELDUNIT) { dprintf( "%sdumpAccessFieldUnit: Coult not read ACCFIELDUNIT %08lx\n", buffer, AccessFieldAddress ); return; } dprintf( "%sAccess Field Unit - %08lx\n" "%s Field Data Object: %08lx\n", buffer, AccessFieldAddress, buffer, fieldUnit.pdataObj ); if (fieldUnit.pdataObj != NULL && (Verbose & VERBOSE_CONTEXT)) { dumpPObject( (ULONG_PTR) fieldUnit.pdataObj, Verbose, IndentLevel + 4 ); } dprintf( "%s Source/Result Object: %08lx\n", buffer, fieldUnit.pdata ); if (fieldUnit.pdata != NULL && (Verbose & VERBOSE_CONTEXT)) { dumpPObject( (ULONG_PTR) fieldUnit.pdata, Verbose, IndentLevel + 4 ); } } VOID dumpAmlTerm( IN ULONG_PTR AmlTermAddress, IN ULONG Verbose, IN ULONG IndentLevel ) { AMLTERM amlTerm; BOOL result; INT i; UCHAR buffer[80]; ULONG returnLength; // // Initialize the indent buffer // IndentLevel = (IndentLevel > 79 ? 79 : IndentLevel); memset( buffer, ' ', IndentLevel ); buffer[IndentLevel] = '\0'; result = ReadMemory( AmlTermAddress, &amlTerm, sizeof(AMLTERM), &returnLength ); if (result != TRUE || returnLength != sizeof(AMLTERM)) { dprintf( "\n%sdumpAmlTerm: Could not read AMLTERM 0x%08lx\n", buffer, AmlTermAddress ); return; } if (amlTerm.pszTermName != NULL) { result = ReadMemory( (ULONG_PTR) amlTerm.pszTermName, Buffer, 32, &returnLength ); if (result && returnLength <= 32) { Buffer[returnLength] = '\0'; dprintf(" - %s\n", Buffer ); } } } VOID dumpCall( IN ULONG_PTR CallAddress, IN ULONG Verbose, IN ULONG IndentLevel ) { BOOL result; CALL call; INT i; UCHAR buffer[80]; ULONG returnLength; // // Initialize the indent buffer // IndentLevel = (IndentLevel > 79 ? 79 : IndentLevel); memset( buffer, ' ', IndentLevel ); buffer[IndentLevel] = '\0'; result = ReadMemory( CallAddress, &call, sizeof(CALL), &returnLength ); if (result != TRUE || returnLength != sizeof(CALL) || call.FrameHdr.dwSig != SIG_CALL) { dprintf( "%sdumpCall: Coult not read CALL %08lx\n", buffer, CallAddress ); return; } dprintf( "%sCall - %08lx\n", buffer, CallAddress ); // // Method // dprintf( "%s Method: %08lx\n", buffer, call.pnsMethod ); if (call.pnsMethod != NULL && (Verbose & VERBOSE_CONTEXT)) { dumpNSObject( (ULONG_PTR) call.pnsMethod, Verbose, IndentLevel + 4); } // // Previous Call Frame // if (Verbose & VERBOSE_CALL) { dprintf( "%s Previous Call Frame: %08lx\n" "%s Previous Owner: %08lx\n", buffer, call.pcallPrev, buffer, call.pownerPrev ); if (call.pownerPrev != NULL && (Verbose & VERBOSE_CONTEXT)) { dumpObjectOwner( (ULONG_PTR) call.pownerPrev, IndentLevel + 2 ); } } if (Verbose & VERBOSE_CONTEXT) { // // Dump arguments // dprintf( "%s Arguments (Current): %1d (%1d)\n", buffer, call.icArgs, call.iArg ); for (i = 0; i < call.icArgs; i++) { dprintf( "%s Argument(%d): %p\n", buffer, i, (ULONG_PTR) (call.pdataArgs + i) ); dumpPObject( (ULONG_PTR) (call.pdataArgs + i), Verbose, IndentLevel + 4 ); } dprintf( "%s Result: %08lx\n", buffer, call.pdataResult ); if (call.pdataResult != NULL) { dumpPObject( (ULONG_PTR) call.pdataResult, Verbose, IndentLevel + 4 ); } if (Verbose & VERBOSE_CALL) { dprintf( "%s Locals:\n", buffer ); for (i = 0; i < MAX_NUM_LOCALS; i++) { dumpObject( (ULONG) ( (PUCHAR) &(call.Locals[i]) - (PUCHAR) &call) + CallAddress, &(call.Locals[i]), Verbose, IndentLevel + 4 ); } } } } VOID dumpContext( IN ULONG_PTR ContextAddress, IN ULONG Verbose ) /*++ Routine Description: This routine dumps a context structure in HRF Arguments: ContextAddress - Where on the target machine the context is located Verbose - How verbose we should be Return Value: None --*/ { ULONG_PTR displacement; BOOL result; CTXT context; ULONG returnLength; // // Read the context from the target // result = ReadMemory( ContextAddress, &context, sizeof(CTXT), &returnLength ); if (result != TRUE || returnLength != sizeof(CTXT) ) { dprintf( "dumpContext: could not read CTXT %08lx\n", ContextAddress ); return; } // // Is it a context? // if (context.dwSig != SIG_CTXT) { dprintf( "dumpContext: Signature (%08lx) != SIG_CTXT (%08lx)\n", context.dwSig, SIG_CTXT ); return; } dprintf("Context - %08lx-%08lx\n",ContextAddress, context.pbCtxtEnd ); if (Verbose & VERBOSE_CONTEXT) { dprintf( " AllocatedContextList: F:%08lx B:%08lx\n" " QueingContextList: F:%08lx B:%08lx\n" " ContextListHead: %08lx\n" " SynchronizeLevel: %08lx\n" " CurrentOpByte: %08lx\n" " AsyncCallBack: %08lx", context.listCtxt.plistNext, context.listCtxt.plistPrev, context.listQueue.plistNext, context.listQueue.plistPrev, context.pplistCtxtQueue, context.dwSyncLevel, context.pbOp, context.pfnAsyncCallBack ); if (context.pfnAsyncCallBack != NULL) { GetSymbol( context.pfnAsyncCallBack, Buffer, &displacement ); dprintf(" %s", Buffer ); } dprintf( "\n" " AsyncCallBackContext: %08lx\n" " AsyncDataCallBack: %08lx\n", context.pvContext, context.pdataCallBack ); } dprintf( " Flags: %08lx", context.dwfCtxt ); if (context.dwfCtxt & CTXTF_TIMER_PENDING) { dprintf(" Timer"); } if (context.dwfCtxt & CTXTF_TIMEOUT) { dprintf(" Timeout"); } if (context.dwfCtxt & CTXTF_READY) { dprintf(" Ready"); } if (context.dwfCtxt & CTXTF_NEED_CALLBACK) { dprintf(" CallBack"); } dprintf("\n"); dprintf( " NameSpace Object: %08lx\n", context.pnsObj ); if (Verbose & VERBOSE_CONTEXT) { dprintf( " NameSpace Scope: %08lx\n" " NameSpace Owner: %08lx\n", context.pnsScope, context.powner ); if (context.powner != NULL) { dumpObjectOwner( (ULONG_PTR) context.powner, 2 ); } } dprintf( " Current Call Frame: %08lx\n", context.pcall ); if (context.pcall != NULL) { dumpCall( (ULONG_PTR) context.pcall, (Verbose & ~VERBOSE_CONTEXT), 4 ); } dumpStack( ContextAddress, &context, Verbose, 2 ); } VOID dumpFieldAddress( IN ULONG_PTR FieldAddress, IN ULONG Verbose, IN ULONG IndentLevel ) { FIELDDESC fd; BOOL result; UCHAR buffer[80]; ULONG returnLength; // // Initialize the indent buffer // IndentLevel = (IndentLevel > 79 ? 79 : IndentLevel); memset( buffer, ' ', IndentLevel ); buffer[IndentLevel] = '\0'; result = ReadMemory( FieldAddress, &fd, sizeof(FIELDDESC), &returnLength ); if (result != TRUE || returnLength != sizeof(FIELDDESC) ) { dprintf( "%sdumpFieldAddress: Coult not read FIELDDESC %08lx\n", buffer, FieldAddress ); return; } dprintf( "%sField Descriptor - %08lx\n" "%s ByteOffset: %08lx\n" "%s Start Bit Position: %08lx\n" "%s Number of Bits: %08lx\n" "%s Flags: %08lx\n", buffer, FieldAddress, buffer, fd.dwByteOffset, buffer, fd.dwStartBitPos, buffer, fd.dwNumBits, buffer, fd.dwFieldFlags ); } VOID dumpListContexts( IN VOID ) /*++ --*/ { PLIST pList; PLIST pListNext; } VOID dumpObjectOwner( IN ULONG_PTR ObjOwnerAddress, IN ULONG IndentLevel ) { BOOL result; OBJOWNER objowner; UCHAR buffer[80]; ULONG returnLength; // // Initialize the indent buffer // IndentLevel = (IndentLevel > 79 ? 79 : IndentLevel); memset( buffer, ' ', IndentLevel ); buffer[IndentLevel] = '\0'; result = ReadMemory( ObjOwnerAddress, &objowner, sizeof(OBJOWNER), &returnLength ); if (result == TRUE && returnLength == sizeof(OBJOWNER) && objowner.dwSig == SIG_OBJOWNER) { dprintf( "%sObjectOwner - %08lx\n" "%s NameSpaceObject: %08lx\n" "%s List: F:%08lx B:%08lx\n", buffer, ObjOwnerAddress, buffer, objowner.pnsObjList, buffer, objowner.list.plistNext, objowner.list.plistPrev ); } else { dprintf( "%sdumpObjectOwner: Could not read OBJOWNER %08lx\n", buffer,ObjOwnerAddress ); } } VOID dumpScope( IN ULONG_PTR ScopeAddress, IN ULONG Verbose, IN ULONG IndentLevel ) { BOOL result; SCOPE scope; UCHAR indent[80]; ULONG returnLength; // // Initialize the indent buffer // IndentLevel = (IndentLevel > 79 ? 79 : IndentLevel); memset( indent, ' ', IndentLevel ); indent[IndentLevel] = '\0'; result = ReadMemory( ScopeAddress, &scope, sizeof(SCOPE), &returnLength ); if (result != TRUE || returnLength != sizeof(SCOPE) || scope.FrameHdr.dwSig != SIG_SCOPE) { dprintf( "%sdumpScope: Coult not read SCOPE %08lx\n", indent, ScopeAddress ); return; } dprintf( "%sScope - %08lx\n", indent, ScopeAddress ); dprintf( "%s ScopeEnd: %08lx\n" "%s ReturnAddress: %08lx\n" "%s Previous Scope: %08lx\n", indent, scope.pbOpEnd, indent, scope.pbOpRet, indent, scope.pnsPrevScope ); if (Verbose & VERBOSE_CALL) { dumpNSObject( (ULONG_PTR) scope.pnsPrevScope, Verbose, IndentLevel + 4); } dprintf( "%s Previous Owner: %08lx\n", indent, scope.pownerPrev ); if (Verbose & VERBOSE_CALL) { dumpObjectOwner( (ULONG_PTR) scope.pownerPrev, IndentLevel + 4 ); } dprintf( "%s Result Object: %08lx\n", indent, scope.pdataResult ); if (scope.pdataResult != NULL && (Verbose & VERBOSE_CALL) ) { dumpPObject( (ULONG_PTR) scope.pdataResult, Verbose, IndentLevel + 4 ); } } VOID dumpStack( IN ULONG_PTR ContextAddress, IN PCTXT Context, IN ULONG Verbose, IN ULONG IndentLevel ) { ULONG_PTR displacement; BOOL result; FRAMEHDR frame; PUCHAR frameAddress; UCHAR indent[80]; UCHAR buffer[5]; ULONG returnLength; // // Initialize the indent buffer // IndentLevel = (IndentLevel > 79 ? 79 : IndentLevel); memset( indent, ' ', IndentLevel ); indent[IndentLevel] = '\0'; buffer[4] = '\0'; dprintf( "%sStack - %p-%08lx (%08lx)\n", indent, ContextAddress, Context->LocalHeap.pbHeapEnd, Context->pbCtxtEnd ); // // Calculate where the first frame lies // frameAddress = Context->LocalHeap.pbHeapEnd; while (frameAddress < Context->pbCtxtEnd) { result = ReadMemory( (ULONG_PTR) frameAddress, &frame, sizeof(FRAMEHDR), &returnLength ); if (result != TRUE || returnLength != sizeof(FRAMEHDR)) { dprintf( "%sdumpStack: could not read FRAMEHDR %08lx\n", indent, (ULONG_PTR) frameAddress ); return; } memcpy( buffer, (PUCHAR) &(frame.dwSig), 4 ); dprintf( "%s %p: %s - (Length %08lx) (Flags %08lx)\n" "%s ParseFunction %08lx", indent, (ULONG_PTR) frameAddress, buffer, frame.dwLen, frame.dwfFrame, indent, frame.pfnParse ); if (frame.pfnParse != NULL) { GetSymbol( frame.pfnParse, Buffer, &displacement ); dprintf(" %s", Buffer ); } dprintf("\n"); // // Do we know how to crack the frame? // switch(frame.dwSig) { case SIG_CALL: dumpCall( (ULONG_PTR) frameAddress, Verbose, IndentLevel + 4 ); break; case SIG_SCOPE: dumpScope( (ULONG_PTR) frameAddress, Verbose, IndentLevel + 4 ); break; case SIG_TERM: dumpTerm( (ULONG_PTR) frameAddress, Verbose, IndentLevel + 4 ); break; case SIG_ACCFIELDUNIT: dumpAccessFieldUnit( (ULONG_PTR) frameAddress, Verbose, IndentLevel + 4 ); break; case SIG_ACCFIELDOBJ: dumpAccessFieldObject( (ULONG_PTR) frameAddress, Verbose, IndentLevel + 4 ); break; } // // Make sure that there is some white space present // dprintf("\n\n"); // // Next11 // frameAddress += frame.dwLen; } } VOID dumpTerm( IN ULONG_PTR TermAddress, IN ULONG Verbose, IN ULONG IndentLevel ) { BOOL result; INT i; TERM term; UCHAR indent[80]; ULONG returnLength; // // Initialize the indent buffer // IndentLevel = (IndentLevel > 79 ? 79 : IndentLevel); memset( indent, ' ', IndentLevel ); indent[IndentLevel] = '\0'; result = ReadMemory( TermAddress, &term, sizeof(TERM), &returnLength ); if (result != TRUE || returnLength != sizeof(TERM) || term.FrameHdr.dwSig != SIG_TERM) { dprintf( "%sdumpTerm: Coult not read TERM %08lx\n", indent, TermAddress ); return; } dprintf( "%sTerm - %08lx\n", indent, TermAddress ); dprintf( "%s OpCodeStart: %08lx\n" "%s OpCodeEnd: %08lx\n" "%s ScopeEnd: %08lx\n" "%s NameSpaceObject: %08lx\n", indent, term.pbOpTerm, indent, term.pbOpEnd, indent, term.pbScopeEnd, indent, term.pnsObj ); if ( term.pnsObj != NULL && (Verbose & VERBOSE_CALL)) { dumpNSObject( (ULONG_PTR) term.pnsObj, Verbose, IndentLevel + 4); } dprintf( "%s Aml Term: %08lx", indent, term.pamlterm ); if (term.pamlterm != NULL) { dumpAmlTerm( (ULONG_PTR) term.pamlterm, Verbose, IndentLevel + 4); } else { dprintf("\n"); } // // Dump arguments // dprintf( "%s Arguments (Current): %1d (%1d)\n", indent, term.icArgs, term.iArg ); for (i = 0; i < term.icArgs; i++) { dprintf( "%s Argument(%d): %p\n", indent, i, (ULONG_PTR) (term.pdataArgs + i) ); if (Verbose & VERBOSE_CALL) { dumpPObject( (ULONG_PTR) (term.pdataArgs + i), Verbose, IndentLevel + 4 ); } } dprintf( "%s Result: %08lx\n", indent, term.pdataResult ); if (term.pdataResult != NULL && (Verbose & VERBOSE_CALL) ) { dumpPObject( (ULONG_PTR) term.pdataResult, Verbose, IndentLevel + 4 ); } }