mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 01:55:19 +00:00
[NTOS:KD] Use a PCONTEXT instead of a PKTRAP_FRAME in KDBG
This commit is contained in:
parent
ba37323a62
commit
baa47fa5e0
7 changed files with 170 additions and 284 deletions
|
@ -29,12 +29,17 @@ KdpReportExceptionStateChange(IN PEXCEPTION_RECORD ExceptionRecord,
|
||||||
{
|
{
|
||||||
KD_CONTINUE_TYPE Return = kdHandleException;
|
KD_CONTINUE_TYPE Return = kdHandleException;
|
||||||
#ifdef KDBG
|
#ifdef KDBG
|
||||||
|
EXCEPTION_RECORD64 ExceptionRecord64;
|
||||||
|
|
||||||
/* Check if this is an assertion failure */
|
/* Check if this is an assertion failure */
|
||||||
if (ExceptionRecord->ExceptionCode == STATUS_ASSERTION_FAILURE)
|
if (ExceptionRecord->ExceptionCode == STATUS_ASSERTION_FAILURE)
|
||||||
{
|
{
|
||||||
/* Bump EIP to the instruction following the int 2C */
|
/* Bump EIP to the instruction following the int 2C */
|
||||||
ContextRecord->Eip += 2;
|
ContextRecord->Eip += 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ExceptionRecord32To64((PEXCEPTION_RECORD32)ExceptionRecord,
|
||||||
|
&ExceptionRecord64);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Get out of here if the Debugger isn't connected */
|
/* Get out of here if the Debugger isn't connected */
|
||||||
|
@ -42,10 +47,9 @@ KdpReportExceptionStateChange(IN PEXCEPTION_RECORD ExceptionRecord,
|
||||||
|
|
||||||
#ifdef KDBG
|
#ifdef KDBG
|
||||||
/* Call KDBG if available */
|
/* Call KDBG if available */
|
||||||
Return = KdbEnterDebuggerException(ExceptionRecord,
|
Return = KdbEnterDebuggerException(&ExceptionRecord64,
|
||||||
PreviousMode,
|
PreviousMode,
|
||||||
ContextRecord,
|
ContextRecord,
|
||||||
TrapFrame,
|
|
||||||
!SecondChanceException);
|
!SecondChanceException);
|
||||||
#else /* not KDBG */
|
#else /* not KDBG */
|
||||||
/* We'll manually dump the stack for the user... */
|
/* We'll manually dump the stack for the user... */
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#include <asm.inc>
|
#include <asm.inc>
|
||||||
#include <ks386.inc>
|
#include <ks386.inc>
|
||||||
|
|
||||||
EXTERN _KdbEnterDebuggerException:PROC
|
EXTERN _KdbEnterDebuggerFirstChanceException:PROC
|
||||||
|
|
||||||
.code
|
.code
|
||||||
|
|
||||||
|
@ -61,12 +61,8 @@ _KdbEnter:
|
||||||
* Call KDB
|
* Call KDB
|
||||||
*/
|
*/
|
||||||
mov eax, esp
|
mov eax, esp
|
||||||
push 1 /* FirstChance */
|
|
||||||
push eax /* Push a pointer to the trap frame */
|
push eax /* Push a pointer to the trap frame */
|
||||||
push 0 /* Context */
|
call _KdbEnterDebuggerFirstChanceException
|
||||||
push 0 /* PreviousMode (KernelMode) */
|
|
||||||
push 0 /* ExceptionRecord */
|
|
||||||
call _KdbEnterDebuggerException
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Pop the arguments and unused portions of the trap frame:
|
* Pop the arguments and unused portions of the trap frame:
|
||||||
|
|
|
@ -49,8 +49,8 @@ PEPROCESS KdbOriginalProcess = NULL; /* The process in whichs context KDB was in
|
||||||
PETHREAD KdbCurrentThread = NULL; /* The current thread context in which KDB runs */
|
PETHREAD KdbCurrentThread = NULL; /* The current thread context in which KDB runs */
|
||||||
PETHREAD KdbOriginalThread = NULL; /* The thread in whichs context KDB was entered */
|
PETHREAD KdbOriginalThread = NULL; /* The thread in whichs context KDB was entered */
|
||||||
PKDB_KTRAP_FRAME KdbCurrentTrapFrame = NULL; /* Pointer to the current trapframe */
|
PKDB_KTRAP_FRAME KdbCurrentTrapFrame = NULL; /* Pointer to the current trapframe */
|
||||||
static KDB_KTRAP_FRAME KdbTrapFrame = { { 0 } }; /* The trapframe which was passed to KdbEnterDebuggerException */
|
static KDB_KTRAP_FRAME KdbTrapFrame = { 0 }; /* The trapframe which was passed to KdbEnterDebuggerException */
|
||||||
static KDB_KTRAP_FRAME KdbThreadTrapFrame = { { 0 } }; /* The trapframe of the current thread (KdbCurrentThread) */
|
static KDB_KTRAP_FRAME KdbThreadTrapFrame = { 0 }; /* The trapframe of the current thread (KdbCurrentThread) */
|
||||||
static KAPC_STATE KdbApcState;
|
static KAPC_STATE KdbApcState;
|
||||||
extern BOOLEAN KdbpBugCheckRequested;
|
extern BOOLEAN KdbpBugCheckRequested;
|
||||||
|
|
||||||
|
@ -108,68 +108,8 @@ static const CHAR *ExceptionNrToString[] =
|
||||||
"Assertion Failure"
|
"Assertion Failure"
|
||||||
};
|
};
|
||||||
|
|
||||||
ULONG
|
|
||||||
NTAPI
|
|
||||||
KiSsFromTrapFrame(
|
|
||||||
IN PKTRAP_FRAME TrapFrame);
|
|
||||||
|
|
||||||
ULONG
|
|
||||||
NTAPI
|
|
||||||
KiEspFromTrapFrame(
|
|
||||||
IN PKTRAP_FRAME TrapFrame);
|
|
||||||
|
|
||||||
VOID
|
|
||||||
NTAPI
|
|
||||||
KiSsToTrapFrame(
|
|
||||||
IN PKTRAP_FRAME TrapFrame,
|
|
||||||
IN ULONG Ss);
|
|
||||||
|
|
||||||
VOID
|
|
||||||
NTAPI
|
|
||||||
KiEspToTrapFrame(
|
|
||||||
IN PKTRAP_FRAME TrapFrame,
|
|
||||||
IN ULONG Esp);
|
|
||||||
|
|
||||||
/* FUNCTIONS *****************************************************************/
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
|
||||||
static VOID
|
|
||||||
KdbpTrapFrameToKdbTrapFrame(
|
|
||||||
PKTRAP_FRAME TrapFrame,
|
|
||||||
PKDB_KTRAP_FRAME KdbTrapFrame)
|
|
||||||
{
|
|
||||||
/* Copy the TrapFrame only up to Eflags and zero the rest*/
|
|
||||||
RtlCopyMemory(&KdbTrapFrame->Tf, TrapFrame, FIELD_OFFSET(KTRAP_FRAME, HardwareEsp));
|
|
||||||
RtlZeroMemory((PVOID)((ULONG_PTR)&KdbTrapFrame->Tf + FIELD_OFFSET(KTRAP_FRAME, HardwareEsp)),
|
|
||||||
sizeof(KTRAP_FRAME) - FIELD_OFFSET(KTRAP_FRAME, HardwareEsp));
|
|
||||||
|
|
||||||
KdbTrapFrame->Cr0 = __readcr0();
|
|
||||||
KdbTrapFrame->Cr2 = __readcr2();
|
|
||||||
KdbTrapFrame->Cr3 = __readcr3();
|
|
||||||
KdbTrapFrame->Cr4 = __readcr4();
|
|
||||||
|
|
||||||
KdbTrapFrame->Tf.HardwareEsp = KiEspFromTrapFrame(TrapFrame);
|
|
||||||
KdbTrapFrame->Tf.HardwareSegSs = (USHORT)(KiSsFromTrapFrame(TrapFrame) & 0xFFFF);
|
|
||||||
|
|
||||||
|
|
||||||
/* FIXME: copy v86 registers if TrapFrame is a V86 trapframe */
|
|
||||||
}
|
|
||||||
|
|
||||||
static VOID
|
|
||||||
KdbpKdbTrapFrameToTrapFrame(
|
|
||||||
PKDB_KTRAP_FRAME KdbTrapFrame,
|
|
||||||
PKTRAP_FRAME TrapFrame)
|
|
||||||
{
|
|
||||||
/* Copy the TrapFrame only up to Eflags and zero the rest*/
|
|
||||||
RtlCopyMemory(TrapFrame, &KdbTrapFrame->Tf, FIELD_OFFSET(KTRAP_FRAME, HardwareEsp));
|
|
||||||
|
|
||||||
/* FIXME: write cr0, cr2, cr3 and cr4 (not needed atm) */
|
|
||||||
|
|
||||||
KiSsToTrapFrame(TrapFrame, KdbTrapFrame->Tf.HardwareSegSs);
|
|
||||||
KiEspToTrapFrame(TrapFrame, KdbTrapFrame->Tf.HardwareEsp);
|
|
||||||
|
|
||||||
/* FIXME: copy v86 registers if TrapFrame is a V86 trapframe */
|
|
||||||
}
|
|
||||||
|
|
||||||
static VOID
|
static VOID
|
||||||
KdbpKdbTrapFrameFromKernelStack(
|
KdbpKdbTrapFrameFromKernelStack(
|
||||||
PVOID KernelStack,
|
PVOID KernelStack,
|
||||||
|
@ -180,17 +120,17 @@ KdbpKdbTrapFrameFromKernelStack(
|
||||||
RtlZeroMemory(KdbTrapFrame, sizeof(KDB_KTRAP_FRAME));
|
RtlZeroMemory(KdbTrapFrame, sizeof(KDB_KTRAP_FRAME));
|
||||||
StackPtr = (ULONG_PTR *) KernelStack;
|
StackPtr = (ULONG_PTR *) KernelStack;
|
||||||
#ifdef _M_IX86
|
#ifdef _M_IX86
|
||||||
KdbTrapFrame->Tf.Ebp = StackPtr[3];
|
KdbTrapFrame->Ebp = StackPtr[3];
|
||||||
KdbTrapFrame->Tf.Edi = StackPtr[4];
|
KdbTrapFrame->Edi = StackPtr[4];
|
||||||
KdbTrapFrame->Tf.Esi = StackPtr[5];
|
KdbTrapFrame->Esi = StackPtr[5];
|
||||||
KdbTrapFrame->Tf.Ebx = StackPtr[6];
|
KdbTrapFrame->Ebx = StackPtr[6];
|
||||||
KdbTrapFrame->Tf.Eip = StackPtr[7];
|
KdbTrapFrame->Eip = StackPtr[7];
|
||||||
KdbTrapFrame->Tf.HardwareEsp = (ULONG) (StackPtr + 8);
|
KdbTrapFrame->Esp = (ULONG) (StackPtr + 8);
|
||||||
KdbTrapFrame->Tf.HardwareSegSs = KGDT_R0_DATA;
|
KdbTrapFrame->SegSs = KGDT_R0_DATA;
|
||||||
KdbTrapFrame->Tf.SegCs = KGDT_R0_CODE;
|
KdbTrapFrame->SegCs = KGDT_R0_CODE;
|
||||||
KdbTrapFrame->Tf.SegDs = KGDT_R0_DATA;
|
KdbTrapFrame->SegDs = KGDT_R0_DATA;
|
||||||
KdbTrapFrame->Tf.SegEs = KGDT_R0_DATA;
|
KdbTrapFrame->SegEs = KGDT_R0_DATA;
|
||||||
KdbTrapFrame->Tf.SegGs = KGDT_R0_DATA;
|
KdbTrapFrame->SegGs = KGDT_R0_DATA;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* FIXME: what about the other registers??? */
|
/* FIXME: what about the other registers??? */
|
||||||
|
@ -374,7 +314,7 @@ KdbpStepIntoInstruction(
|
||||||
IntVect = 3;
|
IntVect = 3;
|
||||||
else if (Mem[0] == 0xcd)
|
else if (Mem[0] == 0xcd)
|
||||||
IntVect = Mem[1];
|
IntVect = Mem[1];
|
||||||
else if (Mem[0] == 0xce && KdbCurrentTrapFrame->Tf.EFlags & (1<<11)) /* 1 << 11 is the overflow flag */
|
else if (Mem[0] == 0xce && KdbCurrentTrapFrame->EFlags & (1<<11)) /* 1 << 11 is the overflow flag */
|
||||||
IntVect = 4;
|
IntVect = 4;
|
||||||
else
|
else
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -703,14 +643,14 @@ KdbpDeleteBreakPoint(
|
||||||
static LONG
|
static LONG
|
||||||
KdbpIsBreakPointOurs(
|
KdbpIsBreakPointOurs(
|
||||||
IN NTSTATUS ExceptionCode,
|
IN NTSTATUS ExceptionCode,
|
||||||
IN PKTRAP_FRAME TrapFrame)
|
IN PCONTEXT Context)
|
||||||
{
|
{
|
||||||
ULONG i;
|
ULONG i;
|
||||||
ASSERT(ExceptionCode == STATUS_SINGLE_STEP || ExceptionCode == STATUS_BREAKPOINT);
|
ASSERT(ExceptionCode == STATUS_SINGLE_STEP || ExceptionCode == STATUS_BREAKPOINT);
|
||||||
|
|
||||||
if (ExceptionCode == STATUS_BREAKPOINT) /* Software interrupt */
|
if (ExceptionCode == STATUS_BREAKPOINT) /* Software interrupt */
|
||||||
{
|
{
|
||||||
ULONG_PTR BpEip = (ULONG_PTR)TrapFrame->Eip - 1; /* Get EIP of INT3 instruction */
|
ULONG_PTR BpEip = (ULONG_PTR)Context->Eip - 1; /* Get EIP of INT3 instruction */
|
||||||
for (i = 0; i < KdbSwBreakPointCount; i++)
|
for (i = 0; i < KdbSwBreakPointCount; i++)
|
||||||
{
|
{
|
||||||
ASSERT((KdbSwBreakPoints[i]->Type == KdbBreakPointSoftware ||
|
ASSERT((KdbSwBreakPoints[i]->Type == KdbBreakPointSoftware ||
|
||||||
|
@ -733,7 +673,7 @@ KdbpIsBreakPointOurs(
|
||||||
KdbHwBreakPoints[i]->Enabled);
|
KdbHwBreakPoints[i]->Enabled);
|
||||||
DebugReg = KdbHwBreakPoints[i]->Data.Hw.DebugReg;
|
DebugReg = KdbHwBreakPoints[i]->Data.Hw.DebugReg;
|
||||||
|
|
||||||
if ((TrapFrame->Dr6 & (1 << DebugReg)) != 0)
|
if ((Context->Dr6 & (1 << DebugReg)) != 0)
|
||||||
{
|
{
|
||||||
return KdbHwBreakPoints[i] - KdbBreakPoints;
|
return KdbHwBreakPoints[i] - KdbBreakPoints;
|
||||||
}
|
}
|
||||||
|
@ -832,7 +772,7 @@ KdbpEnableBreakPoint(
|
||||||
ASSERT(KDB_MAXIMUM_HW_BREAKPOINT_COUNT == 4);
|
ASSERT(KDB_MAXIMUM_HW_BREAKPOINT_COUNT == 4);
|
||||||
for (i = 0; i < KDB_MAXIMUM_HW_BREAKPOINT_COUNT; i++)
|
for (i = 0; i < KDB_MAXIMUM_HW_BREAKPOINT_COUNT; i++)
|
||||||
{
|
{
|
||||||
if ((KdbTrapFrame.Tf.Dr7 & (0x3 << (i * 2))) == 0)
|
if ((KdbTrapFrame.Dr7 & (0x3 << (i * 2))) == 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -842,27 +782,27 @@ KdbpEnableBreakPoint(
|
||||||
switch (i)
|
switch (i)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
KdbTrapFrame.Tf.Dr0 = BreakPoint->Address;
|
KdbTrapFrame.Dr0 = BreakPoint->Address;
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
KdbTrapFrame.Tf.Dr1 = BreakPoint->Address;
|
KdbTrapFrame.Dr1 = BreakPoint->Address;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
KdbTrapFrame.Tf.Dr2 = BreakPoint->Address;
|
KdbTrapFrame.Dr2 = BreakPoint->Address;
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
KdbTrapFrame.Tf.Dr3 = BreakPoint->Address;
|
KdbTrapFrame.Dr3 = BreakPoint->Address;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Enable the global breakpoint */
|
/* Enable the global breakpoint */
|
||||||
KdbTrapFrame.Tf.Dr7 |= (0x2 << (i * 2));
|
KdbTrapFrame.Dr7 |= (0x2 << (i * 2));
|
||||||
|
|
||||||
/* Enable the exact match bits. */
|
/* Enable the exact match bits. */
|
||||||
KdbTrapFrame.Tf.Dr7 |= 0x00000300;
|
KdbTrapFrame.Dr7 |= 0x00000300;
|
||||||
|
|
||||||
/* Clear existing state. */
|
/* Clear existing state. */
|
||||||
KdbTrapFrame.Tf.Dr7 &= ~(0xF << (16 + (i * 4)));
|
KdbTrapFrame.Dr7 &= ~(0xF << (16 + (i * 4)));
|
||||||
|
|
||||||
/* Set the breakpoint type. */
|
/* Set the breakpoint type. */
|
||||||
switch (BreakPoint->Data.Hw.AccessType)
|
switch (BreakPoint->Data.Hw.AccessType)
|
||||||
|
@ -883,20 +823,20 @@ KdbpEnableBreakPoint(
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
KdbTrapFrame.Tf.Dr7 |= (ul << (16 + (i * 4)));
|
KdbTrapFrame.Dr7 |= (ul << (16 + (i * 4)));
|
||||||
|
|
||||||
/* Set the breakpoint length. */
|
/* Set the breakpoint length. */
|
||||||
KdbTrapFrame.Tf.Dr7 |= ((BreakPoint->Data.Hw.Size - 1) << (18 + (i * 4)));
|
KdbTrapFrame.Dr7 |= ((BreakPoint->Data.Hw.Size - 1) << (18 + (i * 4)));
|
||||||
|
|
||||||
/* Update KdbCurrentTrapFrame - values are taken from there by the CLI */
|
/* Update KdbCurrentTrapFrame - values are taken from there by the CLI */
|
||||||
if (&KdbTrapFrame != KdbCurrentTrapFrame)
|
if (&KdbTrapFrame != KdbCurrentTrapFrame)
|
||||||
{
|
{
|
||||||
KdbCurrentTrapFrame->Tf.Dr0 = KdbTrapFrame.Tf.Dr0;
|
KdbCurrentTrapFrame->Dr0 = KdbTrapFrame.Dr0;
|
||||||
KdbCurrentTrapFrame->Tf.Dr1 = KdbTrapFrame.Tf.Dr1;
|
KdbCurrentTrapFrame->Dr1 = KdbTrapFrame.Dr1;
|
||||||
KdbCurrentTrapFrame->Tf.Dr2 = KdbTrapFrame.Tf.Dr2;
|
KdbCurrentTrapFrame->Dr2 = KdbTrapFrame.Dr2;
|
||||||
KdbCurrentTrapFrame->Tf.Dr3 = KdbTrapFrame.Tf.Dr3;
|
KdbCurrentTrapFrame->Dr3 = KdbTrapFrame.Dr3;
|
||||||
KdbCurrentTrapFrame->Tf.Dr6 = KdbTrapFrame.Tf.Dr6;
|
KdbCurrentTrapFrame->Dr6 = KdbTrapFrame.Dr6;
|
||||||
KdbCurrentTrapFrame->Tf.Dr7 = KdbTrapFrame.Tf.Dr7;
|
KdbCurrentTrapFrame->Dr7 = KdbTrapFrame.Dr7;
|
||||||
}
|
}
|
||||||
|
|
||||||
BreakPoint->Data.Hw.DebugReg = i;
|
BreakPoint->Data.Hw.DebugReg = i;
|
||||||
|
@ -988,11 +928,11 @@ KdbpDisableBreakPoint(
|
||||||
ASSERT(BreakPoint->Type == KdbBreakPointHardware);
|
ASSERT(BreakPoint->Type == KdbBreakPointHardware);
|
||||||
|
|
||||||
/* Clear the breakpoint. */
|
/* Clear the breakpoint. */
|
||||||
KdbTrapFrame.Tf.Dr7 &= ~(0x3 << (BreakPoint->Data.Hw.DebugReg * 2));
|
KdbTrapFrame.Dr7 &= ~(0x3 << (BreakPoint->Data.Hw.DebugReg * 2));
|
||||||
if ((KdbTrapFrame.Tf.Dr7 & 0xFF) == 0)
|
if ((KdbTrapFrame.Dr7 & 0xFF) == 0)
|
||||||
{
|
{
|
||||||
/* If no breakpoints are enabled then clear the exact match flags. */
|
/* If no breakpoints are enabled then clear the exact match flags. */
|
||||||
KdbTrapFrame.Tf.Dr7 &= 0xFFFFFCFF;
|
KdbTrapFrame.Dr7 &= 0xFFFFFCFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < KdbHwBreakPointCount; i++)
|
for (i = 0; i < KdbHwBreakPointCount; i++)
|
||||||
|
@ -1316,10 +1256,9 @@ KdbpGetExceptionNumberFromStatus(
|
||||||
*/
|
*/
|
||||||
KD_CONTINUE_TYPE
|
KD_CONTINUE_TYPE
|
||||||
KdbEnterDebuggerException(
|
KdbEnterDebuggerException(
|
||||||
IN PEXCEPTION_RECORD ExceptionRecord OPTIONAL,
|
IN PEXCEPTION_RECORD64 ExceptionRecord,
|
||||||
IN KPROCESSOR_MODE PreviousMode,
|
IN KPROCESSOR_MODE PreviousMode,
|
||||||
IN PCONTEXT Context,
|
IN PCONTEXT Context,
|
||||||
IN OUT PKTRAP_FRAME TrapFrame,
|
|
||||||
IN BOOLEAN FirstChance)
|
IN BOOLEAN FirstChance)
|
||||||
{
|
{
|
||||||
KDB_ENTER_CONDITION EnterCondition;
|
KDB_ENTER_CONDITION EnterCondition;
|
||||||
|
@ -1361,7 +1300,7 @@ KdbEnterDebuggerException(
|
||||||
KdbEnteredOnSingleStep = FALSE;
|
KdbEnteredOnSingleStep = FALSE;
|
||||||
|
|
||||||
if (FirstChance && (ExceptionCode == STATUS_SINGLE_STEP || ExceptionCode == STATUS_BREAKPOINT) &&
|
if (FirstChance && (ExceptionCode == STATUS_SINGLE_STEP || ExceptionCode == STATUS_BREAKPOINT) &&
|
||||||
(KdbLastBreakPointNr = KdbpIsBreakPointOurs(ExceptionCode, TrapFrame)) >= 0)
|
(KdbLastBreakPointNr = KdbpIsBreakPointOurs(ExceptionCode, Context)) >= 0)
|
||||||
{
|
{
|
||||||
BreakPoint = KdbBreakPoints + KdbLastBreakPointNr;
|
BreakPoint = KdbBreakPoints + KdbLastBreakPointNr;
|
||||||
|
|
||||||
|
@ -1382,7 +1321,7 @@ KdbEnterDebuggerException(
|
||||||
KiDispatchException accounts for that. Whatever we do here with
|
KiDispatchException accounts for that. Whatever we do here with
|
||||||
the TrapFrame does not matter anyway, since KiDispatchException
|
the TrapFrame does not matter anyway, since KiDispatchException
|
||||||
will overwrite it with the values from the Context! */
|
will overwrite it with the values from the Context! */
|
||||||
TrapFrame->Eip--;
|
Context->Eip--;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((BreakPoint->Type == KdbBreakPointHardware) &&
|
if ((BreakPoint->Type == KdbBreakPointHardware) &&
|
||||||
|
@ -1399,15 +1338,15 @@ KdbEnterDebuggerException(
|
||||||
else if (BreakPoint->Type == KdbBreakPointTemporary &&
|
else if (BreakPoint->Type == KdbBreakPointTemporary &&
|
||||||
BreakPoint->Process == KdbCurrentProcess)
|
BreakPoint->Process == KdbCurrentProcess)
|
||||||
{
|
{
|
||||||
ASSERT((TrapFrame->EFlags & EFLAGS_TF) == 0);
|
ASSERT((Context->EFlags & EFLAGS_TF) == 0);
|
||||||
|
|
||||||
/* Delete the temporary breakpoint which was used to step over or into the instruction */
|
/* Delete the temporary breakpoint which was used to step over or into the instruction */
|
||||||
KdbpDeleteBreakPoint(-1, BreakPoint);
|
KdbpDeleteBreakPoint(-1, BreakPoint);
|
||||||
|
|
||||||
if (--KdbNumSingleSteps > 0)
|
if (--KdbNumSingleSteps > 0)
|
||||||
{
|
{
|
||||||
if ((KdbSingleStepOver && !KdbpStepOverInstruction(TrapFrame->Eip)) ||
|
if ((KdbSingleStepOver && !KdbpStepOverInstruction(Context->Eip)) ||
|
||||||
(!KdbSingleStepOver && !KdbpStepIntoInstruction(TrapFrame->Eip)))
|
(!KdbSingleStepOver && !KdbpStepIntoInstruction(Context->Eip)))
|
||||||
{
|
{
|
||||||
Context->EFlags |= EFLAGS_TF;
|
Context->EFlags |= EFLAGS_TF;
|
||||||
}
|
}
|
||||||
|
@ -1440,7 +1379,7 @@ KdbEnterDebuggerException(
|
||||||
if (BreakPoint->Condition)
|
if (BreakPoint->Condition)
|
||||||
{
|
{
|
||||||
/* Setup the KDB trap frame */
|
/* Setup the KDB trap frame */
|
||||||
KdbpTrapFrameToKdbTrapFrame(TrapFrame, &KdbTrapFrame);
|
KdbTrapFrame = *Context;
|
||||||
|
|
||||||
ull = 0;
|
ull = 0;
|
||||||
if (!KdbpRpnEvaluateParsedExpression(BreakPoint->Condition, &KdbTrapFrame, &ull, NULL, NULL))
|
if (!KdbpRpnEvaluateParsedExpression(BreakPoint->Condition, &KdbTrapFrame, &ull, NULL, NULL))
|
||||||
|
@ -1456,7 +1395,7 @@ KdbEnterDebuggerException(
|
||||||
if (BreakPoint->Type == KdbBreakPointSoftware)
|
if (BreakPoint->Type == KdbBreakPointSoftware)
|
||||||
{
|
{
|
||||||
KdbpPrint("\nEntered debugger on breakpoint #%d: EXEC 0x%04x:0x%08x\n",
|
KdbpPrint("\nEntered debugger on breakpoint #%d: EXEC 0x%04x:0x%08x\n",
|
||||||
KdbLastBreakPointNr, TrapFrame->SegCs & 0xffff, TrapFrame->Eip);
|
KdbLastBreakPointNr, Context->SegCs & 0xffff, Context->Eip);
|
||||||
}
|
}
|
||||||
else if (BreakPoint->Type == KdbBreakPointHardware)
|
else if (BreakPoint->Type == KdbBreakPointHardware)
|
||||||
{
|
{
|
||||||
|
@ -1471,7 +1410,7 @@ KdbEnterDebuggerException(
|
||||||
else if (ExceptionCode == STATUS_SINGLE_STEP)
|
else if (ExceptionCode == STATUS_SINGLE_STEP)
|
||||||
{
|
{
|
||||||
/* Silently ignore a debugger initiated single step. */
|
/* Silently ignore a debugger initiated single step. */
|
||||||
if ((TrapFrame->Dr6 & 0xf) == 0 && KdbBreakPointToReenable)
|
if ((Context->Dr6 & 0xf) == 0 && KdbBreakPointToReenable)
|
||||||
{
|
{
|
||||||
/* FIXME: Make sure that the breakpoint was really hit (check bp->Address vs. tf->Eip) */
|
/* FIXME: Make sure that the breakpoint was really hit (check bp->Address vs. tf->Eip) */
|
||||||
BreakPoint = KdbBreakPointToReenable;
|
BreakPoint = KdbBreakPointToReenable;
|
||||||
|
@ -1504,13 +1443,13 @@ KdbEnterDebuggerException(
|
||||||
KdbpEvenThoughWeHaveABreakPointToReenableWeAlsoHaveARealSingleStep = FALSE;
|
KdbpEvenThoughWeHaveABreakPointToReenableWeAlsoHaveARealSingleStep = FALSE;
|
||||||
|
|
||||||
/* Check if we expect a single step */
|
/* Check if we expect a single step */
|
||||||
if ((TrapFrame->Dr6 & 0xf) == 0 && KdbNumSingleSteps > 0)
|
if ((Context->Dr6 & 0xf) == 0 && KdbNumSingleSteps > 0)
|
||||||
{
|
{
|
||||||
/*ASSERT((Context->Eflags & EFLAGS_TF) != 0);*/
|
/*ASSERT((Context->Eflags & EFLAGS_TF) != 0);*/
|
||||||
if (--KdbNumSingleSteps > 0)
|
if (--KdbNumSingleSteps > 0)
|
||||||
{
|
{
|
||||||
if ((KdbSingleStepOver && KdbpStepOverInstruction(TrapFrame->Eip)) ||
|
if ((KdbSingleStepOver && KdbpStepOverInstruction(Context->Eip)) ||
|
||||||
(!KdbSingleStepOver && KdbpStepIntoInstruction(TrapFrame->Eip)))
|
(!KdbSingleStepOver && KdbpStepIntoInstruction(Context->Eip)))
|
||||||
{
|
{
|
||||||
Context->EFlags &= ~EFLAGS_TF;
|
Context->EFlags &= ~EFLAGS_TF;
|
||||||
}
|
}
|
||||||
|
@ -1550,7 +1489,7 @@ KdbEnterDebuggerException(
|
||||||
}
|
}
|
||||||
|
|
||||||
KdbpPrint("\nEntered debugger on embedded INT3 at 0x%04x:0x%08x.\n",
|
KdbpPrint("\nEntered debugger on embedded INT3 at 0x%04x:0x%08x.\n",
|
||||||
TrapFrame->SegCs & 0xffff, TrapFrame->Eip - 1);
|
Context->SegCs & 0xffff, Context->Eip - 1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1569,26 +1508,11 @@ KdbEnterDebuggerException(
|
||||||
if (ExceptionCode == STATUS_ACCESS_VIOLATION &&
|
if (ExceptionCode == STATUS_ACCESS_VIOLATION &&
|
||||||
ExceptionRecord && ExceptionRecord->NumberParameters != 0)
|
ExceptionRecord && ExceptionRecord->NumberParameters != 0)
|
||||||
{
|
{
|
||||||
/* FIXME: Add noexec memory stuff */
|
|
||||||
ULONG_PTR TrapCr2;
|
ULONG_PTR TrapCr2;
|
||||||
ULONG Err;
|
|
||||||
|
|
||||||
TrapCr2 = __readcr2();
|
TrapCr2 = __readcr2();
|
||||||
|
|
||||||
Err = TrapFrame->ErrCode;
|
KdbpPrint("Memory at 0x%p could not be accessed\n", TrapCr2);
|
||||||
KdbpPrint("Memory at 0x%p could not be %s: ", TrapCr2, (Err & (1 << 1)) ? "written" : "read");
|
|
||||||
|
|
||||||
if ((Err & (1 << 0)) == 0)
|
|
||||||
{
|
|
||||||
KdbpPrint("Page not present.\n");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if ((Err & (1 << 3)) != 0)
|
|
||||||
KdbpPrint("Reserved bits in page directory set.\n");
|
|
||||||
else
|
|
||||||
KdbpPrint("Page protection violation.\n");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1601,7 +1525,7 @@ KdbEnterDebuggerException(
|
||||||
KdbCurrentTrapFrame = &KdbTrapFrame;
|
KdbCurrentTrapFrame = &KdbTrapFrame;
|
||||||
|
|
||||||
/* Setup the KDB trap frame */
|
/* Setup the KDB trap frame */
|
||||||
KdbpTrapFrameToKdbTrapFrame(TrapFrame, &KdbTrapFrame);
|
KdbTrapFrame = *Context;
|
||||||
|
|
||||||
/* Enter critical section */
|
/* Enter critical section */
|
||||||
OldEflags = __readeflags();
|
OldEflags = __readeflags();
|
||||||
|
@ -1628,15 +1552,15 @@ KdbEnterDebuggerException(
|
||||||
/* Variable explains itself! */
|
/* Variable explains itself! */
|
||||||
KdbpEvenThoughWeHaveABreakPointToReenableWeAlsoHaveARealSingleStep = TRUE;
|
KdbpEvenThoughWeHaveABreakPointToReenableWeAlsoHaveARealSingleStep = TRUE;
|
||||||
|
|
||||||
if ((KdbSingleStepOver && KdbpStepOverInstruction(KdbCurrentTrapFrame->Tf.Eip)) ||
|
if ((KdbSingleStepOver && KdbpStepOverInstruction(KdbCurrentTrapFrame->Eip)) ||
|
||||||
(!KdbSingleStepOver && KdbpStepIntoInstruction(KdbCurrentTrapFrame->Tf.Eip)))
|
(!KdbSingleStepOver && KdbpStepIntoInstruction(KdbCurrentTrapFrame->Eip)))
|
||||||
{
|
{
|
||||||
ASSERT((KdbCurrentTrapFrame->Tf.EFlags & EFLAGS_TF) == 0);
|
ASSERT((KdbCurrentTrapFrame->EFlags & EFLAGS_TF) == 0);
|
||||||
/*KdbCurrentTrapFrame->Tf.EFlags &= ~EFLAGS_TF;*/
|
/*KdbCurrentTrapFrame->EFlags &= ~EFLAGS_TF;*/
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Context->EFlags |= EFLAGS_TF;
|
KdbTrapFrame.EFlags |= EFLAGS_TF;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1648,8 +1572,8 @@ KdbEnterDebuggerException(
|
||||||
KeUnstackDetachProcess(&KdbApcState);
|
KeUnstackDetachProcess(&KdbApcState);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update the exception TrapFrame */
|
/* Update the exception Context */
|
||||||
KdbpKdbTrapFrameToTrapFrame(&KdbTrapFrame, TrapFrame);
|
*Context = KdbTrapFrame;
|
||||||
|
|
||||||
/* Decrement the entry count */
|
/* Decrement the entry count */
|
||||||
InterlockedDecrement(&KdbEntryCount);
|
InterlockedDecrement(&KdbEntryCount);
|
||||||
|
@ -1675,11 +1599,11 @@ continue_execution:
|
||||||
/* Set the RF flag so we don't trigger the same breakpoint again. */
|
/* Set the RF flag so we don't trigger the same breakpoint again. */
|
||||||
if (Resume)
|
if (Resume)
|
||||||
{
|
{
|
||||||
TrapFrame->EFlags |= EFLAGS_RF;
|
Context->EFlags |= EFLAGS_RF;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clear dr6 status flags. */
|
/* Clear dr6 status flags. */
|
||||||
TrapFrame->Dr6 &= ~0x0000e00f;
|
Context->Dr6 &= ~0x0000e00f;
|
||||||
|
|
||||||
if (!(KdbEnteredOnSingleStep && KdbSingleStepOver))
|
if (!(KdbEnteredOnSingleStep && KdbSingleStepOver))
|
||||||
{
|
{
|
||||||
|
@ -1691,6 +1615,35 @@ continue_execution:
|
||||||
return ContinueType;
|
return ContinueType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
KD_CONTINUE_TYPE
|
||||||
|
KdbEnterDebuggerFirstChanceException(
|
||||||
|
IN OUT PKTRAP_FRAME TrapFrame)
|
||||||
|
{
|
||||||
|
EXCEPTION_RECORD64 ExceptionRecord;
|
||||||
|
KD_CONTINUE_TYPE Return;
|
||||||
|
CONTEXT Context;
|
||||||
|
|
||||||
|
/* Copy TrapFrame to Context */
|
||||||
|
RtlZeroMemory(&Context, sizeof(CONTEXT));
|
||||||
|
Context.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS | CONTEXT_EXTENDED_REGISTERS | CONTEXT_FLOATING_POINT | CONTEXT_DEBUG_REGISTERS;
|
||||||
|
KeTrapFrameToContext(TrapFrame, NULL, &Context);
|
||||||
|
|
||||||
|
/* Create ExceptionRecord (assume breakpoint) */
|
||||||
|
RtlZeroMemory(&ExceptionRecord, sizeof(EXCEPTION_RECORD64));
|
||||||
|
ExceptionRecord.ExceptionCode = STATUS_BREAKPOINT;
|
||||||
|
|
||||||
|
/* Call real function */
|
||||||
|
Return = KdbEnterDebuggerException(&ExceptionRecord,
|
||||||
|
KernelMode,
|
||||||
|
&Context,
|
||||||
|
TRUE);
|
||||||
|
|
||||||
|
/* Copy back Context to TrapFrame */
|
||||||
|
KeContextToTrapFrame(&Context, NULL, TrapFrame, Context.ContextFlags, KernelMode);
|
||||||
|
|
||||||
|
return Return;
|
||||||
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
KdbpGetCommandLineSettings(
|
KdbpGetCommandLineSettings(
|
||||||
|
|
|
@ -10,15 +10,7 @@
|
||||||
/* TYPES *********************************************************************/
|
/* TYPES *********************************************************************/
|
||||||
|
|
||||||
/* from kdb.c */
|
/* from kdb.c */
|
||||||
typedef struct _KDB_KTRAP_FRAME
|
typedef CONTEXT KDB_KTRAP_FRAME, *PKDB_KTRAP_FRAME;
|
||||||
{
|
|
||||||
KTRAP_FRAME Tf;
|
|
||||||
ULONG Cr0;
|
|
||||||
ULONG Cr1; /* reserved/unused */
|
|
||||||
ULONG Cr2;
|
|
||||||
ULONG Cr3;
|
|
||||||
ULONG Cr4;
|
|
||||||
} KDB_KTRAP_FRAME, *PKDB_KTRAP_FRAME;
|
|
||||||
|
|
||||||
typedef enum _KDB_BREAKPOINT_TYPE
|
typedef enum _KDB_BREAKPOINT_TYPE
|
||||||
{
|
{
|
||||||
|
@ -163,7 +155,7 @@ KdbpSymFindModule(
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
KdbSymPrintAddress(
|
KdbSymPrintAddress(
|
||||||
IN PVOID Address,
|
IN PVOID Address,
|
||||||
IN PKTRAP_FRAME Context
|
IN PCONTEXT Context
|
||||||
);
|
);
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
|
@ -247,11 +239,15 @@ NTAPI
|
||||||
KdbpGetCommandLineSettings(PCHAR p1);
|
KdbpGetCommandLineSettings(PCHAR p1);
|
||||||
|
|
||||||
KD_CONTINUE_TYPE
|
KD_CONTINUE_TYPE
|
||||||
KdbEnterDebuggerException(PEXCEPTION_RECORD ExceptionRecord,
|
KdbEnterDebuggerException(IN PEXCEPTION_RECORD64 ExceptionRecord,
|
||||||
KPROCESSOR_MODE PreviousMode,
|
IN KPROCESSOR_MODE PreviousMode,
|
||||||
PCONTEXT Context,
|
IN OUT PCONTEXT Context,
|
||||||
PKTRAP_FRAME TrapFrame,
|
IN BOOLEAN FirstChance);
|
||||||
BOOLEAN FirstChance);
|
|
||||||
|
KD_CONTINUE_TYPE
|
||||||
|
KdbEnterDebuggerFirstChanceException(
|
||||||
|
IN OUT PKTRAP_FRAME TrapFrame);
|
||||||
|
|
||||||
/* other functions */
|
/* other functions */
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
|
|
|
@ -345,7 +345,6 @@ static const struct
|
||||||
{ "disasm", "disasm [address] [L count]", "Disassemble count instructions at address.", KdbpCmdDisassembleX },
|
{ "disasm", "disasm [address] [L count]", "Disassemble count instructions at address.", KdbpCmdDisassembleX },
|
||||||
{ "x", "x [address] [L count]", "Display count dwords, starting at address.", KdbpCmdDisassembleX },
|
{ "x", "x [address] [L count]", "Display count dwords, starting at address.", KdbpCmdDisassembleX },
|
||||||
{ "regs", "regs", "Display general purpose registers.", KdbpCmdRegs },
|
{ "regs", "regs", "Display general purpose registers.", KdbpCmdRegs },
|
||||||
{ "cregs", "cregs", "Display control, descriptor table and task segment registers.", KdbpCmdRegs },
|
|
||||||
{ "sregs", "sregs", "Display status registers.", KdbpCmdRegs },
|
{ "sregs", "sregs", "Display status registers.", KdbpCmdRegs },
|
||||||
{ "dregs", "dregs", "Display debug registers.", KdbpCmdRegs },
|
{ "dregs", "dregs", "Display debug registers.", KdbpCmdRegs },
|
||||||
{ "bt", "bt [*frameaddr|thread id]", "Prints current backtrace or from given frame address.", KdbpCmdBackTrace },
|
{ "bt", "bt [*frameaddr|thread id]", "Prints current backtrace or from given frame address.", KdbpCmdBackTrace },
|
||||||
|
@ -794,7 +793,7 @@ KdbpCmdDisassembleX(
|
||||||
ULONG ul;
|
ULONG ul;
|
||||||
INT i;
|
INT i;
|
||||||
ULONGLONG Result = 0;
|
ULONGLONG Result = 0;
|
||||||
ULONG_PTR Address = KdbCurrentTrapFrame->Tf.Eip;
|
ULONG_PTR Address = KdbCurrentTrapFrame->Eip;
|
||||||
LONG InstLen;
|
LONG InstLen;
|
||||||
|
|
||||||
if (Argv[0][0] == 'x') /* display memory */
|
if (Argv[0][0] == 'x') /* display memory */
|
||||||
|
@ -911,7 +910,7 @@ KdbpCmdRegs(
|
||||||
ULONG Argc,
|
ULONG Argc,
|
||||||
PCHAR Argv[])
|
PCHAR Argv[])
|
||||||
{
|
{
|
||||||
PKTRAP_FRAME Tf = &KdbCurrentTrapFrame->Tf;
|
PCONTEXT Context = KdbCurrentTrapFrame;
|
||||||
INT i;
|
INT i;
|
||||||
static const PCHAR EflagsBits[32] = { " CF", NULL, " PF", " BIT3", " AF", " BIT5",
|
static const PCHAR EflagsBits[32] = { " CF", NULL, " PF", " BIT3", " AF", " BIT5",
|
||||||
" ZF", " SF", " TF", " IF", " DF", " OF",
|
" ZF", " SF", " TF", " IF", " DF", " OF",
|
||||||
|
@ -929,109 +928,51 @@ KdbpCmdRegs(
|
||||||
" ECX 0x%08x EDX 0x%08x\n"
|
" ECX 0x%08x EDX 0x%08x\n"
|
||||||
" ESI 0x%08x EDI 0x%08x\n"
|
" ESI 0x%08x EDI 0x%08x\n"
|
||||||
" EBP 0x%08x\n",
|
" EBP 0x%08x\n",
|
||||||
Tf->SegCs & 0xFFFF, Tf->Eip,
|
Context->SegCs & 0xFFFF, Context->Eip,
|
||||||
Tf->HardwareSegSs, Tf->HardwareEsp,
|
Context->SegSs, Context->Esp,
|
||||||
Tf->Eax, Tf->Ebx,
|
Context->Eax, Context->Ebx,
|
||||||
Tf->Ecx, Tf->Edx,
|
Context->Ecx, Context->Edx,
|
||||||
Tf->Esi, Tf->Edi,
|
Context->Esi, Context->Edi,
|
||||||
Tf->Ebp);
|
Context->Ebp);
|
||||||
|
|
||||||
/* Display the EFlags */
|
/* Display the EFlags */
|
||||||
KdbpPrint("EFLAGS 0x%08x ", Tf->EFlags);
|
KdbpPrint("EFLAGS 0x%08x ", Context->EFlags);
|
||||||
for (i = 0; i < 32; i++)
|
for (i = 0; i < 32; i++)
|
||||||
{
|
{
|
||||||
if (i == 1)
|
if (i == 1)
|
||||||
{
|
{
|
||||||
if ((Tf->EFlags & (1 << 1)) == 0)
|
if ((Context->EFlags & (1 << 1)) == 0)
|
||||||
KdbpPrint(" !BIT1");
|
KdbpPrint(" !BIT1");
|
||||||
}
|
}
|
||||||
else if (i == 12)
|
else if (i == 12)
|
||||||
{
|
{
|
||||||
KdbpPrint(" IOPL%d", (Tf->EFlags >> 12) & 3);
|
KdbpPrint(" IOPL%d", (Context->EFlags >> 12) & 3);
|
||||||
}
|
}
|
||||||
else if (i == 13)
|
else if (i == 13)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
else if ((Tf->EFlags & (1 << i)) != 0)
|
else if ((Context->EFlags & (1 << i)) != 0)
|
||||||
{
|
{
|
||||||
KdbpPrint(EflagsBits[i]);
|
KdbpPrint(EflagsBits[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
KdbpPrint("\n");
|
KdbpPrint("\n");
|
||||||
}
|
}
|
||||||
else if (Argv[0][0] == 'c') /* cregs */
|
|
||||||
{
|
|
||||||
ULONG Cr0, Cr2, Cr3, Cr4;
|
|
||||||
KDESCRIPTOR Gdtr = {0, 0, 0}, Idtr = {0, 0, 0};
|
|
||||||
USHORT Ldtr, Tr;
|
|
||||||
static const PCHAR Cr0Bits[32] = { " PE", " MP", " EM", " TS", " ET", " NE", NULL, NULL,
|
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
" WP", NULL, " AM", NULL, NULL, NULL, NULL, NULL,
|
|
||||||
NULL, NULL, NULL, NULL, NULL, " NW", " CD", " PG" };
|
|
||||||
static const PCHAR Cr4Bits[32] = { " VME", " PVI", " TSD", " DE", " PSE", " PAE", " MCE", " PGE",
|
|
||||||
" PCE", " OSFXSR", " OSXMMEXCPT", NULL, NULL, NULL, NULL, NULL,
|
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
|
|
||||||
|
|
||||||
/* Retrieve the control registers */
|
|
||||||
Cr0 = KdbCurrentTrapFrame->Cr0;
|
|
||||||
Cr2 = KdbCurrentTrapFrame->Cr2;
|
|
||||||
Cr3 = KdbCurrentTrapFrame->Cr3;
|
|
||||||
Cr4 = KdbCurrentTrapFrame->Cr4;
|
|
||||||
|
|
||||||
/* Retrieve the descriptor table and task segment registers */
|
|
||||||
Ke386GetGlobalDescriptorTable(&Gdtr.Limit);
|
|
||||||
Ldtr = Ke386GetLocalDescriptorTable();
|
|
||||||
__sidt(&Idtr.Limit);
|
|
||||||
Tr = Ke386GetTr();
|
|
||||||
|
|
||||||
/* Display the control registers */
|
|
||||||
KdbpPrint("CR0 0x%08x ", Cr0);
|
|
||||||
for (i = 0; i < 32; i++)
|
|
||||||
{
|
|
||||||
if (!Cr0Bits[i])
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if ((Cr0 & (1 << i)) != 0)
|
|
||||||
KdbpPrint(Cr0Bits[i]);
|
|
||||||
}
|
|
||||||
KdbpPrint("\n");
|
|
||||||
|
|
||||||
KdbpPrint("CR2 0x%08x\n", Cr2);
|
|
||||||
KdbpPrint("CR3 0x%08x Pagedir-Base 0x%08x %s%s\n", Cr3, (Cr3 & 0xfffff000),
|
|
||||||
(Cr3 & (1 << 3)) ? " PWT" : "", (Cr3 & (1 << 4)) ? " PCD" : "" );
|
|
||||||
KdbpPrint("CR4 0x%08x ", Cr4);
|
|
||||||
for (i = 0; i < 32; i++)
|
|
||||||
{
|
|
||||||
if (!Cr4Bits[i])
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if ((Cr4 & (1 << i)) != 0)
|
|
||||||
KdbpPrint(Cr4Bits[i]);
|
|
||||||
}
|
|
||||||
KdbpPrint("\n");
|
|
||||||
|
|
||||||
/* Display the descriptor table and task segment registers */
|
|
||||||
KdbpPrint("GDTR Base 0x%08x Size 0x%04x\n", Gdtr.Base, Gdtr.Limit);
|
|
||||||
KdbpPrint("LDTR 0x%04x\n", Ldtr);
|
|
||||||
KdbpPrint("IDTR Base 0x%08x Size 0x%04x\n", Idtr.Base, Idtr.Limit);
|
|
||||||
KdbpPrint("TR 0x%04x\n", Tr);
|
|
||||||
}
|
|
||||||
else if (Argv[0][0] == 's') /* sregs */
|
else if (Argv[0][0] == 's') /* sregs */
|
||||||
{
|
{
|
||||||
KdbpPrint("CS 0x%04x Index 0x%04x %cDT RPL%d\n",
|
KdbpPrint("CS 0x%04x Index 0x%04x %cDT RPL%d\n",
|
||||||
Tf->SegCs & 0xffff, (Tf->SegCs & 0xffff) >> 3,
|
Context->SegCs & 0xffff, (Context->SegCs & 0xffff) >> 3,
|
||||||
(Tf->SegCs & (1 << 2)) ? 'L' : 'G', Tf->SegCs & 3);
|
(Context->SegCs & (1 << 2)) ? 'L' : 'G', Context->SegCs & 3);
|
||||||
KdbpPrint("DS 0x%04x Index 0x%04x %cDT RPL%d\n",
|
KdbpPrint("DS 0x%04x Index 0x%04x %cDT RPL%d\n",
|
||||||
Tf->SegDs, Tf->SegDs >> 3, (Tf->SegDs & (1 << 2)) ? 'L' : 'G', Tf->SegDs & 3);
|
Context->SegDs, Context->SegDs >> 3, (Context->SegDs & (1 << 2)) ? 'L' : 'G', Context->SegDs & 3);
|
||||||
KdbpPrint("ES 0x%04x Index 0x%04x %cDT RPL%d\n",
|
KdbpPrint("ES 0x%04x Index 0x%04x %cDT RPL%d\n",
|
||||||
Tf->SegEs, Tf->SegEs >> 3, (Tf->SegEs & (1 << 2)) ? 'L' : 'G', Tf->SegEs & 3);
|
Context->SegEs, Context->SegEs >> 3, (Context->SegEs & (1 << 2)) ? 'L' : 'G', Context->SegEs & 3);
|
||||||
KdbpPrint("FS 0x%04x Index 0x%04x %cDT RPL%d\n",
|
KdbpPrint("FS 0x%04x Index 0x%04x %cDT RPL%d\n",
|
||||||
Tf->SegFs, Tf->SegFs >> 3, (Tf->SegFs & (1 << 2)) ? 'L' : 'G', Tf->SegFs & 3);
|
Context->SegFs, Context->SegFs >> 3, (Context->SegFs & (1 << 2)) ? 'L' : 'G', Context->SegFs & 3);
|
||||||
KdbpPrint("GS 0x%04x Index 0x%04x %cDT RPL%d\n",
|
KdbpPrint("GS 0x%04x Index 0x%04x %cDT RPL%d\n",
|
||||||
Tf->SegGs, Tf->SegGs >> 3, (Tf->SegGs & (1 << 2)) ? 'L' : 'G', Tf->SegGs & 3);
|
Context->SegGs, Context->SegGs >> 3, (Context->SegGs & (1 << 2)) ? 'L' : 'G', Context->SegGs & 3);
|
||||||
KdbpPrint("SS 0x%04x Index 0x%04x %cDT RPL%d\n",
|
KdbpPrint("SS 0x%04x Index 0x%04x %cDT RPL%d\n",
|
||||||
Tf->HardwareSegSs, Tf->HardwareSegSs >> 3, (Tf->HardwareSegSs & (1 << 2)) ? 'L' : 'G', Tf->HardwareSegSs & 3);
|
Context->SegSs, Context->SegSs >> 3, (Context->SegSs & (1 << 2)) ? 'L' : 'G', Context->SegSs & 3);
|
||||||
}
|
}
|
||||||
else /* dregs */
|
else /* dregs */
|
||||||
{
|
{
|
||||||
|
@ -1042,8 +983,8 @@ KdbpCmdRegs(
|
||||||
"DR3 0x%08x\n"
|
"DR3 0x%08x\n"
|
||||||
"DR6 0x%08x\n"
|
"DR6 0x%08x\n"
|
||||||
"DR7 0x%08x\n",
|
"DR7 0x%08x\n",
|
||||||
Tf->Dr0, Tf->Dr1, Tf->Dr2, Tf->Dr3,
|
Context->Dr0, Context->Dr1, Context->Dr2, Context->Dr3,
|
||||||
Tf->Dr6, Tf->Dr7);
|
Context->Dr6, Context->Dr7);
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -1117,8 +1058,8 @@ KdbpIsNestedTss(
|
||||||
}
|
}
|
||||||
|
|
||||||
static BOOLEAN
|
static BOOLEAN
|
||||||
KdbpTrapFrameFromPrevTss(
|
KdbpContextFromPrevTss(
|
||||||
IN OUT PKTRAP_FRAME TrapFrame,
|
IN OUT PCONTEXT Context,
|
||||||
OUT PUSHORT TssSelector,
|
OUT PUSHORT TssSelector,
|
||||||
IN OUT PKTSS* pTss,
|
IN OUT PKTSS* pTss,
|
||||||
IN PKDESCRIPTOR pGdtr)
|
IN PKDESCRIPTOR pGdtr)
|
||||||
|
@ -1157,8 +1098,8 @@ KdbpTrapFrameFromPrevTss(
|
||||||
/* Return the parent TSS and its trap frame */
|
/* Return the parent TSS and its trap frame */
|
||||||
*TssSelector = Backlink;
|
*TssSelector = Backlink;
|
||||||
*pTss = Tss;
|
*pTss = Tss;
|
||||||
TrapFrame->Eip = Eip;
|
Context->Eip = Eip;
|
||||||
TrapFrame->Ebp = Ebp;
|
Context->Ebp = Ebp;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1171,8 +1112,8 @@ KdbpCmdBackTrace(
|
||||||
{
|
{
|
||||||
ULONG ul;
|
ULONG ul;
|
||||||
ULONGLONG Result = 0;
|
ULONGLONG Result = 0;
|
||||||
KTRAP_FRAME TrapFrame = KdbCurrentTrapFrame->Tf;
|
CONTEXT Context = *KdbCurrentTrapFrame;
|
||||||
ULONG_PTR Frame = TrapFrame.Ebp;
|
ULONG_PTR Frame = Context.Ebp;
|
||||||
ULONG_PTR Address;
|
ULONG_PTR Address;
|
||||||
KDESCRIPTOR Gdtr;
|
KDESCRIPTOR Gdtr;
|
||||||
USHORT TssSelector;
|
USHORT TssSelector;
|
||||||
|
@ -1247,8 +1188,8 @@ KdbpCmdBackTrace(
|
||||||
if (Argc <= 1)
|
if (Argc <= 1)
|
||||||
{
|
{
|
||||||
KdbpPrint("Eip:\n");
|
KdbpPrint("Eip:\n");
|
||||||
if (!KdbSymPrintAddress((PVOID)TrapFrame.Eip, &TrapFrame))
|
if (!KdbSymPrintAddress((PVOID)Context.Eip, &Context))
|
||||||
KdbpPrint("<%08x>\n", TrapFrame.Eip);
|
KdbpPrint("<%08x>\n", Context.Eip);
|
||||||
else
|
else
|
||||||
KdbpPrint("\n");
|
KdbpPrint("\n");
|
||||||
}
|
}
|
||||||
|
@ -1274,12 +1215,12 @@ KdbpCmdBackTrace(
|
||||||
|
|
||||||
GotNextFrame = NT_SUCCESS(KdbpSafeReadMemory(&Frame, (PVOID)Frame, sizeof(ULONG_PTR)));
|
GotNextFrame = NT_SUCCESS(KdbpSafeReadMemory(&Frame, (PVOID)Frame, sizeof(ULONG_PTR)));
|
||||||
if (GotNextFrame)
|
if (GotNextFrame)
|
||||||
TrapFrame.Ebp = Frame;
|
Context.Ebp = Frame;
|
||||||
// else
|
// else
|
||||||
// Frame = 0;
|
// Frame = 0;
|
||||||
|
|
||||||
/* Print the location of the call instruction (assumed 5 bytes length) */
|
/* Print the location of the call instruction (assumed 5 bytes length) */
|
||||||
if (!KdbSymPrintAddress((PVOID)(Address - 5), &TrapFrame))
|
if (!KdbSymPrintAddress((PVOID)(Address - 5), &Context))
|
||||||
KdbpPrint("<%08x>\n", Address);
|
KdbpPrint("<%08x>\n", Address);
|
||||||
else
|
else
|
||||||
KdbpPrint("\n");
|
KdbpPrint("\n");
|
||||||
|
@ -1304,18 +1245,18 @@ CheckForParentTSS:
|
||||||
if (!KdbpIsNestedTss(TssSelector, Tss))
|
if (!KdbpIsNestedTss(TssSelector, Tss))
|
||||||
break; // The TSS is not nested, we stop there.
|
break; // The TSS is not nested, we stop there.
|
||||||
|
|
||||||
GotNextFrame = KdbpTrapFrameFromPrevTss(&TrapFrame, &TssSelector, &Tss, &Gdtr);
|
GotNextFrame = KdbpContextFromPrevTss(&Context, &TssSelector, &Tss, &Gdtr);
|
||||||
if (!GotNextFrame)
|
if (!GotNextFrame)
|
||||||
{
|
{
|
||||||
KdbpPrint("Couldn't access parent TSS 0x%04x\n", Tss->Backlink);
|
KdbpPrint("Couldn't access parent TSS 0x%04x\n", Tss->Backlink);
|
||||||
break; // Cannot retrieve the parent TSS, we stop there.
|
break; // Cannot retrieve the parent TSS, we stop there.
|
||||||
}
|
}
|
||||||
Address = TrapFrame.Eip;
|
Address = Context.Eip;
|
||||||
Frame = TrapFrame.Ebp;
|
Frame = Context.Ebp;
|
||||||
|
|
||||||
KdbpPrint("[Parent TSS 0x%04x @ 0x%p]\n", TssSelector, Tss);
|
KdbpPrint("[Parent TSS 0x%04x @ 0x%p]\n", TssSelector, Tss);
|
||||||
|
|
||||||
if (!KdbSymPrintAddress((PVOID)Address, &TrapFrame))
|
if (!KdbSymPrintAddress((PVOID)Address, &Context))
|
||||||
KdbpPrint("<%08x>\n", Address);
|
KdbpPrint("<%08x>\n", Address);
|
||||||
else
|
else
|
||||||
KdbpPrint("\n");
|
KdbpPrint("\n");
|
||||||
|
@ -3672,13 +3613,13 @@ KdbpCliMainLoop(
|
||||||
|
|
||||||
if (EnteredOnSingleStep)
|
if (EnteredOnSingleStep)
|
||||||
{
|
{
|
||||||
if (!KdbSymPrintAddress((PVOID)KdbCurrentTrapFrame->Tf.Eip, &KdbCurrentTrapFrame->Tf))
|
if (!KdbSymPrintAddress((PVOID)KdbCurrentTrapFrame->Eip, KdbCurrentTrapFrame))
|
||||||
{
|
{
|
||||||
KdbpPrint("<%08x>", KdbCurrentTrapFrame->Tf.Eip);
|
KdbpPrint("<%08x>", KdbCurrentTrapFrame->Eip);
|
||||||
}
|
}
|
||||||
|
|
||||||
KdbpPrint(": ");
|
KdbpPrint(": ");
|
||||||
if (KdbpDisassemble(KdbCurrentTrapFrame->Tf.Eip, KdbUseIntelSyntax) < 0)
|
if (KdbpDisassemble(KdbCurrentTrapFrame->Eip, KdbUseIntelSyntax) < 0)
|
||||||
{
|
{
|
||||||
KdbpPrint("<INVALID>");
|
KdbpPrint("<INVALID>");
|
||||||
}
|
}
|
||||||
|
@ -3862,7 +3803,7 @@ KdbpCliInit(VOID)
|
||||||
|
|
||||||
/* Interpret the init file... */
|
/* Interpret the init file... */
|
||||||
KdbInitFileBuffer = FileBuffer;
|
KdbInitFileBuffer = FileBuffer;
|
||||||
KdbEnter();
|
//KdbEnter(); // FIXME
|
||||||
KdbInitFileBuffer = NULL;
|
KdbInitFileBuffer = NULL;
|
||||||
|
|
||||||
/* Leave critical section */
|
/* Leave critical section */
|
||||||
|
|
|
@ -111,32 +111,28 @@ static const struct
|
||||||
}
|
}
|
||||||
RegisterToTrapFrame[] =
|
RegisterToTrapFrame[] =
|
||||||
{
|
{
|
||||||
{"eip", FIELD_OFFSET(KDB_KTRAP_FRAME, Tf.Eip), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Tf.Eip)},
|
{"eip", FIELD_OFFSET(KDB_KTRAP_FRAME, Eip), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Eip)},
|
||||||
{"eflags", FIELD_OFFSET(KDB_KTRAP_FRAME, Tf.EFlags), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Tf.EFlags)},
|
{"eflags", FIELD_OFFSET(KDB_KTRAP_FRAME, EFlags), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, EFlags)},
|
||||||
{"eax", FIELD_OFFSET(KDB_KTRAP_FRAME, Tf.Eax), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Tf.Eax)},
|
{"eax", FIELD_OFFSET(KDB_KTRAP_FRAME, Eax), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Eax)},
|
||||||
{"ebx", FIELD_OFFSET(KDB_KTRAP_FRAME, Tf.Ebx), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Tf.Ebx)},
|
{"ebx", FIELD_OFFSET(KDB_KTRAP_FRAME, Ebx), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Ebx)},
|
||||||
{"ecx", FIELD_OFFSET(KDB_KTRAP_FRAME, Tf.Ecx), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Tf.Ecx)},
|
{"ecx", FIELD_OFFSET(KDB_KTRAP_FRAME, Ecx), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Ecx)},
|
||||||
{"edx", FIELD_OFFSET(KDB_KTRAP_FRAME, Tf.Edx), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Tf.Edx)},
|
{"edx", FIELD_OFFSET(KDB_KTRAP_FRAME, Edx), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Edx)},
|
||||||
{"esi", FIELD_OFFSET(KDB_KTRAP_FRAME, Tf.Esi), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Tf.Esi)},
|
{"esi", FIELD_OFFSET(KDB_KTRAP_FRAME, Esi), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Esi)},
|
||||||
{"edi", FIELD_OFFSET(KDB_KTRAP_FRAME, Tf.Edi), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Tf.Edi)},
|
{"edi", FIELD_OFFSET(KDB_KTRAP_FRAME, Edi), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Edi)},
|
||||||
{"esp", FIELD_OFFSET(KDB_KTRAP_FRAME, Tf.HardwareEsp), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Tf.HardwareEsp)},
|
{"esp", FIELD_OFFSET(KDB_KTRAP_FRAME, Esp), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Esp)},
|
||||||
{"ebp", FIELD_OFFSET(KDB_KTRAP_FRAME, Tf.Ebp), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Tf.Ebp)},
|
{"ebp", FIELD_OFFSET(KDB_KTRAP_FRAME, Ebp), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Ebp)},
|
||||||
{"cs", FIELD_OFFSET(KDB_KTRAP_FRAME, Tf.SegCs), 2 }, /* Use only the lower 2 bytes */
|
{"cs", FIELD_OFFSET(KDB_KTRAP_FRAME, SegCs), 2 }, /* Use only the lower 2 bytes */
|
||||||
{"ds", FIELD_OFFSET(KDB_KTRAP_FRAME, Tf.SegDs), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Tf.SegDs)},
|
{"ds", FIELD_OFFSET(KDB_KTRAP_FRAME, SegDs), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, SegDs)},
|
||||||
{"es", FIELD_OFFSET(KDB_KTRAP_FRAME, Tf.SegEs), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Tf.SegEs)},
|
{"es", FIELD_OFFSET(KDB_KTRAP_FRAME, SegEs), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, SegEs)},
|
||||||
{"fs", FIELD_OFFSET(KDB_KTRAP_FRAME, Tf.SegFs), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Tf.SegFs)},
|
{"fs", FIELD_OFFSET(KDB_KTRAP_FRAME, SegFs), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, SegFs)},
|
||||||
{"gs", FIELD_OFFSET(KDB_KTRAP_FRAME, Tf.SegGs), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Tf.SegGs)},
|
{"gs", FIELD_OFFSET(KDB_KTRAP_FRAME, SegGs), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, SegGs)},
|
||||||
{"ss", FIELD_OFFSET(KDB_KTRAP_FRAME, Tf.HardwareSegSs), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Tf.HardwareSegSs)},
|
{"ss", FIELD_OFFSET(KDB_KTRAP_FRAME, SegSs), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, SegSs)},
|
||||||
{"dr0", FIELD_OFFSET(KDB_KTRAP_FRAME, Tf.Dr0), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Tf.Dr0)},
|
{"dr0", FIELD_OFFSET(KDB_KTRAP_FRAME, Dr0), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Dr0)},
|
||||||
{"dr1", FIELD_OFFSET(KDB_KTRAP_FRAME, Tf.Dr1), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Tf.Dr1)},
|
{"dr1", FIELD_OFFSET(KDB_KTRAP_FRAME, Dr1), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Dr1)},
|
||||||
{"dr2", FIELD_OFFSET(KDB_KTRAP_FRAME, Tf.Dr2), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Tf.Dr2)},
|
{"dr2", FIELD_OFFSET(KDB_KTRAP_FRAME, Dr2), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Dr2)},
|
||||||
{"dr3", FIELD_OFFSET(KDB_KTRAP_FRAME, Tf.Dr3), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Tf.Dr3)},
|
{"dr3", FIELD_OFFSET(KDB_KTRAP_FRAME, Dr3), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Dr3)},
|
||||||
{"dr6", FIELD_OFFSET(KDB_KTRAP_FRAME, Tf.Dr6), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Tf.Dr6)},
|
{"dr6", FIELD_OFFSET(KDB_KTRAP_FRAME, Dr6), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Dr6)},
|
||||||
{"dr7", FIELD_OFFSET(KDB_KTRAP_FRAME, Tf.Dr7), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Tf.Dr7)},
|
{"dr7", FIELD_OFFSET(KDB_KTRAP_FRAME, Dr7), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Dr7)}
|
||||||
{"cr0", FIELD_OFFSET(KDB_KTRAP_FRAME, Cr0), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Cr0)},
|
|
||||||
{"cr2", FIELD_OFFSET(KDB_KTRAP_FRAME, Cr2), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Cr2)},
|
|
||||||
{"cr3", FIELD_OFFSET(KDB_KTRAP_FRAME, Cr3), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Cr3)},
|
|
||||||
{"cr4", FIELD_OFFSET(KDB_KTRAP_FRAME, Cr4), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Cr4)}
|
|
||||||
};
|
};
|
||||||
static const INT RegisterToTrapFrameCount = sizeof (RegisterToTrapFrame) / sizeof (RegisterToTrapFrame[0]);
|
static const INT RegisterToTrapFrameCount = sizeof (RegisterToTrapFrame) / sizeof (RegisterToTrapFrame[0]);
|
||||||
|
|
||||||
|
|
|
@ -155,7 +155,7 @@ KdbpSymUnicodeToAnsi(IN PUNICODE_STRING Unicode,
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
KdbSymPrintAddress(
|
KdbSymPrintAddress(
|
||||||
IN PVOID Address,
|
IN PVOID Address,
|
||||||
IN PKTRAP_FRAME Context)
|
IN PCONTEXT Context)
|
||||||
{
|
{
|
||||||
PLDR_DATA_TABLE_ENTRY LdrEntry;
|
PLDR_DATA_TABLE_ENTRY LdrEntry;
|
||||||
ULONG_PTR RelativeAddress;
|
ULONG_PTR RelativeAddress;
|
||||||
|
|
Loading…
Reference in a new issue