573 lines
10 KiB
C
573 lines
10 KiB
C
/*++
|
||
|
||
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(
|
||
"<buffer> %08lx-%08lx",
|
||
object.pbDataBuff,
|
||
object.pbDataBuff+object.dwDataLen
|
||
);
|
||
break;
|
||
case OBJTYPE_PKGDATA:
|
||
dprintf("<package> %08lx", ObjectAddress );
|
||
break;
|
||
case OBJTYPE_FIELDUNIT:
|
||
dprintf("<fieldunit> %08lx", ObjectAddress );
|
||
break;
|
||
case OBJTYPE_DEVICE:
|
||
dprintf("<device> %08lx", ObjectAddress );
|
||
break;
|
||
case OBJTYPE_EVENT:
|
||
dprintf("<event> %08lx", ObjectAddress );
|
||
break;
|
||
case OBJTYPE_METHOD:
|
||
dprintf("<method> %08lx", ObjectAddress );
|
||
break;
|
||
case OBJTYPE_MUTEX:
|
||
dprintf("<mutex> %08lx", ObjectAddress );
|
||
break;
|
||
case OBJTYPE_OPREGION:
|
||
dprintf("<opregion> %08lx", ObjectAddress );
|
||
break;
|
||
case OBJTYPE_POWERRES:
|
||
dprintf("<powerres> %08lx", ObjectAddress );
|
||
break;
|
||
case OBJTYPE_PROCESSOR:
|
||
dprintf("<processor> %08lx", ObjectAddress );
|
||
break;
|
||
case OBJTYPE_THERMALZONE:
|
||
dprintf("<thermalzone> %08lx", ObjectAddress );
|
||
break;
|
||
case OBJTYPE_BUFFFIELD:
|
||
dprintf("<bufffield> %08lx", ObjectAddress );
|
||
break;
|
||
case OBJTYPE_DDBHANDLE:
|
||
dprintf("<ddbhandle> %08lx", ObjectAddress );
|
||
break;
|
||
case OBJTYPE_DEBUG:
|
||
dprintf("<debug> %08lx", ObjectAddress );
|
||
break;
|
||
case OBJTYPE_DATAALIAS:
|
||
dprintf("<dataalias> %08lx", ObjectAddress );
|
||
break;
|
||
case OBJTYPE_BANKFIELD:
|
||
dprintf("<bankfield> %08lx", ObjectAddress );
|
||
break;
|
||
case OBJTYPE_FIELD:
|
||
dprintf("<field> %08lx", ObjectAddress );
|
||
break;
|
||
case OBJTYPE_INDEXFIELD:
|
||
dprintf("<indexfield> %08lx", ObjectAddress );
|
||
break;
|
||
default:
|
||
dprintf("<unknown> %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;
|
||
|
||
}
|
||
|
||
}
|