From 9bb0e5a772017beb353367af4ccf3a2fd1722db5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Gardou?= Date: Mon, 1 Aug 2016 22:16:58 +0000 Subject: [PATCH] [KDGDB] - Turn this thing into something useful - Pretend we are only one process to GDB (making it a kernel-only debugger...) until the GDB team sorts this out - This is a kernel debugger stub you know. You didn't seriously pretend that recursive functions would be fine, did you ? [NTOS:KD64] - Fix build Pix or it din't happen : https://jira.reactos.org/secure/attachment/36322/source_level_debugging_ros.png svn path=/trunk/; revision=72077 --- reactos/drivers/base/kdgdb/gdb_input.c | 377 +++++++++++++++-------- reactos/drivers/base/kdgdb/gdb_receive.c | 1 + reactos/drivers/base/kdgdb/gdb_send.c | 31 +- reactos/drivers/base/kdgdb/i386_sup.c | 50 ++- reactos/drivers/base/kdgdb/kdcom.c | 11 +- reactos/drivers/base/kdgdb/kdgdb.h | 14 +- reactos/drivers/base/kdgdb/kdpacket.c | 32 +- reactos/drivers/base/kdgdb/utils.c | 37 ++- reactos/ntoskrnl/kd64/kdapi.c | 2 +- 9 files changed, 373 insertions(+), 182 deletions(-) diff --git a/reactos/drivers/base/kdgdb/gdb_input.c b/reactos/drivers/base/kdgdb/gdb_input.c index 115d6804245..dea25971e1f 100644 --- a/reactos/drivers/base/kdgdb/gdb_input.c +++ b/reactos/drivers/base/kdgdb/gdb_input.c @@ -9,9 +9,7 @@ /* LOCALS *********************************************************************/ static ULONG_PTR gdb_run_tid; -/* Keep track of where we are for qfThreadInfo/qsThreadInfo */ -static LIST_ENTRY* CurrentProcessEntry; -static LIST_ENTRY* CurrentThreadEntry; + /* GLOBALS ********************************************************************/ UINT_PTR gdb_dbg_pid; @@ -69,6 +67,17 @@ handle_gdb_set_thread(void) break; case 'g': KDDBGPRINT("Setting debug thread: %s.\n", gdb_input); +#if MONOPROCESS + gdb_dbg_pid = 0; + if (strncmp(&gdb_input[2], "-1", 2) == 0) + { + gdb_dbg_tid = (UINT_PTR)-1; + } + else + { + gdb_dbg_tid = hex_to_tid(&gdb_input[2]); + } +#else if (strncmp(&gdb_input[2], "p-1", 3) == 0) { gdb_dbg_pid = (UINT_PTR)-1; @@ -83,6 +92,7 @@ handle_gdb_set_thread(void) else gdb_dbg_tid = hex_to_tid(ptr); } +#endif send_gdb_packet("OK"); break; default: @@ -91,20 +101,6 @@ handle_gdb_set_thread(void) } } -KDSTATUS -gdb_receive_and_interpret_packet( - _Out_ DBGKD_MANIPULATE_STATE64* State, - _Out_ PSTRING MessageData, - _Out_ PULONG MessageLength, - _Inout_ PKD_CONTEXT KdContext) -{ - KDSTATUS Status = gdb_receive_packet(KdContext); - - if (Status != KdPacketReceived) - return Status; - return gdb_interpret_input(State, MessageData, MessageLength, KdContext); -} - static void handle_gdb_thread_alive(void) @@ -112,12 +108,20 @@ handle_gdb_thread_alive(void) ULONG_PTR Pid, Tid; PETHREAD Thread; +#if MONOPROCESS + Pid = 0; + Tid = hex_to_tid(&gdb_input[1]); + + KDDBGPRINT("Checking if %p is alive.\n", Tid); + +#else 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); +#endif Thread = find_thread(Pid, Tid); @@ -129,40 +133,53 @@ handle_gdb_thread_alive(void) /* q* packets */ static -KDSTATUS -handle_gdb_query( - _Out_ DBGKD_MANIPULATE_STATE64* State, - _Out_ PSTRING MessageData, - _Out_ PULONG MessageLength, - _Inout_ PKD_CONTEXT KdContext) +void +handle_gdb_query(void) { if (strncmp(gdb_input, "qSupported:", 11) == 0) { - send_gdb_packet("PacketSize=4096;multiprocess+;"); - return gdb_receive_and_interpret_packet(State, MessageData, MessageLength, KdContext); +#if MONOPROCESS + send_gdb_packet("PacketSize=1000;"); +#else + send_gdb_packet("PacketSize=1000;multiprocess+;"); +#endif + return; } if (strncmp(gdb_input, "qAttached", 9) == 0) { - /* Say no: We didn't attach, we create the process! */ - send_gdb_packet("0"); - return gdb_receive_and_interpret_packet(State, MessageData, MessageLength, KdContext); +#if MONOPROCESS + send_gdb_packet("1"); +#else + UINT_PTR queried_pid = hex_to_pid(&gdb_input[10]); + /* Let's say we created system process */ + if (gdb_pid_to_handle(queried_pid) == NULL) + send_gdb_packet("0"); + else + send_gdb_packet("1"); +#endif + return; } if (strncmp(gdb_input, "qRcmd,", 6) == 0) { send_gdb_packet("OK"); - return gdb_receive_and_interpret_packet(State, MessageData, MessageLength, KdContext); + return; } if (strcmp(gdb_input, "qC") == 0) { char gdb_out[64]; +#if MONOPROCESS + sprintf(gdb_out, "QC:%"PRIxPTR";", + handle_to_gdb_tid(PsGetThreadId((PETHREAD)(ULONG_PTR)CurrentStateChange.Thread))); +#else 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))); +#endif send_gdb_packet(gdb_out); - return gdb_receive_and_interpret_packet(State, MessageData, MessageLength, KdContext); + return; } if ((strncmp(gdb_input, "qfThreadInfo", 12) == 0) @@ -174,82 +191,162 @@ handle_gdb_query( char gdb_out[1024]; char* ptr = gdb_out; BOOLEAN Resuming = strncmp(gdb_input, "qsThreadInfo", 12) == 0; - - if (Resuming) - { - if (CurrentProcessEntry == (LIST_ENTRY*)1) - { - /* We're done */ - send_gdb_packet("l"); - CurrentProcessEntry = NULL; - return gdb_receive_and_interpret_packet(State, MessageData, MessageLength, KdContext); - } - - if (CurrentThreadEntry == NULL) - CurrentProcessEntry = CurrentProcessEntry->Flink; - } - else - CurrentProcessEntry = ProcessListHead->Flink; - - 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); - } - - Process = CONTAINING_RECORD(CurrentProcessEntry, EPROCESS, ActiveProcessLinks); - - if (Resuming && CurrentThreadEntry != NULL) - CurrentThreadEntry = CurrentThreadEntry->Flink; - else - CurrentThreadEntry = Process->ThreadListHead.Flink; + /* Keep track of where we are. */ + static LIST_ENTRY* CurrentProcessEntry; + static LIST_ENTRY* CurrentThreadEntry; ptr = gdb_out; *ptr++ = 'm'; - /* List threads from this process */ - for ( ; - CurrentThreadEntry != &Process->ThreadListHead; - CurrentThreadEntry = CurrentThreadEntry->Flink) + /* NULL terminate in case we got nothing more to iterate */ + *ptr = '\0'; + + if (!Resuming) { - Thread = CONTAINING_RECORD(CurrentThreadEntry, ETHREAD, ThreadListEntry); + /* Initialize the entries */ + CurrentProcessEntry = ProcessListHead->Flink; + CurrentThreadEntry = NULL; - /* See if we should add a comma */ - if (FirstThread) - { - FirstThread = FALSE; - } - else - { - *ptr++ = ','; - } - - ptr += _snprintf(ptr, 1024 - (ptr - gdb_out), - "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 */ - 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); - } + /* Start with idle thread */ +#if MONOPROCESS + ptr = gdb_out + sprintf(gdb_out, "m1"); +#else + ptr = gdb_out + sprintf(gdb_out, "mp1.1"); +#endif + FirstThread = FALSE; } - /* send the list for this process */ - send_gdb_packet(gdb_out); - CurrentThreadEntry = NULL; + if (CurrentProcessEntry == NULL) /* Ps is not initialized */ + { + send_gdb_packet(Resuming ? "l" : gdb_out); + return; + } + + /* List all the processes */ + for ( ; + CurrentProcessEntry != ProcessListHead; + CurrentProcessEntry = CurrentProcessEntry->Flink) + { + + Process = CONTAINING_RECORD(CurrentProcessEntry, EPROCESS, ActiveProcessLinks); + + if (CurrentThreadEntry != NULL) + CurrentThreadEntry = CurrentThreadEntry->Flink; + else + CurrentThreadEntry = Process->ThreadListHead.Flink; + + /* List threads from this process */ + for ( ; + CurrentThreadEntry != &Process->ThreadListHead; + CurrentThreadEntry = CurrentThreadEntry->Flink) + { + Thread = CONTAINING_RECORD(CurrentThreadEntry, ETHREAD, ThreadListEntry); + + /* See if we should add a comma */ + if (FirstThread) + { + FirstThread = FALSE; + } + else + { + *ptr++ = ','; + } + +#if MONOPROCESS + ptr += _snprintf(ptr, 1024 - (ptr - gdb_out), + "%p", + handle_to_gdb_tid(Thread->Cid.UniqueThread)); +#else + ptr += _snprintf(ptr, 1024 - (ptr - gdb_out), + "p%p.%p", + handle_to_gdb_pid(Process->UniqueProcessId), + handle_to_gdb_tid(Thread->Cid.UniqueThread)); +#endif + if (ptr > (gdb_out + 1024)) + { + /* send what we got */ + send_gdb_packet(gdb_out); + /* GDB can ask anything at this point, it isn't necessarily a qsThreadInfo packet */ + return; + } + } + /* We're done for this process */ + CurrentThreadEntry = NULL; + } + + if (gdb_out[1] == '\0') + { + /* We didn't iterate over anything, meaning we were already done */ + send_gdb_packet("l"); + } + else + { + 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); + return; + } + + if (strncmp(gdb_input, "qThreadExtraInfo,", 17) == 0) + { + ULONG_PTR Pid, Tid; + PETHREAD Thread; + PEPROCESS Process; + char out_string[64]; + STRING String = {0, 64, out_string}; + + KDDBGPRINT("Giving extra info for"); + +#if MONOPROCESS + Pid = 0; + Tid = hex_to_tid(&gdb_input[17]); + + KDDBGPRINT(" %p.\n", Tid); + + Thread = find_thread(Pid, Tid); + Process = CONTAINING_RECORD(Thread->Tcb.Process, EPROCESS, Pcb); +#else + 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(" p%p.%p.\n", Pid, Tid); + + Process = find_process(Pid); + Thread = find_thread(Pid, Tid); +#endif + + if (PsGetThreadProcessId(Thread) == 0) + { + String.Length = sprintf(out_string, "SYSTEM"); + } + else + { + String.Length = sprintf(out_string, "%.*s", 16, Process->ImageFileName); + } + + gdb_send_debug_io(&String, FALSE); + return; + } + + if (strncmp(gdb_input, "qOffsets", 8) == 0) + { + /* We load ntoskrnl at 0x80800000 while compiling it at 0x00800000 base adress */ + send_gdb_packet("TextSeg=80000000"); + return; + } + + if (strcmp(gdb_input, "qTStatus") == 0) + { + /* No tracepoint support */ + send_gdb_packet("T0"); + return; } KDDBGPRINT("KDGDB: Unknown query: %s\n", gdb_input); send_gdb_packet(""); - return gdb_receive_and_interpret_packet(State, MessageData, MessageLength, KdContext); + return; } #if 0 @@ -305,11 +402,13 @@ ReadMemorySendHandler( KdpSendPacketHandler = NULL; KdpManipulateStateHandler = NULL; +#if !MONOPROCESS /* Reset the TLB */ if ((gdb_dbg_pid != 0) && gdb_pid_to_handle(gdb_dbg_pid) != PsGetCurrentProcessId()) { __writecr3(PsGetCurrentProcess()->Pcb.DirectoryTableBase[0]); } +#endif } static @@ -328,6 +427,7 @@ handle_gdb_read_mem( MessageData->Length = 0; *MessageLength = 0; +#if !MONOPROCESS /* 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()) { @@ -340,6 +440,7 @@ handle_gdb_read_mem( } __writecr3(AttachedProcess->Pcb.DirectoryTableBase[0]); } +#endif State->u.ReadMemory.TargetBaseAddress = hex_to_address(&gdb_input[1]); State->u.ReadMemory.TransferCount = hex_to_address(strstr(&gdb_input[1], ",") + 1); @@ -362,16 +463,12 @@ handle_gdb_v( { if (gdb_input[5] == '?') { - KDSTATUS Status; /* Report what we support */ send_gdb_packet("vCont;c;C;s;S"); - Status = gdb_receive_packet(KdContext); - if (Status != KdPacketReceived) - return Status; - return gdb_interpret_input(State, MessageData, MessageLength, KdContext); + return (KDSTATUS)-1; } - if (strcmp(gdb_input, "vCont;c") == 0) + if (strncmp(gdb_input, "vCont;c", 7) == 0) { DBGKM_EXCEPTION64* Exception = NULL; @@ -404,41 +501,63 @@ handle_gdb_v( return KdPacketReceived; } -/* GLOBAL FUNCTIONS ***********************************************************/ KDSTATUS -gdb_interpret_input( +gdb_receive_and_interpret_packet( _Out_ DBGKD_MANIPULATE_STATE64* State, _Out_ PSTRING MessageData, _Out_ PULONG MessageLength, _Inout_ PKD_CONTEXT KdContext) { - switch (gdb_input[0]) + KDSTATUS Status; + + do { - case '?': - /* Send the Status */ - gdb_send_exception(); - break; - case 'g': - return gdb_send_registers(State, MessageData, MessageLength, KdContext); - case 'H': - handle_gdb_set_thread(); - break; - case 'm': - return handle_gdb_read_mem(State, MessageData, MessageLength, KdContext); - case 'p': - return gdb_send_register(State, MessageData, MessageLength, KdContext); - case 'q': - return handle_gdb_query(State, MessageData, MessageLength, KdContext); - case 'T': - handle_gdb_thread_alive(); - break; - case 'v': - return handle_gdb_v(State, MessageData, MessageLength, KdContext); - default: - /* We don't know how to handle this request. Maybe this is something for KD */ - State->ReturnStatus = STATUS_NOT_SUPPORTED; - KDDBGPRINT("Unsupported GDB command: %s.\n", gdb_input); - return KdPacketReceived; - } - return gdb_receive_and_interpret_packet(State, MessageData, MessageLength, KdContext); + Status = gdb_receive_packet(KdContext); + KDDBGPRINT("KDGBD: Packet received with status %u\n", Status); + + if (Status != KdPacketReceived) + return Status; + + Status = (KDSTATUS)-1; + + switch (gdb_input[0]) + { + case '?': + /* Send the Status */ + gdb_send_exception(TRUE); + break; + case '!': + send_gdb_packet("OK"); + break; + case 'g': + gdb_send_registers(); + break; + case 'H': + handle_gdb_set_thread(); + break; + case 'm': + Status = handle_gdb_read_mem(State, MessageData, MessageLength, KdContext); + break; + case 'p': + gdb_send_register(); + break; + case 'q': + handle_gdb_query(); + break; + case 'T': + handle_gdb_thread_alive(); + break; + case 'v': + Status = handle_gdb_v(State, MessageData, MessageLength, KdContext); + break; + default: + /* We don't know how to handle this request. Maybe this is something for KD */ + State->ReturnStatus = STATUS_NOT_SUPPORTED; + KDDBGPRINT("Unsupported GDB command: %s.\n", gdb_input); + return KdPacketReceived; + } + } while (Status == (KDSTATUS)-1); + + return Status; } + diff --git a/reactos/drivers/base/kdgdb/gdb_receive.c b/reactos/drivers/base/kdgdb/gdb_receive.c index 1ce0718deb3..78d75f55b77 100644 --- a/reactos/drivers/base/kdgdb/gdb_receive.c +++ b/reactos/drivers/base/kdgdb/gdb_receive.c @@ -42,6 +42,7 @@ gdb_receive_packet(_Inout_ PKD_CONTEXT KdContext) return Status; if (Byte == 0x03) { + KDDBGPRINT("BREAK!"); KdContext->KdpControlCPending = TRUE; return KdPacketNeedsResend; } diff --git a/reactos/drivers/base/kdgdb/gdb_send.c b/reactos/drivers/base/kdgdb/gdb_send.c index dfbc7b6b9df..fb08e21677b 100644 --- a/reactos/drivers/base/kdgdb/gdb_send.c +++ b/reactos/drivers/base/kdgdb/gdb_send.c @@ -123,22 +123,26 @@ send_gdb_memory( void gdb_send_debug_io( - _In_ PSTRING String) + _In_ PSTRING String, + _In_ BOOLEAN WithPrefix) { UCHAR ack; do { CHAR* ptr = String->Buffer; - CHAR check_sum; + CHAR check_sum = 0; USHORT Length = String->Length; CHAR Byte; KdpSendByte('$'); - KdpSendByte('O'); + if (WithPrefix) + { + KdpSendByte('O'); + check_sum = 'O'; + } /* Send the data */ - check_sum = 'O'; while (Length--) { Byte = hex_chars[(*ptr >> 4) & 0xf]; @@ -164,7 +168,7 @@ gdb_send_debug_io( } void -gdb_send_exception(void) +gdb_send_exception(BOOLEAN WithThread) { char gdb_out[1024]; char* ptr = gdb_out; @@ -180,11 +184,20 @@ gdb_send_exception(void) } else ptr += sprintf(ptr, "05"); - - ptr += sprintf(ptr, "thread:p%" PRIxPTR ".%" PRIxPTR ";", - handle_to_gdb_pid(PsGetThreadProcessId(Thread)), - handle_to_gdb_tid(PsGetThreadId(Thread))); + if (WithThread) + { +#if MONOPROCESS + ptr += sprintf(ptr, "thread:%" PRIxPTR ";", + handle_to_gdb_tid(PsGetThreadId(Thread))); +#else + ptr += sprintf(ptr, "thread:p%" PRIxPTR ".%" PRIxPTR ";", + handle_to_gdb_pid(PsGetThreadProcessId(Thread)), + handle_to_gdb_tid(PsGetThreadId(Thread))); +#endif + } ptr += sprintf(ptr, "core:%x;", CurrentStateChange.Processor); + /* Add program counter */ + gdb_append_pc_to_exception(Thread, ptr); send_gdb_packet(gdb_out); } diff --git a/reactos/drivers/base/kdgdb/i386_sup.c b/reactos/drivers/base/kdgdb/i386_sup.c index 7cab7fef51b..61ff6b42234 100644 --- a/reactos/drivers/base/kdgdb/i386_sup.c +++ b/reactos/drivers/base/kdgdb/i386_sup.c @@ -93,6 +93,7 @@ thread_to_reg(PETHREAD Thread, enum reg_name reg_name, unsigned short* size) case ESP: case EBP: case EIP: + KDDBGPRINT("Returning NULL for register %d.\n", reg_name); *size = 4; return &NullValue; default: @@ -143,12 +144,8 @@ thread_to_reg(PETHREAD Thread, enum reg_name reg_name, unsigned short* size) return NULL; } -KDSTATUS -gdb_send_registers( - _Out_ DBGKD_MANIPULATE_STATE64* State, - _Out_ PSTRING MessageData, - _Out_ PULONG MessageLength, - _Inout_ PKD_CONTEXT KdContext) +void +gdb_send_registers(void) { CHAR Registers[16*8 + 1]; UCHAR* RegisterPtr; @@ -184,7 +181,7 @@ gdb_send_registers( { /* Thread is dead */ send_gdb_packet("E03"); - return gdb_receive_and_interpret_packet(State, MessageData, MessageLength, KdContext); + return; } for(i=0; i < 16; i++) @@ -209,15 +206,10 @@ gdb_send_registers( } *ptr = '\0'; send_gdb_packet(Registers); - return gdb_receive_and_interpret_packet(State, MessageData, MessageLength, KdContext); } -KDSTATUS -gdb_send_register( - _Out_ DBGKD_MANIPULATE_STATE64* State, - _Out_ PSTRING MessageData, - _Out_ PULONG MessageLength, - _Inout_ PKD_CONTEXT KdContext) +void +gdb_send_register(void) { enum reg_name reg_name; void *ptr; @@ -242,7 +234,7 @@ gdb_send_register( { /* Thread is dead */ send_gdb_packet("E03"); - return gdb_receive_and_interpret_packet(State, MessageData, MessageLength, KdContext); + return; } ptr = thread_to_reg(DbgThread, reg_name, &size); @@ -257,6 +249,30 @@ gdb_send_register( { send_gdb_memory(ptr, size); } - - return gdb_receive_and_interpret_packet(State, MessageData, MessageLength, KdContext); } + +char* +gdb_append_pc_to_exception( + _In_ PETHREAD Thread, + _Inout_ char* ptr) +{ + /* Get EIP */ + unsigned short ptrSize; + unsigned char* EipPtr = thread_to_reg(Thread, EIP, &ptrSize); + + /* Print it */ + ptr += sprintf(ptr, "08:"); + *ptr++ = hex_chars[EipPtr[0] >> 4]; + *ptr++ = hex_chars[EipPtr[0] & 0xF]; + *ptr++ = hex_chars[EipPtr[1] >> 4]; + *ptr++ = hex_chars[EipPtr[1] & 0xF]; + *ptr++ = hex_chars[EipPtr[2] >> 4]; + *ptr++ = hex_chars[EipPtr[2] & 0xF]; + *ptr++ = hex_chars[EipPtr[3] >> 4]; + *ptr++ = hex_chars[EipPtr[3] & 0xF]; + *ptr++ = ';'; + *ptr++ = '\0'; + + return ptr; +} + diff --git a/reactos/drivers/base/kdgdb/kdcom.c b/reactos/drivers/base/kdgdb/kdcom.c index be9e634e012..245e8cad669 100644 --- a/reactos/drivers/base/kdgdb/kdcom.c +++ b/reactos/drivers/base/kdgdb/kdcom.c @@ -296,15 +296,15 @@ KDSTATUS NTAPI KdpReceiveByte(_Out_ PUCHAR OutByte) { + USHORT CpStatus = CpGetByte(&KdComPort, OutByte, TRUE, FALSE); /* Get the byte */ - if (CpGetByte(&KdComPort, OutByte, TRUE, FALSE) == CP_GET_SUCCESS) + if (CpStatus == CP_GET_SUCCESS) { return KdPacketReceived; } - else - { - return KdPacketTimedOut; - } + + KDDBGPRINT("CpGetByte returned %u.\n", CpStatus); + return KdPacketTimedOut; } KDSTATUS @@ -319,6 +319,7 @@ KdpPollBreakIn(VOID) { if (Byte == 0x03) { + KDDBGPRINT("BreakIn Polled.\n"); return KdPacketReceived; } else if (Byte == '$') diff --git a/reactos/drivers/base/kdgdb/kdgdb.h b/reactos/drivers/base/kdgdb/kdgdb.h index 24838e7a8a7..81c87c3673d 100644 --- a/reactos/drivers/base/kdgdb/kdgdb.h +++ b/reactos/drivers/base/kdgdb/kdgdb.h @@ -21,6 +21,9 @@ #define KDDEBUG /* uncomment to enable debugging this dll */ +/* To undefine once https://sourceware.org/bugzilla/show_bug.cgi?id=17397 is resolved */ +#define MONOPROCESS 1 + #ifndef KDDEBUG #define KDDBGPRINT(...) #else @@ -34,6 +37,7 @@ 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; @@ -68,7 +72,6 @@ typedef KDSTATUS (*KDP_MANIPULATESTATE_HANDLER)( /* gdb_input.c */ 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); /* gdb_receive.c */ @@ -79,8 +82,8 @@ char hex_value(char ch); /* gdb_send.c */ void send_gdb_packet(_In_ CHAR* Buffer); void send_gdb_memory(_In_ VOID* Buffer, size_t Length); -void gdb_send_debug_io(_In_ PSTRING String); -void gdb_send_exception(void); +void gdb_send_debug_io(_In_ PSTRING String, _In_ BOOLEAN WithPrefix); +void gdb_send_exception(BOOLEAN WithThread); void send_gdb_ntstatus(_In_ NTSTATUS Status); extern const char hex_chars[]; @@ -108,8 +111,9 @@ 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); -extern KDSTATUS gdb_send_registers(_Out_ DBGKD_MANIPULATE_STATE64* State, _Out_ PSTRING MessageData, _Out_ PULONG MessageLength, _Inout_ PKD_CONTEXT KdContext); +extern void gdb_send_register(void); +extern void gdb_send_registers(void); +extern char* gdb_append_pc_to_exception(_In_ PETHREAD Thread, _Inout_ char* ptr); /* Architecture specific defines. See ntoskrnl/include/internal/arch/ke.h */ #ifdef _M_IX86 diff --git a/reactos/drivers/base/kdgdb/kdpacket.c b/reactos/drivers/base/kdgdb/kdpacket.c index 4376d4ebdeb..1cdba7212b5 100644 --- a/reactos/drivers/base/kdgdb/kdpacket.c +++ b/reactos/drivers/base/kdgdb/kdpacket.c @@ -94,6 +94,7 @@ SetContextSendHandler( || (State->ReturnStatus != STATUS_SUCCESS)) { /* Should we bugcheck ? */ + KDDBGPRINT("BAD BAD BAD not manipulating state for sending context.\n"); while (1); } @@ -116,6 +117,7 @@ SetContextManipulateHandler( if (MessageData->MaximumLength < sizeof(CurrentContext)) { + KDDBGPRINT("Wrong message length %u.\n", MessageData->MaximumLength); while (1); } @@ -153,14 +155,18 @@ send_kd_state_change(DBGKD_ANY_WAIT_STATE_CHANGE* StateChange) PsGetThreadId(Thread)); /* Set the current debugged process/thread accordingly */ gdb_dbg_tid = handle_to_gdb_tid(PsGetThreadId(Thread)); +#if MONOPROCESS + gdb_dbg_pid = 0; +#else gdb_dbg_pid = handle_to_gdb_pid(PsGetThreadProcessId(Thread)); - gdb_send_exception(); +#endif + gdb_send_exception(FALSE); /* Next receive call will ask for the context */ KdpManipulateStateHandler = GetContextManipulateHandler; break; } default: - /* FIXME */ + KDDBGPRINT("Unknown StateChange %u.\n", StateChange->NewState); while (1); } } @@ -177,10 +183,10 @@ send_kd_debug_io( switch (DebugIO->ApiNumber) { case DbgKdPrintStringApi: - gdb_send_debug_io(String); + gdb_send_debug_io(String, TRUE); break; default: - /* FIXME */ + KDDBGPRINT("Unknown ApiNumber %u.\n", DebugIO->ApiNumber); while (1); } } @@ -200,7 +206,7 @@ send_kd_state_manipulate( return; #endif default: - /* FIXME */ + KDDBGPRINT("Unknown ApiNumber %u.\n", State->ApiNumber); while (1); } } @@ -314,7 +320,11 @@ FirstSendHandler( /* Set up the current state */ CurrentStateChange = *StateChange; gdb_dbg_tid = handle_to_gdb_tid(PsGetThreadId(Thread)); +#if MONOPROCESS + gdb_dbg_pid = 0; +#else gdb_dbg_pid = handle_to_gdb_pid(PsGetThreadProcessId(Thread)); +#endif /* This is the idle process. Save it! */ TheIdleThread = Thread; TheIdleProcess = (PEPROCESS)Thread->Tcb.ApcState.Process; @@ -352,7 +362,6 @@ KdReceivePacket( _Out_ PULONG DataLength, _Inout_ PKD_CONTEXT KdContext) { - KDSTATUS Status; DBGKD_MANIPULATE_STATE64* State; /* Special handling for breakin packet */ @@ -373,13 +382,8 @@ KdReceivePacket( if (KdpManipulateStateHandler != NULL) return KdpManipulateStateHandler(State, MessageData, DataLength, KdContext); - /* Receive data from GDB */ - Status = gdb_receive_packet(KdContext); - if (Status != KdPacketReceived) - return Status; - - /* Interpret it */ - return gdb_interpret_input(State, MessageData, DataLength, KdContext); + /* Receive data from GDB and interpret it */ + return gdb_receive_and_interpret_packet(State, MessageData, DataLength, KdContext); } VOID @@ -409,7 +413,7 @@ KdSendPacket( send_kd_state_manipulate((DBGKD_MANIPULATE_STATE64*)MessageHeader->Buffer, MessageData); break; default: - /* FIXME */ + KDDBGPRINT("Unknown packet type %u.\n", PacketType); while (1); } } diff --git a/reactos/drivers/base/kdgdb/utils.c b/reactos/drivers/base/kdgdb/utils.c index 01dea3d7f33..2817f648bdf 100644 --- a/reactos/drivers/base/kdgdb/utils.c +++ b/reactos/drivers/base/kdgdb/utils.c @@ -21,7 +21,7 @@ find_process( PEPROCESS Process; /* Special case for idle process */ - if (Pid == 1) + if (ProcessId == NULL) return TheIdleProcess; for (ProcessEntry = ProcessListHead->Flink; @@ -46,15 +46,44 @@ find_thread( PETHREAD Thread; PEPROCESS Process; LIST_ENTRY* ThreadEntry; +#if MONOPROCESS + LIST_ENTRY* ProcessEntry; +#endif + + if ( +#if !MONOPROCESS + (Pid == 0) && +#endif + (Tid == 0)) + { + /* Zero means any, so use the current one */ + return (PETHREAD)(ULONG_PTR)CurrentStateChange.Thread; + } + +#if MONOPROCESS /* Special case for the idle thread */ - if ((Pid == 1) && (Tid == 1)) + if (Tid == 1) return TheIdleThread; + for (ProcessEntry = ProcessListHead->Flink; + ProcessEntry != ProcessListHead; + ProcessEntry = ProcessEntry->Flink) + { + Process = CONTAINING_RECORD(ProcessEntry, EPROCESS, ActiveProcessLinks); +#else + Process = find_process(Pid); + + /* Special case for the idle thread */ + if ((Process == TheIdleProcess) && (Tid == 1)) + return TheIdleThread; + if (!Process) return NULL; +#endif + for (ThreadEntry = Process->ThreadListHead.Flink; ThreadEntry != &Process->ThreadListHead; ThreadEntry = ThreadEntry->Flink) @@ -67,5 +96,9 @@ find_thread( } } +#if MONOPROCESS + } +#endif + return NULL; } diff --git a/reactos/ntoskrnl/kd64/kdapi.c b/reactos/ntoskrnl/kd64/kdapi.c index f0415ba3ae0..eefdf400a73 100644 --- a/reactos/ntoskrnl/kd64/kdapi.c +++ b/reactos/ntoskrnl/kd64/kdapi.c @@ -113,7 +113,7 @@ KdpCopyMemoryChunks(IN ULONG64 Address, /* * We may have modified executable code, flush the instruction cache */ - KeSweepICache((PVOID)Address, TotalSize); + KeSweepICache((PVOID)(ULONG_PTR)Address, TotalSize); /* * Return the size we managed to copy