#define BUFMAX 1000
static BOOLEAN GspInitialized;
-#if 0
-static PKINTERRUPT GspInterrupt;
-#endif
static BOOLEAN GspRemoteDebug;
static PETHREAD GspDbgThread;
static PETHREAD GspEnumThread;
+static FAST_MUTEX GspLock;
+
extern LIST_ENTRY PsActiveProcessHead;
KD_PORT_INFORMATION GdbPortInfo = { 2, 115200, 0 }; /* FIXME hardcoded for COM2, 115200 baud */
BOOLEAN SetInContext;
} CPU_REGISTER, *PCPU_REGISTER;
-#define EIP_REGNO 8
-
static CPU_REGISTER GspRegisters[NUMREGS] =
{
- { 4, FIELD_OFFSET (KTRAP_FRAME, Eax), FIELD_OFFSET (CONTEXT, Eax), TRUE },
- { 4, FIELD_OFFSET (KTRAP_FRAME, Ecx), FIELD_OFFSET (CONTEXT, Ecx), TRUE },
- { 4, FIELD_OFFSET (KTRAP_FRAME, Edx), FIELD_OFFSET (CONTEXT, Edx), FALSE },
- { 4, FIELD_OFFSET (KTRAP_FRAME, Ebx), FIELD_OFFSET (CONTEXT, Ebx), TRUE },
- { 4, FIELD_OFFSET (KTRAP_FRAME, Esp), FIELD_OFFSET (CONTEXT, Esp), TRUE },
- { 4, FIELD_OFFSET (KTRAP_FRAME, DebugEbp), FIELD_OFFSET (CONTEXT, Ebp), TRUE },
- { 4, FIELD_OFFSET (KTRAP_FRAME, Esi), FIELD_OFFSET (CONTEXT, Esi), TRUE },
- { 4, FIELD_OFFSET (KTRAP_FRAME, Edi), FIELD_OFFSET (CONTEXT, Edi), TRUE },
- { 4, FIELD_OFFSET (KTRAP_FRAME, DebugEip), FIELD_OFFSET (CONTEXT, Eip), TRUE },
- { 4, FIELD_OFFSET (KTRAP_FRAME, Eflags), FIELD_OFFSET (CONTEXT, EFlags), TRUE },
- { 4, FIELD_OFFSET (KTRAP_FRAME, Cs), FIELD_OFFSET (CONTEXT, SegCs), TRUE },
- { 4, FIELD_OFFSET (KTRAP_FRAME, Ss), FIELD_OFFSET (CONTEXT, SegSs), TRUE },
- { 4, FIELD_OFFSET (KTRAP_FRAME, Ds), FIELD_OFFSET (CONTEXT, SegDs), TRUE },
- { 4, FIELD_OFFSET (KTRAP_FRAME, Es), FIELD_OFFSET (CONTEXT, SegEs), TRUE },
- { 4, FIELD_OFFSET (KTRAP_FRAME, Fs), FIELD_OFFSET (CONTEXT, SegFs), TRUE },
- { 4, FIELD_OFFSET (KTRAP_FRAME, Gs), FIELD_OFFSET (CONTEXT, SegGs), TRUE }
+ { 4, FIELD_OFFSET(KTRAP_FRAME, Eax), FIELD_OFFSET(CONTEXT, Eax), TRUE },
+ { 4, FIELD_OFFSET(KTRAP_FRAME, Ecx), FIELD_OFFSET(CONTEXT, Ecx), TRUE },
+ { 4, FIELD_OFFSET(KTRAP_FRAME, Edx), FIELD_OFFSET(CONTEXT, Edx), FALSE },
+ { 4, FIELD_OFFSET(KTRAP_FRAME, Ebx), FIELD_OFFSET(CONTEXT, Ebx), TRUE },
+ { 4, FIELD_OFFSET(KTRAP_FRAME, HardwareEsp ), FIELD_OFFSET(CONTEXT, Esp), TRUE },
+ { 4, FIELD_OFFSET(KTRAP_FRAME, DbgEbp), FIELD_OFFSET(CONTEXT, Ebp), TRUE },
+ { 4, FIELD_OFFSET(KTRAP_FRAME, Esi), FIELD_OFFSET(CONTEXT, Esi), TRUE },
+ { 4, FIELD_OFFSET(KTRAP_FRAME, Edi), FIELD_OFFSET(CONTEXT, Edi), TRUE },
+ { 4, FIELD_OFFSET(KTRAP_FRAME, DbgEip), FIELD_OFFSET(CONTEXT, Eip), TRUE },
+ { 4, FIELD_OFFSET(KTRAP_FRAME, EFlags), FIELD_OFFSET(CONTEXT, EFlags), TRUE },
+ { 4, FIELD_OFFSET(KTRAP_FRAME, SegCs), FIELD_OFFSET(CONTEXT, SegCs), TRUE },
+ { 4, FIELD_OFFSET(KTRAP_FRAME, HardwareSegSs), FIELD_OFFSET(CONTEXT, SegSs), TRUE },
+ { 4, FIELD_OFFSET(KTRAP_FRAME, SegDs), FIELD_OFFSET(CONTEXT, SegDs), TRUE },
+ { 4, FIELD_OFFSET(KTRAP_FRAME, SegEs), FIELD_OFFSET(CONTEXT, SegEs), TRUE },
+ { 4, FIELD_OFFSET(KTRAP_FRAME, SegFs), FIELD_OFFSET(CONTEXT, SegFs), TRUE },
+ { 4, FIELD_OFFSET(KTRAP_FRAME, SegGs), FIELD_OFFSET(CONTEXT, SegGs), TRUE }
};
static PCHAR GspThreadStates[DeferredReady+1] =
-{ "Initialized",
+{
+ "Initialized",
"Ready",
"Running",
"Standby",
LONG
-HexValue (CHAR ch)
+HexValue(CHAR ch)
{
- if ((ch >= '0') && (ch <= '9')) return (ch - '0');
- if ((ch >= 'a') && (ch <= 'f')) return (ch - 'a' + 10);
- if ((ch >= 'A') && (ch <= 'F')) return (ch - 'A' + 10);
- return (-1);
+ if ((ch >= '0') && (ch <= '9'))
+ {
+ return (ch - '0');
+ }
+ if ((ch >= 'a') && (ch <= 'f'))
+ {
+ return (ch - 'a' + 10);
+ }
+ if ((ch >= 'A') && (ch <= 'F'))
+ {
+ return (ch - 'A' + 10);
+ }
+
+ return -1;
}
static CHAR GspInBuffer[BUFMAX];
VOID
GdbPutChar(UCHAR Value)
{
- KdPortPutByteEx (&GdbPortInfo, Value);
+ KdPortPutByteEx(&GdbPortInfo, Value);
}
UCHAR
{
UCHAR Value;
- while (!KdPortGetByteEx (&GdbPortInfo, &Value));
+ while (!KdPortGetByteEx(&GdbPortInfo, &Value))
+ ;
return Value;
}
while (TRUE)
{
/* wait around for the start character, ignore all other characters */
- while ((ch = GdbGetChar ()) != '$');
+ while ((ch = GdbGetChar ()) != '$')
+ ;
retry:
Checksum = 0;
/* now, read until a # or end of Buffer is found */
while (Count < BUFMAX)
{
- ch = GdbGetChar ();
+ ch = GdbGetChar();
if (ch == '$')
- goto retry;
+ {
+ goto retry;
+ }
if (ch == '#')
- break;
+ {
+ break;
+ }
Checksum = Checksum + ch;
Buffer[Count] = ch;
Count = Count + 1;
if (ch == '#')
{
- ch = GdbGetChar ();
- XmitChecksum = (CHAR)(HexValue (ch) << 4);
- ch = GdbGetChar ();
- XmitChecksum += (CHAR)(HexValue (ch));
+ ch = GdbGetChar();
+ XmitChecksum = (CHAR)(HexValue(ch) << 4);
+ ch = GdbGetChar();
+ XmitChecksum += (CHAR)(HexValue(ch));
if (Checksum != XmitChecksum)
{
- GdbPutChar ('-'); /* failed checksum */
+ GdbPutChar('-'); /* failed checksum */
}
else
{
- GdbPutChar ('+'); /* successful transfer */
+ GdbPutChar('+'); /* successful transfer */
return &Buffer[0];
}
/* send the packet in Buffer. */
VOID
-GspPutPacket (PCHAR Buffer)
+GspPutPacket(PCHAR Buffer)
{
CHAR Checksum;
LONG Count;
/* $<packet info>#<Checksum>. */
do
{
- GdbPutChar ('$');
+ GdbPutChar('$');
Checksum = 0;
Count = 0;
while ((ch = Buffer[Count]))
{
- GdbPutChar (ch);
+ GdbPutChar(ch);
Checksum += ch;
Count += 1;
}
- GdbPutChar ('#');
- GdbPutChar (HexChars[(Checksum >> 4) & 0xf]);
- GdbPutChar (HexChars[Checksum & 0xf]);
+ GdbPutChar('#');
+ GdbPutChar(HexChars[(Checksum >> 4) & 0xf]);
+ GdbPutChar(HexChars[Checksum & 0xf]);
}
- while (GdbGetChar () != '+');
+ while (GdbGetChar() != '+');
}
VOID
-GspPutPacketNoWait (PCHAR Buffer)
+GspPutPacketNoWait(PCHAR Buffer)
{
CHAR Checksum;
LONG Count;
CHAR ch;
/* $<packet info>#<Checksum>. */
- GdbPutChar ('$');
+ GdbPutChar('$');
Checksum = 0;
Count = 0;
while ((ch = Buffer[Count]))
{
- GdbPutChar (ch);
+ GdbPutChar(ch);
Checksum += ch;
Count += 1;
}
- GdbPutChar ('#');
- GdbPutChar (HexChars[(Checksum >> 4) & 0xf]);
- GdbPutChar (HexChars[Checksum & 0xf]);
+ GdbPutChar('#');
+ GdbPutChar(HexChars[(Checksum >> 4) & 0xf]);
+ GdbPutChar(HexChars[Checksum & 0xf]);
}
/* Indicate to caller of GspMem2Hex or GspHex2Mem that there has been an
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
-GspMem2Hex (PCHAR Address,
+static PCHAR
+GspMem2Hex(PCHAR Address,
PCHAR Buffer,
LONG Count,
BOOLEAN MayFault)
ULONG i;
CHAR ch;
- if (NULL == Address && MayFault)
- {
- GspMemoryError = TRUE;
- return Buffer;
- }
-
for (i = 0; i < (ULONG) Count; i++)
{
if (MayFault)
- GspAccessLocation = Address;
- ch = *Address;
- GspAccessLocation = NULL;
- if (MayFault && GspMemoryError)
{
- return (Buffer);
+ ch = GspReadMemSafe(Address);
+ if (GspMemoryError)
+ {
+ return Buffer;
+ }
+ }
+ else
+ {
+ ch = *Address;
}
*Buffer++ = HexChars[(ch >> 4) & 0xf];
*Buffer++ = HexChars[ch & 0xf];
Address++;
}
+
*Buffer = 0;
- return (Buffer);
+ 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);
- MmSetPageProtect (NULL, Address, PAGE_EXECUTE_READWRITE);
+ 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
-GspComputeSignal (NTSTATUS ExceptionCode)
+GspComputeSignal(NTSTATUS ExceptionCode)
{
ULONG SigVal;
case STATUS_ILLEGAL_INSTRUCTION:
SigVal = 4; /* Invalid opcode */
break;
-#if 0
- case STATUS_FLT_INVALID_OPERATION:
- SigVal = 8;
- break;
-#endif
case STATUS_STACK_OVERFLOW:
case STATUS_DATATYPE_MISALIGNMENT:
case STATUS_ACCESS_VIOLATION:
/* RETURN NUMBER OF CHARS PROCESSED */
/**********************************************/
LONG
-GspHex2Long (PCHAR *Address,
+GspHex2Long(PCHAR *Address,
PLONG Value)
{
LONG NumChars = 0;
while (**Address)
{
- Hex = HexValue (**Address);
+ Hex = HexValue(**Address);
if (Hex >= 0)
{
*Value = (*Value << 4) | Hex;
(*Address)++;
}
- return (NumChars);
+ return NumChars;
}
VOID
-GspLong2Hex (PCHAR *Address,
+GspLong2Hex(PCHAR *Address,
LONG Value)
{
LONG Save;
(((Value >> 8) & 0xff) << 16) |
(((Value >> 16) & 0xff) << 8) |
(((Value >> 24) & 0xff) << 0);
- *Address = GspMem2Hex ((PCHAR) &Save, *Address, 4, FALSE);
+ *Address = GspMem2Hex((PCHAR) &Save, *Address, 4, FALSE);
}
static LONG
GspGetEspFromTrapFrame(PKTRAP_FRAME TrapFrame)
{
-
return KeGetPreviousMode() == KernelMode
- ? (LONG) &TrapFrame->Esp : (LONG)TrapFrame->Esp;
+ ? (LONG) &TrapFrame->HardwareEsp : (LONG)TrapFrame->HardwareEsp;
}
-VOID
-GspGetRegistersFromTrapFrame(PCHAR Address,
- PCONTEXT Context,
+static VOID
+GspGetRegisters(PCHAR Address,
PKTRAP_FRAME TrapFrame)
{
- ULONG Value;
- PCHAR Buffer;
+ ULONG_PTR Value;
PULONG p;
DWORD i;
+ PETHREAD Thread;
+ ULONG_PTR *KernelStack;
- Buffer = Address;
- for (i = 0; i < sizeof (GspRegisters) / sizeof (GspRegisters[0]); i++)
- {
- if (TrapFrame)
+ if (NULL == GspDbgThread)
{
- if (ESP == i)
- {
- Value = GspGetEspFromTrapFrame (TrapFrame);
- }
- else
- {
- p = (PULONG) ((ULONG_PTR) TrapFrame + GspRegisters[i].OffsetInTF);
- Value = *p;
- }
+ Thread = PsGetCurrentThread();
}
- else if (i == EIP_REGNO)
+ else
{
- /*
- * This thread has not been sheduled yet so assume it
- * is still in PsBeginThreadWithContextInternal().
- */
- Value = (ULONG)KiThreadStartup;
+ TrapFrame = GspDbgThread->Tcb.TrapFrame;
+ Thread = GspDbgThread;
}
- else
+
+ if (Waiting == Thread->Tcb.State)
{
- Value = 0;
+ KernelStack = Thread->Tcb.KernelStack;
+ for (i = 0; i < sizeof(GspRegisters) / sizeof(GspRegisters[0]); i++)
+ {
+ switch(i)
+ {
+ case EBP:
+ Value = KernelStack[3];
+ break;
+ case EDI:
+ Value = KernelStack[4];
+ break;
+ case ESI:
+ Value = KernelStack[5];
+ break;
+ case EBX:
+ Value = KernelStack[6];
+ break;
+ case PC:
+ Value = KernelStack[7];
+ break;
+ case ESP:
+ Value = (ULONG_PTR) (KernelStack + 8);
+ break;
+ case CS:
+ Value = KGDT_R0_CODE;
+ break;
+ case DS:
+ Value = KGDT_R0_DATA;
+ break;
+ default:
+ Value = 0;
+ break;
+ }
+ Address = GspMem2Hex((PCHAR) &Value, Address, GspRegisters[i].Size,
+ FALSE);
+ }
+ }
+ else
+ {
+ for (i = 0; i < sizeof(GspRegisters) / sizeof(GspRegisters[0]); i++)
+ {
+ if (TrapFrame)
+ {
+ if (ESP == i)
+ {
+ Value = GspGetEspFromTrapFrame(TrapFrame);
+ }
+ else
+ {
+ p = (PULONG)((ULONG_PTR) TrapFrame +
+ GspRegisters[i].OffsetInTF);
+ Value = *p;
+ }
+ }
+ else if (i == PC)
+ {
+ /*
+ * This thread has not been sheduled yet so assume it
+ * is still in PsBeginThreadWithContextInternal().
+ */
+ Value = (ULONG)KiThreadStartup;
+ }
+ else
+ {
+ Value = 0;
+ }
+ Address = GspMem2Hex((PCHAR) &Value, Address,
+ GspRegisters[i].Size, FALSE);
+ }
}
- Buffer = GspMem2Hex ((PCHAR) &Value, Buffer, GspRegisters[i].Size, FALSE);
- }
}
DWORD i;
if (!TrapFrame)
- return;
+ {
+ return;
+ }
Buffer = Address;
for (i = 0; i < NUMREGS; i++)
- {
- if (GspRegisters[i].SetInContext)
- p = (PULONG) ((ULONG_PTR) Context + GspRegisters[i].OffsetInContext);
- else
- p = (PULONG) ((ULONG_PTR) TrapFrame + GspRegisters[i].OffsetInTF);
- Value = 0;
- Buffer = GspHex2Mem (Buffer, (PCHAR) &Value, GspRegisters[i].Size, FALSE);
- *p = Value;
- }
+ {
+ if (GspRegisters[i].SetInContext)
+ {
+ p = (PULONG) ((ULONG_PTR) Context + GspRegisters[i].OffsetInContext);
+ }
+ else
+ {
+ p = (PULONG) ((ULONG_PTR) TrapFrame + GspRegisters[i].OffsetInTF);
+ }
+ Value = 0;
+ Buffer = GspHex2Mem(Buffer, (PCHAR) &Value, GspRegisters[i].Size, FALSE);
+ *p = Value;
+ }
}
PULONG p;
if (!TrapFrame)
- return;
+ {
+ return;
+ }
if (GspRegisters[Number].SetInContext)
- p = (PULONG) ((ULONG_PTR) Context + GspRegisters[Number].OffsetInContext);
+ {
+ p = (PULONG) ((ULONG_PTR) Context + GspRegisters[Number].OffsetInContext);
+ }
else
- p = (PULONG) ((ULONG_PTR) TrapFrame + GspRegisters[Number].OffsetInTF);
+ {
+ p = (PULONG) ((ULONG_PTR) TrapFrame + GspRegisters[Number].OffsetInTF);
+ }
Value = 0;
- GspHex2Mem (Address, (PCHAR) &Value, GspRegisters[Number].Size, FALSE);
+ GspHex2Mem(Address, (PCHAR) &Value, GspRegisters[Number].Size, FALSE);
*p = Value;
}
/* All threads */
ThreadInfo = NULL;
}
- else
+ else
{
ULONG uThreadId;
HANDLE ThreadId;
PCHAR ptr = &Data[0];
- GspHex2Long (&ptr, (PLONG) &uThreadId);
+ GspHex2Long(&ptr, (PLONG) &uThreadId);
ThreadId = (HANDLE)uThreadId;
- if (!NT_SUCCESS (PsLookupThreadByThreadId (ThreadId, &ThreadInfo)))
+ if (!NT_SUCCESS(PsLookupThreadByThreadId(ThreadId, &ThreadInfo)))
{
*Thread = NULL;
return FALSE;
}
break;
case 'g': /* Debug thread */
- if (GspFindThread (ptr, &ThreadInfo))
+ if (GspFindThread(ptr, &ThreadInfo))
{
GspOutBuffer[0] = 'O';
GspOutBuffer[1] = 'K';
- if (GspDbgThread)
+ if (NULL != GspDbgThread)
{
ObDereferenceObject(GspDbgThread);
}
- GspDbgThread = ThreadInfo;
+ if (ThreadInfo == PsGetCurrentThread())
+ {
+ GspDbgThread = NULL;
+ ObDereferenceObject(ThreadInfo);
+ }
+ else
+ {
+ GspDbgThread = ThreadInfo;
+ }
}
else
{
ULONG Value;
if (strncmp(Request, "C", 1) == 0)
- {
- PCHAR ptr = &GspOutBuffer[2];
-
- /* Get current thread id */
- GspOutBuffer[0] = 'Q';
- GspOutBuffer[1] = 'C';
- if (NULL != GspDbgThread)
{
- Value = (ULONG) GspDbgThread->Cid.UniqueThread;
- }
- else
- {
- Value = (ULONG) PsGetCurrentThread()->Cid.UniqueThread;
- }
- GspLong2Hex (&ptr, Value);
- }
- else if (strncmp (Request, "fThreadInfo", 11) == 0)
- {
- PEPROCESS Process;
- PLIST_ENTRY AThread, AProcess;
- PCHAR ptr = &GspOutBuffer[1];
-
- /* Get first thread id */
- GspEnumThread = NULL;
- AProcess = PsActiveProcessHead.Flink;
- while(AProcess != &PsActiveProcessHead)
- {
- Process = CONTAINING_RECORD(AProcess, EPROCESS, ActiveProcessLinks);
- AThread = Process->ThreadListHead.Flink;
- if(AThread != &Process->ThreadListHead)
- {
- GspEnumThread = CONTAINING_RECORD (Process->ThreadListHead.Flink,
- ETHREAD, ThreadListEntry);
- break;
- }
- AProcess = AProcess->Flink;
- }
- if(GspEnumThread != NULL)
- {
- GspOutBuffer[0] = 'm';
- Value = (ULONG) GspEnumThread->Cid.UniqueThread;
- GspLong2Hex (&ptr, Value);
+ PCHAR ptr = &GspOutBuffer[2];
+
+ /* Get current thread id */
+ GspOutBuffer[0] = 'Q';
+ GspOutBuffer[1] = 'C';
+ if (NULL != GspDbgThread)
+ {
+ Value = (ULONG) GspDbgThread->Cid.UniqueThread;
+ }
+ else
+ {
+ Value = (ULONG) PsGetCurrentThread()->Cid.UniqueThread;
+ }
+ GspLong2Hex(&ptr, Value);
}
- else
+ else if (strncmp(Request, "fThreadInfo", 11) == 0)
{
- /* FIXME - what to do here? This case should never happen though, there
- should always be at least one thread on the system... */
- /* GspOutBuffer[0] = 'l'; */
- }
- }
- else if (strncmp (Request, "sThreadInfo", 11) == 0)
- {
- PEPROCESS Process;
- PLIST_ENTRY AThread, AProcess;
- PCHAR ptr = &GspOutBuffer[1];
+ PEPROCESS Process;
+ PLIST_ENTRY AThread, AProcess;
+ PCHAR ptr = &GspOutBuffer[1];
- /* Get next thread id */
- if (GspEnumThread != NULL)
- {
- /* find the next thread */
- Process = GspEnumThread->ThreadsProcess;
- if(GspEnumThread->ThreadListEntry.Flink != &Process->ThreadListHead)
- {
- GspEnumThread = CONTAINING_RECORD (GspEnumThread->ThreadListEntry.Flink,
- ETHREAD, ThreadListEntry);
- }
- else
- {
- PETHREAD Thread = NULL;
- AProcess = Process->ActiveProcessLinks.Flink;
- while(AProcess != &PsActiveProcessHead)
+ /* Get first thread id */
+ GspEnumThread = NULL;
+ AProcess = PsActiveProcessHead.Flink;
+ while(AProcess != &PsActiveProcessHead)
{
Process = CONTAINING_RECORD(AProcess, EPROCESS, ActiveProcessLinks);
AThread = Process->ThreadListHead.Flink;
- if(AThread != &Process->ThreadListHead)
- {
- Thread = CONTAINING_RECORD (Process->ThreadListHead.Flink,
- ETHREAD, ThreadListEntry);
- break;
- }
+ if (AThread != &Process->ThreadListHead)
+ {
+ GspEnumThread = CONTAINING_RECORD(Process->ThreadListHead.Flink,
+ ETHREAD, ThreadListEntry);
+ break;
+ }
AProcess = AProcess->Flink;
}
- GspEnumThread = Thread;
- }
-
if(GspEnumThread != NULL)
- {
- /* return the ID */
- GspOutBuffer[0] = 'm';
- Value = (ULONG) GspEnumThread->Cid.UniqueThread;
- GspLong2Hex (&ptr, Value);
- }
+ {
+ GspOutBuffer[0] = 'm';
+ Value = (ULONG) GspEnumThread->Cid.UniqueThread;
+ GspLong2Hex(&ptr, Value);
+ }
else
- {
- GspOutBuffer[0] = 'l';
- }
+ {
+ /* FIXME - what to do here? This case should never happen though, there
+ should always be at least one thread on the system... */
+ /* GspOutBuffer[0] = 'l'; */
+ }
}
- else
+ else if (strncmp(Request, "sThreadInfo", 11) == 0)
{
- GspOutBuffer[0] = 'l';
- }
- }
- else if (strncmp (Request, "ThreadExtraInfo", 15) == 0)
- {
- PETHREAD ThreadInfo;
+ PEPROCESS Process;
+ PLIST_ENTRY AThread, AProcess;
+ PCHAR ptr = &GspOutBuffer[1];
- /* Get thread information */
- if (GspFindThread(Request + 16, &ThreadInfo))
+ /* Get next thread id */
+ if (GspEnumThread != NULL)
+ {
+ /* find the next thread */
+ Process = GspEnumThread->ThreadsProcess;
+ if(GspEnumThread->ThreadListEntry.Flink != &Process->ThreadListHead)
+ {
+ GspEnumThread = CONTAINING_RECORD(GspEnumThread->ThreadListEntry.Flink,
+ ETHREAD, ThreadListEntry);
+ }
+ else
+ {
+ PETHREAD Thread = NULL;
+ AProcess = Process->ActiveProcessLinks.Flink;
+ while(AProcess != &PsActiveProcessHead)
+ {
+ Process = CONTAINING_RECORD(AProcess, EPROCESS, ActiveProcessLinks);
+ AThread = Process->ThreadListHead.Flink;
+ if (AThread != &Process->ThreadListHead)
+ {
+ Thread = CONTAINING_RECORD(Process->ThreadListHead.Flink,
+ ETHREAD, ThreadListEntry);
+ break;
+ }
+ AProcess = AProcess->Flink;
+ }
+ GspEnumThread = Thread;
+ }
+
+ if (GspEnumThread != NULL)
+ {
+ /* return the ID */
+ GspOutBuffer[0] = 'm';
+ Value = (ULONG) GspEnumThread->Cid.UniqueThread;
+ GspLong2Hex(&ptr, Value);
+ }
+ else
+ {
+ GspOutBuffer[0] = 'l';
+ }
+ }
+ else
+ {
+ GspOutBuffer[0] = 'l';
+ }
+ }
+ else if (strncmp(Request, "ThreadExtraInfo", 15) == 0)
{
- char Buffer[64];
- PEPROCESS Proc;
+ PETHREAD ThreadInfo;
- Proc = (PEPROCESS) ThreadInfo->Tcb.ApcState.Process;
+ /* Get thread information */
+ if (GspFindThread(Request + 16, &ThreadInfo))
+ {
+ char Buffer[64];
+ PEPROCESS Proc;
- Buffer[0] = '\0';
- if (NULL != Proc )
- {
- sprintf(Buffer, "%s [%d:0x%x], ", Proc->ImageFileName,
- (int) Proc->UniqueProcessId,
- (int) ThreadInfo->Cid.UniqueThread);
- }
- strcpy(Buffer + strlen(Buffer), GspThreadStates[ThreadInfo->Tcb.State]);
+ Proc = (PEPROCESS) ThreadInfo->ThreadsProcess;
- ObDereferenceObject(ThreadInfo);
+ Buffer[0] = '\0';
+ if (NULL != Proc )
+ {
+ sprintf(Buffer, "%s [%d:0x%x], ", Proc->ImageFileName,
+ (int) Proc->UniqueProcessId,
+ (int) ThreadInfo->Cid.UniqueThread);
+ }
+ strcpy(Buffer + strlen(Buffer),
+ GspThreadStates[ThreadInfo->Tcb.State]);
+
+ ObDereferenceObject(ThreadInfo);
- GspMem2Hex(Buffer, &GspOutBuffer[0], strlen(Buffer), FALSE);
+ GspMem2Hex(Buffer, &GspOutBuffer[0], strlen(Buffer), FALSE);
+ }
}
- }
-#if 0
- else if (strncmp (Request, "Offsets", 7) == 0)
- {
- strcpy (GspOutBuffer, "Text=0;Data=0;Bss=0");
- }
-#endif
}
VOID
PETHREAD ThreadInfo;
PCHAR ptr = &Request[0];
- if (GspFindThread (ptr, &ThreadInfo))
- {
- ObDereferenceObject(ThreadInfo);
+ if (GspFindThread(ptr, &ThreadInfo))
+ {
+ ObDereferenceObject(ThreadInfo);
- GspOutBuffer[0] = 'O';
- GspOutBuffer[1] = 'K';
- GspOutBuffer[2] = '\0';
- }
+ GspOutBuffer[0] = 'O';
+ GspOutBuffer[1] = 'K';
+ GspOutBuffer[2] = '\0';
+ }
else
- {
- GspOutBuffer[0] = 'E';
- GspOutBuffer[1] = '\0';
- }
+ {
+ GspOutBuffer[0] = 'E';
+ GspOutBuffer[1] = '\0';
+ }
}
-
-typedef struct _GsHwBreakPoint
+#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)))
+
+#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] =
-{
- { Enabled : FALSE },
- { Enabled : FALSE },
- { Enabled : FALSE },
- { Enabled : FALSE }
-};
-#else
-GsHwBreakPoint GspBreakpoints[4] =
+#define MAX_HW_BREAKPOINTS 4
+static unsigned GspHwBreakpointCount = 0;
+static GSPHWBREAKPOINT GspHwBreakpoints[MAX_HW_BREAKPOINTS];
+
+typedef struct _GSPSWBREAKPOINT
{
- { 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)
+ {
+ 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++)
{
- Bit = 2 << (BreakpointNumber << 1);
- if (!(dr7_ & Bit) && GspBreakpoints[BreakpointNumber].Enabled)
+ 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
- }
- }
- else if ((dr7_ & Bit) && !GspBreakpoints[BreakpointNumber].Enabled)
- {
- CorrectIt = TRUE;
- dr7_ &= ~Bit;
- dr7_ &= ~(0xf0000 << (BreakpointNumber << 2));
- }
+ if (MAX_SW_BREAKPOINTS == GspSwBreakpointCount)
+ {
+ DPRINT1("Trying to set too many software breakpoints\n");
+ strcpy(GspOutBuffer, "E22");
}
- if (CorrectIt)
+ else
{
-#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
+ DPRINT("Stored at index %u\n", GspSwBreakpointCount);
+ GspSwBreakpoints[GspSwBreakpointCount].Address = Address;
+ GspSwBreakpoints[GspSwBreakpointCount].Active = FALSE;
+ GspSwBreakpointCount++;
+ strcpy(GspOutBuffer, "OK");
}
}
-ULONG
-GspRemoveHwBreakpoint(ULONG BreakpointNumber)
+static void
+GspRemoveSwBreakpoint(ULONG_PTR Address)
{
- if (!GspBreakpoints[BreakpointNumber].Enabled)
+ unsigned Index;
+
+ DPRINT("GspRemoveSwBreakpoint(0x%p)\n", Address);
+ for (Index = 0; Index < GspSwBreakpointCount; Index++)
{
- return -1;
+ 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;
+ }
}
- GspBreakpoints[BreakpointNumber].Enabled = 0;
- return 0;
+
+ 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);
-ULONG
-GspSetHwBreakpoint(ULONG BreakpointNumber,
- ULONG Type,
- ULONG Length,
- ULONG Address)
+ /* 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)
+ {
+ 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;
+ }
+}
+
+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++)
+ {
+ 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);
+ }
+
+ for (Index = 0; Index < GspSwBreakpointCount; Index++)
{
- return -1;
+ 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);
+ }
+ }
}
- GspBreakpoints[BreakpointNumber].Enabled = TRUE;
- GspBreakpoints[BreakpointNumber].Type = Type;
- GspBreakpoints[BreakpointNumber].Length = Length;
- GspBreakpoints[BreakpointNumber].Address = Address;
- return 0;
+
+ DPRINT("Final DR7 value 0x%08x\n", TrapFrame->Dr7);
}
+static void
+GspUnloadBreakpoints(PKTRAP_FRAME TrapFrame)
+{
+ unsigned Index;
+
+ DPRINT("GspUnloadHwBreakpoints\n");
-static BOOL gdb_attached_yet = FALSE;
+ for (Index = 0; Index < GspSwBreakpointCount; Index++)
+ {
+ 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);
+ }
+ }
+ }
+}
+
+static BOOLEAN gdb_attached_yet = FALSE;
/*
* This function does all command procesing for interfacing to gdb.
*/
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 &&
}
else
{
- /* Don't switch threads */
+ DPRINT("Thread %p entering stub\n", PsGetCurrentThread());
+ /* Can only debug 1 thread at a time... */
+ ExAcquireFastMutex(&GspLock);
+ DPRINT("Thread %p acquired mutex\n", PsGetCurrentThread());
- /* Always use the current thread when entering the exception handler */
+ /* 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)
{
+ DPRINT1("Internal error: entering stub with non-NULL GspDbgThread\n");
ObDereferenceObject(GspDbgThread);
GspDbgThread = NULL;
}
stop_reply:
/* reply to host that an exception has occurred */
- SigVal = GspComputeSignal (ExceptionRecord->ExceptionCode);
+ SigVal = GspComputeSignal(ExceptionRecord->ExceptionCode);
- ptr = &GspOutBuffer[0];
+ ptr = GspOutBuffer;
*ptr++ = 'T'; /* notify gdb with signo, PC, FP and SP */
*ptr++ = HexChars[(SigVal >> 4) & 0xf];
*ptr++ = HexChars[ESP];
*ptr++ = ':';
- Esp = GspGetEspFromTrapFrame (TrapFrame); /* SP */
- ptr = GspMem2Hex ((PCHAR) &Esp, ptr, 4, 0);
+ Esp = GspGetEspFromTrapFrame(TrapFrame); /* SP */
+ ptr = GspMem2Hex((PCHAR) &Esp, ptr, 4, 0);
*ptr++ = ';';
*ptr++ = HexChars[EBP];
*ptr++ = ':';
- ptr = GspMem2Hex ((PCHAR) &TrapFrame->Ebp, ptr, 4, 0); /* FP */
+ ptr = GspMem2Hex((PCHAR) &TrapFrame->Ebp, ptr, 4, 0); /* FP */
*ptr++ = ';';
*ptr++ = HexChars[PC];
*ptr = '\0';
- GspPutPacket (&GspOutBuffer[0]);
+ GspPutPacket(&GspOutBuffer[0]);
}
else
{
while (TRUE)
{
/* Zero the buffer now so we don't have to worry about the terminating zero character */
- memset (GspOutBuffer, 0, sizeof (GspInBuffer));
- ptr = GspGetPacket ();
+ memset(GspOutBuffer, 0, sizeof(GspInBuffer));
+ ptr = GspGetPacket();
- switch (*ptr++)
+ switch(*ptr++)
{
case '?':
/* a little hack to send more complete status information */
GspRemoteDebug = !GspRemoteDebug; /* toggle debug flag */
break;
case 'g': /* return the value of the CPU Registers */
- if (NULL != GspDbgThread)
- {
- GspGetRegistersFromTrapFrame (&GspOutBuffer[0], Context, GspDbgThread->Tcb.TrapFrame);
- }
- else
- {
- GspGetRegistersFromTrapFrame (&GspOutBuffer[0], Context, TrapFrame);
- }
+ GspGetRegisters(GspOutBuffer, TrapFrame);
break;
case 'G': /* set the value of the CPU Registers - return OK */
if (NULL != GspDbgThread)
{
- GspSetRegistersInTrapFrame (ptr, Context, GspDbgThread->Tcb.TrapFrame);
+ GspSetRegistersInTrapFrame(ptr, Context, GspDbgThread->Tcb.TrapFrame);
}
else
{
- GspSetRegistersInTrapFrame (ptr, Context, TrapFrame);
+ GspSetRegistersInTrapFrame(ptr, Context, TrapFrame);
}
- strcpy (GspOutBuffer, "OK");
+ strcpy(GspOutBuffer, "OK");
break;
case 'P': /* set the value of a single CPU register - return OK */
{
LONG Register;
- if ((GspHex2Long (&ptr, &Register)) && (*ptr++ == '='))
- if ((Register >= 0) && (Register < NUMREGS))
- {
- if (GspDbgThread)
- {
- GspSetSingleRegisterInTrapFrame(ptr, Register,
- Context, GspDbgThread->Tcb.TrapFrame);
- }
- else
- {
- GspSetSingleRegisterInTrapFrame (ptr, Register, Context, TrapFrame);
- }
- strcpy (GspOutBuffer, "OK");
- break;
- }
+ if ((GspHex2Long(&ptr, &Register)) && (*ptr++ == '='))
+ {
+ if ((Register >= 0) && (Register < NUMREGS))
+ {
+ if (GspDbgThread)
+ {
+ GspSetSingleRegisterInTrapFrame(ptr, Register,
+ Context,
+ GspDbgThread->Tcb.TrapFrame);
+ }
+ else
+ {
+ GspSetSingleRegisterInTrapFrame(ptr, Register,
+ Context, TrapFrame);
+ }
+ strcpy(GspOutBuffer, "OK");
+ break;
+ }
+ }
- strcpy (GspOutBuffer, "E01");
+ strcpy(GspOutBuffer, "E01");
break;
}
/* mAA..AA,LLLL Read LLLL bytes at address AA..AA */
case 'm':
/* TRY TO READ %x,%x. IF SUCCEED, SET PTR = 0 */
- if (GspHex2Long (&ptr, &Address))
- if (*(ptr++) == ',')
- if (GspHex2Long (&ptr, &Length))
+ if (GspHex2Long(&ptr, &Address) &&
+ *(ptr++) == ',' &&
+ GspHex2Long(&ptr, &Length))
+ {
+ PEPROCESS DbgProcess = NULL;
+
+ ptr = NULL;
+ if (NULL != GspDbgThread &&
+ PsGetCurrentProcess() != GspDbgThread->ThreadsProcess)
{
- ptr = 0;
- GspMemoryError = FALSE;
- GspMem2Hex ((PCHAR) Address, GspOutBuffer, Length, 1);
- if (GspMemoryError)
- {
- strcpy (GspOutBuffer, "E03");
- DPRINT ("Fault during memory read\n");
- }
+ DbgProcess = GspDbgThread->ThreadsProcess;
+ KeAttachProcess(&DbgProcess->Pcb);
+ }
+ GspMemoryError = FALSE;
+ GspMem2Hex((PCHAR) Address, GspOutBuffer, Length, 1);
+ if (NULL != DbgProcess)
+ {
+ KeDetachProcess();
+ }
+ if (GspMemoryError)
+ {
+ strcpy(GspOutBuffer, "E03");
+ DPRINT("Fault during memory read\n");
}
+ }
- if (ptr)
- strcpy (GspOutBuffer, "E01");
+ if (NULL != ptr)
+ {
+ strcpy(GspOutBuffer, "E01");
+ }
break;
/* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
case 'M':
/* TRY TO READ '%x,%x:'. IF SUCCEED, SET PTR = 0 */
- if (GspHex2Long (&ptr, &Address))
- if (*(ptr++) == ',')
- if (GspHex2Long (&ptr, &Length))
- if (*(ptr++) == ':')
- {
- GspMemoryError = FALSE;
- GspHex2Mem (ptr, (PCHAR) Address, Length, TRUE);
+ if (GspHex2Long(&ptr, &Address))
+ {
+ if (*(ptr++) == ',' &&
+ GspHex2Long(&ptr, &Length) &&
+ *(ptr++) == ':')
+ {
+ PEPROCESS DbgProcess = NULL;
- if (GspMemoryError)
- {
- strcpy (GspOutBuffer, "E03");
- DPRINT ("Fault during memory write\n");
- }
- else
- {
- strcpy (GspOutBuffer, "OK");
- }
+ if (NULL != GspDbgThread &&
+ PsGetCurrentProcess() != GspDbgThread->ThreadsProcess)
+ {
+ DbgProcess = GspDbgThread->ThreadsProcess;
+ KeAttachProcess(&DbgProcess->Pcb);
+ }
+ GspMemoryError = FALSE;
+ GspHex2Mem(ptr, (PCHAR) Address, Length, TRUE);
+ if (NULL != DbgProcess)
+ {
+ KeDetachProcess();
+ }
+ if (GspMemoryError)
+ {
+ strcpy(GspOutBuffer, "E03");
+ DPRINT("Fault during memory write\n");
+ }
+ else
+ {
+ strcpy(GspOutBuffer, "OK");
+ }
+ ptr = NULL;
+ }
+ }
- ptr = NULL;
- }
- if (ptr)
- strcpy (GspOutBuffer, "E02");
+ if (NULL != ptr)
+ {
+ strcpy(GspOutBuffer, "E02");
+ }
break;
/* cAA..AA Continue at address AA..AA(optional) */
/* try to read optional parameter, pc unchanged if no parm */
if (GspHex2Long (&ptr, &Address))
- Context->Eip = Address;
+ {
+ Context->Eip = Address;
+ }
NewPC = Context->Eip;
/* set the trace bit if we're Stepping */
if (Stepping)
- Context->EFlags |= 0x100;
+ {
+ Context->EFlags |= 0x100;
+ }
#if defined(__GNUC__)
asm volatile ("movl %%db6, %0\n" : "=r" (dr6_) : );
{
if (dr6_ & (1 << BreakpointNumber))
{
- if (GspBreakpoints[BreakpointNumber].Type == 0)
+ if (GspHwBreakpoints[BreakpointNumber].Type == 0)
{
/* Set restore flag */
Context->EFlags |= 0x10000;
}
}
}
- GspCorrectHwBreakpoint();
+ GspLoadBreakpoints(TrapFrame);
#if defined(__GNUC__)
asm volatile ("movl %0, %%db6\n" : : "r" (0));
#elif defined(_MSC_VER)
#error Unknown compiler for inline assembler
#endif
+ if (NULL != GspDbgThread)
+ {
+ ObDereferenceObject(GspDbgThread);
+ GspDbgThread = NULL;
+ }
+
+ DPRINT("Thread %p releasing mutex\n", PsGetCurrentThread());
+ ExReleaseFastMutex(&GspLock);
+ DPRINT("Thread %p leaving stub\n", PsGetCurrentThread());
return kdContinue;
break;
}
case 'k': /* kill the program */
- strcpy (GspOutBuffer, "OK");
+ strcpy(GspOutBuffer, "OK");
break;
/* kill the program */
case 'H': /* Set thread */
- GspSetThread (ptr);
+ GspSetThread(ptr);
break;
case 'q': /* Query */
- GspQuery (ptr);
+ GspQuery(ptr);
break;
case 'T': /* Query thread status */
- GspQueryThreadStatus (ptr);
+ 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);
+ GspHex2Long(&ptr, &Type);
ptr++;
- GspHex2Long (&ptr, &Length);
+ GspHex2Long(&ptr, &Address);
ptr++;
- GspHex2Long (&ptr, &Address);
- if (GspSetHwBreakpoint (Number & 0x3, Type & 0x3 , Length & 0x3, Address) == 0)
+ GspHex2Long(&ptr, &Length);
+ 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;
}
}
/* reply to the request */
- GspPutPacket (&GspOutBuffer[0]);
+ GspPutPacket(GspOutBuffer);
}
/* not reached */
ASSERT(0);
}
- return kdContinue;
+ if (NULL != GspDbgThread)
+ {
+ ObDereferenceObject(GspDbgThread);
+ GspDbgThread = NULL;
+ }
+
+ return kdContinue;
}
KIRQL OldIrql;
UCHAR Value;
- DPRINT ("Break In\n");
+ DPRINT("Break In\n");
DoBreakIn = FALSE;
- while (KdPortGetByteEx (&GdbPortInfo, &Value))
+ while (KdPortGetByteEx(&GdbPortInfo, &Value))
{
if (Value == 0x03)
- DoBreakIn = TRUE;
+ {
+ DoBreakIn = TRUE;
+ }
}
if (!DoBreakIn)
- return TRUE;
+ {
+ return TRUE;
+ }
- KeRaiseIrql (HIGH_LEVEL, &OldIrql);
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
TrapFrame = PsGetCurrentThread()->Tcb.TrapFrame;
- KeTrapFrameToContext (TrapFrame, NULL, &Context);
+ KeTrapFrameToContext(TrapFrame, NULL, &Context);
- KdpGdbEnterDebuggerException (NULL, &Context, TrapFrame);
+ KdpGdbEnterDebuggerException(NULL, &Context, TrapFrame);
- KeContextToTrapFrame (&Context, NULL, TrapFrame, KernelMode);
+ KeContextToTrapFrame(&Context, NULL, TrapFrame, KernelMode);
- KeLowerIrql (OldIrql);
+ KeLowerIrql(OldIrql);
return TRUE;
}
-
-extern ULONG KdpPortIrq;
-
-
VOID
STDCALL
KdpGdbDebugPrint(PCH Message, ULONG Length)
{
}
-extern LIST_ENTRY ModuleListHead;
-
-VOID
-KdGdbListModules()
-{
- PLIST_ENTRY CurrentEntry;
- PLDR_DATA_TABLE_ENTRY Current;
- ULONG ModuleCount;
-
- DPRINT1("\n");
-
- ModuleCount = 0;
-
- CurrentEntry = ModuleListHead.Flink;
- while (CurrentEntry != (&ModuleListHead))
- {
- Current = CONTAINING_RECORD (CurrentEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderModuleList);
-
- DbgPrint ("Module %wZ Base 0x%.08x Length 0x%.08x\n",
- &Current->BaseDllName, Current->DllBase, Current->SizeOfImage);
-
- ModuleCount++;
- CurrentEntry = CurrentEntry->Flink;
- }
-
- DbgPrint ("%d modules listed\n", ModuleCount);
-}
-
/* Initialize the GDB stub */
VOID
STDCALL
KdpGdbStubInit(PKD_DISPATCH_TABLE WrapperTable,
ULONG BootPhase)
{
- if (!KdDebuggerEnabled || !KdpDebugMode.Gdb) return;
+ if (!KdDebuggerEnabled || !KdpDebugMode.Gdb)
+ {
+ return;
+ }
- if (BootPhase == 0)
+ if (BootPhase == 0)
{
+ ExInitializeFastMutex(&GspLock);
+
/* Write out the functions that we support for now */
WrapperTable->KdpInitRoutine = KdpGdbStubInit;
WrapperTable->KdpPrintRoutine = KdpGdbDebugPrint;
/* Initialize the Port */
KdPortInitializeEx(&GdbPortInfo, 0, 0);
+
+ KdpPort = GdbPortInfo.ComPort;
}
- else if (BootPhase == 1)
+ else if (BootPhase == 1)
{
GspInitialized = TRUE;
HalDisplayString("Waiting for GDB to attach\n");
DbgPrint("Module 'hal.dll' loaded at 0x%.08x.\n", LdrHalBase);
- DbgBreakPointWithStatus (DBG_STATUS_CONTROL_C);
+ DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C);
}
- else if (BootPhase == 2)
+ else if (BootPhase == 2)
{
HalDisplayString("\n GDB debugging enabled\n\n");
}