Author: jgardou
Date: Mon Sep 15 22:05:21 2014
New Revision: 64166
URL:
http://svn.reactos.org/svn/reactos?rev=64166&view=rev
Log:
[KDGDB]
- As pid and tid 0 have a special meaning in GDB, use off-by-one thread and process ID
when communicating with it
- Properly read registers and memory from foreign thread and processes. (This time it was
tested and proved to work reliably. __writecr3 ftw!)
- Loop the list of processes and threads when trying to find them from ID, as
PsLookupProessByThreadId and friends can't be used since we can be at any IRQL.
- Add a few more debug prints to help diagnosing problems.
CORE-8531
Added:
trunk/reactos/drivers/base/kdgdb/utils.c (with props)
Modified:
trunk/reactos/drivers/base/kdgdb/CMakeLists.txt
trunk/reactos/drivers/base/kdgdb/gdb_input.c
trunk/reactos/drivers/base/kdgdb/gdb_send.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/CMakeLists.txt
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/base/kdgdb/CMakeLi…
==============================================================================
--- trunk/reactos/drivers/base/kdgdb/CMakeLists.txt [iso-8859-1] (original)
+++ trunk/reactos/drivers/base/kdgdb/CMakeLists.txt [iso-8859-1] Mon Sep 15 22:05:21 2014
@@ -7,6 +7,7 @@
gdb_send.c
kdcom.c
kdpacket.c
+ utils.c
kdgdb.h)
# TODO: AMD64, ARM...
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] Mon Sep 15 22:05:21 2014
@@ -7,43 +7,22 @@
#include "kdgdb.h"
-#include <pstypes.h>
-
/* LOCALS *********************************************************************/
-static HANDLE gdb_run_thread;
-/* We might have to attach to a process to read its memory */
-static PEPROCESS AttachedProcess = NULL;
+static ULONG_PTR gdb_run_tid;
/* Keep track of where we are for qfThreadInfo/qsThreadInfo */
static LIST_ENTRY* CurrentProcessEntry;
static LIST_ENTRY* CurrentThreadEntry;
/* GLOBALS ********************************************************************/
-HANDLE gdb_dbg_process;
-HANDLE gdb_dbg_thread;
+UINT_PTR gdb_dbg_pid;
+UINT_PTR gdb_dbg_tid;
/* PRIVATE FUNCTIONS **********************************************************/
static
-HANDLE
-hex_to_thread(char* buffer)
+UINT_PTR
+hex_to_tid(char* buffer)
{
ULONG_PTR ret = 0;
- char hex;
- while (*buffer)
- {
- hex = hex_value(*buffer++);
- if (hex < 0)
- return (HANDLE)ret;
- ret <<= 4;
- ret += hex;
- }
- return (HANDLE)ret;
-}
-
-static
-ULONG64
-hex_to_address(char* buffer)
-{
- ULONG64 ret = 0;
char hex;
while (*buffer)
{
@@ -55,6 +34,24 @@
}
return ret;
}
+#define hex_to_pid hex_to_tid
+
+static
+ULONG64
+hex_to_address(char* buffer)
+{
+ ULONG64 ret = 0;
+ char hex;
+ while (*buffer)
+ {
+ hex = hex_value(*buffer++);
+ if (hex < 0)
+ return ret;
+ ret <<= 4;
+ ret += hex;
+ }
+ return ret;
+}
/* H* packets */
static
@@ -65,26 +62,26 @@
{
case 'c':
if (strcmp(&gdb_input[2], "-1") == 0)
- gdb_run_thread = (HANDLE)-1;
+ gdb_run_tid = (ULONG_PTR)-1;
else
- gdb_run_thread = hex_to_thread(&gdb_input[2]);
+ gdb_run_tid = hex_to_tid(&gdb_input[2]);
send_gdb_packet("OK");
break;
case 'g':
KDDBGPRINT("Setting debug thread: %s.\n", gdb_input);
if (strncmp(&gdb_input[2], "p-1", 3) == 0)
{
- gdb_dbg_process = (HANDLE)-1;
- gdb_dbg_thread = (HANDLE)-1;
+ gdb_dbg_pid = (UINT_PTR)-1;
+ gdb_dbg_tid = (UINT_PTR)-1;
}
else
{
char* ptr = strstr(gdb_input, ".") + 1;
- gdb_dbg_process = hex_to_thread(&gdb_input[3]);
+ gdb_dbg_pid = hex_to_pid(&gdb_input[3]);
if (strncmp(ptr, "-1", 2) == 0)
- gdb_dbg_thread = (HANDLE)-1;
+ gdb_dbg_tid = (UINT_PTR)-1;
else
- gdb_dbg_thread = hex_to_thread(ptr);
+ gdb_dbg_tid = hex_to_tid(ptr);
}
send_gdb_packet("OK");
break;
@@ -112,26 +109,22 @@
void
handle_gdb_thread_alive(void)
{
- char* ptr = strstr(gdb_input, ".") + 1;
- CLIENT_ID ClientId;
+ ULONG_PTR Pid, Tid;
PETHREAD Thread;
- NTSTATUS Status;
-
- ClientId.UniqueProcess = hex_to_thread(&gdb_input[2]);
- ClientId.UniqueThread = hex_to_thread(ptr);
-
- Status = PsLookupProcessThreadByCid(&ClientId, NULL, &Thread);
-
- if (!NT_SUCCESS(Status))
- {
- /* Thread doesn't exist */
+
+ Pid = hex_to_pid(&gdb_input[2]);
+ Tid = hex_to_tid(strstr(gdb_input, ".") + 1);
+
+ /* We cannot use PsLookupProcessThreadByCid as we could be running at any IRQL.
+ * So loop. */
+ KDDBGPRINT("Checking if p%p.%p is alive.\n", Pid, Tid);
+
+ Thread = find_thread(Pid, Tid);
+
+ if (Thread != NULL)
+ send_gdb_packet("OK");
+ else
send_gdb_packet("E03");
- return;
- }
-
- /* It's OK */
- ObDereferenceObject(Thread);
- send_gdb_packet("OK");
}
/* q* packets */
@@ -165,9 +158,9 @@
if (strcmp(gdb_input, "qC") == 0)
{
char gdb_out[64];
- sprintf(gdb_out, "QC:p%p.%p;",
- PsGetThreadProcessId((PETHREAD)(ULONG_PTR)CurrentStateChange.Thread),
- PsGetThreadId((PETHREAD)(ULONG_PTR)CurrentStateChange.Thread));
+ sprintf(gdb_out, "QC:p%"PRIxPTR".%"PRIxPTR";",
+
handle_to_gdb_pid(PsGetThreadProcessId((PETHREAD)(ULONG_PTR)CurrentStateChange.Thread)),
+
handle_to_gdb_tid(PsGetThreadId((PETHREAD)(ULONG_PTR)CurrentStateChange.Thread)));
send_gdb_packet(gdb_out);
return gdb_receive_and_interpret_packet(State, MessageData, MessageLength,
KdContext);
}
@@ -175,44 +168,35 @@
if ((strncmp(gdb_input, "qfThreadInfo", 12) == 0)
|| (strncmp(gdb_input, "qsThreadInfo", 12) == 0))
{
- LIST_ENTRY* ProcessListHead =
(LIST_ENTRY*)KdDebuggerDataBlock->PsActiveProcessHead.Pointer;
BOOLEAN FirstThread = TRUE;
PEPROCESS Process;
PETHREAD Thread;
char gdb_out[1024];
- char* ptr;
+ char* ptr = gdb_out;
BOOLEAN Resuming = strncmp(gdb_input, "qsThreadInfo", 12) == 0;
- /* Maybe this was not initialized yet */
- if (!ProcessListHead->Flink)
- {
- char gdb_out[64];
-
- if (Resuming)
+ if (Resuming)
+ {
+ if (CurrentProcessEntry == (LIST_ENTRY*)1)
{
- /* there is only one thread to tell about */
+ /* We're done */
send_gdb_packet("l");
+ CurrentProcessEntry = NULL;
return gdb_receive_and_interpret_packet(State, MessageData,
MessageLength, KdContext);
}
- /* Just tell GDB about the current thread */
- sprintf(gdb_out, "mp%p.%p", PsGetCurrentProcessId(),
PsGetCurrentThreadId());
- send_gdb_packet(gdb_out);
- /* GDB can ask anything at this point, it isn't necessarily a
qsThreadInfo packet */
- return gdb_receive_and_interpret_packet(State, MessageData, MessageLength,
KdContext);
- }
-
- if (Resuming)
- {
+
if (CurrentThreadEntry == NULL)
CurrentProcessEntry = CurrentProcessEntry->Flink;
}
else
CurrentProcessEntry = ProcessListHead->Flink;
- if (CurrentProcessEntry == ProcessListHead)
- {
- /* We're done */
- send_gdb_packet("l");
+ if ((CurrentProcessEntry == ProcessListHead) ||
+ (CurrentProcessEntry == NULL)) /* Ps is not initialized */
+ {
+ /* We're almost done. Tell GDB about the idle thread */
+ send_gdb_packet("mp1.1");
+ CurrentProcessEntry = (LIST_ENTRY*)1;
return gdb_receive_and_interpret_packet(State, MessageData, MessageLength,
KdContext);
}
@@ -244,7 +228,9 @@
}
ptr += _snprintf(ptr, 1024 - (ptr - gdb_out),
- "p%p.%p", PsGetProcessId(Process), PsGetThreadId(Thread));
+ "p%p.%p",
+ handle_to_gdb_pid(Process->UniqueProcessId),
+ handle_to_gdb_tid(Thread->Cid.UniqueThread));
if (ptr > (gdb_out + 1024))
{
/* send what we got */
@@ -319,11 +305,10 @@
KdpSendPacketHandler = NULL;
KdpManipulateStateHandler = NULL;
- /* Detach if we have to */
- if (AttachedProcess != NULL)
- {
- KeDetachProcess();
- AttachedProcess = NULL;
+ /* Reset the TLB */
+ if ((gdb_dbg_pid != 0) && gdb_pid_to_handle(gdb_dbg_pid) !=
PsGetCurrentProcessId())
+ {
+ __writecr3(PsGetCurrentProcess()->Pcb.DirectoryTableBase[0]);
}
}
@@ -343,17 +328,17 @@
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))
+ /* Set the TLB according to the process being read. Pid 0 means any process. */
+ if ((gdb_dbg_pid != 0) && gdb_pid_to_handle(gdb_dbg_pid) !=
PsGetCurrentProcessId())
+ {
+ PEPROCESS AttachedProcess = find_process(gdb_dbg_pid);
+ if (AttachedProcess == NULL)
{
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);
+ __writecr3(AttachedProcess->Pcb.DirectoryTableBase[0]);
}
State->u.ReadMemory.TargetBaseAddress = hex_to_address(&gdb_input[1]);
Modified: trunk/reactos/drivers/base/kdgdb/gdb_send.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/base/kdgdb/gdb_sen…
==============================================================================
--- trunk/reactos/drivers/base/kdgdb/gdb_send.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/base/kdgdb/gdb_send.c [iso-8859-1] Mon Sep 15 22:05:21 2014
@@ -168,15 +168,22 @@
{
char gdb_out[1024];
char* ptr = gdb_out;
- DBGKM_EXCEPTION64* Exception = &CurrentStateChange.u.Exception;
+ PETHREAD Thread = (PETHREAD)(ULONG_PTR)CurrentStateChange.Thread;
/* Report to GDB */
*ptr++ = 'T';
- ptr = exception_code_to_gdb(Exception->ExceptionRecord.ExceptionCode, ptr);
- ptr += sprintf(ptr, "thread:p%p.%p;",
- PsGetThreadProcessId((PETHREAD)(ULONG_PTR)CurrentStateChange.Thread),
- PsGetThreadId((PETHREAD)(ULONG_PTR)CurrentStateChange.Thread));
+ if (CurrentStateChange.NewState == DbgKdExceptionStateChange)
+ {
+ EXCEPTION_RECORD64* ExceptionRecord =
&CurrentStateChange.u.Exception.ExceptionRecord;
+ ptr = exception_code_to_gdb(ExceptionRecord->ExceptionCode, ptr);
+ }
+ else
+ ptr += sprintf(ptr, "05");
+
+ ptr += sprintf(ptr, "thread:p%" PRIxPTR ".%" PRIxPTR
";",
+ handle_to_gdb_pid(PsGetThreadProcessId(Thread)),
+ handle_to_gdb_tid(PsGetThreadId(Thread)));
ptr += sprintf(ptr, "core:%x;", CurrentStateChange.Processor);
send_gdb_packet(gdb_out);
}
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] Mon Sep 15 22:05:21 2014
@@ -6,8 +6,6 @@
*/
#include "kdgdb.h"
-
-#include <pstypes.h>
enum reg_name
{
@@ -85,36 +83,62 @@
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);
+ /* See if the guy got a stack */
+ if (Thread->Tcb.InitialStack == NULL)
+ {
+ static const void* NullValue = NULL;
+ /* Terminated thread ? */
+ switch (reg_name)
+ {
+ case ESP:
+ case EBP:
+ case EIP:
+ *size = 4;
+ return &NullValue;
+ default:
+ return NULL;
+ }
+ }
+ else if (Thread->Tcb.TrapFrame)
+ {
+ PKTRAP_FRAME TrapFrame = Thread->Tcb.TrapFrame;
+
+ *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);
+ }
+ }
+ else
+ {
+ /* The thread was not yet scheduled */
+ *size = 4;
+ switch(reg_name)
+ {
+ case ESP: return &Thread->Tcb.KernelStack;
+ case EBP: return &((ULONG*)Thread->Tcb.KernelStack)[4];
+ case EIP: return &Thread->StartAddress;
+ default:
+ return NULL;
+ }
}
return NULL;
}
@@ -132,7 +156,10 @@
unsigned short size;
CHAR* ptr = Registers;
- if (gdb_dbg_thread == PsGetThreadId((PETHREAD)(ULONG_PTR)CurrentStateChange.Thread))
+ KDDBGPRINT("Sending registers of thread %" PRIxPTR ".\n",
gdb_dbg_tid);
+ KDDBGPRINT("Current thread_id: %p.\n",
PsGetThreadId((PETHREAD)(ULONG_PTR)CurrentStateChange.Thread));
+ if (((gdb_dbg_pid == 0) && (gdb_dbg_tid == 0)) ||
+ gdb_tid_to_handle(gdb_dbg_tid) ==
PsGetThreadId((PETHREAD)(ULONG_PTR)CurrentStateChange.Thread))
{
for(i=0; i < 16; i++)
{
@@ -150,10 +177,10 @@
else
{
PETHREAD DbgThread;
- NTSTATUS Status;
-
- Status = PsLookupThreadByThreadId(gdb_dbg_thread, &DbgThread);
- if (!NT_SUCCESS(Status))
+
+ DbgThread = find_thread(gdb_dbg_pid, gdb_dbg_tid);
+
+ if (DbgThread == NULL)
{
/* Thread is dead */
send_gdb_packet("E03");
@@ -199,7 +226,8 @@
/* Get the GDB register name (gdb_input = "pXX") */
reg_name = (hex_value(gdb_input[1]) << 4) | hex_value(gdb_input[2]);
- if (gdb_dbg_thread == PsGetThreadId((PETHREAD)(ULONG_PTR)CurrentStateChange.Thread))
+ if (((gdb_dbg_pid == 0) && (gdb_dbg_tid == 0)) ||
+ gdb_tid_to_handle(gdb_dbg_tid) ==
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);
@@ -207,10 +235,10 @@
else
{
PETHREAD DbgThread;
- NTSTATUS Status;
-
- Status = PsLookupThreadByThreadId(gdb_dbg_thread, &DbgThread);
- if (!NT_SUCCESS(Status))
+
+ DbgThread = find_thread(gdb_dbg_pid, gdb_dbg_tid);
+
+ if (DbgThread == NULL)
{
/* Thread is dead */
send_gdb_packet("E03");
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] Mon Sep 15 22:05:21 2014
@@ -13,8 +13,11 @@
#include <halfuncs.h>
#include <stdio.h>
#include <arc/arc.h>
+#include <inttypes.h>
#include <windbgkd.h>
#include <kddll.h>
+
+#include <pstypes.h>
#define KDDEBUG /* uncomment to enable debugging this dll */
@@ -24,6 +27,18 @@
extern ULONG KdpDbgPrint(const char* Format, ...);
#define KDDBGPRINT KdpDbgPrint
#endif
+
+/* GDB doesn't like pid - tid 0, so +1 them */
+FORCEINLINE HANDLE gdb_tid_to_handle(UINT_PTR Tid)
+{
+ return (HANDLE)(Tid - 1);
+}
+#define gdb_pid_to_handle gdb_tid_to_handle
+FORCEINLINE UINT_PTR handle_to_gdb_tid(HANDLE Handle)
+{
+ return (UINT_PTR)Handle + 1;
+}
+#define handle_to_gdb_pid handle_to_gdb_tid
FORCEINLINE
VOID
@@ -51,8 +66,8 @@
);
/* gdb_input.c */
-extern HANDLE gdb_dbg_thread;
-extern HANDLE gdb_dbg_process;
+extern UINT_PTR gdb_dbg_tid;
+extern UINT_PTR gdb_dbg_pid;
extern KDSTATUS gdb_interpret_input(_Out_ DBGKD_MANIPULATE_STATE64* State, _Out_ PSTRING
MessageData, _Out_ PULONG MessageLength, _Inout_ PKD_CONTEXT KdContext);
extern KDSTATUS gdb_receive_and_interpret_packet(_Out_ DBGKD_MANIPULATE_STATE64* State,
_Out_ PSTRING MessageData, _Out_ PULONG MessageLength, _Inout_ PKD_CONTEXT KdContext);
@@ -79,11 +94,18 @@
extern CONTEXT CurrentContext;
extern DBGKD_GET_VERSION64 KdVersion;
extern KDDEBUGGER_DATA64* KdDebuggerDataBlock;
+extern LIST_ENTRY* ProcessListHead;
extern KDP_SEND_HANDLER KdpSendPacketHandler;
extern KDP_MANIPULATESTATE_HANDLER KdpManipulateStateHandler;
/* Commone ManipulateState handlers */
extern KDSTATUS ContinueManipulateStateHandler(_Out_ DBGKD_MANIPULATE_STATE64* State,
_Out_ PSTRING MessageData, _Out_ PULONG MessageLength, _Inout_ PKD_CONTEXT KdContext);
extern KDSTATUS SetContextManipulateHandler(_Out_ DBGKD_MANIPULATE_STATE64* State, _Out_
PSTRING MessageData, _Out_ PULONG MessageLength, _Inout_ PKD_CONTEXT KdContext);
+extern PEPROCESS TheIdleProcess;
+extern PETHREAD TheIdleThread;
+
+/* utils.c */
+extern PEPROCESS find_process( _In_ UINT_PTR Pid);
+extern PETHREAD find_thread(_In_ UINT_PTR Pid, _In_ UINT_PTR Tid);
/* arch_sup.c */
extern KDSTATUS gdb_send_register(_Out_ DBGKD_MANIPULATE_STATE64* State, _Out_ PSTRING
MessageData, _Out_ PULONG MessageLength, _Inout_ PKD_CONTEXT KdContext);
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] Mon Sep 15 22:05:21 2014
@@ -14,18 +14,20 @@
_In_ ULONG PacketType,
_In_ PSTRING MessageHeader,
_In_ PSTRING MessageData);
-static BOOLEAN CanSendData = FALSE;
+static BOOLEAN InException = FALSE;
/* GLOBALS ********************************************************************/
DBGKD_GET_VERSION64 KdVersion;
KDDEBUGGER_DATA64* KdDebuggerDataBlock;
-BOOLEAN InException = FALSE;
+LIST_ENTRY* ProcessListHead;
/* Callbacks used to communicate with KD aside from GDB */
KDP_SEND_HANDLER KdpSendPacketHandler = FirstSendHandler;
KDP_MANIPULATESTATE_HANDLER KdpManipulateStateHandler = NULL;
/* Data describing the current exception */
DBGKD_ANY_WAIT_STATE_CHANGE CurrentStateChange;
CONTEXT CurrentContext;
+PEPROCESS TheIdleProcess;
+PETHREAD TheIdleThread;
/* PRIVATE FUNCTIONS **********************************************************/
@@ -130,6 +132,8 @@
void
send_kd_state_change(DBGKD_ANY_WAIT_STATE_CHANGE* StateChange)
{
+ InException = TRUE;
+
switch (StateChange->NewState)
{
case DbgKdLoadSymbolsStateChange:
@@ -139,17 +143,22 @@
break;
}
case DbgKdExceptionStateChange:
+ {
+ PETHREAD Thread = (PETHREAD)(ULONG_PTR)StateChange->Thread;
/* 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)(ULONG_PTR)StateChange->Thread);
- gdb_dbg_process =
PsGetThreadProcessId((PETHREAD)(ULONG_PTR)StateChange->Thread);
+ KDDBGPRINT("Exception 0x%08x in thread p%p.%p.\n",
+ StateChange->u.Exception.ExceptionRecord.ExceptionCode,
+ PsGetThreadProcessId(Thread),
+ PsGetThreadId(Thread));
+ /* Set the current debugged process/thread accordingly */
+ gdb_dbg_tid = handle_to_gdb_tid(PsGetThreadId(Thread));
+ gdb_dbg_pid = handle_to_gdb_pid(PsGetThreadProcessId(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 */
while (1);
@@ -162,7 +171,7 @@
_In_ DBGKD_DEBUG_IO* DebugIO,
_In_ PSTRING String)
{
- if (!CanSendData)
+ if (InException)
return;
switch (DebugIO->ApiNumber)
@@ -217,6 +226,9 @@
/* We definitely are at the end of the send <-> receive loop, if any */
KdpSendPacketHandler = NULL;
KdpManipulateStateHandler = NULL;
+ /* We're not handling an exception anymore */
+ InException = FALSE;
+
return KdPacketReceived;
}
@@ -244,10 +256,11 @@
RtlCopyMemory(&KdVersion, &State->u.GetVersion64, sizeof(KdVersion));
DebuggerDataList = (LIST_ENTRY*)(ULONG_PTR)KdVersion.DebuggerDataList;
KdDebuggerDataBlock = CONTAINING_RECORD(DebuggerDataList->Flink,
KDDEBUGGER_DATA64, Header.List);
-
- /* We can tell KD to continue */
+ ProcessListHead = (LIST_ENTRY*)KdDebuggerDataBlock->PsActiveProcessHead.Pointer;
+
+ /* Now we can get the context for the current state */
KdpSendPacketHandler = NULL;
- KdpManipulateStateHandler = ContinueManipulateStateHandler;
+ KdpManipulateStateHandler = GetContextManipulateHandler;
}
static
@@ -267,9 +280,6 @@
KdpSendPacketHandler = GetVersionSendHandler;
KdpManipulateStateHandler = NULL;
- /* This will make KD breakin and we will be able to properly attach to GDB */
- KdContext->KdpControlCPending = TRUE;
-
return KdPacketReceived;
}
@@ -281,6 +291,7 @@
_In_ PSTRING MessageData)
{
DBGKD_ANY_WAIT_STATE_CHANGE* StateChange =
(DBGKD_ANY_WAIT_STATE_CHANGE*)MessageHeader->Buffer;
+ PETHREAD Thread;
if (PacketType == PACKET_TYPE_KD_DEBUG_IO)
{
@@ -296,7 +307,19 @@
while(1);
}
+ KDDBGPRINT("KDGDB: START!\n");
+
+ Thread = (PETHREAD)(ULONG_PTR)StateChange->Thread;
+
+ /* Set up the current state */
CurrentStateChange = *StateChange;
+ gdb_dbg_tid = handle_to_gdb_tid(PsGetThreadId(Thread));
+ gdb_dbg_pid = handle_to_gdb_pid(PsGetThreadProcessId(Thread));
+ /* This is the idle process. Save it! */
+ TheIdleThread = Thread;
+ TheIdleProcess = (PEPROCESS)Thread->Tcb.ApcState.Process;
+
+ KDDBGPRINT("Pid Tid of the first message: %" PRIxPTR", %" PRIxPTR
".\n", gdb_dbg_pid, gdb_dbg_tid);
/* The next receive call will be asking for the version data */
KdpSendPacketHandler = NULL;
Added: trunk/reactos/drivers/base/kdgdb/utils.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/base/kdgdb/utils.c…
==============================================================================
--- trunk/reactos/drivers/base/kdgdb/utils.c (added)
+++ trunk/reactos/drivers/base/kdgdb/utils.c [iso-8859-1] Mon Sep 15 22:05:21 2014
@@ -0,0 +1,71 @@
+/*
+ * COPYRIGHT: GPL, see COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * FILE: drivers/base/kddll/utils.c
+ * PURPOSE: Misc helper functions.
+ */
+
+#include "kdgdb.h"
+
+/*
+ * We cannot use PsLookupProcessThreadByCid or alike as we could be running at any IRQL.
+ * So we have to loop over the process list.
+ */
+
+PEPROCESS
+find_process(
+ _In_ UINT_PTR Pid)
+{
+ HANDLE ProcessId = gdb_pid_to_handle(Pid);
+ LIST_ENTRY* ProcessEntry;
+ PEPROCESS Process;
+
+ /* Special case for idle process */
+ if (Pid == 1)
+ return TheIdleProcess;
+
+ for (ProcessEntry = ProcessListHead->Flink;
+ ProcessEntry != ProcessListHead;
+ ProcessEntry = ProcessEntry->Flink)
+ {
+ Process = CONTAINING_RECORD(ProcessEntry, EPROCESS, ActiveProcessLinks);
+
+ if (Process->UniqueProcessId == ProcessId)
+ return Process;
+ }
+
+ return NULL;
+}
+
+PETHREAD
+find_thread(
+ _In_ UINT_PTR Pid,
+ _In_ UINT_PTR Tid)
+{
+ HANDLE ThreadId = gdb_tid_to_handle(Tid);
+ PETHREAD Thread;
+ PEPROCESS Process;
+ LIST_ENTRY* ThreadEntry;
+
+ /* Special case for the idle thread */
+ if ((Pid == 1) && (Tid == 1))
+ return TheIdleThread;
+
+ Process = find_process(Pid);
+ if (!Process)
+ return NULL;
+
+ for (ThreadEntry = Process->ThreadListHead.Flink;
+ ThreadEntry != &Process->ThreadListHead;
+ ThreadEntry = ThreadEntry->Flink)
+ {
+ Thread = CONTAINING_RECORD(ThreadEntry, ETHREAD, ThreadListEntry);
+ /* For GDB, Tid == 0 means any thread */
+ if ((Thread->Cid.UniqueThread == ThreadId) || (Tid == 0))
+ {
+ return Thread;
+ }
+ }
+
+ return NULL;
+}
Propchange: trunk/reactos/drivers/base/kdgdb/utils.c
------------------------------------------------------------------------------
charset = UTF-8
Propchange: trunk/reactos/drivers/base/kdgdb/utils.c
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: trunk/reactos/drivers/base/kdgdb/utils.c
------------------------------------------------------------------------------
svn:mime-type = text/plain