- Add support for the qfThreadInfo GDB request

svn path=/trunk/; revision=64144
This commit is contained in:
Jérôme Gardou 2014-09-14 14:27:44 +00:00
parent 7d06aab495
commit 50d072fe6a
4 changed files with 147 additions and 48 deletions

View file

@ -7,6 +7,8 @@
#include "kdgdb.h" #include "kdgdb.h"
#include <pstypes.h>
/* LOCALS *********************************************************************/ /* LOCALS *********************************************************************/
static HANDLE gdb_run_thread; static HANDLE gdb_run_thread;
static HANDLE gdb_dbg_process; static HANDLE gdb_dbg_process;
@ -114,7 +116,7 @@ handle_gdb_thread_alive(void)
/* q* packets */ /* q* packets */
static static
void void
handle_gdb_query(void) handle_gdb_query(_Inout_ PKD_CONTEXT KdContext)
{ {
if (strncmp(gdb_input, "qSupported:", 11) == 0) if (strncmp(gdb_input, "qSupported:", 11) == 0)
{ {
@ -145,10 +147,103 @@ handle_gdb_query(void)
return; return;
} }
if (strncmp(gdb_input, "qTStatus", 8) == 0) if (strncmp(gdb_input, "qfThreadInfo", 12) == 0)
{ {
/* We don't support tracepoints. */ LIST_ENTRY* ProcessListHead = (LIST_ENTRY*)KdDebuggerDataBlock->PsActiveProcessHead.Pointer;
send_gdb_packet("T0"); 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; return;
} }
@ -409,7 +504,7 @@ gdb_interpret_input(
case 'm': case 'm':
return handle_gdb_read_mem(State, MessageData, MessageLength); return handle_gdb_read_mem(State, MessageData, MessageLength);
case 'q': case 'q':
handle_gdb_query(); handle_gdb_query(KdContext);
break; break;
case 'T': case 'T':
handle_gdb_thread_alive(); handle_gdb_thread_alive();

View file

@ -185,36 +185,3 @@ gdb_send_exception(void)
ptr += sprintf(ptr, "core:%x;", CurrentStateChange.Processor); ptr += sprintf(ptr, "core:%x;", CurrentStateChange.Processor);
send_gdb_packet(gdb_out); send_gdb_packet(gdb_out);
} }
#ifdef KDDEBUG
ULONG KdpDbgPrint(const char* Format, ...)
{
va_list ap;
CHAR Buffer[512];
struct _STRING Str;
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);
}
Str.Buffer = Buffer;
Str.Length = Length;
Str.MaximumLength = sizeof(Buffer);
gdb_send_debug_io(&Str);
return 0;
}
#endif

View file

@ -34,8 +34,11 @@ const ULONG BaseArray[] = {0, 0xF1012000};
/* GLOBALS ********************************************************************/ /* GLOBALS ********************************************************************/
CPPORT KdComPort;
ULONG KdComPortIrq = 0; // Not used at the moment.
#ifdef KDDEBUG
CPPORT KdDebugComPort; CPPORT KdDebugComPort;
ULONG KdDebugComPortIrq = 0; // Not used at the moment. #endif
/* FUNCTIONS ******************************************************************/ /* FUNCTIONS ******************************************************************/
@ -77,7 +80,7 @@ KdpPortInitialize(IN ULONG ComPortNumber,
{ {
NTSTATUS Status; NTSTATUS Status;
Status = CpInitialize(&KdDebugComPort, Status = CpInitialize(&KdComPort,
UlongToPtr(BaseArray[ComPortNumber]), UlongToPtr(BaseArray[ComPortNumber]),
ComPortBaudRate); ComPortBaudRate);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
@ -86,7 +89,7 @@ KdpPortInitialize(IN ULONG ComPortNumber,
} }
else else
{ {
KdComPortInUse = KdDebugComPort.Address; KdComPortInUse = KdComPort.Address;
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
} }
@ -107,10 +110,9 @@ KdDebuggerInitialize0(IN PLOADER_PARAMETER_BLOCK LoaderBlock OPTIONAL)
PCHAR CommandLine, PortString, BaudString, IrqString; PCHAR CommandLine, PortString, BaudString, IrqString;
ULONG Value; ULONG Value;
/* Check if e have a LoaderBlock */ /* Check if we have a LoaderBlock */
if (LoaderBlock) if (LoaderBlock)
{ {
/* Get the Command Line */ /* Get the Command Line */
CommandLine = LoaderBlock->LoadOptions; CommandLine = LoaderBlock->LoadOptions;
@ -182,11 +184,16 @@ KdDebuggerInitialize0(IN PLOADER_PARAMETER_BLOCK LoaderBlock OPTIONAL)
{ {
/* Read and set it */ /* Read and set it */
Value = atol(IrqString + 1); 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 */ /* Initialize the port */
return KdpPortInitialize(ComPortNumber, ComPortBaudRate); return KdpPortInitialize(ComPortNumber, ComPortBaudRate);
} }
@ -210,7 +217,7 @@ NTAPI
KdpSendByte(_In_ UCHAR Byte) KdpSendByte(_In_ UCHAR Byte)
{ {
/* Send the byte */ /* Send the byte */
CpPutByte(&KdDebugComPort, Byte); CpPutByte(&KdComPort, Byte);
} }
KDSTATUS KDSTATUS
@ -218,7 +225,7 @@ NTAPI
KdpPollByte(OUT PUCHAR OutByte) KdpPollByte(OUT PUCHAR OutByte)
{ {
/* Poll the byte */ /* Poll the byte */
if (CpGetByte(&KdDebugComPort, OutByte, FALSE, FALSE) == CP_GET_SUCCESS) if (CpGetByte(&KdComPort, OutByte, FALSE, FALSE) == CP_GET_SUCCESS)
{ {
return KdPacketReceived; return KdPacketReceived;
} }
@ -233,7 +240,7 @@ NTAPI
KdpReceiveByte(_Out_ PUCHAR OutByte) KdpReceiveByte(_Out_ PUCHAR OutByte)
{ {
/* Get the byte */ /* Get the byte */
if (CpGetByte(&KdDebugComPort, OutByte, TRUE, FALSE) == CP_GET_SUCCESS) if (CpGetByte(&KdComPort, OutByte, TRUE, FALSE) == CP_GET_SUCCESS)
{ {
return KdPacketReceived; return KdPacketReceived;
} }
@ -266,4 +273,34 @@ KdpPollBreakIn(VOID)
return KdPacketTimedOut; 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 */ /* EOF */

View file

@ -16,7 +16,7 @@
#include <windbgkd.h> #include <windbgkd.h>
#include <kddll.h> #include <kddll.h>
// #define KDDEBUG /* uncomment to enable debugging this dll */ #define KDDEBUG /* uncomment to enable debugging this dll */
#ifndef KDDEBUG #ifndef KDDEBUG
#define KDDBGPRINT(...) #define KDDBGPRINT(...)