void gdb_send_registers(void) { CHAR Registers[16*8 + 1]; UCHAR* RegisterPtr; unsigned i; unsigned short size; CHAR* ptr = Registers; KDDBGPRINT("Sending registers of thread %" PRIxPTR ".\n", gdb_dbg_tid); KDDBGPRINT("Current thread_id: %p.\n", PsGetThreadId((PETHREAD)(ULONG_PTR)CurrentStateChange.Thread)); if (((gdb_dbg_pid == 0) && (gdb_dbg_tid == 0)) || gdb_tid_to_handle(gdb_dbg_tid) == PsGetThreadId((PETHREAD)(ULONG_PTR)CurrentStateChange.Thread)) { for(i=0; i < 16; i++) { RegisterPtr = ctx_to_reg(&CurrentContext, i, &size); *ptr++ = hex_chars[RegisterPtr[0] >> 4]; *ptr++ = hex_chars[RegisterPtr[0] & 0xF]; *ptr++ = hex_chars[RegisterPtr[1] >> 4]; *ptr++ = hex_chars[RegisterPtr[1] & 0xF]; *ptr++ = hex_chars[RegisterPtr[2] >> 4]; *ptr++ = hex_chars[RegisterPtr[2] & 0xF]; *ptr++ = hex_chars[RegisterPtr[3] >> 4]; *ptr++ = hex_chars[RegisterPtr[3] & 0xF]; } } else {
static void send_kd_state_change(DBGKD_ANY_WAIT_STATE_CHANGE* StateChange) { InException = TRUE; switch (StateChange->NewState) { case DbgKdLoadSymbolsStateChange: { /* We don't care about symbols loading */ KdpManipulateStateHandler = ContinueManipulateStateHandler; break; } case DbgKdExceptionStateChange: { PETHREAD Thread = (PETHREAD)(ULONG_PTR)StateChange->Thread; /* Save current state for later GDB queries */ CurrentStateChange = *StateChange; KDDBGPRINT("Exception 0x%08x in thread p%p.%p.\n", StateChange->u.Exception.ExceptionRecord.ExceptionCode, PsGetThreadProcessId(Thread), 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)); #endif gdb_send_exception(FALSE); /* Next receive call will ask for the context */ KdpManipulateStateHandler = GetContextManipulateHandler; break; } default: KDDBGPRINT("Unknown StateChange %u.\n", StateChange->NewState); while (1); } }
static VOID FirstSendHandler( _In_ ULONG PacketType, _In_ PSTRING MessageHeader, _In_ PSTRING MessageData) { DBGKD_ANY_WAIT_STATE_CHANGE* StateChange = (DBGKD_ANY_WAIT_STATE_CHANGE*)MessageHeader->Buffer; PETHREAD Thread; if (PacketType == PACKET_TYPE_KD_DEBUG_IO) { /* This is not the packet we are waiting for */ send_kd_debug_io((DBGKD_DEBUG_IO*)MessageHeader->Buffer, MessageData); return; } if (PacketType != PACKET_TYPE_KD_STATE_CHANGE64) { KDDBGPRINT("First KD packet is not a state change!\n"); /* FIXME: What should we send back to KD ? */ while(1); } KDDBGPRINT("KDGDB: START!\n"); Thread = (PETHREAD)(ULONG_PTR)StateChange->Thread; /* 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; KDDBGPRINT("Pid Tid of the first message: %" PRIxPTR", %" PRIxPTR ".\n", gdb_dbg_pid, gdb_dbg_tid); /* The next receive call will be asking for the version data */ KdpSendPacketHandler = NULL; KdpManipulateStateHandler = GetVersionManipulateStateHandler; }
/* * Test the Thread to verify and validate it. Hard to the core tests are required. */ PTHREADINFO FASTCALL IntTID2PTI(HANDLE id) { NTSTATUS Status; PETHREAD Thread; PTHREADINFO pti; Status = PsLookupThreadByThreadId(id, &Thread); if (!NT_SUCCESS(Status)) { return NULL; } if (PsIsThreadTerminating(Thread)) { ObDereferenceObject(Thread); return NULL; } pti = PsGetThreadWin32Thread(Thread); if (!pti) { ObDereferenceObject(Thread); return NULL; } // Validate and verify! _SEH2_TRY { if (pti->TIF_flags & TIF_INCLEANUP) pti = NULL; if (pti && !(pti->TIF_flags & TIF_GUITHREADINITIALIZED)) pti = NULL; if (PsGetThreadId(Thread) != id) pti = NULL; } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { pti = NULL; } _SEH2_END ObDereferenceObject(Thread); return pti; }
/* * UserGetKeyboardLayout * * Returns hkl of given thread keyboard layout */ HKL FASTCALL UserGetKeyboardLayout( DWORD dwThreadId) { PTHREADINFO pti; PLIST_ENTRY ListEntry; PKL pKl; pti = PsGetCurrentThreadWin32Thread(); if (!dwThreadId) { pKl = pti->KeyboardLayout; return pKl ? pKl->hkl : NULL; } ListEntry = pti->rpdesk->PtiList.Flink; // // Search the Desktop Thread list for related Desktop active Threads. // while(ListEntry != &pti->rpdesk->PtiList) { pti = CONTAINING_RECORD(ListEntry, THREADINFO, PtiLink); if (PsGetThreadId(pti->pEThread) == UlongToHandle(dwThreadId)) { pKl = pti->KeyboardLayout; return pKl ? pKl->hkl : NULL; } ListEntry = ListEntry->Flink; } return NULL; }
/* q* packets */ static void handle_gdb_query(void) { if (strncmp(gdb_input, "qSupported:", 11) == 0) { #if MONOPROCESS send_gdb_packet("PacketSize=1000;"); #else send_gdb_packet("PacketSize=1000;multiprocess+;"); #endif return; } if (strncmp(gdb_input, "qAttached", 9) == 0) { #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; } 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; } if ((strncmp(gdb_input, "qfThreadInfo", 12) == 0) || (strncmp(gdb_input, "qsThreadInfo", 12) == 0)) { BOOLEAN FirstThread = TRUE; PEPROCESS Process; PETHREAD Thread; char gdb_out[1024]; char* ptr = gdb_out; BOOLEAN Resuming = strncmp(gdb_input, "qsThreadInfo", 12) == 0; /* Keep track of where we are. */ static LIST_ENTRY* CurrentProcessEntry; static LIST_ENTRY* CurrentThreadEntry; ptr = gdb_out; *ptr++ = 'm'; /* NULL terminate in case we got nothing more to iterate */ *ptr = '\0'; if (!Resuming) { /* Initialize the entries */ CurrentProcessEntry = ProcessListHead->Flink; CurrentThreadEntry = NULL; /* 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; } 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; } 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; }