mirror of
https://github.com/reactos/reactos.git
synced 2025-08-03 14:25:52 +00:00
[KDGDB]
- Add support for the qfThreadInfo GDB request svn path=/trunk/; revision=64144
This commit is contained in:
parent
7d06aab495
commit
50d072fe6a
4 changed files with 147 additions and 48 deletions
|
@ -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();
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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(...)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue