Author: jgardou
Date: Sun Sep 14 22:50:10 2014
New Revision: 64156
URL:
http://svn.reactos.org/svn/reactos?rev=64156&view=rev
Log:
[KDGDB]
- Fix an embarassing works-for-me but uncommited cast.
- Add support for reading registers and memory from foreign threads. Highly experimental
and nearly untested, use at your own risk.
Modified:
trunk/reactos/drivers/base/kdgdb/gdb_input.c
trunk/reactos/drivers/base/kdgdb/i386_sup.c
trunk/reactos/drivers/base/kdgdb/kdgdb.h
trunk/reactos/drivers/base/kdgdb/kdpacket.c
Modified: trunk/reactos/drivers/base/kdgdb/gdb_input.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/base/kdgdb/gdb_inp…
==============================================================================
--- trunk/reactos/drivers/base/kdgdb/gdb_input.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/base/kdgdb/gdb_input.c [iso-8859-1] Sun Sep 14 22:50:10 2014
@@ -11,6 +11,8 @@
/* LOCALS *********************************************************************/
static HANDLE gdb_run_thread;
+/* We might have to attach to a process to read its memory */
+static PEPROCESS AttachedProcess = NULL;
/* Keep track of where we are for qfThreadInfo/qsThreadInfo */
static LIST_ENTRY* CurrentProcessEntry;
static LIST_ENTRY* CurrentThreadEntry;
@@ -316,6 +318,13 @@
send_gdb_memory(MessageData->Buffer, MessageData->Length);
KdpSendPacketHandler = NULL;
KdpManipulateStateHandler = NULL;
+
+ /* Detach if we have to */
+ if (AttachedProcess != NULL)
+ {
+ KeDetachProcess();
+ AttachedProcess = NULL;
+ }
}
static
@@ -323,7 +332,8 @@
handle_gdb_read_mem(
_Out_ DBGKD_MANIPULATE_STATE64* State,
_Out_ PSTRING MessageData,
- _Out_ PULONG MessageLength)
+ _Out_ PULONG MessageLength,
+ _Inout_ PKD_CONTEXT KdContext)
{
State->ApiNumber = DbgKdReadVirtualMemoryApi;
State->ReturnStatus = STATUS_SUCCESS; /* ? */
@@ -332,6 +342,19 @@
if (MessageData)
MessageData->Length = 0;
*MessageLength = 0;
+
+ /* Attach to the debug process to read its memory */
+ if (gdb_dbg_process != PsGetCurrentProcessId())
+ {
+ NTSTATUS Status = PsLookupProcessByProcessId(gdb_dbg_process,
&AttachedProcess);
+ if (!NT_SUCCESS(Status))
+ {
+ KDDBGPRINT("The current GDB debug thread is invalid!");
+ send_gdb_packet("E03");
+ return gdb_receive_and_interpret_packet(State, MessageData, MessageLength,
KdContext);
+ }
+ KeAttachProcess(&AttachedProcess->Pcb);
+ }
State->u.ReadMemory.TargetBaseAddress = hex_to_address(&gdb_input[1]);
State->u.ReadMemory.TransferCount = hex_to_address(strstr(&gdb_input[1],
",") + 1);
@@ -416,7 +439,7 @@
handle_gdb_set_thread();
break;
case 'm':
- return handle_gdb_read_mem(State, MessageData, MessageLength);
+ return handle_gdb_read_mem(State, MessageData, MessageLength, KdContext);
case 'p':
return gdb_send_register(State, MessageData, MessageLength, KdContext);
case 'q':
Modified: trunk/reactos/drivers/base/kdgdb/i386_sup.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/base/kdgdb/i386_su…
==============================================================================
--- trunk/reactos/drivers/base/kdgdb/i386_sup.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/base/kdgdb/i386_sup.c [iso-8859-1] Sun Sep 14 22:50:10 2014
@@ -6,6 +6,8 @@
*/
#include "kdgdb.h"
+
+#include <pstypes.h>
enum reg_name
{
@@ -79,6 +81,44 @@
return 0;
}
+static
+void*
+thread_to_reg(PETHREAD Thread, enum reg_name reg_name, unsigned short* size)
+{
+ PKTRAP_FRAME TrapFrame = Thread->Tcb.TrapFrame;
+
+ /* See if the thread was actually scheduled */
+ if (TrapFrame == NULL)
+ {
+ return NULL;
+ }
+
+ *size = 4;
+ switch (reg_name)
+ {
+ case EAX: return &TrapFrame->Eax;
+ case ECX: return &TrapFrame->Ecx;
+ case EDX: return &TrapFrame->Edx;
+ case EBX: return &TrapFrame->Ebx;
+ case ESP: return (TrapFrame->PreviousPreviousMode == KernelMode) ?
+ &TrapFrame->TempEsp : &TrapFrame->HardwareEsp;
+ case EBP: return &TrapFrame->Ebp;
+ case ESI: return &TrapFrame->Esi;
+ case EDI: return &TrapFrame->Edi;
+ case EIP: return &TrapFrame->Eip;
+ case EFLAGS: return &TrapFrame->EFlags;
+ case CS: return &TrapFrame->SegCs;
+ case SS: return &TrapFrame->HardwareSegSs;
+ case DS: return &TrapFrame->SegDs;
+ case ES: return &TrapFrame->SegEs;
+ case FS: return &TrapFrame->SegFs;
+ case GS: return &TrapFrame->SegGs;
+ default:
+ KDDBGPRINT("Unhandled regname: %d.\n", reg_name);
+ }
+ return NULL;
+}
+
KDSTATUS
gdb_send_registers(
_Out_ DBGKD_MANIPULATE_STATE64* State,
@@ -86,15 +126,62 @@
_Out_ PULONG MessageLength,
_Inout_ PKD_CONTEXT KdContext)
{
- ULONG32 Registers[16];
+ CHAR Registers[16*8 + 1];
+ UCHAR* RegisterPtr;
unsigned i;
unsigned short size;
-
- for(i=0; i < 16; i++)
- {
- Registers[i] = *(ULONG32*)ctx_to_reg(&CurrentContext, i, &size);
- }
- send_gdb_memory(Registers, sizeof(Registers));
+ CHAR* ptr = Registers;
+
+ if (gdb_dbg_thread == PsGetThreadId((PETHREAD)(ULONG_PTR)CurrentStateChange.Thread))
+ {
+ for(i=0; i < 16; i++)
+ {
+ RegisterPtr = ctx_to_reg(&CurrentContext, i, &size);
+ *ptr++ = hex_chars[RegisterPtr[0] >> 4];
+ *ptr++ = hex_chars[RegisterPtr[0] & 0xF];
+ *ptr++ = hex_chars[RegisterPtr[1] >> 4];
+ *ptr++ = hex_chars[RegisterPtr[1] & 0xF];
+ *ptr++ = hex_chars[RegisterPtr[2] >> 4];
+ *ptr++ = hex_chars[RegisterPtr[2] & 0xF];
+ *ptr++ = hex_chars[RegisterPtr[3] >> 4];
+ *ptr++ = hex_chars[RegisterPtr[3] & 0xF];
+ }
+ }
+ else
+ {
+ PETHREAD DbgThread;
+ NTSTATUS Status;
+
+ Status = PsLookupThreadByThreadId(gdb_dbg_thread, &DbgThread);
+ if (!NT_SUCCESS(Status))
+ {
+ /* Thread is dead */
+ send_gdb_packet("E03");
+ return gdb_receive_and_interpret_packet(State, MessageData, MessageLength,
KdContext);
+ }
+
+ for(i=0; i < 16; i++)
+ {
+ RegisterPtr = thread_to_reg(DbgThread, i, &size);
+ if (RegisterPtr)
+ {
+ *ptr++ = hex_chars[RegisterPtr[0] >> 4];
+ *ptr++ = hex_chars[RegisterPtr[0] & 0xF];
+ *ptr++ = hex_chars[RegisterPtr[1] >> 4];
+ *ptr++ = hex_chars[RegisterPtr[1] & 0xF];
+ *ptr++ = hex_chars[RegisterPtr[2] >> 4];
+ *ptr++ = hex_chars[RegisterPtr[2] & 0xF];
+ *ptr++ = hex_chars[RegisterPtr[3] >> 4];
+ *ptr++ = hex_chars[RegisterPtr[3] & 0xF];
+ }
+ else
+ {
+ ptr += sprintf(ptr, "xxxxxxxx");
+ }
+ }
+ }
+ *ptr = '\0';
+ send_gdb_packet(Registers);
return gdb_receive_and_interpret_packet(State, MessageData, MessageLength,
KdContext);
}
@@ -112,7 +199,27 @@
/* Get the GDB register name (gdb_input = "pXX") */
reg_name = (hex_value(gdb_input[1]) << 4) | hex_value(gdb_input[2]);
- ptr = ctx_to_reg(&CurrentContext, reg_name, &size);
+ if (gdb_dbg_thread == PsGetThreadId((PETHREAD)(ULONG_PTR)CurrentStateChange.Thread))
+ {
+ /* We can get it from the context of the current exception */
+ ptr = ctx_to_reg(&CurrentContext, reg_name, &size);
+ }
+ else
+ {
+ PETHREAD DbgThread;
+ NTSTATUS Status;
+
+ Status = PsLookupThreadByThreadId(gdb_dbg_thread, &DbgThread);
+ if (!NT_SUCCESS(Status))
+ {
+ /* Thread is dead */
+ send_gdb_packet("E03");
+ return gdb_receive_and_interpret_packet(State, MessageData, MessageLength,
KdContext);
+ }
+
+ ptr = thread_to_reg(DbgThread, reg_name, &size);
+ }
+
if (!ptr)
{
/* Undefined. Let's assume 32 bit register */
@@ -122,5 +229,6 @@
{
send_gdb_memory(ptr, size);
}
+
return gdb_receive_and_interpret_packet(State, MessageData, MessageLength,
KdContext);
}
Modified: trunk/reactos/drivers/base/kdgdb/kdgdb.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/base/kdgdb/kdgdb.h…
==============================================================================
--- trunk/reactos/drivers/base/kdgdb/kdgdb.h [iso-8859-1] (original)
+++ trunk/reactos/drivers/base/kdgdb/kdgdb.h [iso-8859-1] Sun Sep 14 22:50:10 2014
@@ -67,6 +67,7 @@
void gdb_send_debug_io(_In_ PSTRING String);
void gdb_send_exception(void);
void send_gdb_ntstatus(_In_ NTSTATUS Status);
+extern const char hex_chars[];
/* kdcom.c */
KDSTATUS NTAPI KdpPollBreakIn(VOID);
Modified: trunk/reactos/drivers/base/kdgdb/kdpacket.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/base/kdgdb/kdpacke…
==============================================================================
--- trunk/reactos/drivers/base/kdgdb/kdpacket.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/base/kdgdb/kdpacket.c [iso-8859-1] Sun Sep 14 22:50:10 2014
@@ -14,6 +14,7 @@
_In_ ULONG PacketType,
_In_ PSTRING MessageHeader,
_In_ PSTRING MessageData);
+static BOOLEAN CanSendData = FALSE;
/* GLOBALS ********************************************************************/
DBGKD_GET_VERSION64 KdVersion;
@@ -141,11 +142,13 @@
/* Save current state for later GDB queries */
CurrentStateChange = *StateChange;
/* Unless GDB tells us otherwise, those are what we should have */
- gdb_dbg_thread = PsGetThreadId((PETHREAD)StateChange->Thread);
- gdb_dbg_process = PsGetThreadProcessId((PETHREAD)StateChange->Thread);
+ gdb_dbg_thread = PsGetThreadId((PETHREAD)(ULONG_PTR)StateChange->Thread);
+ gdb_dbg_process =
PsGetThreadProcessId((PETHREAD)(ULONG_PTR)StateChange->Thread);
gdb_send_exception();
/* Next receive call will ask for the context */
KdpManipulateStateHandler = GetContextManipulateHandler;
+ /* We can now send data, since after this we will be connected to GDB */
+ CanSendData = TRUE;
break;
default:
/* FIXME */
@@ -159,6 +162,9 @@
_In_ DBGKD_DEBUG_IO* DebugIO,
_In_ PSTRING String)
{
+ if (!CanSendData)
+ return;
+
switch (DebugIO->ApiNumber)
{
case DbgKdPrintStringApi: