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/CMakeLis... ============================================================================== --- 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_inpu... ============================================================================== --- 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_send... ============================================================================== --- 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_sup... ============================================================================== --- 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/kdpacket... ============================================================================== --- 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