mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 21:32:56 +00:00
[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
This commit is contained in:
parent
0f196e05cc
commit
9bb0e5a772
9 changed files with 373 additions and 182 deletions
|
@ -9,9 +9,7 @@
|
||||||
|
|
||||||
/* LOCALS *********************************************************************/
|
/* LOCALS *********************************************************************/
|
||||||
static ULONG_PTR gdb_run_tid;
|
static ULONG_PTR gdb_run_tid;
|
||||||
/* Keep track of where we are for qfThreadInfo/qsThreadInfo */
|
|
||||||
static LIST_ENTRY* CurrentProcessEntry;
|
|
||||||
static LIST_ENTRY* CurrentThreadEntry;
|
|
||||||
|
|
||||||
/* GLOBALS ********************************************************************/
|
/* GLOBALS ********************************************************************/
|
||||||
UINT_PTR gdb_dbg_pid;
|
UINT_PTR gdb_dbg_pid;
|
||||||
|
@ -69,6 +67,17 @@ handle_gdb_set_thread(void)
|
||||||
break;
|
break;
|
||||||
case 'g':
|
case 'g':
|
||||||
KDDBGPRINT("Setting debug thread: %s.\n", gdb_input);
|
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)
|
if (strncmp(&gdb_input[2], "p-1", 3) == 0)
|
||||||
{
|
{
|
||||||
gdb_dbg_pid = (UINT_PTR)-1;
|
gdb_dbg_pid = (UINT_PTR)-1;
|
||||||
|
@ -83,6 +92,7 @@ handle_gdb_set_thread(void)
|
||||||
else
|
else
|
||||||
gdb_dbg_tid = hex_to_tid(ptr);
|
gdb_dbg_tid = hex_to_tid(ptr);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
send_gdb_packet("OK");
|
send_gdb_packet("OK");
|
||||||
break;
|
break;
|
||||||
default:
|
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
|
static
|
||||||
void
|
void
|
||||||
handle_gdb_thread_alive(void)
|
handle_gdb_thread_alive(void)
|
||||||
|
@ -112,12 +108,20 @@ handle_gdb_thread_alive(void)
|
||||||
ULONG_PTR Pid, Tid;
|
ULONG_PTR Pid, Tid;
|
||||||
PETHREAD Thread;
|
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]);
|
Pid = hex_to_pid(&gdb_input[2]);
|
||||||
Tid = hex_to_tid(strstr(gdb_input, ".") + 1);
|
Tid = hex_to_tid(strstr(gdb_input, ".") + 1);
|
||||||
|
|
||||||
/* We cannot use PsLookupProcessThreadByCid as we could be running at any IRQL.
|
/* We cannot use PsLookupProcessThreadByCid as we could be running at any IRQL.
|
||||||
* So loop. */
|
* So loop. */
|
||||||
KDDBGPRINT("Checking if p%p.%p is alive.\n", Pid, Tid);
|
KDDBGPRINT("Checking if p%p.%p is alive.\n", Pid, Tid);
|
||||||
|
#endif
|
||||||
|
|
||||||
Thread = find_thread(Pid, Tid);
|
Thread = find_thread(Pid, Tid);
|
||||||
|
|
||||||
|
@ -129,40 +133,53 @@ handle_gdb_thread_alive(void)
|
||||||
|
|
||||||
/* q* packets */
|
/* q* packets */
|
||||||
static
|
static
|
||||||
KDSTATUS
|
void
|
||||||
handle_gdb_query(
|
handle_gdb_query(void)
|
||||||
_Out_ DBGKD_MANIPULATE_STATE64* State,
|
|
||||||
_Out_ PSTRING MessageData,
|
|
||||||
_Out_ PULONG MessageLength,
|
|
||||||
_Inout_ PKD_CONTEXT KdContext)
|
|
||||||
{
|
{
|
||||||
if (strncmp(gdb_input, "qSupported:", 11) == 0)
|
if (strncmp(gdb_input, "qSupported:", 11) == 0)
|
||||||
{
|
{
|
||||||
send_gdb_packet("PacketSize=4096;multiprocess+;");
|
#if MONOPROCESS
|
||||||
return gdb_receive_and_interpret_packet(State, MessageData, MessageLength, KdContext);
|
send_gdb_packet("PacketSize=1000;");
|
||||||
|
#else
|
||||||
|
send_gdb_packet("PacketSize=1000;multiprocess+;");
|
||||||
|
#endif
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strncmp(gdb_input, "qAttached", 9) == 0)
|
if (strncmp(gdb_input, "qAttached", 9) == 0)
|
||||||
{
|
{
|
||||||
/* Say no: We didn't attach, we create the process! */
|
#if MONOPROCESS
|
||||||
send_gdb_packet("0");
|
send_gdb_packet("1");
|
||||||
return gdb_receive_and_interpret_packet(State, MessageData, MessageLength, KdContext);
|
#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)
|
if (strncmp(gdb_input, "qRcmd,", 6) == 0)
|
||||||
{
|
{
|
||||||
send_gdb_packet("OK");
|
send_gdb_packet("OK");
|
||||||
return gdb_receive_and_interpret_packet(State, MessageData, MessageLength, KdContext);
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(gdb_input, "qC") == 0)
|
if (strcmp(gdb_input, "qC") == 0)
|
||||||
{
|
{
|
||||||
char gdb_out[64];
|
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";",
|
sprintf(gdb_out, "QC:p%"PRIxPTR".%"PRIxPTR";",
|
||||||
handle_to_gdb_pid(PsGetThreadProcessId((PETHREAD)(ULONG_PTR)CurrentStateChange.Thread)),
|
handle_to_gdb_pid(PsGetThreadProcessId((PETHREAD)(ULONG_PTR)CurrentStateChange.Thread)),
|
||||||
handle_to_gdb_tid(PsGetThreadId((PETHREAD)(ULONG_PTR)CurrentStateChange.Thread)));
|
handle_to_gdb_tid(PsGetThreadId((PETHREAD)(ULONG_PTR)CurrentStateChange.Thread)));
|
||||||
|
#endif
|
||||||
send_gdb_packet(gdb_out);
|
send_gdb_packet(gdb_out);
|
||||||
return gdb_receive_and_interpret_packet(State, MessageData, MessageLength, KdContext);
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((strncmp(gdb_input, "qfThreadInfo", 12) == 0)
|
if ((strncmp(gdb_input, "qfThreadInfo", 12) == 0)
|
||||||
|
@ -174,82 +191,162 @@ handle_gdb_query(
|
||||||
char gdb_out[1024];
|
char gdb_out[1024];
|
||||||
char* ptr = gdb_out;
|
char* ptr = gdb_out;
|
||||||
BOOLEAN Resuming = strncmp(gdb_input, "qsThreadInfo", 12) == 0;
|
BOOLEAN Resuming = strncmp(gdb_input, "qsThreadInfo", 12) == 0;
|
||||||
|
/* Keep track of where we are. */
|
||||||
if (Resuming)
|
static LIST_ENTRY* CurrentProcessEntry;
|
||||||
{
|
static LIST_ENTRY* CurrentThreadEntry;
|
||||||
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;
|
|
||||||
|
|
||||||
ptr = gdb_out;
|
ptr = gdb_out;
|
||||||
|
|
||||||
*ptr++ = 'm';
|
*ptr++ = 'm';
|
||||||
/* List threads from this process */
|
/* NULL terminate in case we got nothing more to iterate */
|
||||||
for ( ;
|
*ptr = '\0';
|
||||||
CurrentThreadEntry != &Process->ThreadListHead;
|
|
||||||
CurrentThreadEntry = CurrentThreadEntry->Flink)
|
if (!Resuming)
|
||||||
{
|
{
|
||||||
Thread = CONTAINING_RECORD(CurrentThreadEntry, ETHREAD, ThreadListEntry);
|
/* Initialize the entries */
|
||||||
|
CurrentProcessEntry = ProcessListHead->Flink;
|
||||||
|
CurrentThreadEntry = NULL;
|
||||||
|
|
||||||
/* See if we should add a comma */
|
/* Start with idle thread */
|
||||||
if (FirstThread)
|
#if MONOPROCESS
|
||||||
{
|
ptr = gdb_out + sprintf(gdb_out, "m1");
|
||||||
FirstThread = FALSE;
|
#else
|
||||||
}
|
ptr = gdb_out + sprintf(gdb_out, "mp1.1");
|
||||||
else
|
#endif
|
||||||
{
|
FirstThread = FALSE;
|
||||||
*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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* send the list for this process */
|
if (CurrentProcessEntry == NULL) /* Ps is not initialized */
|
||||||
send_gdb_packet(gdb_out);
|
{
|
||||||
CurrentThreadEntry = NULL;
|
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 */
|
/* 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);
|
KDDBGPRINT("KDGDB: Unknown query: %s\n", gdb_input);
|
||||||
send_gdb_packet("");
|
send_gdb_packet("");
|
||||||
return gdb_receive_and_interpret_packet(State, MessageData, MessageLength, KdContext);
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
@ -305,11 +402,13 @@ ReadMemorySendHandler(
|
||||||
KdpSendPacketHandler = NULL;
|
KdpSendPacketHandler = NULL;
|
||||||
KdpManipulateStateHandler = NULL;
|
KdpManipulateStateHandler = NULL;
|
||||||
|
|
||||||
|
#if !MONOPROCESS
|
||||||
/* Reset the TLB */
|
/* Reset the TLB */
|
||||||
if ((gdb_dbg_pid != 0) && gdb_pid_to_handle(gdb_dbg_pid) != PsGetCurrentProcessId())
|
if ((gdb_dbg_pid != 0) && gdb_pid_to_handle(gdb_dbg_pid) != PsGetCurrentProcessId())
|
||||||
{
|
{
|
||||||
__writecr3(PsGetCurrentProcess()->Pcb.DirectoryTableBase[0]);
|
__writecr3(PsGetCurrentProcess()->Pcb.DirectoryTableBase[0]);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
|
@ -328,6 +427,7 @@ handle_gdb_read_mem(
|
||||||
MessageData->Length = 0;
|
MessageData->Length = 0;
|
||||||
*MessageLength = 0;
|
*MessageLength = 0;
|
||||||
|
|
||||||
|
#if !MONOPROCESS
|
||||||
/* Set the TLB according to the process being read. Pid 0 means any process. */
|
/* 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())
|
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]);
|
__writecr3(AttachedProcess->Pcb.DirectoryTableBase[0]);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
State->u.ReadMemory.TargetBaseAddress = hex_to_address(&gdb_input[1]);
|
State->u.ReadMemory.TargetBaseAddress = hex_to_address(&gdb_input[1]);
|
||||||
State->u.ReadMemory.TransferCount = hex_to_address(strstr(&gdb_input[1], ",") + 1);
|
State->u.ReadMemory.TransferCount = hex_to_address(strstr(&gdb_input[1], ",") + 1);
|
||||||
|
@ -362,16 +463,12 @@ handle_gdb_v(
|
||||||
{
|
{
|
||||||
if (gdb_input[5] == '?')
|
if (gdb_input[5] == '?')
|
||||||
{
|
{
|
||||||
KDSTATUS Status;
|
|
||||||
/* Report what we support */
|
/* Report what we support */
|
||||||
send_gdb_packet("vCont;c;C;s;S");
|
send_gdb_packet("vCont;c;C;s;S");
|
||||||
Status = gdb_receive_packet(KdContext);
|
return (KDSTATUS)-1;
|
||||||
if (Status != KdPacketReceived)
|
|
||||||
return Status;
|
|
||||||
return gdb_interpret_input(State, MessageData, MessageLength, KdContext);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(gdb_input, "vCont;c") == 0)
|
if (strncmp(gdb_input, "vCont;c", 7) == 0)
|
||||||
{
|
{
|
||||||
DBGKM_EXCEPTION64* Exception = NULL;
|
DBGKM_EXCEPTION64* Exception = NULL;
|
||||||
|
|
||||||
|
@ -404,41 +501,63 @@ handle_gdb_v(
|
||||||
return KdPacketReceived;
|
return KdPacketReceived;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* GLOBAL FUNCTIONS ***********************************************************/
|
|
||||||
KDSTATUS
|
KDSTATUS
|
||||||
gdb_interpret_input(
|
gdb_receive_and_interpret_packet(
|
||||||
_Out_ DBGKD_MANIPULATE_STATE64* State,
|
_Out_ DBGKD_MANIPULATE_STATE64* State,
|
||||||
_Out_ PSTRING MessageData,
|
_Out_ PSTRING MessageData,
|
||||||
_Out_ PULONG MessageLength,
|
_Out_ PULONG MessageLength,
|
||||||
_Inout_ PKD_CONTEXT KdContext)
|
_Inout_ PKD_CONTEXT KdContext)
|
||||||
{
|
{
|
||||||
switch (gdb_input[0])
|
KDSTATUS Status;
|
||||||
|
|
||||||
|
do
|
||||||
{
|
{
|
||||||
case '?':
|
Status = gdb_receive_packet(KdContext);
|
||||||
/* Send the Status */
|
KDDBGPRINT("KDGBD: Packet received with status %u\n", Status);
|
||||||
gdb_send_exception();
|
|
||||||
break;
|
if (Status != KdPacketReceived)
|
||||||
case 'g':
|
return Status;
|
||||||
return gdb_send_registers(State, MessageData, MessageLength, KdContext);
|
|
||||||
case 'H':
|
Status = (KDSTATUS)-1;
|
||||||
handle_gdb_set_thread();
|
|
||||||
break;
|
switch (gdb_input[0])
|
||||||
case 'm':
|
{
|
||||||
return handle_gdb_read_mem(State, MessageData, MessageLength, KdContext);
|
case '?':
|
||||||
case 'p':
|
/* Send the Status */
|
||||||
return gdb_send_register(State, MessageData, MessageLength, KdContext);
|
gdb_send_exception(TRUE);
|
||||||
case 'q':
|
break;
|
||||||
return handle_gdb_query(State, MessageData, MessageLength, KdContext);
|
case '!':
|
||||||
case 'T':
|
send_gdb_packet("OK");
|
||||||
handle_gdb_thread_alive();
|
break;
|
||||||
break;
|
case 'g':
|
||||||
case 'v':
|
gdb_send_registers();
|
||||||
return handle_gdb_v(State, MessageData, MessageLength, KdContext);
|
break;
|
||||||
default:
|
case 'H':
|
||||||
/* We don't know how to handle this request. Maybe this is something for KD */
|
handle_gdb_set_thread();
|
||||||
State->ReturnStatus = STATUS_NOT_SUPPORTED;
|
break;
|
||||||
KDDBGPRINT("Unsupported GDB command: %s.\n", gdb_input);
|
case 'm':
|
||||||
return KdPacketReceived;
|
Status = handle_gdb_read_mem(State, MessageData, MessageLength, KdContext);
|
||||||
}
|
break;
|
||||||
return gdb_receive_and_interpret_packet(State, MessageData, MessageLength, KdContext);
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,7 @@ gdb_receive_packet(_Inout_ PKD_CONTEXT KdContext)
|
||||||
return Status;
|
return Status;
|
||||||
if (Byte == 0x03)
|
if (Byte == 0x03)
|
||||||
{
|
{
|
||||||
|
KDDBGPRINT("BREAK!");
|
||||||
KdContext->KdpControlCPending = TRUE;
|
KdContext->KdpControlCPending = TRUE;
|
||||||
return KdPacketNeedsResend;
|
return KdPacketNeedsResend;
|
||||||
}
|
}
|
||||||
|
|
|
@ -123,22 +123,26 @@ send_gdb_memory(
|
||||||
|
|
||||||
void
|
void
|
||||||
gdb_send_debug_io(
|
gdb_send_debug_io(
|
||||||
_In_ PSTRING String)
|
_In_ PSTRING String,
|
||||||
|
_In_ BOOLEAN WithPrefix)
|
||||||
{
|
{
|
||||||
UCHAR ack;
|
UCHAR ack;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
CHAR* ptr = String->Buffer;
|
CHAR* ptr = String->Buffer;
|
||||||
CHAR check_sum;
|
CHAR check_sum = 0;
|
||||||
USHORT Length = String->Length;
|
USHORT Length = String->Length;
|
||||||
CHAR Byte;
|
CHAR Byte;
|
||||||
|
|
||||||
KdpSendByte('$');
|
KdpSendByte('$');
|
||||||
|
|
||||||
KdpSendByte('O');
|
if (WithPrefix)
|
||||||
|
{
|
||||||
|
KdpSendByte('O');
|
||||||
|
check_sum = 'O';
|
||||||
|
}
|
||||||
|
|
||||||
/* Send the data */
|
/* Send the data */
|
||||||
check_sum = 'O';
|
|
||||||
while (Length--)
|
while (Length--)
|
||||||
{
|
{
|
||||||
Byte = hex_chars[(*ptr >> 4) & 0xf];
|
Byte = hex_chars[(*ptr >> 4) & 0xf];
|
||||||
|
@ -164,7 +168,7 @@ gdb_send_debug_io(
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
gdb_send_exception(void)
|
gdb_send_exception(BOOLEAN WithThread)
|
||||||
{
|
{
|
||||||
char gdb_out[1024];
|
char gdb_out[1024];
|
||||||
char* ptr = gdb_out;
|
char* ptr = gdb_out;
|
||||||
|
@ -180,11 +184,20 @@ gdb_send_exception(void)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
ptr += sprintf(ptr, "05");
|
ptr += sprintf(ptr, "05");
|
||||||
|
if (WithThread)
|
||||||
ptr += sprintf(ptr, "thread:p%" PRIxPTR ".%" PRIxPTR ";",
|
{
|
||||||
handle_to_gdb_pid(PsGetThreadProcessId(Thread)),
|
#if MONOPROCESS
|
||||||
handle_to_gdb_tid(PsGetThreadId(Thread)));
|
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);
|
ptr += sprintf(ptr, "core:%x;", CurrentStateChange.Processor);
|
||||||
|
/* Add program counter */
|
||||||
|
gdb_append_pc_to_exception(Thread, ptr);
|
||||||
send_gdb_packet(gdb_out);
|
send_gdb_packet(gdb_out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -93,6 +93,7 @@ thread_to_reg(PETHREAD Thread, enum reg_name reg_name, unsigned short* size)
|
||||||
case ESP:
|
case ESP:
|
||||||
case EBP:
|
case EBP:
|
||||||
case EIP:
|
case EIP:
|
||||||
|
KDDBGPRINT("Returning NULL for register %d.\n", reg_name);
|
||||||
*size = 4;
|
*size = 4;
|
||||||
return &NullValue;
|
return &NullValue;
|
||||||
default:
|
default:
|
||||||
|
@ -143,12 +144,8 @@ thread_to_reg(PETHREAD Thread, enum reg_name reg_name, unsigned short* size)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
KDSTATUS
|
void
|
||||||
gdb_send_registers(
|
gdb_send_registers(void)
|
||||||
_Out_ DBGKD_MANIPULATE_STATE64* State,
|
|
||||||
_Out_ PSTRING MessageData,
|
|
||||||
_Out_ PULONG MessageLength,
|
|
||||||
_Inout_ PKD_CONTEXT KdContext)
|
|
||||||
{
|
{
|
||||||
CHAR Registers[16*8 + 1];
|
CHAR Registers[16*8 + 1];
|
||||||
UCHAR* RegisterPtr;
|
UCHAR* RegisterPtr;
|
||||||
|
@ -184,7 +181,7 @@ gdb_send_registers(
|
||||||
{
|
{
|
||||||
/* Thread is dead */
|
/* Thread is dead */
|
||||||
send_gdb_packet("E03");
|
send_gdb_packet("E03");
|
||||||
return gdb_receive_and_interpret_packet(State, MessageData, MessageLength, KdContext);
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(i=0; i < 16; i++)
|
for(i=0; i < 16; i++)
|
||||||
|
@ -209,15 +206,10 @@ gdb_send_registers(
|
||||||
}
|
}
|
||||||
*ptr = '\0';
|
*ptr = '\0';
|
||||||
send_gdb_packet(Registers);
|
send_gdb_packet(Registers);
|
||||||
return gdb_receive_and_interpret_packet(State, MessageData, MessageLength, KdContext);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
KDSTATUS
|
void
|
||||||
gdb_send_register(
|
gdb_send_register(void)
|
||||||
_Out_ DBGKD_MANIPULATE_STATE64* State,
|
|
||||||
_Out_ PSTRING MessageData,
|
|
||||||
_Out_ PULONG MessageLength,
|
|
||||||
_Inout_ PKD_CONTEXT KdContext)
|
|
||||||
{
|
{
|
||||||
enum reg_name reg_name;
|
enum reg_name reg_name;
|
||||||
void *ptr;
|
void *ptr;
|
||||||
|
@ -242,7 +234,7 @@ gdb_send_register(
|
||||||
{
|
{
|
||||||
/* Thread is dead */
|
/* Thread is dead */
|
||||||
send_gdb_packet("E03");
|
send_gdb_packet("E03");
|
||||||
return gdb_receive_and_interpret_packet(State, MessageData, MessageLength, KdContext);
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ptr = thread_to_reg(DbgThread, reg_name, &size);
|
ptr = thread_to_reg(DbgThread, reg_name, &size);
|
||||||
|
@ -257,6 +249,30 @@ gdb_send_register(
|
||||||
{
|
{
|
||||||
send_gdb_memory(ptr, size);
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -296,15 +296,15 @@ KDSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
KdpReceiveByte(_Out_ PUCHAR OutByte)
|
KdpReceiveByte(_Out_ PUCHAR OutByte)
|
||||||
{
|
{
|
||||||
|
USHORT CpStatus = CpGetByte(&KdComPort, OutByte, TRUE, FALSE);
|
||||||
/* Get the byte */
|
/* Get the byte */
|
||||||
if (CpGetByte(&KdComPort, OutByte, TRUE, FALSE) == CP_GET_SUCCESS)
|
if (CpStatus == CP_GET_SUCCESS)
|
||||||
{
|
{
|
||||||
return KdPacketReceived;
|
return KdPacketReceived;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
KDDBGPRINT("CpGetByte returned %u.\n", CpStatus);
|
||||||
return KdPacketTimedOut;
|
return KdPacketTimedOut;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
KDSTATUS
|
KDSTATUS
|
||||||
|
@ -319,6 +319,7 @@ KdpPollBreakIn(VOID)
|
||||||
{
|
{
|
||||||
if (Byte == 0x03)
|
if (Byte == 0x03)
|
||||||
{
|
{
|
||||||
|
KDDBGPRINT("BreakIn Polled.\n");
|
||||||
return KdPacketReceived;
|
return KdPacketReceived;
|
||||||
}
|
}
|
||||||
else if (Byte == '$')
|
else if (Byte == '$')
|
||||||
|
|
|
@ -21,6 +21,9 @@
|
||||||
|
|
||||||
#define KDDEBUG /* uncomment to enable debugging this dll */
|
#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
|
#ifndef KDDEBUG
|
||||||
#define KDDBGPRINT(...)
|
#define KDDBGPRINT(...)
|
||||||
#else
|
#else
|
||||||
|
@ -34,6 +37,7 @@ FORCEINLINE HANDLE gdb_tid_to_handle(UINT_PTR Tid)
|
||||||
return (HANDLE)(Tid - 1);
|
return (HANDLE)(Tid - 1);
|
||||||
}
|
}
|
||||||
#define gdb_pid_to_handle gdb_tid_to_handle
|
#define gdb_pid_to_handle gdb_tid_to_handle
|
||||||
|
|
||||||
FORCEINLINE UINT_PTR handle_to_gdb_tid(HANDLE Handle)
|
FORCEINLINE UINT_PTR handle_to_gdb_tid(HANDLE Handle)
|
||||||
{
|
{
|
||||||
return (UINT_PTR)Handle + 1;
|
return (UINT_PTR)Handle + 1;
|
||||||
|
@ -68,7 +72,6 @@ typedef KDSTATUS (*KDP_MANIPULATESTATE_HANDLER)(
|
||||||
/* gdb_input.c */
|
/* gdb_input.c */
|
||||||
extern UINT_PTR gdb_dbg_tid;
|
extern UINT_PTR gdb_dbg_tid;
|
||||||
extern UINT_PTR gdb_dbg_pid;
|
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);
|
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 */
|
/* gdb_receive.c */
|
||||||
|
@ -79,8 +82,8 @@ char hex_value(char ch);
|
||||||
/* gdb_send.c */
|
/* gdb_send.c */
|
||||||
void send_gdb_packet(_In_ CHAR* Buffer);
|
void send_gdb_packet(_In_ CHAR* Buffer);
|
||||||
void send_gdb_memory(_In_ VOID* Buffer, size_t Length);
|
void send_gdb_memory(_In_ VOID* Buffer, size_t Length);
|
||||||
void gdb_send_debug_io(_In_ PSTRING String);
|
void gdb_send_debug_io(_In_ PSTRING String, _In_ BOOLEAN WithPrefix);
|
||||||
void gdb_send_exception(void);
|
void gdb_send_exception(BOOLEAN WithThread);
|
||||||
void send_gdb_ntstatus(_In_ NTSTATUS Status);
|
void send_gdb_ntstatus(_In_ NTSTATUS Status);
|
||||||
extern const char hex_chars[];
|
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);
|
extern PETHREAD find_thread(_In_ UINT_PTR Pid, _In_ UINT_PTR Tid);
|
||||||
|
|
||||||
/* arch_sup.c */
|
/* arch_sup.c */
|
||||||
extern KDSTATUS gdb_send_register(_Out_ DBGKD_MANIPULATE_STATE64* State, _Out_ PSTRING MessageData, _Out_ PULONG MessageLength, _Inout_ PKD_CONTEXT KdContext);
|
extern void gdb_send_register(void);
|
||||||
extern KDSTATUS gdb_send_registers(_Out_ DBGKD_MANIPULATE_STATE64* State, _Out_ PSTRING MessageData, _Out_ PULONG MessageLength, _Inout_ PKD_CONTEXT KdContext);
|
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 */
|
/* Architecture specific defines. See ntoskrnl/include/internal/arch/ke.h */
|
||||||
#ifdef _M_IX86
|
#ifdef _M_IX86
|
||||||
|
|
|
@ -94,6 +94,7 @@ SetContextSendHandler(
|
||||||
|| (State->ReturnStatus != STATUS_SUCCESS))
|
|| (State->ReturnStatus != STATUS_SUCCESS))
|
||||||
{
|
{
|
||||||
/* Should we bugcheck ? */
|
/* Should we bugcheck ? */
|
||||||
|
KDDBGPRINT("BAD BAD BAD not manipulating state for sending context.\n");
|
||||||
while (1);
|
while (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,6 +117,7 @@ SetContextManipulateHandler(
|
||||||
|
|
||||||
if (MessageData->MaximumLength < sizeof(CurrentContext))
|
if (MessageData->MaximumLength < sizeof(CurrentContext))
|
||||||
{
|
{
|
||||||
|
KDDBGPRINT("Wrong message length %u.\n", MessageData->MaximumLength);
|
||||||
while (1);
|
while (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,14 +155,18 @@ send_kd_state_change(DBGKD_ANY_WAIT_STATE_CHANGE* StateChange)
|
||||||
PsGetThreadId(Thread));
|
PsGetThreadId(Thread));
|
||||||
/* Set the current debugged process/thread accordingly */
|
/* Set the current debugged process/thread accordingly */
|
||||||
gdb_dbg_tid = handle_to_gdb_tid(PsGetThreadId(Thread));
|
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_dbg_pid = handle_to_gdb_pid(PsGetThreadProcessId(Thread));
|
||||||
gdb_send_exception();
|
#endif
|
||||||
|
gdb_send_exception(FALSE);
|
||||||
/* Next receive call will ask for the context */
|
/* Next receive call will ask for the context */
|
||||||
KdpManipulateStateHandler = GetContextManipulateHandler;
|
KdpManipulateStateHandler = GetContextManipulateHandler;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
/* FIXME */
|
KDDBGPRINT("Unknown StateChange %u.\n", StateChange->NewState);
|
||||||
while (1);
|
while (1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -177,10 +183,10 @@ send_kd_debug_io(
|
||||||
switch (DebugIO->ApiNumber)
|
switch (DebugIO->ApiNumber)
|
||||||
{
|
{
|
||||||
case DbgKdPrintStringApi:
|
case DbgKdPrintStringApi:
|
||||||
gdb_send_debug_io(String);
|
gdb_send_debug_io(String, TRUE);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* FIXME */
|
KDDBGPRINT("Unknown ApiNumber %u.\n", DebugIO->ApiNumber);
|
||||||
while (1);
|
while (1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -200,7 +206,7 @@ send_kd_state_manipulate(
|
||||||
return;
|
return;
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
/* FIXME */
|
KDDBGPRINT("Unknown ApiNumber %u.\n", State->ApiNumber);
|
||||||
while (1);
|
while (1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -314,7 +320,11 @@ FirstSendHandler(
|
||||||
/* Set up the current state */
|
/* Set up the current state */
|
||||||
CurrentStateChange = *StateChange;
|
CurrentStateChange = *StateChange;
|
||||||
gdb_dbg_tid = handle_to_gdb_tid(PsGetThreadId(Thread));
|
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_dbg_pid = handle_to_gdb_pid(PsGetThreadProcessId(Thread));
|
||||||
|
#endif
|
||||||
/* This is the idle process. Save it! */
|
/* This is the idle process. Save it! */
|
||||||
TheIdleThread = Thread;
|
TheIdleThread = Thread;
|
||||||
TheIdleProcess = (PEPROCESS)Thread->Tcb.ApcState.Process;
|
TheIdleProcess = (PEPROCESS)Thread->Tcb.ApcState.Process;
|
||||||
|
@ -352,7 +362,6 @@ KdReceivePacket(
|
||||||
_Out_ PULONG DataLength,
|
_Out_ PULONG DataLength,
|
||||||
_Inout_ PKD_CONTEXT KdContext)
|
_Inout_ PKD_CONTEXT KdContext)
|
||||||
{
|
{
|
||||||
KDSTATUS Status;
|
|
||||||
DBGKD_MANIPULATE_STATE64* State;
|
DBGKD_MANIPULATE_STATE64* State;
|
||||||
|
|
||||||
/* Special handling for breakin packet */
|
/* Special handling for breakin packet */
|
||||||
|
@ -373,13 +382,8 @@ KdReceivePacket(
|
||||||
if (KdpManipulateStateHandler != NULL)
|
if (KdpManipulateStateHandler != NULL)
|
||||||
return KdpManipulateStateHandler(State, MessageData, DataLength, KdContext);
|
return KdpManipulateStateHandler(State, MessageData, DataLength, KdContext);
|
||||||
|
|
||||||
/* Receive data from GDB */
|
/* Receive data from GDB and interpret it */
|
||||||
Status = gdb_receive_packet(KdContext);
|
return gdb_receive_and_interpret_packet(State, MessageData, DataLength, KdContext);
|
||||||
if (Status != KdPacketReceived)
|
|
||||||
return Status;
|
|
||||||
|
|
||||||
/* Interpret it */
|
|
||||||
return gdb_interpret_input(State, MessageData, DataLength, KdContext);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
|
@ -409,7 +413,7 @@ KdSendPacket(
|
||||||
send_kd_state_manipulate((DBGKD_MANIPULATE_STATE64*)MessageHeader->Buffer, MessageData);
|
send_kd_state_manipulate((DBGKD_MANIPULATE_STATE64*)MessageHeader->Buffer, MessageData);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* FIXME */
|
KDDBGPRINT("Unknown packet type %u.\n", PacketType);
|
||||||
while (1);
|
while (1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ find_process(
|
||||||
PEPROCESS Process;
|
PEPROCESS Process;
|
||||||
|
|
||||||
/* Special case for idle process */
|
/* Special case for idle process */
|
||||||
if (Pid == 1)
|
if (ProcessId == NULL)
|
||||||
return TheIdleProcess;
|
return TheIdleProcess;
|
||||||
|
|
||||||
for (ProcessEntry = ProcessListHead->Flink;
|
for (ProcessEntry = ProcessListHead->Flink;
|
||||||
|
@ -46,15 +46,44 @@ find_thread(
|
||||||
PETHREAD Thread;
|
PETHREAD Thread;
|
||||||
PEPROCESS Process;
|
PEPROCESS Process;
|
||||||
LIST_ENTRY* ThreadEntry;
|
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 */
|
/* Special case for the idle thread */
|
||||||
if ((Pid == 1) && (Tid == 1))
|
if (Tid == 1)
|
||||||
return TheIdleThread;
|
return TheIdleThread;
|
||||||
|
|
||||||
|
for (ProcessEntry = ProcessListHead->Flink;
|
||||||
|
ProcessEntry != ProcessListHead;
|
||||||
|
ProcessEntry = ProcessEntry->Flink)
|
||||||
|
{
|
||||||
|
Process = CONTAINING_RECORD(ProcessEntry, EPROCESS, ActiveProcessLinks);
|
||||||
|
#else
|
||||||
|
|
||||||
Process = find_process(Pid);
|
Process = find_process(Pid);
|
||||||
|
|
||||||
|
/* Special case for the idle thread */
|
||||||
|
if ((Process == TheIdleProcess) && (Tid == 1))
|
||||||
|
return TheIdleThread;
|
||||||
|
|
||||||
if (!Process)
|
if (!Process)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
for (ThreadEntry = Process->ThreadListHead.Flink;
|
for (ThreadEntry = Process->ThreadListHead.Flink;
|
||||||
ThreadEntry != &Process->ThreadListHead;
|
ThreadEntry != &Process->ThreadListHead;
|
||||||
ThreadEntry = ThreadEntry->Flink)
|
ThreadEntry = ThreadEntry->Flink)
|
||||||
|
@ -67,5 +96,9 @@ find_thread(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if MONOPROCESS
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -113,7 +113,7 @@ KdpCopyMemoryChunks(IN ULONG64 Address,
|
||||||
/*
|
/*
|
||||||
* We may have modified executable code, flush the instruction cache
|
* 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
|
* Return the size we managed to copy
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue