- 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 <pstypes.h>
/* LOCALS *********************************************************************/
static HANDLE gdb_run_thread;
static HANDLE gdb_dbg_process;
@ -114,7 +116,7 @@ handle_gdb_thread_alive(void)
/* q* packets */
static
void
handle_gdb_query(void)
handle_gdb_query(_Inout_ PKD_CONTEXT KdContext)
{
if (strncmp(gdb_input, "qSupported:", 11) == 0)
{
@ -145,10 +147,103 @@ handle_gdb_query(void)
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;
}
@ -409,7 +504,7 @@ gdb_interpret_input(
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();

View file

@ -185,36 +185,3 @@ gdb_send_exception(void)
ptr += sprintf(ptr, "core:%x;", CurrentStateChange.Processor);
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 ********************************************************************/
CPPORT KdComPort;
ULONG KdComPortIrq = 0; // Not used at the moment.
#ifdef KDDEBUG
CPPORT KdDebugComPort;
ULONG KdDebugComPortIrq = 0; // Not used at the moment.
#endif
/* FUNCTIONS ******************************************************************/
@ -77,7 +80,7 @@ KdpPortInitialize(IN ULONG ComPortNumber,
{
NTSTATUS Status;
Status = CpInitialize(&KdDebugComPort,
Status = CpInitialize(&KdComPort,
UlongToPtr(BaseArray[ComPortNumber]),
ComPortBaudRate);
if (!NT_SUCCESS(Status))
@ -86,7 +89,7 @@ KdpPortInitialize(IN ULONG ComPortNumber,
}
else
{
KdComPortInUse = KdDebugComPort.Address;
KdComPortInUse = KdComPort.Address;
return STATUS_SUCCESS;
}
}
@ -107,10 +110,9 @@ KdDebuggerInitialize0(IN PLOADER_PARAMETER_BLOCK LoaderBlock OPTIONAL)
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;
@ -182,11 +184,16 @@ KdDebuggerInitialize0(IN PLOADER_PARAMETER_BLOCK LoaderBlock OPTIONAL)
{
/* 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);
}
@ -210,7 +217,7 @@ NTAPI
KdpSendByte(_In_ UCHAR Byte)
{
/* Send the byte */
CpPutByte(&KdDebugComPort, Byte);
CpPutByte(&KdComPort, Byte);
}
KDSTATUS
@ -218,7 +225,7 @@ NTAPI
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;
}
@ -233,7 +240,7 @@ NTAPI
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;
}
@ -266,4 +273,34 @@ KdpPollBreakIn(VOID)
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 */

View file

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