#include "kdgdb.h"
+#include <pstypes.h>
+
/* LOCALS *********************************************************************/
static HANDLE gdb_run_thread;
static HANDLE gdb_dbg_process;
/* q* packets */
static
void
-handle_gdb_query(void)
+handle_gdb_query(_Inout_ PKD_CONTEXT KdContext)
{
if (strncmp(gdb_input, "qSupported:", 11) == 0)
{
return;
}
- if (strncmp(gdb_input, "qTStatus", 8) == 0)
+ if (strncmp(gdb_input, "qfThreadInfo", 12) == 0)
{
- /* We don't support tracepoints. */
- send_gdb_packet("T0");
+ LIST_ENTRY* ProcessListHead = (LIST_ENTRY*)KdDebuggerDataBlock->PsActiveProcessHead.Pointer;
+ LIST_ENTRY* ProcessEntry;
+ PEPROCESS Process;
+
+ KDDBGPRINT("ProcessListHead: %p.\n", ProcessListHead);
+
+ /* Maybe this was not initialized yet */
+ if (!ProcessListHead->Flink)
+ {
+ char gdb_out[64];
+ /* Just tell GDB about the current thread */
+ sprintf(gdb_out, "mp%p.%p", PsGetCurrentProcessId(), PsGetCurrentThreadId());
+ send_gdb_packet(gdb_out);
+ gdb_receive_packet(KdContext);
+ if (strncmp(gdb_input, "qsThreadInfo", 12) != 0)
+ {
+ // KdAssert
+ KDDBGPRINT("Received %s instead of qsThreadInfo!\n", gdb_input);
+ while(1);
+ }
+ send_gdb_packet("l");
+ return;
+ }
+
+ /* List all processes */
+ for (ProcessEntry = ProcessListHead->Flink;
+ ProcessEntry != ProcessListHead;
+ ProcessEntry = ProcessEntry->Flink)
+ {
+ BOOLEAN FirstThread = TRUE;
+ LIST_ENTRY* ThreadEntry;
+ PETHREAD Thread;
+ static char gdb_out[1024];
+ char* ptr;
+
+ ptr = gdb_out;
+ Process = CONTAINING_RECORD(ProcessEntry, EPROCESS, ActiveProcessLinks);
+
+ KDDBGPRINT("gdb_out %p.\n", gdb_out);
+
+ *ptr++ = 'm';
+ /* List threads from this process */
+ for (ThreadEntry = Process->ThreadListHead.Flink;
+ ThreadEntry != &Process->ThreadListHead;
+ ThreadEntry = ThreadEntry->Flink)
+ {
+ Thread = CONTAINING_RECORD(ThreadEntry, ETHREAD, ThreadListEntry);
+
+ KDDBGPRINT("ptr %p.\n", ptr);
+
+ /* See if we should add a comma */
+ if (FirstThread)
+ {
+ FirstThread = FALSE;
+ }
+ else
+ {
+ *ptr++ = ',';
+ }
+
+ ptr += _snprintf(ptr, 1024 - (ptr - gdb_out),
+ "p%p.%p", PsGetProcessId(Process), PsGetThreadId(Thread));
+ if (ptr > (gdb_out + 1024))
+ {
+ /* send what we got */
+ KDDBGPRINT("Sending %s.\n", gdb_out);
+ send_gdb_packet(gdb_out);
+ gdb_receive_packet(KdContext);
+ if (strncmp(gdb_input, "qsThreadInfo", 12) != 0)
+ {
+ // KdAssert
+ KDDBGPRINT("Received %s instead of qsThreadInfo!\n", gdb_input);
+ while(1);
+ }
+ /* Start anew */
+ ptr = gdb_out;
+ *ptr++ = 'm';
+ FirstThread = TRUE;
+ }
+ }
+
+ /* send the list for this process */
+ KDDBGPRINT("Sending %s.\n", gdb_out);
+ send_gdb_packet(gdb_out);
+ gdb_receive_packet(KdContext);
+ if (strncmp(gdb_input, "qsThreadInfo", 12) != 0)
+ {
+ // KdAssert
+ KDDBGPRINT("Received %s instead of qsThreadInfo!\n", gdb_input);
+ while(1);
+ }
+ }
+
+ /* We're done. Send end-of-list packet */
+ send_gdb_packet("l");
return;
}
case 'm':
return handle_gdb_read_mem(State, MessageData, MessageLength);
case 'q':
- handle_gdb_query();
+ handle_gdb_query(KdContext);
break;
case 'T':
handle_gdb_thread_alive();
/* GLOBALS ********************************************************************/
+CPPORT KdComPort;
+ULONG KdComPortIrq = 0; // Not used at the moment.
+#ifdef KDDEBUG
CPPORT KdDebugComPort;
-ULONG KdDebugComPortIrq = 0; // Not used at the moment.
+#endif
/* FUNCTIONS ******************************************************************/
{
NTSTATUS Status;
- Status = CpInitialize(&KdDebugComPort,
+ Status = CpInitialize(&KdComPort,
UlongToPtr(BaseArray[ComPortNumber]),
ComPortBaudRate);
if (!NT_SUCCESS(Status))
}
else
{
- KdComPortInUse = KdDebugComPort.Address;
+ KdComPortInUse = KdComPort.Address;
return STATUS_SUCCESS;
}
}
PCHAR CommandLine, PortString, BaudString, IrqString;
ULONG Value;
- /* Check if e have a LoaderBlock */
+ /* Check if we have a LoaderBlock */
if (LoaderBlock)
{
-
/* Get the Command Line */
CommandLine = LoaderBlock->LoadOptions;
{
/* Read and set it */
Value = atol(IrqString + 1);
- if (Value) KdDebugComPortIrq = Value;
+ if (Value) KdComPortIrq = Value;
}
}
}
+#ifdef KDDEBUG
+ /* Use DEBUGPORT=COM1 if you want to debug KDGDB, as we use COM2 for debugging it */
+ CpInitialize(&KdDebugComPort, UlongToPtr(BaseArray[2]), DEFAULT_BAUD_RATE);
+#endif
+
/* Initialize the port */
return KdpPortInitialize(ComPortNumber, ComPortBaudRate);
}
KdpSendByte(_In_ UCHAR Byte)
{
/* Send the byte */
- CpPutByte(&KdDebugComPort, Byte);
+ CpPutByte(&KdComPort, Byte);
}
KDSTATUS
KdpPollByte(OUT PUCHAR OutByte)
{
/* Poll the byte */
- if (CpGetByte(&KdDebugComPort, OutByte, FALSE, FALSE) == CP_GET_SUCCESS)
+ if (CpGetByte(&KdComPort, OutByte, FALSE, FALSE) == CP_GET_SUCCESS)
{
return KdPacketReceived;
}
KdpReceiveByte(_Out_ PUCHAR OutByte)
{
/* Get the byte */
- if (CpGetByte(&KdDebugComPort, OutByte, TRUE, FALSE) == CP_GET_SUCCESS)
+ if (CpGetByte(&KdComPort, OutByte, TRUE, FALSE) == CP_GET_SUCCESS)
{
return KdPacketReceived;
}
return KdPacketTimedOut;
}
+#ifdef KDDEBUG
+ULONG KdpDbgPrint(const char* Format, ...)
+{
+ va_list ap;
+ static CHAR Buffer[512];
+ char* ptr;
+ int Length;
+
+ va_start(ap, Format);
+ Length = _vsnprintf(Buffer, sizeof(Buffer), Format, ap);
+ va_end(ap);
+
+ /* Check if we went past the buffer */
+ if (Length == -1)
+ {
+ /* Terminate it if we went over-board */
+ Buffer[sizeof(Buffer) - 1] = '\n';
+
+ /* Put maximum */
+ Length = sizeof(Buffer);
+ }
+
+ ptr = Buffer;
+ while (Length--)
+ CpPutByte(&KdDebugComPort, *ptr++);
+
+ return 0;
+}
+#endif
+
/* EOF */