mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 19:12:57 +00:00
- Fix critical bugs in DR_TRAP_FIXUP, TRAP_PROLOG and TRAP_EPILOG which would either cause infinite loops during exceptions or corruption of the correct code path when dealing with debug registers.
- Fix a bug in KiRecordDr7 setting the new DR7 mask. - Make KiEspToTrapFrame thread-safe by raising to APC_LEVEL to make sure a thread/set context doesn't corrupt the state. - Fix thread-safe IRQL Code in KeContexToTrapFrame/KeTrapFrameToContext. - Fix KiDispatchException to properly handle KI_EXCEPTION_ACCESS_VIOLATION and convert it back to STATUS_ACCESS_VIOLATION which is what the system expects. - Also fix the way we do bugchecks so the the trapframe gets properly put as a parameter. - Make KiDebugService call into KiTrap3 to share code (merge from kd-branch). - Changes to the KdpEnterDebuggerException hack we have to handle this change. - Temporarily disable DebugPrint functionality (sorry, I'm onto a big bug here!) svn path=/trunk/; revision=25975
This commit is contained in:
parent
037363f05d
commit
a195100319
5 changed files with 77 additions and 60 deletions
|
@ -23,7 +23,7 @@ DebugPrint(IN PANSI_STRING DebugString,
|
||||||
IN ULONG Level)
|
IN ULONG Level)
|
||||||
{
|
{
|
||||||
/* Call the INT2D Service */
|
/* Call the INT2D Service */
|
||||||
//return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
return DebugService(BREAKPOINT_PRINT,
|
return DebugService(BREAKPOINT_PRINT,
|
||||||
DebugString->Buffer,
|
DebugString->Buffer,
|
||||||
DebugString->Length,
|
DebugString->Length,
|
||||||
|
|
|
@ -304,7 +304,7 @@ _KiUnexpectedInterrupt&Number:
|
||||||
/* Set them */
|
/* Set them */
|
||||||
mov dr6, ebx
|
mov dr6, ebx
|
||||||
mov dr7, ecx
|
mov dr7, ecx
|
||||||
jz 3f
|
jmp 3f
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -482,12 +482,12 @@ _KiUnexpectedInterrupt&Number:
|
||||||
/* Flush DR7 */
|
/* Flush DR7 */
|
||||||
and dword ptr [ebp+KTRAP_FRAME_DR7], 0
|
and dword ptr [ebp+KTRAP_FRAME_DR7], 0
|
||||||
|
|
||||||
3:
|
|
||||||
/* Check if the thread was being debugged */
|
/* Check if the thread was being debugged */
|
||||||
test byte ptr [ecx+KTHREAD_DEBUG_ACTIVE], 0xFF
|
test byte ptr [ecx+KTHREAD_DEBUG_ACTIVE], 0xFF
|
||||||
jnz Dr_&Label
|
jnz Dr_&Label
|
||||||
|
|
||||||
/* Set the Trap Frame Debug Header */
|
/* Set the Trap Frame Debug Header */
|
||||||
|
3:
|
||||||
SET_TF_DEBUG_HEADER
|
SET_TF_DEBUG_HEADER
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
|
@ -1171,7 +1171,7 @@ FastExit:
|
||||||
mov dr3, esi
|
mov dr3, esi
|
||||||
mov dr6, edi
|
mov dr6, edi
|
||||||
mov dr7, ebx
|
mov dr7, ebx
|
||||||
jz 4b
|
jmp 4b
|
||||||
|
|
||||||
7:
|
7:
|
||||||
/* Restore real CS value */
|
/* Restore real CS value */
|
||||||
|
|
|
@ -106,9 +106,28 @@ KdpEnterDebuggerException(IN PKTRAP_FRAME TrapFrame,
|
||||||
IN BOOLEAN SecondChance)
|
IN BOOLEAN SecondChance)
|
||||||
{
|
{
|
||||||
KD_CONTINUE_TYPE Return;
|
KD_CONTINUE_TYPE Return;
|
||||||
|
ULONG ExceptionCommand = ExceptionRecord->ExceptionInformation[0];
|
||||||
|
|
||||||
/* HACK (just like all this routine */
|
/* Check if this was a breakpoint due to DbgPrint or Load/UnloadSymbols */
|
||||||
if (ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) Context->Eip++;
|
if ((ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) &&
|
||||||
|
(ExceptionRecord->NumberParameters > 0) &&
|
||||||
|
((ExceptionCommand == BREAKPOINT_LOAD_SYMBOLS) ||
|
||||||
|
(ExceptionCommand == BREAKPOINT_UNLOAD_SYMBOLS) ||
|
||||||
|
(ExceptionCommand == BREAKPOINT_COMMAND_STRING) ||
|
||||||
|
(ExceptionCommand == BREAKPOINT_PRINT)))
|
||||||
|
{
|
||||||
|
/* Check if this is a debug print */
|
||||||
|
if (ExceptionCommand == BREAKPOINT_PRINT)
|
||||||
|
{
|
||||||
|
/* Print the string */
|
||||||
|
KdpServiceDispatcher(BREAKPOINT_PRINT,
|
||||||
|
(PVOID)ExceptionRecord->ExceptionInformation[1],
|
||||||
|
ExceptionRecord->ExceptionInformation[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This we can handle: simply bump EIP */
|
||||||
|
Context->Eip++;
|
||||||
|
}
|
||||||
|
|
||||||
/* Get out of here if the Debugger isn't connected */
|
/* Get out of here if the Debugger isn't connected */
|
||||||
if (KdDebuggerNotPresent) return FALSE;
|
if (KdDebuggerNotPresent) return FALSE;
|
||||||
|
|
|
@ -140,7 +140,7 @@ KiRecordDr7(OUT PULONG Dr7Ptr,
|
||||||
NewMask |= DR_MASK(DR7_OVERRIDE_V);
|
NewMask |= DR_MASK(DR7_OVERRIDE_V);
|
||||||
|
|
||||||
/* Set DR7 override */
|
/* Set DR7 override */
|
||||||
*DrMask = DR7_OVERRIDE_MASK;
|
*DrMask |= DR7_OVERRIDE_MASK;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -210,10 +210,19 @@ NTAPI
|
||||||
KiEspToTrapFrame(IN PKTRAP_FRAME TrapFrame,
|
KiEspToTrapFrame(IN PKTRAP_FRAME TrapFrame,
|
||||||
IN ULONG Esp)
|
IN ULONG Esp)
|
||||||
{
|
{
|
||||||
ULONG Previous = KiEspFromTrapFrame(TrapFrame);
|
KIRQL OldIrql;
|
||||||
|
ULONG Previous;
|
||||||
|
|
||||||
|
/* Raise to APC_LEVEL if needed */
|
||||||
|
OldIrql = KeGetCurrentIrql();
|
||||||
|
if (OldIrql < APC_LEVEL) KeRaiseIrql(APC_LEVEL, &OldIrql);
|
||||||
|
|
||||||
|
/* Get the old ESP */
|
||||||
|
Previous = KiEspFromTrapFrame(TrapFrame);
|
||||||
|
|
||||||
/* Check if this is user-mode or V86 */
|
/* Check if this is user-mode or V86 */
|
||||||
if ((TrapFrame->SegCs & MODE_MASK) || (TrapFrame->EFlags & EFLAGS_V86_MASK))
|
if ((TrapFrame->SegCs & MODE_MASK) ||
|
||||||
|
(TrapFrame->EFlags & EFLAGS_V86_MASK))
|
||||||
{
|
{
|
||||||
/* Write it directly */
|
/* Write it directly */
|
||||||
TrapFrame->HardwareEsp = Esp;
|
TrapFrame->HardwareEsp = Esp;
|
||||||
|
@ -221,7 +230,11 @@ KiEspToTrapFrame(IN PKTRAP_FRAME TrapFrame,
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Don't allow ESP to be lowered, this is illegal */
|
/* Don't allow ESP to be lowered, this is illegal */
|
||||||
if (Esp < Previous) KeBugCheck(SET_OF_INVALID_CONTEXT);
|
if (Esp < Previous) KeBugCheckEx(SET_OF_INVALID_CONTEXT,
|
||||||
|
Esp,
|
||||||
|
Previous,
|
||||||
|
(ULONG_PTR)TrapFrame,
|
||||||
|
0);
|
||||||
|
|
||||||
/* Create an edit frame, check if it was alrady */
|
/* Create an edit frame, check if it was alrady */
|
||||||
if (!(TrapFrame->SegCs & FRAME_EDITED))
|
if (!(TrapFrame->SegCs & FRAME_EDITED))
|
||||||
|
@ -243,6 +256,9 @@ KiEspToTrapFrame(IN PKTRAP_FRAME TrapFrame,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Restore IRQL */
|
||||||
|
if (OldIrql < APC_LEVEL) KeLowerIrql(OldIrql);
|
||||||
}
|
}
|
||||||
|
|
||||||
ULONG
|
ULONG
|
||||||
|
@ -316,12 +332,13 @@ KeContextToTrapFrame(IN PCONTEXT Context,
|
||||||
PFX_SAVE_AREA FxSaveArea;
|
PFX_SAVE_AREA FxSaveArea;
|
||||||
ULONG i;
|
ULONG i;
|
||||||
BOOLEAN V86Switch = FALSE;
|
BOOLEAN V86Switch = FALSE;
|
||||||
KIRQL OldIrql = APC_LEVEL;
|
KIRQL OldIrql;
|
||||||
ULONG DrMask = 0;
|
ULONG DrMask = 0;
|
||||||
PVOID SafeDr;
|
PVOID SafeDr;
|
||||||
|
|
||||||
/* Do this at APC_LEVEL */
|
/* Do this at APC_LEVEL */
|
||||||
if (KeGetCurrentIrql() < APC_LEVEL) KeRaiseIrql(APC_LEVEL, &OldIrql);
|
OldIrql = KeGetCurrentIrql();
|
||||||
|
if (OldIrql < APC_LEVEL) KeRaiseIrql(APC_LEVEL, &OldIrql);
|
||||||
|
|
||||||
/* Start with the basic Registers */
|
/* Start with the basic Registers */
|
||||||
if ((ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL)
|
if ((ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL)
|
||||||
|
@ -544,7 +561,7 @@ KeContextToTrapFrame(IN PCONTEXT Context,
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* FIXME: Handle FPU Emulation */
|
/* FIXME: Handle FPU Emulation */
|
||||||
ASSERT(FALSE);
|
//ASSERT(FALSE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -600,11 +617,12 @@ KeTrapFrameToContext(IN PKTRAP_FRAME TrapFrame,
|
||||||
FLOATING_SAVE_AREA UnalignedArea;
|
FLOATING_SAVE_AREA UnalignedArea;
|
||||||
} FloatSaveBuffer;
|
} FloatSaveBuffer;
|
||||||
FLOATING_SAVE_AREA *FloatSaveArea;
|
FLOATING_SAVE_AREA *FloatSaveArea;
|
||||||
KIRQL OldIrql = APC_LEVEL;
|
KIRQL OldIrql;
|
||||||
ULONG i;
|
ULONG i;
|
||||||
|
|
||||||
/* Do this at APC_LEVEL */
|
/* Do this at APC_LEVEL */
|
||||||
if (KeGetCurrentIrql() < APC_LEVEL) KeRaiseIrql(APC_LEVEL, &OldIrql);
|
OldIrql = KeGetCurrentIrql();
|
||||||
|
if (OldIrql < APC_LEVEL) KeRaiseIrql(APC_LEVEL, &OldIrql);
|
||||||
|
|
||||||
/* Start with the Control flags */
|
/* Start with the Control flags */
|
||||||
if ((Context->ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL)
|
if ((Context->ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL)
|
||||||
|
@ -817,11 +835,26 @@ KiDispatchException(IN PEXCEPTION_RECORD ExceptionRecord,
|
||||||
/* Get a Context */
|
/* Get a Context */
|
||||||
KeTrapFrameToContext(TrapFrame, ExceptionFrame, &Context);
|
KeTrapFrameToContext(TrapFrame, ExceptionFrame, &Context);
|
||||||
|
|
||||||
/* Fix up EIP */
|
/* Look at our exception code */
|
||||||
if (ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT)
|
switch (ExceptionRecord->ExceptionCode)
|
||||||
{
|
{
|
||||||
/* Decrement EIP by one */
|
/* Breapoint */
|
||||||
Context.Eip--;
|
case STATUS_BREAKPOINT:
|
||||||
|
|
||||||
|
/* Decrement EIP by one */
|
||||||
|
Context.Eip--;
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Internal exception */
|
||||||
|
case KI_EXCEPTION_ACCESS_VIOLATION:
|
||||||
|
|
||||||
|
/* Set correct code */
|
||||||
|
ExceptionRecord->ExceptionCode = STATUS_ACCESS_VIOLATION;
|
||||||
|
if (PreviousMode == UserMode)
|
||||||
|
{
|
||||||
|
/* FIXME: Handle no execute */
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Sanity check */
|
/* Sanity check */
|
||||||
|
@ -866,8 +899,8 @@ KiDispatchException(IN PEXCEPTION_RECORD ExceptionRecord,
|
||||||
KeBugCheckEx(KMODE_EXCEPTION_NOT_HANDLED,
|
KeBugCheckEx(KMODE_EXCEPTION_NOT_HANDLED,
|
||||||
ExceptionRecord->ExceptionCode,
|
ExceptionRecord->ExceptionCode,
|
||||||
(ULONG_PTR)ExceptionRecord->ExceptionAddress,
|
(ULONG_PTR)ExceptionRecord->ExceptionAddress,
|
||||||
ExceptionRecord->ExceptionInformation[0],
|
(ULONG_PTR)TrapFrame,
|
||||||
ExceptionRecord->ExceptionInformation[1]);
|
0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -989,8 +1022,8 @@ DispatchToUser:
|
||||||
KeBugCheckEx(KMODE_EXCEPTION_NOT_HANDLED,
|
KeBugCheckEx(KMODE_EXCEPTION_NOT_HANDLED,
|
||||||
ExceptionRecord->ExceptionCode,
|
ExceptionRecord->ExceptionCode,
|
||||||
(ULONG_PTR)ExceptionRecord->ExceptionAddress,
|
(ULONG_PTR)ExceptionRecord->ExceptionAddress,
|
||||||
ExceptionRecord->ExceptionInformation[0],
|
(ULONG_PTR)TrapFrame,
|
||||||
ExceptionRecord->ExceptionInformation[1]);
|
0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Handled:
|
Handled:
|
||||||
|
|
|
@ -473,43 +473,8 @@ _KiDebugService:
|
||||||
mov ecx, [ebp+KTRAP_FRAME_ECX]
|
mov ecx, [ebp+KTRAP_FRAME_ECX]
|
||||||
mov edx, [ebp+KTRAP_FRAME_EDX]
|
mov edx, [ebp+KTRAP_FRAME_EDX]
|
||||||
|
|
||||||
/* Check for V86 mode */
|
/* Jump to INT3 handler */
|
||||||
test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
|
jmp PrepareInt3
|
||||||
jnz NotUserMode
|
|
||||||
|
|
||||||
/* Check if this is kernel or user-mode */
|
|
||||||
test byte ptr [ebp+KTRAP_FRAME_CS], 1
|
|
||||||
jz CallDispatch
|
|
||||||
cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R3_CODE + RPL_MASK
|
|
||||||
jnz NotUserMode
|
|
||||||
|
|
||||||
/* Re-enable interrupts */
|
|
||||||
VdmProc:
|
|
||||||
sti
|
|
||||||
|
|
||||||
/* Call the debug routine */
|
|
||||||
CallDispatch:
|
|
||||||
mov esi, ecx
|
|
||||||
mov edi, edx
|
|
||||||
mov edx, eax
|
|
||||||
mov ecx, 3
|
|
||||||
push edi
|
|
||||||
push esi
|
|
||||||
push edx
|
|
||||||
call _KdpServiceDispatcher@12
|
|
||||||
|
|
||||||
NotUserMode:
|
|
||||||
|
|
||||||
/* Get the current process */
|
|
||||||
mov ebx, [fs:KPCR_CURRENT_THREAD]
|
|
||||||
mov ebx, [ebx+KTHREAD_APCSTATE_PROCESS]
|
|
||||||
|
|
||||||
/* Check if this is a VDM Process */
|
|
||||||
//cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0
|
|
||||||
//jz VdmProc
|
|
||||||
|
|
||||||
/* Exit through common routine */
|
|
||||||
jmp _Kei386EoiHelper@0
|
|
||||||
.endfunc
|
.endfunc
|
||||||
|
|
||||||
.func NtRaiseException@12
|
.func NtRaiseException@12
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue