1 /* 2 * PROJECT: ReactOS KDBG Kernel Debugger 3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) 4 * PURPOSE: Kernel Debugger Initialization 5 * COPYRIGHT: Copyright 2020-2021 Hervé Poussineau <hpoussin@reactos.org> 6 * Copyright 2021 Jérôme Gardou <jerome.gardou@reactos.org> 7 * Copyright 2023 Hermès Bélusca-Maïto <hermes.belusca-maito@reactos.org> 8 */ 9 10 /* INCLUDES ******************************************************************/ 11 12 #include <ntoskrnl.h> 13 #include "kdb.h" 14 15 /* GLOBALS *******************************************************************/ 16 17 static ULONG KdbgNextApiNumber = DbgKdContinueApi; 18 static CONTEXT KdbgContext; 19 static EXCEPTION_RECORD64 KdbgExceptionRecord; 20 static BOOLEAN KdbgFirstChanceException; 21 static NTSTATUS KdbgContinueStatus = STATUS_SUCCESS; 22 23 /* FUNCTIONS *****************************************************************/ 24 25 NTSTATUS 26 NTAPI 27 KdD0Transition(VOID) 28 #undef KdD0Transition 29 #define pKdD0Transition KdD0Transition 30 { 31 /* Call KdTerm */ 32 return pKdD0Transition(); 33 } 34 35 NTSTATUS 36 NTAPI 37 KdD3Transition(VOID) 38 #undef KdD3Transition 39 #define pKdD3Transition KdD3Transition 40 { 41 /* Call KdTerm */ 42 return pKdD3Transition(); 43 } 44 45 NTSTATUS 46 NTAPI 47 KdSave( 48 _In_ BOOLEAN SleepTransition) 49 #undef KdSave 50 #define pKdSave KdSave 51 { 52 /* Call KdTerm */ 53 return pKdSave(SleepTransition); 54 } 55 56 NTSTATUS 57 NTAPI 58 KdRestore( 59 _In_ BOOLEAN SleepTransition) 60 #undef KdRestore 61 #define pKdRestore KdRestore 62 { 63 /* Call KdTerm */ 64 return pKdRestore(SleepTransition); 65 } 66 67 VOID 68 NTAPI 69 KdSendPacket( 70 _In_ ULONG PacketType, 71 _In_ PSTRING MessageHeader, 72 _In_opt_ PSTRING MessageData, 73 _Inout_ PKD_CONTEXT Context) 74 #undef KdSendPacket 75 #define pKdSendPacket KdSendPacket 76 { 77 if (PacketType == PACKET_TYPE_KD_DEBUG_IO) 78 { 79 /* Call KdTerm */ 80 pKdSendPacket(PacketType, MessageHeader, MessageData, Context); 81 return; 82 } 83 84 /* Debugger-only packets */ 85 if (PacketType == PACKET_TYPE_KD_STATE_CHANGE64) 86 { 87 PDBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange = (PDBGKD_ANY_WAIT_STATE_CHANGE)MessageHeader->Buffer; 88 if (WaitStateChange->NewState == DbgKdLoadSymbolsStateChange) 89 { 90 /* Load or unload symbols */ 91 PLDR_DATA_TABLE_ENTRY LdrEntry; 92 if (KdbpSymFindModule((PVOID)(ULONG_PTR)WaitStateChange->u.LoadSymbols.BaseOfDll, -1, &LdrEntry)) 93 { 94 KdbSymProcessSymbols(LdrEntry, !WaitStateChange->u.LoadSymbols.UnloadSymbols); 95 } 96 return; 97 } 98 else if (WaitStateChange->NewState == DbgKdExceptionStateChange) 99 { 100 KdbgNextApiNumber = DbgKdGetContextApi; 101 KdbgExceptionRecord = WaitStateChange->u.Exception.ExceptionRecord; 102 KdbgFirstChanceException = WaitStateChange->u.Exception.FirstChance; 103 return; 104 } 105 } 106 else if (PacketType == PACKET_TYPE_KD_STATE_MANIPULATE) 107 { 108 PDBGKD_MANIPULATE_STATE64 ManipulateState = (PDBGKD_MANIPULATE_STATE64)MessageHeader->Buffer; 109 if (ManipulateState->ApiNumber == DbgKdGetContextApi) 110 { 111 KD_CONTINUE_TYPE Result; 112 113 /* Check if this is an assertion failure */ 114 if (KdbgExceptionRecord.ExceptionCode == STATUS_ASSERTION_FAILURE) 115 { 116 /* Bump EIP to the instruction following the int 2C */ 117 KeSetContextPc(&KdbgContext, KeGetContextPc(&KdbgContext) + 2); 118 } 119 120 Result = KdbEnterDebuggerException(&KdbgExceptionRecord, 121 KdbgContext.SegCs & 1, 122 &KdbgContext, 123 KdbgFirstChanceException); 124 #if 0 125 /* Manually dump the stack for the user */ 126 KeRosDumpStackFrames(NULL, 0); 127 Result = kdHandleException; 128 #endif 129 if (Result != kdHandleException) 130 KdbgContinueStatus = STATUS_SUCCESS; 131 else 132 KdbgContinueStatus = STATUS_UNSUCCESSFUL; 133 KdbgNextApiNumber = DbgKdSetContextApi; 134 return; 135 } 136 else if (ManipulateState->ApiNumber == DbgKdSetContextApi) 137 { 138 KdbgNextApiNumber = DbgKdContinueApi; 139 return; 140 } 141 } 142 143 KdbPrintf("%s: PacketType %d is UNIMPLEMENTED\n", __FUNCTION__, PacketType); 144 return; 145 } 146 147 KDSTATUS 148 NTAPI 149 KdReceivePacket( 150 _In_ ULONG PacketType, 151 _Out_ PSTRING MessageHeader, 152 _Out_ PSTRING MessageData, 153 _Out_ PULONG DataLength, 154 _Inout_ PKD_CONTEXT Context) 155 #undef KdReceivePacket 156 #define pKdReceivePacket KdReceivePacket 157 { 158 if (PacketType == PACKET_TYPE_KD_POLL_BREAKIN) 159 { 160 // FIXME TODO: Implement break-in for the debugger 161 // and return KdPacketReceived when handled properly. 162 return KdPacketTimedOut; 163 } 164 165 if (PacketType == PACKET_TYPE_KD_DEBUG_IO) 166 { 167 /* Call KdTerm */ 168 return pKdReceivePacket(PacketType, 169 MessageHeader, 170 MessageData, 171 DataLength, 172 Context); 173 } 174 175 /* Debugger-only packets */ 176 if (PacketType == PACKET_TYPE_KD_STATE_MANIPULATE) 177 { 178 PDBGKD_MANIPULATE_STATE64 ManipulateState = (PDBGKD_MANIPULATE_STATE64)MessageHeader->Buffer; 179 RtlZeroMemory(MessageHeader->Buffer, MessageHeader->MaximumLength); 180 if (KdbgNextApiNumber == DbgKdGetContextApi) 181 { 182 ManipulateState->ApiNumber = DbgKdGetContextApi; 183 MessageData->Length = 0; 184 MessageData->Buffer = (PCHAR)&KdbgContext; 185 return KdPacketReceived; 186 } 187 else if (KdbgNextApiNumber == DbgKdSetContextApi) 188 { 189 ManipulateState->ApiNumber = DbgKdSetContextApi; 190 MessageData->Length = sizeof(KdbgContext); 191 MessageData->Buffer = (PCHAR)&KdbgContext; 192 return KdPacketReceived; 193 } 194 else if (KdbgNextApiNumber != DbgKdContinueApi) 195 { 196 KdbPrintf("%s:%d is UNIMPLEMENTED\n", __FUNCTION__, __LINE__); 197 } 198 ManipulateState->ApiNumber = DbgKdContinueApi; 199 ManipulateState->u.Continue.ContinueStatus = KdbgContinueStatus; 200 201 /* Prepare for next time */ 202 KdbgNextApiNumber = DbgKdContinueApi; 203 KdbgContinueStatus = STATUS_SUCCESS; 204 205 return KdPacketReceived; 206 } 207 208 KdbPrintf("%s: PacketType %d is UNIMPLEMENTED\n", __FUNCTION__, PacketType); 209 return KdPacketTimedOut; 210 } 211 212 /* EOF */ 213