windows-nt/Source/XPSP1/NT/base/win32/fusion/debugexts/dumputils.cpp

330 lines
10 KiB
C++
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
#include "windows.h"
#include "sxstypes.h"
#define KDEXT_64BIT
#include "wdbgexts.h"
#include "fusiondbgext.h"
#define RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_RELEASE_ON_DEACTIVATION (0x00000001)
#define RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_NO_DEACTIVATE (0x00000002)
#define RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ON_FREE_LIST (0x00000004)
#define RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_HEAP_ALLOCATED (0x00000008)
BOOL
DumpActivationContextStackFrame(
PCSTR pcsLineHeader,
ULONG64 ulStackFrameAddress,
ULONG ulDepth,
DWORD dwFlags
)
{
ULONG64 ulPreviousPtr = 0;
ULONG64 ulActivationContextPointer = 0;
ULONG ulFrameFlags = 0;
if (!pcsLineHeader) pcsLineHeader = "";
GetFieldValue(ulStackFrameAddress, "nt!_RTL_ACTIVATION_CONTEXT_STACK_FRAME", "Previous", ulPreviousPtr);
GetFieldValue(ulStackFrameAddress, "nt!_RTL_ACTIVATION_CONTEXT_STACK_FRAME", "ActivationContext", ulActivationContextPointer);
GetFieldValue(ulStackFrameAddress, "nt!_RTL_ACTIVATION_CONTEXT_STACK_FRAME", "Flags", ulFrameFlags);
dprintf(
"%sActivation stack frame @ 0x%p (depth %ld):\n"
"%s Previous : 0x%p\n"
"%s ActivationContext : 0x%p\n"
"%s Flags : 0x%08lx ",
pcsLineHeader, ulStackFrameAddress, ulDepth,
pcsLineHeader, ulPreviousPtr,
pcsLineHeader, ulActivationContextPointer,
pcsLineHeader, ulFrameFlags);
if (ulFrameFlags != 0)
{
dprintf("(");
if (ulFrameFlags & RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_RELEASE_ON_DEACTIVATION)
dprintf("ReleaseOnDeactivate ");
if (ulFrameFlags & RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_NO_DEACTIVATE)
dprintf("NoDeactivate ");
if (ulFrameFlags & RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ON_FREE_LIST)
dprintf("OnFreeList");
if (ulFrameFlags & RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_HEAP_ALLOCATED)
dprintf("HeapAllocated ");
dprintf(")");
}
dprintf ("\n");
return 0;
}
BOOL
DumpActCtxStackFullStack(
ULONG64 ulFirstStackFramePointer
)
{
ULONG ulDepth = 0;
ULONG64 ulStackFramePtr = ulFirstStackFramePointer;
while (ulStackFramePtr)
{
DumpActivationContextStackFrame(" ", ulStackFramePtr, ulDepth++, 0xffff);
GetFieldValue(ulStackFramePtr, "nt!_RTL_ACTIVATION_CONTEXT_STACK_FRAME", "Previous", ulStackFramePtr);
if (CheckControlC() || (ulStackFramePtr == 0))
break;
}
return TRUE;
}
BOOL
DumpActCtxData(
PCSTR LineHeader,
const ULONG64 ActCtxDataAddressInDebugeeSpace,
ULONG ulFlags
)
{
//
// ACTIVATION_CONTEXT_DATA is a self-referential type, so dumping it is
// easy once it's all in memory.
//
ACTIVATION_CONTEXT_DATA ActData;
BYTE *pbActualData = NULL;
BOOL fOk = FALSE;
ULONG cbRead = 0;
if (!LineHeader) LineHeader = "";
if (!ReadMemory(ActCtxDataAddressInDebugeeSpace, &ActData, sizeof(ActData), &cbRead) ||
(cbRead != sizeof(ActData)))
{
dprintf(
"%sFailed reading ACTIVATION_CONTEXT_DATA @ %p , or wrong kind of block is there.\n",
LineHeader,
ActCtxDataAddressInDebugeeSpace);
goto Exit;
}
//
// Let's create a blob of memory that can hold the whole thing, then
//
pbActualData = new BYTE[ActData.TotalSize];
if (!pbActualData)
{
dprintf(
"%sUnable to allocate %d bytes to store activation context data\n",
LineHeader,
ActData.TotalSize);
goto Exit;
}
//
// And re-read from the debugee
//
if (!ReadMemory(ActCtxDataAddressInDebugeeSpace, pbActualData, ActData.TotalSize, &cbRead) ||
(cbRead != ActData.TotalSize))
{
dprintf(
"%sUnable to read in %d bytes from %p as an activation context object?\n",
LineHeader,
ActData.TotalSize,
ActCtxDataAddressInDebugeeSpace);
goto Exit;
}
DbgExtPrintActivationContextData(
(ulFlags & DUMPACTCTXDATA_FLAG_FULL) == DUMPACTCTXDATA_FLAG_FULL,
(PCACTIVATION_CONTEXT_DATA)pbActualData,
L" "
);
fOk = TRUE;
Exit:
if (pbActualData)
delete[] pbActualData;
return fOk;
}
BOOL
DumpActCtx(
const ULONG64 ActCtxAddressInDebugeeSpace,
ULONG ulFlags
)
{
ULONG64 ActCtxAddr = ActCtxAddressInDebugeeSpace;
ULONG64 ulSymbolOffset = 0;
PRIVATE_ACTIVATION_CONTEXT prvContextFilled = { 0 };
CHAR NotificationSymbol[1024] = { 0 };
BOOL fOk = FALSE;
int i = 0;
#define GET_FIELD(a, fn, dst) { GetFieldData((a), "nt!_ACTIVATION_CONTEXT", #fn, sizeof((dst).##fn), (PVOID)&((dst).##fn)); }
GET_FIELD(ActCtxAddr, Flags, prvContextFilled);
GET_FIELD(ActCtxAddr, RefCount, prvContextFilled);
GET_FIELD(ActCtxAddr, ActivationContextData, prvContextFilled);
GET_FIELD(ActCtxAddr, NotificationRoutine, prvContextFilled);
GET_FIELD(ActCtxAddr, NotificationContext, prvContextFilled);
// GET_FIELD(ActCtxAddr, SentNotifications, prvContextFilled);
// GET_FIELD(ActCtxAddr, DisabledNotifications, prvContextFilled);
// GET_FIELD(ActCtxAddr, StorageMap, prvContextFilled);
// GET_FIELD(ActCtxAddr, InlineStorageMapEntries, prvContextFilled);
#undef GET_FIELD
dprintf(
"Activation context structure @ 0x%p\n"
" RefCount %d\n"
" Flags 0x%08x\n"
" ActivationContextData 0x%p\n",
ActCtxAddressInDebugeeSpace,
(LONG)prvContextFilled.RefCount,
(ULONG)prvContextFilled.Flags,
(PVOID)prvContextFilled.ActivationContextData);
if (ulFlags & DUMPACTCTX_DATA)
{
// if (!DumpActCtxData(" ", (ULONG64)prvContextFilled.ActivationContextData, ulFlags))
// goto Exit;
DumpActCtxData(" ", (ULONG64)prvContextFilled.ActivationContextData, ulFlags);
}
//
// This icky gunk is to print out a symbol name properly...
//
dprintf(" NotificationRoutine 0x%p ", prvContextFilled.NotificationRoutine);
GetSymbol((ULONG64)prvContextFilled.NotificationRoutine, NotificationSymbol, &ulSymbolOffset);
if (strlen(NotificationSymbol))
{
dprintf("(%s" , NotificationSymbol);
if (ulSymbolOffset)
dprintf("+0x%p", ulSymbolOffset);
dprintf(")");
}
dprintf("\n");
dprintf(" NotificationContext 0x%p\n", prvContextFilled.NotificationContext);
dprintf(" SentNotifications [");
for (i = 0; i < NUMBER_OF(prvContextFilled.SentNotifications); i++)
{
if (i) dprintf(" ");
dprintf("%d", prvContextFilled.SentNotifications[i]);
}
dprintf("]\n");
dprintf(" DisabledNotifications [");
for (i = 0; i < NUMBER_OF(prvContextFilled.DisabledNotifications); i++)
{
if (i) dprintf(" ");
dprintf("%d", prvContextFilled.DisabledNotifications[i]);
}
dprintf("]\n");
{
ULONG ulFlags, ulCount;
ULONG64 ulMapAddress;
GetFieldValue(ActCtxAddressInDebugeeSpace, "_ACTIVATION_CONTEXT", "StorageMap.Flags", ulFlags);
GetFieldValue(ActCtxAddressInDebugeeSpace, "_ACTIVATION_CONTEXT", "StorageMap.AssemblyCount", ulCount);
GetFieldValue(ActCtxAddressInDebugeeSpace, "_ACTIVATION_CONTEXT", "StorageMap.AssemblyArray", ulMapAddress);
dprintf(
" StorageMap (Flags = 0x%08lx Count = %d MapArray = %p)\n",
ulFlags,
ulCount,
ulMapAddress);
}
fOk = TRUE;
return fOk;
}
BOOL
GetActiveActivationContextData(
PULONG64 pulActiveActCtx
)
{
ULONG64 ulTebAddress = 0, ulPebAddress = 0;
ULONG64 ulTebActiveFrameAddress = 0;
//
// The algorithm is like this:
// - Look at Teb.ActivationContextStack.ActiveFrame.ActivationContext. If this is
// nonzero, stop looking.
// - Now look at the process default activation context in Peb.ActivationContextData.
// If this is nonzero, stop looking.
// - Look at the system default act ctx data, in Peb.SystemDefaultActivationContextData
// If this is nonzero, stop looking.
// - Didn't find any active activation context data? Fooey.
//
*pulActiveActCtx = 0;
GetTebAddress(&ulTebAddress);
GetPebAddress(0, &ulPebAddress);
if (ulTebAddress != NULL)
{
// Look at the active stack frame in the teb
GetFieldValue(ulTebAddress, "nt!TEB", "ActivationContextStack.ActiveFrame", ulTebActiveFrameAddress);
if (ulTebActiveFrameAddress)
{
ULONG64 ulActivationContextFrame;
// Get the pointer to the active activation context itself
GetFieldValue(
ulTebActiveFrameAddress,
"nt!_RTL_ACTIVATION_CONTEXT_STACK_FRAME",
"ActivationContext",
ulActivationContextFrame);
// If that was valid, then ask for the pointer to the activation context data
if (ulActivationContextFrame)
{
GetFieldValue(
ulActivationContextFrame,
"nt!ACTIVATION_CONTEXT",
"ActivationContextData",
*pulActiveActCtx);
return TRUE;
}
// Is this really requesting the process default?
else if (ulActivationContextFrame == NULL)
{
// Then get it and return
GetFieldValue(ulPebAddress, "nt!PEB", "ActivationContextData", *pulActiveActCtx);
return TRUE;
}
}
}
//
// Still nothing, so go look at the process default directly
//
GetFieldValue(ulPebAddress, "nt!PEB", "ActivationContextData", *pulActiveActCtx);
if (*pulActiveActCtx)
{
return TRUE;
}
//
// Otherwise...
//
GetFieldValue(ulPebAddress, "nt!PEB", "SystemDefaultActivationContextData", *pulActiveActCtx);
return (*pulActiveActCtx ? TRUE : FALSE);
}