/*++ Copyright (c) 1997 Microsoft Corporation Module Name: stack.c Abstract: Dumps the AML Context Structure in Human-Readable-Form (HRF) Author: Stephane Plante (splante) 26-Oct-1997 Environment: User Mode. Revision History: --*/ #include "pch.h" VOID stackArgument( IN ULONG_PTR ObjectAddress ) { BOOL result; OBJDATA object; PUCHAR buffer = NULL; ULONG returnLength; // // Read the object // result = ReadMemory( ObjectAddress, &object, sizeof(OBJDATA), &returnLength ); if (!result || returnLength != sizeof(OBJDATA)) { dprintf("_BAD_"); return; } if (object.pbDataBuff != 0) { buffer = LocalAlloc( LPTR, object.dwDataLen+1 ); if (buffer == NULL) { dprintf("_MEM_"); return; } result = ReadMemory( (ULONG_PTR) object.pbDataBuff, buffer, object.dwDataLen, &returnLength ); if (!result || returnLength != object.dwDataLen) { dprintf("_BUF_"); return; } } switch (object.dwDataType) { case OBJTYPE_INTDATA: dprintf("0x%x", object.uipDataValue); break; case OBJTYPE_STRDATA: buffer[object.dwDataLen] = '\0'; dprintf("%s",buffer); break; case OBJTYPE_BUFFDATA: dprintf( " %08lx-%08lx", object.pbDataBuff, object.pbDataBuff+object.dwDataLen ); break; case OBJTYPE_PKGDATA: dprintf(" %08lx", ObjectAddress ); break; case OBJTYPE_FIELDUNIT: dprintf(" %08lx", ObjectAddress ); break; case OBJTYPE_DEVICE: dprintf(" %08lx", ObjectAddress ); break; case OBJTYPE_EVENT: dprintf(" %08lx", ObjectAddress ); break; case OBJTYPE_METHOD: dprintf(" %08lx", ObjectAddress ); break; case OBJTYPE_MUTEX: dprintf(" %08lx", ObjectAddress ); break; case OBJTYPE_OPREGION: dprintf(" %08lx", ObjectAddress ); break; case OBJTYPE_POWERRES: dprintf(" %08lx", ObjectAddress ); break; case OBJTYPE_PROCESSOR: dprintf(" %08lx", ObjectAddress ); break; case OBJTYPE_THERMALZONE: dprintf(" %08lx", ObjectAddress ); break; case OBJTYPE_BUFFFIELD: dprintf(" %08lx", ObjectAddress ); break; case OBJTYPE_DDBHANDLE: dprintf(" %08lx", ObjectAddress ); break; case OBJTYPE_DEBUG: dprintf(" %08lx", ObjectAddress ); break; case OBJTYPE_DATAALIAS: dprintf(" %08lx", ObjectAddress ); break; case OBJTYPE_BANKFIELD: dprintf(" %08lx", ObjectAddress ); break; case OBJTYPE_FIELD: dprintf(" %08lx", ObjectAddress ); break; case OBJTYPE_INDEXFIELD: dprintf(" %08lx", ObjectAddress ); break; default: dprintf(" %08lx", ObjectAddress ); break; } } VOID stackCall( IN ULONG_PTR CallAddress ) /*++ Format Displayed: ResultAddress MethodName( Arg0, ..., ArgN ) --*/ { ULONG_PTR address; BOOL result; CALL call; INT i; NSOBJ object; PUCHAR objectPath; ULONG returnLength; result = ReadMemory( CallAddress, &call, sizeof(CALL), &returnLength ); if (result != TRUE || returnLength != sizeof(CALL) || call.FrameHdr.dwSig != SIG_CALL) { dprintf( "stackCall: --- Coult not read call frame %08lx\n", CallAddress ); return; } if (call.pnsMethod == NULL) { dprintf( "%08lx --- No method\n", CallAddress ); return; } // // Display result address // dprintf("CALL %08lx ", CallAddress ); // // Display the function name // objectPath = stackGetObjectPath( (ULONG_PTR) call.pnsMethod ); dprintf("%s(", objectPath); // // Display all parsed arguments; // for (i = 0; i < call.iArg; i++) { // // What is the address of the argument // address = (ULONG_PTR) &call.pdataArgs[i]; // // Display that argument // stackArgument( address ); if (i < (call.icArgs - 1)) { dprintf(","); } } // // Let the user know how many unprocessed arguments there are // for (; i < call.icArgs; i++) { dprintf("_???_"); if (i < (call.icArgs-1)) { dprintf(","); } } dprintf(")\n"); } PUCHAR stackGetAmlTermPath( IN ULONG_PTR AmlTermAddress ) { AMLTERM amlTerm; BOOL result; static UCHAR termPath[2049]; ULONG i; ULONG resultLength; result = ReadMemory( AmlTermAddress, &amlTerm, sizeof(AMLTERM), &resultLength ); if (!result || resultLength != sizeof(AMLTERM)) { return NULL; } if (amlTerm.pszTermName == NULL) { return NULL; } result = ReadMemory( (ULONG_PTR) amlTerm.pszTermName, &termPath, 2048, &resultLength ); if (!result || resultLength == 0) { return NULL; } termPath[resultLength] = '\0'; return termPath; } PUCHAR stackGetObjectPath( IN ULONG_PTR ObjectAddress ) { BOOL result; NSOBJ object; static UCHAR namePath[2049]; ULONG i; ULONG resultLength; // // Read the object // result = ReadMemory( ObjectAddress, &object, sizeof(NSOBJ), &resultLength ); if (!result || resultLength != sizeof(NSOBJ)) { return NULL; } if (object.pnsParent == NULL) { strcpy( namePath, "\\"); } else { NSOBJ parent; stackGetObjectPath( (ULONG_PTR) object.pnsParent ); result = ReadMemory( (ULONG_PTR) object.pnsParent, &parent, sizeof(NSOBJ), &resultLength ); if (!result || resultLength != sizeof(NSOBJ)) { return NULL; } if (parent.pnsParent != NULL) { strcat(namePath, "."); } strncat( namePath, (PUCHAR) &(object.dwNameSeg), sizeof(NAMESEG) ); for (i = strlen(namePath); i > 0; --i) { if (namePath[i-1] == '_') { namePath[i-1] = '\0'; } else { break; } } } return namePath; } VOID stackTerm( IN ULONG_PTR TermAddress ) /*++ Format Displayed: term TermAddress TermName( Arg0, ..., ArgN ) --*/ { ULONG_PTR address; BOOL result; INT i; NSOBJ object; PUCHAR objectPath; TERM term; ULONG returnLength; result = ReadMemory( TermAddress, &term, sizeof(TERM), &returnLength ); if (result != TRUE || returnLength != sizeof(TERM) || term.FrameHdr.dwSig != SIG_TERM) { dprintf( "stackTerm: --- Coult not read call frame %08lx\n", TermAddress ); return; } if (term.pamlterm == NULL) { dprintf( "%08lx --- No term\n", TermAddress ); return; } // // Display result address // dprintf("TERM %08lx ", TermAddress ); // // Display the function name // objectPath = stackGetAmlTermPath( (ULONG_PTR) term.pamlterm ); dprintf("%s(", objectPath); // // Display all parsed arguments; // for (i = 0; i < term.iArg; i++) { // // What is the address of the argument // address = (ULONG_PTR) &term.pdataArgs[i]; // // Display that argument // stackArgument( address ); if (i < (term.icArgs - 1)) { dprintf(","); } } // // Let the user know how many unprocessed arguments there are // for (; i < term.icArgs; i++) { dprintf("_???_"); if (i < (term.icArgs-1)) { dprintf(","); } } dprintf(")\n"); } VOID stackTrace( IN ULONG_PTR ContextAddress, IN ULONG Verbose ) /*++ Routine Description: This routine dumps a context as a stack Arguments: ContextAddress - Where the stack is located Verbose - How much information to display Return Value: None --*/ { BOOL callSeen = FALSE; BOOL result; CTXT context; FRAMEHDR frame; PUCHAR frameAddress; ULONG returnLength; // // Read the context from the target // result = ReadMemory( ContextAddress, &context, sizeof(CTXT), &returnLength ); if (result != TRUE || returnLength != sizeof(CTXT)) { dprintf( "stackTrace: --- Could not read Context %08lx\n", ContextAddress ); return; } if (context.dwSig != SIG_CTXT) { dprintf( "stackTrace: --- Not a Context (%08lx)\n", context.dwSig ); return; } // // Begin to walk the frames // frameAddress = context.LocalHeap.pbHeapEnd; while (frameAddress < context.pbCtxtEnd) { result = ReadMemory( (ULONG_PTR) frameAddress, &frame, sizeof(FRAMEHDR), &returnLength ); if (result != TRUE || returnLength != sizeof(FRAMEHDR)) { dprintf( "stackTrace: --- could not read frame %08lx\n", frameAddress ); return; } // // Do we care about the frame? // switch(frame.dwSig) { case SIG_CALL: callSeen = TRUE; stackCall( (ULONG_PTR) frameAddress ); break; case SIG_TERM: if (!callSeen || (callSeen && Verbose)) { stackTerm( (ULONG_PTR) frameAddress ); } } // switch // // Next // frameAddress += frame.dwLen; } }