mirror of
https://github.com/reactos/reactos.git
synced 2024-12-27 01:24:38 +00:00
Some work-in-progress improvements and rethought of system-level code...notable improvemnts till now are: -The KTHREAD alterted flag is now properly set to FALSE during APC delivery during traps, -More support for PKEXCEPTION_FRAME has been added for future PPC/IA64/etc compatibility -Context to/from TrapFrame functions have been greatly fixed to allow for edited frames, special cases, exceptions and also have the necessary support for supporting sanitation based on PreviousMode - KDBG now shows the proper CS/SS at all times, previous hack was removed. - Systemcall code was optimized a bit and the trap code was made a lot more generic so that in can be made into macros (it currently isn't, for debugging purposes). - V86 Mode trap frame bias has now been added to make trap code a lot more generic and shareable in the future. -More support and fixes for future Debugging capabilities have been added. - Random other scalability and stability code. This is still being worked on, syscall.S looks nasty for now (visually)
svn path=/trunk/; revision=17838
This commit is contained in:
parent
3b0cfca870
commit
7a5244c46d
18 changed files with 1124 additions and 374 deletions
|
@ -256,13 +256,13 @@ LdrpInit(PCONTEXT Context,
|
|||
SYSTEM_BASIC_INFORMATION SystemInformation;
|
||||
NTSTATUS Status;
|
||||
|
||||
DPRINT("LdrpInit()\n");
|
||||
DPRINT1("LdrpInit()\n");
|
||||
if (NtCurrentPeb()->Ldr == NULL || NtCurrentPeb()->Ldr->Initialized == FALSE)
|
||||
{
|
||||
Peb = (PPEB)(PEB_BASE);
|
||||
DPRINT("Peb %x\n", Peb);
|
||||
DPRINT1("Peb %x\n", Peb);
|
||||
ImageBase = Peb->ImageBaseAddress;
|
||||
DPRINT("ImageBase %x\n", ImageBase);
|
||||
DPRINT1("ImageBase %x\n", ImageBase);
|
||||
if (ImageBase <= (PVOID)0x1000)
|
||||
{
|
||||
DPRINT("ImageBase is null\n");
|
||||
|
@ -271,7 +271,7 @@ LdrpInit(PCONTEXT Context,
|
|||
|
||||
/* If MZ header exists */
|
||||
PEDosHeader = (PIMAGE_DOS_HEADER) ImageBase;
|
||||
DPRINT("PEDosHeader %x\n", PEDosHeader);
|
||||
DPRINT1("PEDosHeader %x\n", PEDosHeader);
|
||||
|
||||
if (PEDosHeader->e_magic != IMAGE_DOS_SIGNATURE ||
|
||||
PEDosHeader->e_lfanew == 0L ||
|
||||
|
@ -294,10 +294,12 @@ LdrpInit(PCONTEXT Context,
|
|||
NTHeaders = (PIMAGE_NT_HEADERS)((ULONG_PTR)ImageBase + PEDosHeader->e_lfanew);
|
||||
|
||||
/* Get number of processors */
|
||||
DPRINT1("Here\n");
|
||||
Status = ZwQuerySystemInformation(SystemBasicInformation,
|
||||
&SystemInformation,
|
||||
sizeof(SYSTEM_BASIC_INFORMATION),
|
||||
NULL);
|
||||
DPRINT1("Here2\n");
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ZwTerminateProcess(NtCurrentProcess(), Status);
|
||||
|
|
|
@ -165,7 +165,7 @@ RtlDispatchException(IN PEXCEPTION_RECORD ExceptionRecord,
|
|||
}
|
||||
|
||||
/* Unhandled, return false */
|
||||
DPRINT1("FALSE:(\n");
|
||||
DPRINT1("FALSE\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
|
@ -241,7 +241,6 @@ ExecuteRuntimeAsserts(VOID)
|
|||
ASSERT(FIELD_OFFSET(KPROCESS, DirectoryTableBase) == KPROCESS_DIRECTORY_TABLE_BASE);
|
||||
ASSERT(FIELD_OFFSET(KPROCESS, IopmOffset) == KPROCESS_IOPM_OFFSET);
|
||||
ASSERT(FIELD_OFFSET(KPROCESS, LdtDescriptor) == KPROCESS_LDT_DESCRIPTOR0);
|
||||
ASSERT(FIELD_OFFSET(KTRAP_FRAME, Reserved9) == KTRAP_FRAME_RESERVED9);
|
||||
ASSERT(FIELD_OFFSET(KV86M_TRAP_FRAME, SavedExceptionStack) == TF_SAVED_EXCEPTION_STACK);
|
||||
ASSERT(FIELD_OFFSET(KV86M_TRAP_FRAME, regs) == TF_REGS);
|
||||
ASSERT(FIELD_OFFSET(KV86M_TRAP_FRAME, orig_ebp) == TF_ORIG_EBP);
|
||||
|
|
|
@ -40,11 +40,15 @@
|
|||
#define X86_EXT_FEATURE_SSE3 0x00000001 /* SSE3 extension present */
|
||||
#define X86_EXT_FEATURE_3DNOW 0x40000000 /* 3DNOW! extension present */
|
||||
|
||||
#define DR7_ACTIVE 0x00000055 /* If any of these bits are set, a Dr is active */
|
||||
|
||||
/* Possible values for KTHREAD's NpxState */
|
||||
#define NPX_STATE_INVALID 0x01
|
||||
#define NPX_STATE_VALID 0x02
|
||||
#define NPX_STATE_DIRTY 0x04
|
||||
|
||||
#define FRAME_EDITED 0xFFF8
|
||||
|
||||
#ifndef __ASM__
|
||||
|
||||
typedef struct _KIRQ_TRAPFRAME
|
||||
|
|
|
@ -287,7 +287,10 @@ VOID inline FASTCALL KiSatisifyMultipleObjectWaits(PKWAIT_BLOCK WaitBlock);
|
|||
VOID FASTCALL KiWaitTest(PDISPATCHER_HEADER Object, KPRIORITY Increment);
|
||||
|
||||
PULONG KeGetStackTopThread(struct _ETHREAD* Thread);
|
||||
BOOLEAN STDCALL KeContextToTrapFrame(PCONTEXT Context, PKEXCEPTION_FRAME ExeptionFrame, PKTRAP_FRAME TrapFrame);
|
||||
BOOLEAN STDCALL KeContextToTrapFrame(PCONTEXT Context,
|
||||
PKEXCEPTION_FRAME ExeptionFrame,
|
||||
PKTRAP_FRAME TrapFrame,
|
||||
KPROCESSOR_MODE PreviousMode);
|
||||
VOID STDCALL KiDeliverApc(KPROCESSOR_MODE PreviousMode,
|
||||
PVOID Reserved,
|
||||
PKTRAP_FRAME TrapFrame);
|
||||
|
@ -368,8 +371,11 @@ KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
|
|||
PKTRAP_FRAME Tf,
|
||||
KPROCESSOR_MODE PreviousMode,
|
||||
BOOLEAN SearchFrames);
|
||||
VOID KeTrapFrameToContext(PKTRAP_FRAME TrapFrame,
|
||||
PCONTEXT Context);
|
||||
VOID
|
||||
NTAPI
|
||||
KeTrapFrameToContext(IN PKTRAP_FRAME TrapFrame,
|
||||
IN PKEXCEPTION_FRAME ExceptionFrame,
|
||||
IN OUT PCONTEXT Context);
|
||||
VOID
|
||||
KeApplicationProcessorInit(VOID);
|
||||
VOID
|
||||
|
|
|
@ -1321,7 +1321,7 @@ KdpGdbEnterDebuggerException(PEXCEPTION_RECORD ExceptionRecord,
|
|||
#error Unknown compiler for inline assembler
|
||||
#endif
|
||||
|
||||
KeContextToTrapFrame(Context, NULL, TrapFrame);
|
||||
KeContextToTrapFrame(Context, NULL, TrapFrame, KernelMode);
|
||||
return ((SigVal == 5) ? (kdContinue) : (kdHandleException));
|
||||
break;
|
||||
}
|
||||
|
@ -1430,11 +1430,11 @@ GspBreakIn(PKINTERRUPT Interrupt,
|
|||
|
||||
TrapFrame = PsGetCurrentThread()->Tcb.TrapFrame;
|
||||
|
||||
KeTrapFrameToContext (TrapFrame, &Context);
|
||||
KeTrapFrameToContext (TrapFrame, NULL, &Context);
|
||||
|
||||
KdpGdbEnterDebuggerException (NULL, &Context, TrapFrame);
|
||||
|
||||
KeContextToTrapFrame (&Context, NULL, TrapFrame);
|
||||
KeContextToTrapFrame (&Context, NULL, TrapFrame, KernelMode);
|
||||
|
||||
KeLowerIrql (OldIrql);
|
||||
|
||||
|
|
|
@ -15,10 +15,6 @@
|
|||
|
||||
/* TYPES *********************************************************************/
|
||||
|
||||
/* FIXME: NDK headers */
|
||||
#define TempEsp TempEip
|
||||
#define TempSegSs TempCs
|
||||
|
||||
/* DEFINES *******************************************************************/
|
||||
|
||||
#define KDB_STACK_SIZE (4096*3)
|
||||
|
@ -108,6 +104,24 @@ STATIC CONST PCHAR ExceptionNrToString[] =
|
|||
"SIMD Fault"
|
||||
};
|
||||
|
||||
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 *****************************************************************/
|
||||
|
||||
STATIC VOID
|
||||
|
@ -124,22 +138,11 @@ KdbpTrapFrameToKdbTrapFrame(PKTRAP_FRAME TrapFrame, PKDB_KTRAP_FRAME KdbTrapFram
|
|||
"movl %%cr4, %3" "\n\t"
|
||||
: "=r"(KdbTrapFrame->Cr0), "=r"(KdbTrapFrame->Cr2),
|
||||
"=r"(KdbTrapFrame->Cr3), "=r"(KdbTrapFrame->Cr4));
|
||||
|
||||
if (TrapFrame->PreviousMode == KernelMode)
|
||||
{
|
||||
/* If the trapframe is a kmode one use the temp ss:esp */
|
||||
KdbTrapFrame->Tf.Esp = (ULONG)TrapFrame->TempEsp;
|
||||
KdbTrapFrame->Tf.Ss = (USHORT)((ULONG)TrapFrame->TempSegSs & 0xFFFF);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Otherwise use ss:esp pushed by the CPU */
|
||||
/* FIXME: maybe change all trapframes to always put ss:esp into tempss:tempesp so we
|
||||
* can handle umode and kmode the same way */
|
||||
KdbTrapFrame->Tf.Esp = TrapFrame->Esp;
|
||||
KdbTrapFrame->Tf.Ss = TrapFrame->Ss;
|
||||
}
|
||||
|
||||
|
||||
KdbTrapFrame->Tf.Esp = KiEspFromTrapFrame(TrapFrame);
|
||||
KdbTrapFrame->Tf.Ss = (USHORT)(KiSsFromTrapFrame(TrapFrame) & 0xFFFF);
|
||||
|
||||
|
||||
/* FIXME: copy v86 registers if TrapFrame is a V86 trapframe */
|
||||
}
|
||||
|
||||
|
@ -151,20 +154,8 @@ KdbpKdbTrapFrameToTrapFrame(PKDB_KTRAP_FRAME KdbTrapFrame, PKTRAP_FRAME TrapFram
|
|||
|
||||
/* FIXME: write cr0, cr2, cr3 and cr4 (not needed atm) */
|
||||
|
||||
if (TrapFrame->PreviousMode == KernelMode)
|
||||
{
|
||||
/* If the trapframe is a kmode one write to the temp ss:esp */
|
||||
TrapFrame->TempEsp = (PVOID)KdbTrapFrame->Tf.Esp;
|
||||
TrapFrame->TempSegSs = (PVOID)(((ULONG)TrapFrame->TempSegSs & ~0xffff) | KdbTrapFrame->Tf.Ss);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Otherwise write to ss:esp pushed by the CPU */
|
||||
/* FIXME: maybe change all trap-epilogs to always put temp ss:esp into ss:esp so we
|
||||
* can handle umode and kmode the same way */
|
||||
TrapFrame->Esp = KdbTrapFrame->Tf.Esp;
|
||||
TrapFrame->Ss = KdbTrapFrame->Tf.Ss;
|
||||
}
|
||||
KiSsToTrapFrame(TrapFrame, KdbTrapFrame->Tf.Ss);
|
||||
KiEspToTrapFrame(TrapFrame, KdbTrapFrame->Tf.Esp);
|
||||
|
||||
/* FIXME: copy v86 registers if TrapFrame is a V86 trapframe */
|
||||
}
|
||||
|
|
|
@ -35,10 +35,6 @@
|
|||
|
||||
/* DEFINES *******************************************************************/
|
||||
|
||||
/* FIXME: NDK headers */
|
||||
#define TempEsp TempEip
|
||||
#define TempSegSs TempCs
|
||||
|
||||
#define KEY_BS 8
|
||||
#define KEY_ESC 27
|
||||
#define KEY_DEL 127
|
||||
|
|
|
@ -812,7 +812,7 @@ KiInitializeUserApc(IN PKEXCEPTION_FRAME ExceptionFrame,
|
|||
|
||||
/* Save the full context */
|
||||
Context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
|
||||
KeTrapFrameToContext(TrapFrame, &Context);
|
||||
KeTrapFrameToContext(TrapFrame, ExceptionFrame, &Context);
|
||||
|
||||
/* Protect with SEH */
|
||||
_SEH_TRY
|
||||
|
|
|
@ -28,7 +28,7 @@ KiContinuePreviousModeUser(IN PCONTEXT Context,
|
|||
Context = &LocalContext;
|
||||
|
||||
/* Convert the context into Exception/Trap Frames */
|
||||
KeContextToTrapFrame(&LocalContext, ExceptionFrame, TrapFrame);
|
||||
KeContextToTrapFrame(&LocalContext, ExceptionFrame, TrapFrame, UserMode);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
|
@ -62,7 +62,7 @@ KiContinue(IN PCONTEXT Context,
|
|||
else
|
||||
{
|
||||
/* Convert the context into Exception/Trap Frames */
|
||||
KeContextToTrapFrame(Context, ExceptionFrame, TrapFrame);
|
||||
KeContextToTrapFrame(Context, ExceptionFrame, TrapFrame, KernelMode);
|
||||
}
|
||||
}
|
||||
_SEH_HANDLE
|
||||
|
@ -142,7 +142,7 @@ KiRaiseException(PEXCEPTION_RECORD ExceptionRecord,
|
|||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* Convert the context record */
|
||||
KeContextToTrapFrame(Context, ExceptionFrame, TrapFrame);
|
||||
KeContextToTrapFrame(Context, ExceptionFrame, TrapFrame, PreviousMode);
|
||||
|
||||
/* Dispatch the exception */
|
||||
KiDispatchException(ExceptionRecord,
|
||||
|
|
|
@ -114,7 +114,7 @@ BadThread:
|
|||
.globl @KiSwapContextInternal@0
|
||||
@KiSwapContextInternal@0:
|
||||
#ifdef KDBG
|
||||
jmp SaveTrapFrameForKDB
|
||||
//jmp SaveTrapFrameForKDB
|
||||
SaveTrapFrameForKDB_Return:
|
||||
#endif
|
||||
|
||||
|
@ -130,12 +130,14 @@ SaveTrapFrameForKDB_Return:
|
|||
/* Switching, disable interrupts now */
|
||||
cli
|
||||
|
||||
/* Save the initial stack in EAX */
|
||||
mov eax, [edi+KTHREAD_INITIAL_STACK]
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
/* Save FPU state if the thread has used it. */
|
||||
mov dword ptr [ebx+KPCR_NPX_THREAD], 0
|
||||
test byte ptr [edi+KTHREAD_NPX_STATE], NPX_STATE_DIRTY
|
||||
jz 3f
|
||||
mov eax, [edi+KTHREAD_INITIAL_STACK]
|
||||
cmp dword ptr _FxsrSupport, 0
|
||||
je 1f
|
||||
fxsave [eax-SIZEOF_FX_SAVE_AREA]
|
||||
|
@ -149,8 +151,18 @@ SaveTrapFrameForKDB_Return:
|
|||
|
||||
/* Save the stack pointer in this processors TSS */
|
||||
mov ebp, [ebx+KPCR_TSS]
|
||||
|
||||
/* Check if this isn't V86 Mode, so we can bias the Esp0 */
|
||||
test dword ptr [eax - KTRAP_FRAME_SIZE + KTRAP_FRAME_EFLAGS], X86_EFLAGS_VM
|
||||
jnz NoAdjust
|
||||
|
||||
/* Bias esp */
|
||||
//sub dword ptr ss:[ebp+KTSS_ESP0], KTRAP_FRAME_V86_GS - KTRAP_FRAME_SS
|
||||
|
||||
NoAdjust:
|
||||
/* Push ESP0 Value */
|
||||
push ss:[ebp+KTSS_ESP0]
|
||||
|
||||
|
||||
/* Check if address space switch is needed */
|
||||
mov eax, [esi+KTHREAD_APCSTATE_PROCESS]
|
||||
cmp eax, [edi+KTHREAD_APCSTATE_PROCESS]
|
||||
|
|
|
@ -17,14 +17,18 @@
|
|||
|
||||
/*
|
||||
* FIXMES:
|
||||
* - Put back VEH.
|
||||
* - Clean up file.
|
||||
* - Add more exception frame support for non-i386 compatibility.
|
||||
* - Sanitize some context fields.
|
||||
* - Add PSEH handler when an exception occurs in an exception (KiCopyExceptionRecord).
|
||||
* - Implement official stack trace functions (exported) and remove stuff here.
|
||||
* - Forward exceptions to user-mode debugger.
|
||||
* - Wrap Ki NTDLL callbacks in SEH.
|
||||
*/
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
Ki386AdjustEsp0(IN PKTRAP_FRAME TrapFrame);
|
||||
|
||||
/* GLOBALS *****************************************************************/
|
||||
|
||||
#define FLAG_IF (1<<9)
|
||||
|
@ -485,14 +489,14 @@ KiTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr)
|
|||
ASSERT(ExceptionNr != 14);
|
||||
|
||||
/* Store the exception number in an unused field in the trap frame. */
|
||||
Tf->DebugArgMark = (PVOID)ExceptionNr;
|
||||
Tf->DebugArgMark = ExceptionNr;
|
||||
|
||||
/* Use the address of the trap frame as approximation to the ring0 esp */
|
||||
Esp0 = (ULONG)&Tf->Eip;
|
||||
|
||||
/* Get CR2 */
|
||||
cr2 = Ke386GetCr2();
|
||||
Tf->DebugPointer = (PVOID)cr2;
|
||||
Tf->DebugPointer = cr2;
|
||||
|
||||
/*
|
||||
* If this was a V86 mode exception then handle it specially
|
||||
|
@ -566,21 +570,172 @@ KiTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr)
|
|||
}
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
STDCALL
|
||||
KeContextToTrapFrame(PCONTEXT Context,
|
||||
PKEXCEPTION_FRAME ExceptionFrame,
|
||||
PKTRAP_FRAME TrapFrame)
|
||||
ULONG
|
||||
NTAPI
|
||||
KiEspFromTrapFrame(IN PKTRAP_FRAME TrapFrame)
|
||||
{
|
||||
/* Check if this is user-mode or V86 */
|
||||
if ((TrapFrame->Cs & 1) || (TrapFrame->Eflags & X86_EFLAGS_VM))
|
||||
{
|
||||
/* Return it directly */
|
||||
return TrapFrame->Esp;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Edited frame */
|
||||
if (!(TrapFrame->Cs & FRAME_EDITED))
|
||||
{
|
||||
/* Return edited value */
|
||||
return TrapFrame->TempEsp;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Virgin frame, calculate */
|
||||
return (ULONG)&TrapFrame->Esp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
KiEspToTrapFrame(IN PKTRAP_FRAME TrapFrame,
|
||||
IN ULONG Esp)
|
||||
{
|
||||
ULONG Previous = KiEspFromTrapFrame(TrapFrame);
|
||||
|
||||
/* Check if this is user-mode or V86 */
|
||||
if ((TrapFrame->Cs & 1) || (TrapFrame->Eflags & X86_EFLAGS_VM))
|
||||
{
|
||||
/* Write it directly */
|
||||
TrapFrame->Esp = Esp;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Don't allow ESP to be lowered, this is illegal */
|
||||
if (Esp < Previous)
|
||||
{
|
||||
//KeBugCheck(SET_OF_INVALID_CONTEXT);
|
||||
}
|
||||
|
||||
/* Create an edit frame, check if it was alrady */
|
||||
if (!(TrapFrame->Cs & FRAME_EDITED))
|
||||
{
|
||||
/* Update the value */
|
||||
TrapFrame->TempEsp = Esp;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Check if ESP changed */
|
||||
if (Previous != Esp)
|
||||
{
|
||||
/* Save CS */
|
||||
TrapFrame->TempCs = TrapFrame->Cs;
|
||||
TrapFrame->Cs &= ~FRAME_EDITED;
|
||||
|
||||
/* Save ESP */
|
||||
TrapFrame->TempEsp = Esp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ULONG
|
||||
NTAPI
|
||||
KiSsFromTrapFrame(IN PKTRAP_FRAME TrapFrame)
|
||||
{
|
||||
/* If this was V86 Mode */
|
||||
if (TrapFrame->Eflags & X86_EFLAGS_VM)
|
||||
{
|
||||
/* Just return it */
|
||||
return TrapFrame->Ss;
|
||||
}
|
||||
else if (TrapFrame->Cs & 1)
|
||||
{
|
||||
/* Usermode, return the User SS */
|
||||
return TrapFrame->Ss | 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Kernel mode */
|
||||
return KERNEL_DS;
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
KiSsToTrapFrame(IN PKTRAP_FRAME TrapFrame,
|
||||
IN ULONG Ss)
|
||||
{
|
||||
/* Remove the high-bits */
|
||||
Ss &= 0xFFFF;
|
||||
|
||||
/* If this was V86 Mode */
|
||||
if (TrapFrame->Eflags & X86_EFLAGS_VM)
|
||||
{
|
||||
/* Just write it */
|
||||
TrapFrame->Ss = Ss;
|
||||
}
|
||||
else if (TrapFrame->Cs & 1)
|
||||
{
|
||||
/* Usermode, save the User SS */
|
||||
TrapFrame->Ss = Ss | 3;
|
||||
}
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
KeContextToTrapFrame(IN PCONTEXT Context,
|
||||
IN OUT PKEXCEPTION_FRAME ExceptionFrame,
|
||||
IN OUT PKTRAP_FRAME TrapFrame,
|
||||
IN KPROCESSOR_MODE PreviousMode)
|
||||
{
|
||||
BOOLEAN V86Switch = FALSE;
|
||||
|
||||
/* Start with the basic Registers */
|
||||
if ((Context->ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL)
|
||||
{
|
||||
TrapFrame->Esp = Context->Esp;
|
||||
TrapFrame->Ss = Context->SegSs;
|
||||
TrapFrame->Cs = Context->SegCs;
|
||||
TrapFrame->Eip = Context->Eip;
|
||||
/* Check if we went through a V86 switch */
|
||||
if ((Context->EFlags & X86_EFLAGS_VM) !=
|
||||
(TrapFrame->Eflags & X86_EFLAGS_VM))
|
||||
{
|
||||
/* We did, remember this for later */
|
||||
V86Switch = TRUE;
|
||||
}
|
||||
|
||||
/* Copy EFLAGS. FIXME: Needs to be sanitized */
|
||||
TrapFrame->Eflags = Context->EFlags;
|
||||
|
||||
/* Copy EBP and EIP */
|
||||
TrapFrame->Ebp = Context->Ebp;
|
||||
TrapFrame->Eip = Context->Eip;
|
||||
|
||||
/* Check if we were in V86 Mode */
|
||||
if (TrapFrame->Eflags & X86_EFLAGS_VM)
|
||||
{
|
||||
/* Simply copy the CS value */
|
||||
TrapFrame->Cs = Context->SegCs;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We weren't in V86, so sanitize the CS (FIXME!) */
|
||||
TrapFrame->Cs = Context->SegCs;
|
||||
|
||||
/* Don't let it under 8, that's invalid */
|
||||
if ((PreviousMode !=KernelMode) && (TrapFrame->Cs < 8))
|
||||
{
|
||||
/* Force it to User CS */
|
||||
TrapFrame->Cs = USER_CS;
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle SS Specially for validation */
|
||||
KiSsToTrapFrame(TrapFrame, Context->SegSs);
|
||||
|
||||
/* Write ESP back; take into account Edited Trap Frames */
|
||||
KiEspToTrapFrame(TrapFrame, Context->Esp);
|
||||
|
||||
/* Handle our V86 Bias if we went through a switch */
|
||||
if (V86Switch) Ki386AdjustEsp0(TrapFrame);
|
||||
}
|
||||
|
||||
/* Process the Integer Registers */
|
||||
|
@ -597,21 +752,62 @@ KeContextToTrapFrame(PCONTEXT Context,
|
|||
/* Process the Context Segments */
|
||||
if ((Context->ContextFlags & CONTEXT_SEGMENTS) == CONTEXT_SEGMENTS)
|
||||
{
|
||||
TrapFrame->Ds = Context->SegDs;
|
||||
TrapFrame->Es = Context->SegEs;
|
||||
TrapFrame->Fs = Context->SegFs;
|
||||
TrapFrame->Gs = Context->SegGs;
|
||||
/* Check if we were in V86 Mode */
|
||||
if (TrapFrame->Eflags & X86_EFLAGS_VM)
|
||||
{
|
||||
/* Copy the V86 Segments directlry */
|
||||
TrapFrame->V86_Ds = Context->SegDs;
|
||||
TrapFrame->V86_Es = Context->SegEs;
|
||||
TrapFrame->V86_Fs = Context->SegFs;
|
||||
TrapFrame->V86_Gs = Context->SegGs;
|
||||
}
|
||||
else if (!(TrapFrame->Cs & 1))
|
||||
{
|
||||
/* For user mode, write the values directly */
|
||||
TrapFrame->Ds = USER_DS;
|
||||
TrapFrame->Es = USER_DS;
|
||||
TrapFrame->Fs = Context->SegFs;
|
||||
KEBUGCHECK(0);
|
||||
TrapFrame->Gs = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* For kernel-mode, return the values */
|
||||
TrapFrame->Ds = Context->SegDs;
|
||||
TrapFrame->Es = Context->SegEs;
|
||||
TrapFrame->Fs = Context->SegFs;
|
||||
|
||||
/* Handle GS specially */
|
||||
if (TrapFrame->Cs == USER_CS)
|
||||
{
|
||||
/* Don't use it, if user */
|
||||
TrapFrame->Gs = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Copy it if kernel */
|
||||
TrapFrame->Gs = Context->SegGs;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle the Debug Registers */
|
||||
if ((Context->ContextFlags & CONTEXT_DEBUG_REGISTERS) == CONTEXT_DEBUG_REGISTERS)
|
||||
{
|
||||
/* FIXME: All these should be sanitized */
|
||||
TrapFrame->Dr0 = Context->Dr0;
|
||||
TrapFrame->Dr1 = Context->Dr1;
|
||||
TrapFrame->Dr2 = Context->Dr2;
|
||||
TrapFrame->Dr3 = Context->Dr3;
|
||||
TrapFrame->Dr6 = Context->Dr6;
|
||||
TrapFrame->Dr7 = Context->Dr7;
|
||||
|
||||
/* Check if usermode */
|
||||
if (PreviousMode != KernelMode)
|
||||
{
|
||||
/* Set the Debug Flag */
|
||||
KeGetCurrentThread()->DebugActive = (Context->Dr7 & DR7_ACTIVE);
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle FPU and Extended Registers */
|
||||
|
@ -619,51 +815,90 @@ KeContextToTrapFrame(PCONTEXT Context,
|
|||
}
|
||||
|
||||
VOID
|
||||
KeTrapFrameToContext(PKTRAP_FRAME TrapFrame,
|
||||
PCONTEXT Context)
|
||||
NTAPI
|
||||
KeTrapFrameToContext(IN PKTRAP_FRAME TrapFrame,
|
||||
IN PKEXCEPTION_FRAME ExceptionFrame,
|
||||
IN OUT PCONTEXT Context)
|
||||
{
|
||||
if ((Context->ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL)
|
||||
{
|
||||
Context->SegSs = TrapFrame->Ss;
|
||||
Context->Esp = TrapFrame->Esp;
|
||||
Context->SegCs = TrapFrame->Cs;
|
||||
Context->Eip = TrapFrame->Eip;
|
||||
Context->EFlags = TrapFrame->Eflags;
|
||||
Context->Ebp = TrapFrame->Ebp;
|
||||
}
|
||||
if ((Context->ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER)
|
||||
{
|
||||
Context->Eax = TrapFrame->Eax;
|
||||
Context->Ebx = TrapFrame->Ebx;
|
||||
Context->Ecx = TrapFrame->Ecx;
|
||||
/*
|
||||
* NOTE: In the trap frame which is built on entry to a system
|
||||
* call TrapFrame->Edx will actually hold the address of the
|
||||
* previous TrapFrame. I don't believe leaking this information
|
||||
* has security implications. Also EDX holds the address of the
|
||||
* arguments to the system call in progress so it isn't of much
|
||||
* interest to the debugger.
|
||||
*/
|
||||
Context->Edx = TrapFrame->Edx;
|
||||
Context->Esi = TrapFrame->Esi;
|
||||
Context->Edi = TrapFrame->Edi;
|
||||
}
|
||||
if ((Context->ContextFlags & CONTEXT_SEGMENTS) == CONTEXT_SEGMENTS)
|
||||
{
|
||||
Context->SegDs = TrapFrame->Ds;
|
||||
Context->SegEs = TrapFrame->Es;
|
||||
Context->SegFs = TrapFrame->Fs;
|
||||
Context->SegGs = TrapFrame->Gs;
|
||||
}
|
||||
/* Start with the Control flags */
|
||||
if ((Context->ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL)
|
||||
{
|
||||
/* EBP, EIP and EFLAGS */
|
||||
Context->Ebp = TrapFrame->Ebp;
|
||||
Context->Eip = TrapFrame->Eip;
|
||||
Context->EFlags = TrapFrame->Eflags;
|
||||
|
||||
/* Return the correct CS */
|
||||
if (!(TrapFrame->Cs & FRAME_EDITED) &&
|
||||
!(TrapFrame->Eflags & X86_EFLAGS_VM))
|
||||
{
|
||||
/* Get it from the Temp location */
|
||||
Context->SegCs = TrapFrame->TempCs & 0xFFFF;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Return it directly */
|
||||
Context->SegCs = TrapFrame->Cs & 0xFFFF;
|
||||
}
|
||||
|
||||
/* Get the Ss and ESP */
|
||||
Context->SegSs = KiSsFromTrapFrame(TrapFrame);
|
||||
Context->Esp = KiEspFromTrapFrame(TrapFrame);
|
||||
}
|
||||
|
||||
/* Handle the Segments */
|
||||
if ((Context->ContextFlags & CONTEXT_SEGMENTS) == CONTEXT_SEGMENTS)
|
||||
{
|
||||
/* Do V86 Mode first */
|
||||
if (TrapFrame->Eflags & X86_EFLAGS_VM)
|
||||
{
|
||||
/* Return from the V86 location */
|
||||
Context->SegGs = TrapFrame->V86_Gs & 0xFFFF;
|
||||
Context->SegFs = TrapFrame->V86_Fs & 0xFFFF;
|
||||
Context->SegEs = TrapFrame->V86_Es & 0xFFFF;
|
||||
Context->SegDs = TrapFrame->V86_Ds & 0xFFFF;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Check if this was a Kernel Trap */
|
||||
if (TrapFrame->Cs == KERNEL_CS)
|
||||
{
|
||||
/* Set valid selectors */
|
||||
TrapFrame->Gs = 0;
|
||||
TrapFrame->Fs = PCR_SELECTOR;
|
||||
TrapFrame->Es = USER_DS;
|
||||
TrapFrame->Ds = USER_DS;
|
||||
}
|
||||
|
||||
/* Return the segments */
|
||||
Context->SegGs = TrapFrame->Gs & 0xFFFF;
|
||||
Context->SegFs = TrapFrame->Fs & 0xFFFF;
|
||||
Context->SegEs = TrapFrame->Es & 0xFFFF;
|
||||
Context->SegDs = TrapFrame->Ds & 0xFFFF;
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle the simple registers */
|
||||
if ((Context->ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER)
|
||||
{
|
||||
/* Return them directly */
|
||||
Context->Eax = TrapFrame->Eax;
|
||||
Context->Ebx = TrapFrame->Ebx;
|
||||
Context->Ecx = TrapFrame->Ecx;
|
||||
Context->Edx = TrapFrame->Edx;
|
||||
Context->Esi = TrapFrame->Esi;
|
||||
Context->Edi = TrapFrame->Edi;
|
||||
}
|
||||
|
||||
if ((Context->ContextFlags & CONTEXT_DEBUG_REGISTERS) == CONTEXT_DEBUG_REGISTERS)
|
||||
{
|
||||
{
|
||||
/*
|
||||
* FIXME: Implement this case
|
||||
*/
|
||||
Context->ContextFlags &= (~CONTEXT_DEBUG_REGISTERS) | CONTEXT_i386;
|
||||
}
|
||||
if ((Context->ContextFlags & CONTEXT_FLOATING_POINT) == CONTEXT_FLOATING_POINT)
|
||||
{
|
||||
{
|
||||
/*
|
||||
* FIXME: Implement this case
|
||||
*
|
||||
|
@ -676,7 +911,7 @@ KeTrapFrameToContext(PKTRAP_FRAME TrapFrame,
|
|||
}
|
||||
#if 0
|
||||
if ((Context->ContextFlags & CONTEXT_EXTENDED_REGISTERS) == CONTEXT_EXTENDED_REGISTERS)
|
||||
{
|
||||
{
|
||||
/*
|
||||
* FIXME: Investigate this
|
||||
*
|
||||
|
@ -931,7 +1166,7 @@ KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
|
|||
ULONG_PTR Stack, NewStack;
|
||||
ULONG Size;
|
||||
BOOLEAN UserDispatch = FALSE;
|
||||
DPRINT1("KiDispatchException() called\n");
|
||||
DPRINT("KiDispatchException() called\n");
|
||||
|
||||
/* Increase number of Exception Dispatches */
|
||||
KeGetCurrentPrcb()->KeExceptionDispatchCount++;
|
||||
|
@ -947,7 +1182,7 @@ KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
|
|||
}
|
||||
|
||||
/* Get a Context */
|
||||
KeTrapFrameToContext(TrapFrame, &Context);
|
||||
KeTrapFrameToContext(TrapFrame, ExceptionFrame, &Context);
|
||||
|
||||
/* Handle kernel-mode first, it's simpler */
|
||||
if (PreviousMode == KernelMode)
|
||||
|
@ -1017,7 +1252,7 @@ KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
|
|||
/* Align context size and get stack pointer */
|
||||
Size = (sizeof(CONTEXT) + 3) & ~3;
|
||||
Stack = (Context.Esp & ~3) - Size;
|
||||
DPRINT1("Stack: %lx\n", Stack);
|
||||
DPRINT("Stack: %lx\n", Stack);
|
||||
|
||||
/* Probe stack and copy Context */
|
||||
ProbeForWrite((PVOID)Stack, Size, sizeof(ULONG));
|
||||
|
@ -1028,7 +1263,7 @@ KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
|
|||
(EXCEPTION_MAXIMUM_PARAMETERS - ExceptionRecord->NumberParameters) *
|
||||
sizeof(ULONG) + 3) & ~3;
|
||||
NewStack = Stack - Size;
|
||||
DPRINT1("NewStack: %lx\n", NewStack);
|
||||
DPRINT("NewStack: %lx\n", NewStack);
|
||||
|
||||
/* Probe stack and copy exception record. Don't forget to add the two params */
|
||||
ProbeForWrite((PVOID)(NewStack - 2 * sizeof(ULONG_PTR)),
|
||||
|
@ -1041,7 +1276,7 @@ KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
|
|||
*(PULONG_PTR)(NewStack - 2 * sizeof(ULONG_PTR)) = NewStack;
|
||||
|
||||
/* Set new Stack Pointer */
|
||||
TrapFrame->Esp = NewStack - 2 * sizeof(ULONG_PTR);
|
||||
KiEspToTrapFrame(TrapFrame, NewStack - 2 * sizeof(ULONG_PTR));
|
||||
|
||||
/* Set EIP to the User-mode Dispathcer */
|
||||
TrapFrame->Eip = (ULONG)KeUserExceptionDispatcher;
|
||||
|
@ -1073,7 +1308,7 @@ KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
|
|||
|
||||
Handled:
|
||||
/* Convert the context back into Trap/Exception Frames */
|
||||
KeContextToTrapFrame(&Context, NULL, TrapFrame);
|
||||
KeContextToTrapFrame(&Context, NULL, TrapFrame, PreviousMode);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -528,7 +528,7 @@ KiHandleFpuFault(PKTRAP_FRAME Tf, ULONG ExceptionNr)
|
|||
|
||||
/* Fill the rest of the context */
|
||||
Context->ContextFlags = CONTEXT_FULL;
|
||||
KeTrapFrameToContext(Tf, Context);
|
||||
KeTrapFrameToContext(Tf, NULL, Context);
|
||||
Context->ContextFlags |= CONTEXT_FLOATING_POINT | CONTEXT_EXTENDED_REGISTERS;
|
||||
|
||||
/* Determine exception code */
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -85,7 +85,7 @@ Ke386InitThreadWithContext(PKTHREAD Thread,
|
|||
TrapFrame = &InitFrame->TrapFrame;
|
||||
|
||||
/* Set up a trap frame from the context. */
|
||||
if (KeContextToTrapFrame(Context, NULL, TrapFrame))
|
||||
if (KeContextToTrapFrame(Context, NULL, TrapFrame, UserMode))
|
||||
{
|
||||
Thread->NpxState = NPX_STATE_VALID;
|
||||
}
|
||||
|
@ -146,7 +146,9 @@ Ke386InitThreadWithContext(PKTHREAD Thread,
|
|||
|
||||
/* And set up the Context Switch Frame */
|
||||
CtxSwitchFrame->RetEip = KiThreadStartup;
|
||||
CtxSwitchFrame->Esp0 = (ULONG)Thread->InitialStack - sizeof(FX_SAVE_AREA);
|
||||
CtxSwitchFrame->Esp0 = (ULONG_PTR)Thread->InitialStack -
|
||||
sizeof(FX_SAVE_AREA) -
|
||||
0x10;
|
||||
CtxSwitchFrame->ExceptionList = (PVOID)0xFFFFFFFF;
|
||||
|
||||
/* Save back the new value of the kernel stack. */
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
#include <roscfg.h>
|
||||
#include <ndk/asm.h>
|
||||
#include <internal/i386/ke.h>
|
||||
#include <ndk/i386/segment.h>
|
||||
|
||||
#define KernelMode 0
|
||||
|
@ -374,4 +375,37 @@ _KiCoprocessorError@0:
|
|||
/* Return to caller */
|
||||
ret
|
||||
|
||||
.globl _Ki386AdjustEsp0@4
|
||||
_Ki386AdjustEsp0@4:
|
||||
|
||||
/* Get the current thread */
|
||||
mov eax, [fs:KPCR_CURRENT_THREAD]
|
||||
|
||||
/* Get trap frame and stack */
|
||||
mov edx, [esp+4]
|
||||
mov eax, [eax+KTHREAD_INITIAL_STACK]
|
||||
|
||||
/* Check if V86 */
|
||||
test dword ptr [edx+KTRAP_FRAME_EFLAGS], X86_EFLAGS_VM
|
||||
jnz NoAdjust
|
||||
|
||||
/* Bias the stack */
|
||||
sub eax, KTRAP_FRAME_V86_GS - KTRAP_FRAME_SS
|
||||
|
||||
NoAdjust:
|
||||
/* Skip FX Save Area */
|
||||
sub eax, SIZEOF_FX_SAVE_AREA
|
||||
|
||||
/* Disable interrupts */
|
||||
pushf
|
||||
cli
|
||||
|
||||
/* Adjust ESP0 */
|
||||
mov edx, [fs:KPCR_TSS]
|
||||
mov ss:[edx+KTSS_ESP0], eax
|
||||
|
||||
/* Enable interrupts and return */
|
||||
popf
|
||||
ret 4
|
||||
|
||||
/* EOF */
|
||||
|
|
|
@ -36,11 +36,11 @@ ULONG KiPageFaultHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr)
|
|||
ASSERT(ExceptionNr == 14);
|
||||
|
||||
/* Store the exception number in an unused field in the trap frame. */
|
||||
Tf->DebugArgMark = (PVOID)14;
|
||||
Tf->DebugArgMark = 14;
|
||||
|
||||
/* get the faulting address */
|
||||
cr2 = Ke386GetCr2();
|
||||
Tf->DebugPointer = (PVOID)cr2;
|
||||
Tf->DebugPointer = cr2;
|
||||
|
||||
/* it's safe to enable interrupts after cr2 has been saved */
|
||||
if (Tf->Eflags & (X86_EFLAGS_VM|X86_EFLAGS_IF))
|
||||
|
|
|
@ -22,6 +22,7 @@ typedef struct _GET_SET_CTX_CONTEXT {
|
|||
KAPC Apc;
|
||||
KEVENT Event;
|
||||
CONTEXT Context;
|
||||
KPROCESSOR_MODE Mode;
|
||||
} GET_SET_CTX_CONTEXT, *PGET_SET_CTX_CONTEXT;
|
||||
|
||||
|
||||
|
@ -42,22 +43,24 @@ PspGetOrSetContextKernelRoutine(PKAPC Apc,
|
|||
PGET_SET_CTX_CONTEXT GetSetContext;
|
||||
PKEVENT Event;
|
||||
PCONTEXT Context;
|
||||
KPROCESSOR_MODE Mode;
|
||||
|
||||
/* Get the Context Structure */
|
||||
GetSetContext = CONTAINING_RECORD(Apc, GET_SET_CTX_CONTEXT, Apc);
|
||||
Context = &GetSetContext->Context;
|
||||
Event = &GetSetContext->Event;
|
||||
Mode = GetSetContext->Mode;
|
||||
|
||||
/* Check if it's a set or get */
|
||||
if (SystemArgument1) {
|
||||
|
||||
/* Get the Context */
|
||||
KeTrapFrameToContext(KeGetCurrentThread()->TrapFrame, Context);
|
||||
KeTrapFrameToContext(KeGetCurrentThread()->TrapFrame, NULL, Context);
|
||||
|
||||
} else {
|
||||
|
||||
/* Set the Context */
|
||||
KeContextToTrapFrame(Context, NULL, KeGetCurrentThread()->TrapFrame);
|
||||
KeContextToTrapFrame(Context, NULL, KeGetCurrentThread()->TrapFrame, Mode);
|
||||
}
|
||||
|
||||
/* Notify the Native API that we are done */
|
||||
|
@ -111,7 +114,7 @@ NtGetContextThread(IN HANDLE ThreadHandle,
|
|||
* I don't know if trying to get your own context makes much
|
||||
* sense but we can handle it more efficently.
|
||||
*/
|
||||
KeTrapFrameToContext(Thread->Tcb.TrapFrame, &GetSetContext.Context);
|
||||
KeTrapFrameToContext(Thread->Tcb.TrapFrame, NULL, &GetSetContext.Context);
|
||||
|
||||
} else {
|
||||
|
||||
|
@ -120,6 +123,9 @@ NtGetContextThread(IN HANDLE ThreadHandle,
|
|||
NotificationEvent,
|
||||
FALSE);
|
||||
|
||||
/* Set the previous mode */
|
||||
GetSetContext.Mode = PreviousMode;
|
||||
|
||||
/* Initialize the APC */
|
||||
KeInitializeApc(&GetSetContext.Apc,
|
||||
&Thread->Tcb,
|
||||
|
@ -221,7 +227,7 @@ NtSetContextThread(IN HANDLE ThreadHandle,
|
|||
* I don't know if trying to get your own context makes much
|
||||
* sense but we can handle it more efficently.
|
||||
*/
|
||||
KeContextToTrapFrame(&GetSetContext.Context, NULL, Thread->Tcb.TrapFrame);
|
||||
KeContextToTrapFrame(&GetSetContext.Context, NULL, Thread->Tcb.TrapFrame, PreviousMode);
|
||||
|
||||
} else {
|
||||
|
||||
|
@ -230,6 +236,9 @@ NtSetContextThread(IN HANDLE ThreadHandle,
|
|||
NotificationEvent,
|
||||
FALSE);
|
||||
|
||||
/* Set the previous mode */
|
||||
GetSetContext.Mode = PreviousMode;
|
||||
|
||||
/* Initialize the APC */
|
||||
KeInitializeApc(&GetSetContext.Apc,
|
||||
&Thread->Tcb,
|
||||
|
|
Loading…
Reference in a new issue