Implement hardware breakpoints and watchpoints
Modified: trunk/reactos/ntoskrnl/kd/wrappers/gdbstub.c
_____
Modified: trunk/reactos/ntoskrnl/kd/wrappers/gdbstub.c
--- trunk/reactos/ntoskrnl/kd/wrappers/gdbstub.c 2005-11-20
17:48:30 UTC (rev 19379)
+++ trunk/reactos/ntoskrnl/kd/wrappers/gdbstub.c 2005-11-20
17:51:09 UTC (rev 19380)
@@ -320,12 +320,29 @@
static volatile BOOLEAN GspMemoryError = FALSE;
static volatile void *GspAccessLocation = NULL;
+static CHAR
+GspReadMemSafe(PCHAR Address)
+{
+ CHAR ch;
+ if (NULL == Address)
+ {
+ GspMemoryError = TRUE;
+ return '\0';
+ }
+
+ GspAccessLocation = Address;
+ ch = *Address;
+ GspAccessLocation = NULL;
+
+ return ch;
+}
+
/* Convert the memory pointed to by Address into hex, placing result in
Buffer */
/* Return a pointer to the last char put in Buffer (null) */
/* If MayFault is TRUE, then we should set GspMemoryError in response
to
a fault; if FALSE treat a fault like any other fault in the stub.
*/
-PCHAR
+static PCHAR
GspMem2Hex(PCHAR Address,
PCHAR Buffer,
LONG Count,
@@ -334,92 +351,127 @@
ULONG i;
CHAR ch;
- if (NULL == Address && MayFault)
- {
- GspMemoryError = TRUE;
- return Buffer;
- }
-
for (i = 0; i < (ULONG) Count; i++)
{
if (MayFault)
{
- GspAccessLocation = Address;
+ ch = GspReadMemSafe(Address);
+ if (GspMemoryError)
+ {
+ return Buffer;
+ }
}
- ch = *Address;
- GspAccessLocation = NULL;
- if (MayFault && GspMemoryError)
+ else
{
- return Buffer;
+ ch = *Address;
}
*Buffer++ = HexChars[(ch >> 4) & 0xf];
*Buffer++ = HexChars[ch & 0xf];
Address++;
}
+
*Buffer = 0;
return Buffer;
}
-
-/* Convert the hex array pointed to by Buffer into binary to be placed
at Address */
-/* Return a pointer to the character AFTER the last byte read from
Buffer */
-PCHAR
-GspHex2Mem(PCHAR Buffer,
- PCHAR Address,
+static ULONG
+GspWriteMem(PCHAR Address,
ULONG Count,
- BOOLEAN MayFault)
+ BOOLEAN MayFault,
+ CHAR (*GetContent)(PVOID Context, ULONG Offset),
+ PVOID Context)
{
- PCHAR current;
- PCHAR page;
- ULONG countinpage;
+ PCHAR Current;
+ PCHAR Page;
+ ULONG CountInPage;
ULONG i;
CHAR ch;
- ULONG oldprot = 0;
+ ULONG OldProt = 0;
- current = Address;
- while ( current < Address + Count )
+ Current = Address;
+ while (Current < Address + Count)
{
- page = (PCHAR)PAGE_ROUND_DOWN(current);
- if (Address + Count <= page + PAGE_SIZE)
+ Page = (PCHAR)PAGE_ROUND_DOWN(Current);
+ if (Address + Count <= Page + PAGE_SIZE)
{
/* Fits in this page */
- countinpage = Count;
+ CountInPage = Count;
}
else
{
/* Flows into next page, handle only current page in this
iteration */
- countinpage = PAGE_SIZE - (Address - page);
+ CountInPage = PAGE_SIZE - (Address - Page);
}
if (MayFault)
{
- oldprot = MmGetPageProtect(NULL, Address);
+ OldProt = MmGetPageProtect(NULL, Address);
MmSetPageProtect(NULL, Address, PAGE_EXECUTE_READWRITE);
}
- for (i = 0; i < countinpage && ! GspMemoryError; i++)
+ for (i = 0; i < CountInPage && ! GspMemoryError; i++)
{
- ch = (CHAR)(HexValue(*Buffer++) << 4);
- ch = (CHAR)(ch + HexValue(*Buffer++));
+ ch = (*GetContent)(Context, Current - Address);
- GspAccessLocation = current;
- *current = ch;
- GspAccessLocation = NULL;
- current++;
+ if (MayFault)
+ {
+ GspAccessLocation = Current;
+ }
+ *Current = ch;
+ if (MayFault)
+ {
+ GspAccessLocation = NULL;
+ }
+ Current++;
}
if (MayFault)
{
- MmSetPageProtect(NULL, page, oldprot);
+ MmSetPageProtect(NULL, Page, OldProt);
if (GspMemoryError)
{
- return Buffer;
+ return Current - Address;
}
}
}
- return Buffer;
+ return Current - Address;
}
+static CHAR
+GspHex2MemGetContent(PVOID Context, ULONG Offset)
+{
+ return (CHAR)((HexValue(*((PCHAR) Context + 2 * Offset)) << 4) +
+ HexValue(*((PCHAR) Context + 2 * Offset + 1)));
+}
+/* Convert the hex array pointed to by Buffer into binary to be placed
at Address */
+/* Return a pointer to the character AFTER the last byte read from
Buffer */
+static PCHAR
+GspHex2Mem(PCHAR Buffer,
+ PCHAR Address,
+ ULONG Count,
+ BOOLEAN MayFault)
+{
+ Count = GspWriteMem(Address, Count, MayFault, GspHex2MemGetContent,
Buffer);
+
+ 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);
+}
+
+
/* This function takes the 386 exception vector and attempts to
translate this number into a unix compatible signal value */
ULONG
@@ -922,186 +974,329 @@
}
}
+#define DR7_L0 0x00000001 /* Local breakpoint 0 enable */
+#define DR7_G0 0x00000002 /* Global breakpoint 0 enable */
+#define DR7_L1 0x00000004 /* Local breakpoint 1 enable */
+#define DR7_G1 0x00000008 /* Global breakpoint 1 enable */
+#define DR7_L2 0x00000010 /* Local breakpoint 2 enable */
+#define DR7_G2 0x00000020 /* Global breakpoint 2 enable */
+#define DR7_L3 0x00000040 /* Local breakpoint 3 enable */
+#define DR7_G3 0x00000080 /* Global breakpoint 3 enable */
+#define DR7_LE 0x00000100 /* Local exact breakpoint enable
(old) */
+#define DR7_GE 0x00000200 /* Global exact breakpoint enable
(old) */
+#define DR7_GD 0x00002000 /* General detect enable */
+#define DR7_TYPE0_MASK 0x00030000 /* Breakpoint 0 condition */
+#define DR7_LEN0_MASK 0x000c0000 /* Breakpoint 0 length */
+#define DR7_TYPE1_MASK 0x00300000 /* Breakpoint 1 condition */
+#define DR7_LEN1_MASK 0x00c00000 /* Breakpoint 1 length */
+#define DR7_TYPE2_MASK 0x03000000 /* Breakpoint 2 condition */
+#define DR7_LEN2_MASK 0x0c000000 /* Breakpoint 2 length */
+#define DR7_TYPE3_MASK 0x30000000 /* Breakpoint 3 condition */
+#define DR7_LEN3_MASK 0xc0000000 /* Breakpoint 3 length */
+#define DR7_GLOBAL_ENABLE(Bp) (2 << (2 * (Bp)))
+#define DR7_TYPE(Bp, Type) ((Type) << (16 + 4 * (Bp)))
+#define DR7_LEN(Bp, Len) ((Len) << (18 + 4 * (Bp)))
-typedef struct _GsHwBreakPoint
+#define I386_BP_TYPE_EXECUTE 0
+#define I386_BP_TYPE_DATA_WRITE 1
+#define I386_BP_TYPE_DATA_READWRITE 3
+
+#define I386_OPCODE_INT3 0xcc
+
+#define GDB_ZTYPE_MEMORY_BREAKPOINT 0
+#define GDB_ZTYPE_HARDWARE_BREAKPOINT 1
+#define GDB_ZTYPE_WRITE_WATCHPOINT 2
+#define GDB_ZTYPE_READ_WATCHPOINT 3
+#define GDB_ZTYPE_ACCESS_WATCHPOINT 4
+
+typedef struct _GSPHWBREAKPOINT
{
- BOOLEAN Enabled;
ULONG Type;
+ ULONG_PTR Address;
ULONG Length;
- ULONG Address;
-} GsHwBreakPoint;
+} GSPHWBREAKPOINT;
-#if defined(__GNUC__)
-GsHwBreakPoint GspBreakpoints[4] =
+#define MAX_HW_BREAKPOINTS 4
+static unsigned GspHwBreakpointCount = 0;
+static GSPHWBREAKPOINT GspHwBreakpoints[MAX_HW_BREAKPOINTS];
+
+typedef struct _GSPSWBREAKPOINT
{
- { Enabled : FALSE },
- { Enabled : FALSE },
- { Enabled : FALSE },
- { Enabled : FALSE }
-};
-#else
-GsHwBreakPoint GspBreakpoints[4] =
-{
- { FALSE },
- { FALSE },
- { FALSE },
- { FALSE }
-};
-#endif
+ ULONG_PTR Address;
+ CHAR PrevContent;
+ BOOLEAN Active;
+} GSPSWBREAKPOINT;
-VOID
-GspCorrectHwBreakpoint()
+#define MAX_SW_BREAKPOINTS 64
+static unsigned GspSwBreakpointCount = 0;
+static GSPSWBREAKPOINT GspSwBreakpoints[MAX_SW_BREAKPOINTS];
+
+static void
+GspSetHwBreakpoint(ULONG Type, ULONG_PTR Address, ULONG Length)
{
- ULONG BreakpointNumber;
- BOOLEAN CorrectIt;
- BOOLEAN Bit;
- ULONG dr7_;
+ DPRINT("GspSetHwBreakpoint(%lu, 0x%p, %lu)\n", Type, Address,
Length);
-#if defined(__GNUC__)
- asm volatile (
- "movl %%db7, %0\n" : "=r" (dr7_) : );
- do
+ if (GDB_ZTYPE_READ_WATCHPOINT == Type)
{
- ULONG addr0, addr1, addr2, addr3;
-
- asm volatile (
- "movl %%db0, %0\n"
- "movl %%db1, %1\n"
- "movl %%db2, %2\n"
- "movl %%db3, %3\n"
- : "=r" (addr0), "=r" (addr1),
- "=r" (addr2), "=r" (addr3) : );
- } while (FALSE);
-#elif defined(_MSC_VER)
- __asm
+ DPRINT1("Read watchpoint not supported\n");
+ strcpy(GspOutBuffer, "E22");
+ }
+ else if (GDB_ZTYPE_HARDWARE_BREAKPOINT == Type && 1 != Length)
{
- mov eax, dr7; mov dr7_, eax;
- mov eax, dr0; mov addr0, eax;
- mov eax, dr1; mov addr1, eax;
- mov eax, dr2; mov addr2, eax;
- mov eax, dr3; mov addr3, eax;
+ DPRINT1("Invalid length %lu for hardware breakpoint\n", Length);
+ strcpy(GspOutBuffer, "E22");
}
-#else
-#error Unknown compiler for inline assembler
-#endif
- CorrectIt = FALSE;
- for (BreakpointNumber = 0; BreakpointNumber < 3; BreakpointNumber++)
+ else if (1 != Length && 2 != Length && 4 != Length)
{
- Bit = 2 << (BreakpointNumber << 1);
- if (!(dr7_ & Bit) && GspBreakpoints[BreakpointNumber].Enabled)
+ DPRINT1("Invalid length %lu for GDB Z type %lu\n", Length, Type);
+ strcpy(GspOutBuffer, "E22");
+ }
+ else if (0 != (Address & (Length - 1)))
+ {
+ DPRINT1("Invalid alignment for address 0x%p and length %d\n",
+ Address, Length);
+ strcpy(GspOutBuffer, "E22");
+ }
+ else if (MAX_HW_BREAKPOINTS == GspHwBreakpointCount)
+ {
+ DPRINT1("Trying to set too many hardware breakpoints\n");
+ strcpy(GspOutBuffer, "E22");
+ }
+ else
+ {
+ DPRINT("Stored at index %u\n", GspHwBreakpointCount);
+ GspHwBreakpoints[GspHwBreakpointCount].Type = Type;
+ GspHwBreakpoints[GspHwBreakpointCount].Address = Address;
+ GspHwBreakpoints[GspHwBreakpointCount].Length = Length;
+ GspHwBreakpointCount++;
+ strcpy(GspOutBuffer, "OK");
+ }
+}
+
+static void
+GspRemoveHwBreakpoint(ULONG Type, ULONG_PTR Address, ULONG Length)
+{
+ unsigned Index;
+
+ DPRINT("GspRemoveHwBreakpoint(%lu, 0x%p, %lu)\n", Type, Address,
Length);
+ for (Index = 0; Index < GspHwBreakpointCount; Index++)
+ {
+ if (GspHwBreakpoints[Index].Type == Type &&
+ GspHwBreakpoints[Index].Address == Address &&
+ GspHwBreakpoints[Index].Length == Length)
{
- CorrectIt = TRUE;
- dr7_ |= Bit;
- dr7_ &= ~(0xf0000 << (BreakpointNumber << 2));
- dr7_ |= (((GspBreakpoints[BreakpointNumber].Length << 2) |
- GspBreakpoints[BreakpointNumber].Type) << 16) <<
(BreakpointNumber << 2);
- switch (BreakpointNumber)
+ DPRINT("Found match at index %u\n", Index);
+ if (Index + 1 < GspHwBreakpointCount)
{
-#if defined(__GNUC__)
- case 0:
- asm volatile ("movl %0, %%dr0\n"
- : : "r"
(GspBreakpoints[BreakpointNumber].Address) );
- break;
+ memmove(GspHwBreakpoints + Index,
+ GspHwBreakpoints + (Index + 1),
+ (GspHwBreakpointCount - Index - 1) *
+ sizeof(GSPHWBREAKPOINT));
+ }
+ GspHwBreakpointCount--;
+ strcpy(GspOutBuffer, "OK");
+ return;
+ }
+ }
- case 1:
- asm volatile ("movl %0, %%dr1\n"
- : : "r"
(GspBreakpoints[BreakpointNumber].Address) );
- break;
+ DPRINT1("Not found\n");
+ strcpy(GspOutBuffer, "E22");
+}
- case 2:
- asm volatile ("movl %0, %%dr2\n"
- : : "r"
(GspBreakpoints[BreakpointNumber].Address) );
- break;
+static void
+GspSetSwBreakpoint(ULONG_PTR Address)
+{
+ DPRINT("GspSetSwBreakpoint(0x%p)\n", Address);
- case 3:
- asm volatile ("movl %0, %%dr3\n"
- : : "r"
(GspBreakpoints[BreakpointNumber].Address) );
- break;
-#elif defined(_MSC_VER)
- case 0:
- {
- ULONG addr = GspBreakpoints[BreakpointNumber].Address;
- __asm mov eax, addr;
- __asm mov dr0, eax;
- }
- break;
- case 1:
- {
- ULONG addr = GspBreakpoints[BreakpointNumber].Address;
- __asm mov eax, addr;
- __asm mov dr1, eax;
- }
- break;
- case 2:
- {
- ULONG addr = GspBreakpoints[BreakpointNumber].Address;
- __asm mov eax, addr;
- __asm mov dr2, eax;
- }
- break;
- case 3:
- {
- ULONG addr = GspBreakpoints[BreakpointNumber].Address;
- __asm mov eax, addr;
- __asm mov dr3, eax;
- }
- break;
-#else
-#error Unknown compiler for inline assembler
-#endif
+ if (MAX_SW_BREAKPOINTS == GspSwBreakpointCount)
+ {
+ DPRINT1("Trying to set too many software breakpoints\n");
+ strcpy(GspOutBuffer, "E22");
+ }
+ else
+ {
+ DPRINT("Stored at index %u\n", GspSwBreakpointCount);
+ GspSwBreakpoints[GspSwBreakpointCount].Address = Address;
+ GspSwBreakpoints[GspSwBreakpointCount].Active = FALSE;
+ GspSwBreakpointCount++;
+ strcpy(GspOutBuffer, "OK");
+ }
+}
+
+static void
+GspRemoveSwBreakpoint(ULONG_PTR Address)
+{
+ unsigned Index;
+
+ DPRINT("GspRemoveSwBreakpoint(0x%p)\n", Address);
+ for (Index = 0; Index < GspSwBreakpointCount; Index++)
+ {
+ if (GspSwBreakpoints[Index].Address == Address)
+ {
+ DPRINT("Found match at index %u\n", Index);
+ ASSERT(! GspSwBreakpoints[Index].Active);
+ if (Index + 1 < GspSwBreakpointCount)
+ {
+ memmove(GspSwBreakpoints + Index,
+ GspSwBreakpoints + (Index + 1),
+ (GspSwBreakpointCount - Index - 1) *
+ sizeof(GSPSWBREAKPOINT));
}
+ GspSwBreakpointCount--;
+ strcpy(GspOutBuffer, "OK");
+ return;
}
- else if ((dr7_ & Bit) &&
!GspBreakpoints[BreakpointNumber].Enabled)
- {
- CorrectIt = TRUE;
- dr7_ &= ~Bit;
- dr7_ &= ~(0xf0000 << (BreakpointNumber << 2));
- }
}
- if (CorrectIt)
+
+ DPRINT1("Not found\n");
+ strcpy(GspOutBuffer, "E22");
+}
+
+static void
+GspLoadHwBreakpoint(PKTRAP_FRAME TrapFrame,
+ unsigned BpIndex,
+ ULONG_PTR Address,
+ ULONG Length,
+ ULONG Type)
+{
+ DPRINT("GspLoadHwBreakpoint(0x%p, %d, 0x%p, %d)\n", TrapFrame,
BpIndex,
+ Address, Type);
+
+ /* Set the DR7_Gx bit to globally enable the breakpoint */
+ TrapFrame->Dr7 |= DR7_GLOBAL_ENABLE(BpIndex) |
+ DR7_LEN(BpIndex, Length) |
+ DR7_TYPE(BpIndex, Type);
+
+ switch (BpIndex)
{
-#if defined(__GNUC__)
- asm volatile ( "movl %0, %%db7\n" : : "r" (dr7_));
-#elif defined(_MSC_VER)
- __asm mov eax, dr7_;
- __asm mov dr7, eax;
-#else
-#error Unknown compiler for inline assembler
-#endif
+ case 0:
+ DPRINT("Setting DR0 to 0x%p\n", Address);
+ TrapFrame->Dr0 = Address;
+ break;
+
+ case 1:
+ DPRINT("Setting DR1 to 0x%p\n", Address);
+ TrapFrame->Dr1 = Address;
+ break;
+
+ case 2:
+ DPRINT("Setting DR2 to 0x%p\n", Address);
+ TrapFrame->Dr2 = Address;
+ break;
+
+ case 3:
+ DPRINT("Setting DR3 to 0x%p\n", Address);
+ TrapFrame->Dr3 = Address;
+ break;
}
}
-ULONG
-GspRemoveHwBreakpoint(ULONG BreakpointNumber)
+static void
+GspLoadBreakpoints(PKTRAP_FRAME TrapFrame)
{
- if (!GspBreakpoints[BreakpointNumber].Enabled)
+ unsigned Index;
+ ULONG i386Type;
+
+ DPRINT("GspLoadBreakpoints\n");
+ DPRINT("DR7 on entry: 0x%08x\n", TrapFrame->Dr7);
+ /* Remove all breakpoints */
+ TrapFrame->Dr7 &= ~(DR7_L0 | DR7_L1 | DR7_L2 | DR7_L3 |
+ DR7_G0 | DR7_G1 | DR7_G2 | DR7_G3 |
+ DR7_TYPE0_MASK | DR7_LEN0_MASK |
+ DR7_TYPE1_MASK | DR7_LEN1_MASK |
+ DR7_TYPE2_MASK | DR7_LEN2_MASK |
+ DR7_TYPE3_MASK | DR7_LEN3_MASK);
+
+ for (Index = 0; Index < GspHwBreakpointCount; Index++)
{
- return -1;
+ switch(GspHwBreakpoints[Index].Type)
+ {
+ case GDB_ZTYPE_HARDWARE_BREAKPOINT:
+ i386Type = I386_BP_TYPE_EXECUTE;
+ break;
+ case GDB_ZTYPE_WRITE_WATCHPOINT:
+ i386Type = I386_BP_TYPE_DATA_WRITE;
+ break;
+ case GDB_ZTYPE_ACCESS_WATCHPOINT:
+ i386Type = I386_BP_TYPE_DATA_READWRITE;
+ break;
+ default:
+ ASSERT(FALSE);
+ i386Type = I386_BP_TYPE_EXECUTE;
+ break;
+ }
+
+ GspLoadHwBreakpoint(TrapFrame, Index,
GspHwBreakpoints[Index].Address,
+ GspHwBreakpoints[Index].Length - 1,
i386Type);
}
- GspBreakpoints[BreakpointNumber].Enabled = 0;
- return 0;
+
+ for (Index = 0; Index < GspSwBreakpointCount; Index++)
+ {
+ if (GspHwBreakpointCount + Index < MAX_HW_BREAKPOINTS)
+ {
+ DPRINT("Implementing software interrupt using hardware
register\n");
+ GspLoadHwBreakpoint(TrapFrame, GspHwBreakpointCount + Index,
+ GspSwBreakpoints[Index].Address, 0,
+ I386_BP_TYPE_EXECUTE);
+ GspSwBreakpoints[Index].Active = FALSE;
+ }
+ else
+ {
+ DPRINT("Using real software breakpoint\n");
+ GspMemoryError = FALSE;
+ GspSwBreakpoints[Index].PrevContent = GspReadMemSafe((PCHAR)
GspSwBreakpoints[Index].Address);
+ if (! GspMemoryError)
+ {
+ GspWriteMemSafe((PCHAR) GspSwBreakpoints[Index].Address,
I386_OPCODE_INT3);
+ }
+ GspSwBreakpoints[Index].Active = ! GspMemoryError;
+ if (GspMemoryError)
+ {
+ DPRINT1("Failed to set software breakpoint at 0x%p\n",
+ GspSwBreakpoints[Index].Address);
+ }
+ else
+ {
+ DPRINT("Successfully set software breakpoint at 0x%p\n",
+ GspSwBreakpoints[Index].Address);
+ DPRINT1("Successfully set software breakpoint at 0x%p\n",
GspSwBreakpoints[Index].Address);
+ }
+ }
+ }
+
+ DPRINT("Final DR7 value 0x%08x\n", TrapFrame->Dr7);
}
+static void
+GspUnloadBreakpoints(PKTRAP_FRAME TrapFrame)
+{
+ unsigned Index;
-ULONG
-GspSetHwBreakpoint(ULONG BreakpointNumber,
- ULONG Type,
- ULONG Length,
- ULONG Address)
-{
- if (GspBreakpoints[BreakpointNumber].Enabled)
+ DPRINT("GspUnloadHwBreakpoints\n");
+
+ for (Index = 0; Index < GspSwBreakpointCount; Index++)
{
- return -1;
+ if (GspSwBreakpoints[Index].Active)
+ {
+ GspMemoryError = FALSE;
+ GspWriteMemSafe((PCHAR) GspSwBreakpoints[Index].Address,
+ GspSwBreakpoints[Index].PrevContent);
+ GspSwBreakpoints[Index].Active = FALSE;
+ if (GspMemoryError)
+ {
+ DPRINT1("Failed to remove software breakpoint from
0x%p\n",
+ GspSwBreakpoints[Index].Address);
+ }
+ else
+ {
+ DPRINT("Successfully removed software breakpoint from
0x%p\n",
+ GspSwBreakpoints[Index].Address);
+ }
+ }
}
- GspBreakpoints[BreakpointNumber].Enabled = TRUE;
- GspBreakpoints[BreakpointNumber].Type = Type;
- GspBreakpoints[BreakpointNumber].Length = Length;
- GspBreakpoints[BreakpointNumber].Address = Address;
- return 0;
}
-
-static BOOL gdb_attached_yet = FALSE;
+static BOOLEAN gdb_attached_yet = FALSE;
/*
* This function does all command procesing for interfacing to gdb.
*/
@@ -1119,14 +1314,6 @@
PCHAR ptr;
/* FIXME: Stop on other CPUs too */
- /* Disable hardware debugging while we are inside the stub */
-#if defined(__GNUC__)
- __asm__("movl %0,%%db7" : /* no output */ : "r" (0));
-#elif defined(_MSC_VER)
- __asm mov eax, 0 __asm mov dr7, eax
-#else
-#error Unknown compiler for inline assembler
-#endif
if (STATUS_ACCESS_VIOLATION == (NTSTATUS)
ExceptionRecord->ExceptionCode &&
NULL != GspAccessLocation &&
@@ -1139,9 +1326,22 @@
}
else
{
+ DPRINT("Thread %p entering stub\n", PsGetCurrentThread());
/* Can only debug 1 thread at a time... */
ExAcquireFastMutex(&GspLock);
+ DPRINT("Thread %p acquired mutex\n", PsGetCurrentThread());
+ /* Disable hardware debugging while we are inside the stub */
+#if defined(__GNUC__)
+ __asm__("movl %0,%%db7" : /* no output */ : "r" (0));
+#elif defined(_MSC_VER)
+ __asm mov eax, 0 __asm mov dr7, eax
+#else
+#error Unknown compiler for inline assembler
+#endif
+
+ GspUnloadBreakpoints(TrapFrame);
+
/* Make sure we're debugging the current thread. */
if (NULL != GspDbgThread)
{
@@ -1371,7 +1571,7 @@
{
if (dr6_ & (1 << BreakpointNumber))
{
- if (GspBreakpoints[BreakpointNumber].Type
== 0)
+ if (GspHwBreakpoints[BreakpointNumber].Type
== 0)
{
/* Set restore flag */
Context->EFlags |= 0x10000;
@@ -1380,7 +1580,7 @@
}
}
}
- GspCorrectHwBreakpoint();
+ GspLoadBreakpoints(TrapFrame);
#if defined(__GNUC__)
asm volatile ("movl %0, %%db6\n" : : "r" (0));
#elif defined(_MSC_VER)
@@ -1395,7 +1595,9 @@
GspDbgThread = NULL;
}
+ DPRINT("Thread %p releasing mutex\n",
PsGetCurrentThread());
ExReleaseFastMutex(&GspLock);
+ DPRINT("Thread %p leaving stub\n",
PsGetCurrentThread());
return kdContinue;
break;
}
@@ -1417,46 +1619,46 @@
GspQueryThreadStatus(ptr);
break;
- case 'Y':
+ case 'Z':
{
- LONG Number;
- LONG Length;
LONG Type;
LONG Address;
+ LONG Length;
- ptr = &GspOutBuffer[1];
- GspHex2Long(&ptr, &Number);
- ptr++;
GspHex2Long(&ptr, &Type);
ptr++;
+ GspHex2Long(&ptr, &Address);
+ ptr++;
GspHex2Long(&ptr, &Length);
- ptr++;
- GspHex2Long(&ptr, &Address);
- if (GspSetHwBreakpoint(Number & 0x3, Type & 0x3 ,
Length & 0x3, Address) == 0)
+ if (0 == Type)
{
- strcpy(GspOutBuffer, "OK");
+ GspSetSwBreakpoint((ULONG_PTR) Address);
}
else
{
- strcpy(GspOutBuffer, "E");
+ GspSetHwBreakpoint(Type, (ULONG_PTR) Address,
Length);
}
break;
}
- /* Remove hardware breakpoint */
- case 'y':
+ case 'z':
{
- LONG Number;
+ LONG Type;
+ LONG Address;
+ LONG Length;
- ptr = &GspOutBuffer[1];
- GspHex2Long(&ptr, &Number);
- if (GspRemoveHwBreakpoint(Number & 0x3) == 0)
+ GspHex2Long(&ptr, &Type);
+ ptr++;
+ GspHex2Long(&ptr, &Address);
+ ptr++;
+ GspHex2Long(&ptr, &Length);
+ if (0 == Type)
{
- strcpy(GspOutBuffer, "OK");
+ GspRemoveSwBreakpoint((ULONG_PTR) Address);
}
else
{
- strcpy(GspOutBuffer, "E");
+ GspRemoveHwBreakpoint(Type, (ULONG_PTR) Address,
Length);
}
break;
}
@@ -1466,7 +1668,7 @@
}
/* reply to the request */
- GspPutPacket(&GspOutBuffer[0]);
+ GspPutPacket(GspOutBuffer);
}
/* not reached */