Author: arty
Date: Mon Jul 28 09:47:17 2008
New Revision: 34904
URL:
http://svn.reactos.org/svn/reactos?rev=34904&view=rev
Log:
This is a patch i've been keeping for a while. Yes, it's not "as nt does
it",
but it solves a practical problem, and isn't particularly invasive (the main
change is the call to KdpEnableSafeMem ... everything else could be macroed
out if desired).
This provides armour for kdbg and gdb that avoid faulting on bad addresses by
implementing a simple poor-man's mmu and letting the debuggers use it.
Added:
trunk/reactos/ntoskrnl/kd/i386/
trunk/reactos/ntoskrnl/kd/i386/kdmemsup.c (with props)
Modified:
trunk/reactos/ntoskrnl/include/internal/kd.h
trunk/reactos/ntoskrnl/kd/kdinit.c
trunk/reactos/ntoskrnl/kd/wrappers/gdbstub.c
trunk/reactos/ntoskrnl/kdbg/kdb.c
trunk/reactos/ntoskrnl/ntoskrnl-generic.rbuild
trunk/reactos/ntoskrnl/vdm/vdmmain.c
Modified: trunk/reactos/ntoskrnl/include/internal/kd.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/…
==============================================================================
--- trunk/reactos/ntoskrnl/include/internal/kd.h [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/include/internal/kd.h [iso-8859-1] Mon Jul 28 09:47:17 2008
@@ -250,6 +250,27 @@
IN PCH Message,
IN ULONG Length
);
+
+BOOLEAN
+STDCALL
+KdpSafeReadMemory(
+ IN ULONG_PTR Addr,
+ IN LONG Len,
+ OUT PVOID Value
+);
+
+BOOLEAN
+STDCALL
+KdpSafeWriteMemory(
+ IN ULONG_PTR Addr,
+ IN LONG Len,
+ IN ULONGLONG Value
+);
+
+VOID
+STDCALL
+KdpEnableSafeMem();
+
/* KD GLOBALS ***************************************************************/
Added: trunk/reactos/ntoskrnl/kd/i386/kdmemsup.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/kd/i386/kdmemsup.…
==============================================================================
--- trunk/reactos/ntoskrnl/kd/i386/kdmemsup.c (added)
+++ trunk/reactos/ntoskrnl/kd/i386/kdmemsup.c [iso-8859-1] Mon Jul 28 09:47:17 2008
@@ -1,0 +1,247 @@
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS Kernel
+ * FILE: ntoskrnl/kd/i386/kdmemsup.c
+ * PURPOSE: Kernel Debugger Safe Memory Support
+ *
+ * PROGRAMMERS: arty
+ */
+
+#include <ntoskrnl.h>
+#define NDEBUG
+#include <internal/debug.h>
+
+#define HIGH_PHYS_MASK 0x80000000
+#define PAGE_TABLE_MASK 0x3ff
+#define BIG_PAGE_SIZE (1<<22)
+#define CR4_PAGE_SIZE_BIT 0x10
+#define PDE_PRESENT_BIT 1
+#define PDE_W_BIT 2
+#define PDE_PS_BIT 0x80
+
+/* VARIABLES ***************************************************************/
+
+extern ULONG MmGlobalKernelPageDirectory[1024];
+static BOOLEAN KdpPhysAccess = FALSE;
+ULONG_PTR IdentityMapAddrHigh, IdentityMapAddrLow;
+extern PFN_TYPE NTAPI MmAllocEarlyPage();
+
+ULONGLONG
+FASTCALL
+KdpPhysRead(ULONG_PTR Addr, LONG Len)
+{
+ ULONGLONG Result = 0;
+ ULONG_PTR OldCR3 = __readcr3(), OldCR4 = __readcr4();
+
+ if (Addr & HIGH_PHYS_MASK)
+ {
+ Addr &= ~HIGH_PHYS_MASK;
+ __writecr3(IdentityMapAddrHigh);
+ }
+ else
+ __writecr3(IdentityMapAddrLow);
+
+ __writecr4(OldCR4|CR4_PAGE_SIZE_BIT); // Turn on large page translation
+ __invlpg((PVOID)Addr);
+
+ switch (Len)
+ {
+ case 8:
+ Result = *((PULONGLONG)Addr);
+ break;
+ case 4:
+ Result = *((PULONG)Addr);
+ break;
+ case 2:
+ Result = *((PUSHORT)Addr);
+ break;
+ case 1:
+ Result = *((PUCHAR)Addr);
+ break;
+ }
+ __writecr4(OldCR4); // Turn off large page translation
+ __writecr3(OldCR3);
+ __invlpg((PVOID)Addr);
+
+ return Result;
+}
+
+
+VOID
+NTAPI
+KdpPhysWrite(ULONG_PTR Addr, LONG Len, ULONGLONG Value)
+{
+ ULONG_PTR OldCR3 = __readcr3(), OldCR4 = __readcr4();
+
+ if (Addr & HIGH_PHYS_MASK)
+ {
+ Addr &= ~HIGH_PHYS_MASK;
+ __writecr3(IdentityMapAddrHigh);
+ }
+ else
+ __writecr3(IdentityMapAddrLow);
+
+ __writecr4(OldCR4|CR4_PAGE_SIZE_BIT); // Turn on large page translation
+ __invlpg((PVOID)Addr);
+
+ switch (Len)
+ {
+ case 8:
+ *((PULONGLONG)Addr) = Value;
+ break;
+ case 4:
+ *((PULONG)Addr) = Value;
+ break;
+ case 2:
+ *((PUSHORT)Addr) = Value;
+ break;
+ case 1:
+ *((PUCHAR)Addr) = Value;
+ break;
+ }
+ __writecr4(OldCR4); // Turn off large page translation
+ __writecr3(OldCR3);
+ __invlpg((PVOID)Addr);
+}
+
+BOOLEAN
+NTAPI
+KdpTranslateAddress(ULONG_PTR Addr, PULONG_PTR ResultAddr)
+{
+ ULONG_PTR CR3Value = __readcr3();
+ ULONG_PTR CR4Value = __readcr4();
+ ULONG_PTR PageDirectory = (CR3Value & ~(PAGE_SIZE-1)) +
+ ((Addr >> 22) * sizeof(ULONG));
+ ULONG_PTR PageDirectoryEntry = KdpPhysRead(PageDirectory, sizeof(ULONG));
+
+ /* Not present -> fail */
+ if (!(PageDirectoryEntry & PDE_PRESENT_BIT))
+ {
+ return FALSE;
+ }
+
+ /* Big Page? */
+ if ((PageDirectoryEntry & PDE_PS_BIT) && (CR4Value &
CR4_PAGE_SIZE_BIT))
+ {
+ *ResultAddr = (PageDirectoryEntry & ~(BIG_PAGE_SIZE-1)) +
+ (Addr & (BIG_PAGE_SIZE-1));
+ return TRUE;
+ }
+ else
+ {
+ ULONG_PTR PageTableAddr =
+ (PageDirectoryEntry & ~(PAGE_SIZE-1)) +
+ ((Addr >> PAGE_SHIFT) & PAGE_TABLE_MASK) * sizeof(ULONG);
+ ULONG_PTR PageTableEntry = KdpPhysRead(PageTableAddr, sizeof(ULONG));
+ if (PageTableEntry & PDE_PRESENT_BIT)
+ {
+ *ResultAddr = (PageTableEntry & ~(PAGE_SIZE-1)) +
+ (Addr & (PAGE_SIZE-1));
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+BOOLEAN
+NTAPI
+KdpSafeReadMemory(ULONG_PTR Addr, LONG Len, PVOID Value)
+{
+ ULONG_PTR ResultPhysAddr;
+
+ if (!KdpPhysAccess)
+ {
+ memcpy(Value, (PVOID)Addr, Len);
+ return TRUE;
+ }
+
+ memset(Value, 0, Len);
+
+ if (!KdpTranslateAddress(Addr, &ResultPhysAddr))
+ return FALSE;
+
+ switch (Len)
+ {
+ case 8:
+ *((PULONGLONG)Value) = KdpPhysRead(ResultPhysAddr, Len);
+ break;
+ case 4:
+ *((PULONG)Value) = KdpPhysRead(ResultPhysAddr, Len);
+ break;
+ case 2:
+ *((PUSHORT)Value) = KdpPhysRead(ResultPhysAddr, Len);
+ break;
+ case 1:
+ *((PUCHAR)Value) = KdpPhysRead(ResultPhysAddr, Len);
+ break;
+ }
+
+ return TRUE;
+}
+
+BOOLEAN
+NTAPI
+KdpSafeWriteMemory(ULONG_PTR Addr, LONG Len, ULONGLONG Value)
+{
+ ULONG_PTR ResultPhysAddr;
+
+ if (!KdpPhysAccess)
+ {
+ memcpy((PVOID)Addr, &Value, Len);
+ return TRUE;
+ }
+
+ if (!KdpTranslateAddress(Addr, &ResultPhysAddr))
+ return FALSE;
+
+ KdpPhysWrite(ResultPhysAddr, Len, Value);
+ return TRUE;
+}
+
+VOID
+NTAPI
+KdpEnableSafeMem()
+{
+ int i;
+ PULONG IdentityMapVirt;
+ PHYSICAL_ADDRESS IdentityMapPhys, Highest = { };
+
+ if (KdpPhysAccess)
+ return;
+
+ Highest.LowPart = (ULONG)-1;
+ /* Allocate a physical page and map it to copy the phys copy code onto */
+ IdentityMapVirt = (PULONG)MmAllocateContiguousMemory(2 * PAGE_SIZE, Highest);
+ IdentityMapPhys = MmGetPhysicalAddress(IdentityMapVirt);
+ IdentityMapAddrHigh = IdentityMapPhys.LowPart;
+
+ /* Copy the kernel space */
+ memcpy(IdentityMapVirt,
+ MmGlobalKernelPageDirectory,
+ PAGE_SIZE);
+
+ /* Set up 512 4Mb pages (high 2Gig identity mapped) */
+ for (i = 0; i < 512; i++)
+ {
+ IdentityMapVirt[i] =
+ HIGH_PHYS_MASK | (i << 22) | PDE_PS_BIT | PDE_W_BIT | PDE_PRESENT_BIT;
+ }
+
+ /* Allocate a physical page and map it to copy the phys copy code onto */
+ IdentityMapAddrLow = IdentityMapAddrHigh + PAGE_SIZE;
+ IdentityMapVirt += PAGE_SIZE / sizeof(ULONG);
+
+ /* Copy the kernel space */
+ memcpy(IdentityMapVirt,
+ MmGlobalKernelPageDirectory,
+ PAGE_SIZE);
+
+ /* Set up 512 4Mb pages (low 2Gig identity mapped) */
+ for (i = 0; i < 512; i++)
+ {
+ IdentityMapVirt[i] = (i << 22) | PDE_PS_BIT | PDE_W_BIT | PDE_PRESENT_BIT;
+ }
+
+ KdpPhysAccess = TRUE;
+}
Propchange: trunk/reactos/ntoskrnl/kd/i386/kdmemsup.c
------------------------------------------------------------------------------
svn:eol-style = native
Modified: trunk/reactos/ntoskrnl/kd/kdinit.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/kd/kdinit.c?rev=3…
==============================================================================
--- trunk/reactos/ntoskrnl/kd/kdinit.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/kd/kdinit.c [iso-8859-1] Mon Jul 28 09:47:17 2008
@@ -257,6 +257,8 @@
if (WrapperInitRoutine) WrapperInitRoutine(&WrapperTable, 0);
return TRUE;
}
+ else
+ KdpEnableSafeMem();
/* Call the Initialization Routines of the Registered Providers */
KdpCallInitRoutine(BootPhase);
Modified: trunk/reactos/ntoskrnl/kd/wrappers/gdbstub.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/kd/wrappers/gdbst…
==============================================================================
--- trunk/reactos/ntoskrnl/kd/wrappers/gdbstub.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/kd/wrappers/gdbstub.c [iso-8859-1] Mon Jul 28 09:47:17 2008
@@ -322,19 +322,9 @@
static CHAR
GspReadMemSafe(PCHAR Address)
{
- CHAR ch;
-
- if (NULL == Address)
- {
- GspMemoryError = TRUE;
- return '\0';
- }
-
- GspAccessLocation = Address;
- ch = *Address;
- GspAccessLocation = NULL;
-
- return ch;
+ CHAR ch;
+ KdpSafeReadMemory((ULONG_PTR)Address, 1, &ch);
+ return ch;
}
/* Convert the memory pointed to by Address into hex, placing result in Buffer */
@@ -455,19 +445,11 @@
return Buffer + 2 * Count;
}
-static CHAR
-GspWriteMemSafeGetContent(PVOID Context, ULONG Offset)
-{
- ASSERT(0 == Offset);
-
- return *((PCHAR) Context);
-}
-
static void
GspWriteMemSafe(PCHAR Address,
CHAR Ch)
{
- GspWriteMem(Address, 1, TRUE, GspWriteMemSafeGetContent, &Ch);
+ KdpSafeWriteMemory((ULONG_PTR)Address, 1, Ch);
}
Modified: trunk/reactos/ntoskrnl/kdbg/kdb.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/kdbg/kdb.c?rev=34…
==============================================================================
--- trunk/reactos/ntoskrnl/kdbg/kdb.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/kdbg/kdb.c [iso-8859-1] Mon Jul 28 09:47:17 2008
@@ -1658,21 +1658,31 @@
IN PVOID Src,
IN ULONG Bytes)
{
- NTSTATUS Status = STATUS_SUCCESS;
-
- _SEH_TRY
- {
- RtlCopyMemory(Dest,
- Src,
- Bytes);
- }
- _SEH_HANDLE
- {
- Status = _SEH_GetExceptionCode();
- }
- _SEH_END;
-
- return Status;
+ BOOLEAN Result = TRUE;
+
+ switch (Bytes)
+ {
+ case 1:
+ case 2:
+ case 4:
+ case 8:
+ Result = KdpSafeReadMemory((ULONG_PTR)Src, Bytes, Dest);
+ break;
+ default:
+ {
+ ULONG_PTR Start, End, Write;
+ for (Start = (ULONG_PTR)Src,
+ End = Start + Bytes,
+ Write = (ULONG_PTR)Dest;
+ Result && (Start < End);
+ Start++, Write++)
+ if (!KdpSafeReadMemory(Start, 1, (PVOID)Write))
+ Result = FALSE;
+ break;
+ }
+ }
+
+ return Result ? STATUS_SUCCESS : STATUS_ACCESS_VIOLATION;
}
NTSTATUS
@@ -1680,19 +1690,16 @@
IN PVOID Src,
IN ULONG Bytes)
{
- NTSTATUS Status = STATUS_SUCCESS;
-
- _SEH_TRY
- {
- RtlCopyMemory(Dest,
- Src,
- Bytes);
- }
- _SEH_HANDLE
- {
- Status = _SEH_GetExceptionCode();
- }
- _SEH_END;
-
- return Status;
-}
+ BOOLEAN Result;
+ ULONG_PTR Start, End, Write;
+
+ for (Start = (ULONG_PTR)Src,
+ End = Start + Bytes,
+ Write = (ULONG_PTR)Dest;
+ Result && (Start < End);
+ Start++, Write++)
+ if (!KdpSafeReadMemory(Start, 1, (PVOID)Write))
+ Result = FALSE;
+
+ return Result ? STATUS_SUCCESS : STATUS_ACCESS_VIOLATION;
+}
Modified: trunk/reactos/ntoskrnl/ntoskrnl-generic.rbuild
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ntoskrnl-generic.…
==============================================================================
--- trunk/reactos/ntoskrnl/ntoskrnl-generic.rbuild [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/ntoskrnl-generic.rbuild [iso-8859-1] Mon Jul 28 09:47:17 2008
@@ -272,6 +272,13 @@
<file>pnproot.c</file>
</directory>
</directory>
+ <if property="DBG" value="1">
+ <directory name="kd">
+ <directory name="i386">
+ <file>kdmemsup.c</file>
+ </directory>
+ </directory>
+ </if>
<if property="_WINKD_" value="0">
<directory name="kdbg">
<if property="ARCH" value="i386">
Modified: trunk/reactos/ntoskrnl/vdm/vdmmain.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/vdm/vdmmain.c?rev…
==============================================================================
--- trunk/reactos/ntoskrnl/vdm/vdmmain.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/vdm/vdmmain.c [iso-8859-1] Mon Jul 28 09:47:17 2008
@@ -23,16 +23,10 @@
INIT_FUNCTION
NtEarlyInitVdm(VOID)
{
- /* GCC 3.4 hack */
- PVOID start = (PVOID)0x0;
-
- /*
- * Save various BIOS data tables. At this point the lower 4MB memory
- * map is still active so we can just copy the data from low memory.
- * HACK HACK HACK: We should just map Physical Memory!!!
- */
+ PCHAR start = MmCreateHyperspaceMapping(0);
memcpy(OrigIVT, start, 1024);
- memcpy(OrigBDA, (PVOID)0x400, 256);
+ memcpy(OrigBDA, start+0x400, 256);
+ MmDeleteHyperspaceMapping(start);
}
VOID