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