Reactos

[NTOS:KD:KDBG] Integration into KD framework (Part 1/3)

Split KdSendPacket and KdReceivePacket into those that manipulate the
KDBG state proper (reside in kdbg/kdbg.c), and those that deal only with
debug input/output that will reside in a KDTERM "KD Terminal Driver" DLL.

Based on some previous preparatory work by Hervé Poussineau in PR #4600.
(Equivalents of commits 5162bf106 and partly e9bcf7275.)

+242 -149
-7
ntoskrnl/include/internal/kd.h
··· 30 30 31 31 /* KD GLOBALS ****************************************************************/ 32 32 33 - typedef enum _KD_CONTINUE_TYPE 34 - { 35 - kdContinue = 0, 36 - kdDoNotHandleException, 37 - kdHandleException 38 - } KD_CONTINUE_TYPE; 39 - 40 33 /* KD Internal Debug Services */ 41 34 typedef enum _KDP_DEBUG_SERVICE 42 35 {
+7 -5
ntoskrnl/include/ntoskrnl.h
··· 88 88 #define NOEXTAPI 89 89 #include <windbgkd.h> 90 90 #include <wdbgexts.h> 91 + #include <kddll.h> 91 92 #ifdef KDBG 92 - #define KdDebuggerInitialize0 KdpDebuggerInitialize0 93 - #define KdDebuggerInitialize1 KdpDebuggerInitialize1 94 - #define KdSendPacket KdpSendPacket 95 - #define KdReceivePacket KdpReceivePacket 93 + /* Define new names for these exports also present in KDBG */ 94 + #define KdSendPacket KdbgSendPacket 95 + #define KdReceivePacket KdbgReceivePacket 96 + /* And reload the definitions with these new names */ 97 + #undef _KDDLL_ 98 + #include <kddll.h> 96 99 #endif 97 - #include <kddll.h> 98 100 #ifdef __ROS_ROSSYM__ 99 101 #include <reactos/rossym.h> 100 102 #endif
+29 -122
ntoskrnl/kd/kdio.c
··· 20 20 #define NDEBUG 21 21 #include <debug.h> 22 22 23 + #undef KdSendPacket 24 + #undef KdReceivePacket 25 + 23 26 /* GLOBALS *******************************************************************/ 24 27 25 28 #define KdpBufferSize (1024 * 512) ··· 53 56 KdpKdbgInit 54 57 #endif 55 58 }; 56 - 57 - static ULONG KdbgNextApiNumber = DbgKdContinueApi; 58 - static CONTEXT KdbgContext; 59 - static EXCEPTION_RECORD64 KdbgExceptionRecord; 60 - static BOOLEAN KdbgFirstChanceException; 61 - static NTSTATUS KdbgContinueStatus = STATUS_SUCCESS; 62 59 63 60 /* LOCKING FUNCTIONS *********************************************************/ 64 61 ··· 607 604 _In_opt_ PSTRING MessageData, 608 605 _Inout_ PKD_CONTEXT Context) 609 606 { 610 - if (PacketType == PACKET_TYPE_KD_DEBUG_IO) 611 - { 612 - ULONG ApiNumber = ((PDBGKD_DEBUG_IO)MessageHeader->Buffer)->ApiNumber; 613 - 614 - /* Validate API call */ 615 - if (MessageHeader->Length != sizeof(DBGKD_DEBUG_IO)) 616 - return; 617 - if ((ApiNumber != DbgKdPrintStringApi) && 618 - (ApiNumber != DbgKdGetStringApi)) 619 - { 620 - return; 621 - } 622 - if (!MessageData) 623 - return; 607 + PDBGKD_DEBUG_IO DebugIo; 624 608 625 - /* NOTE: MessageData->Length should be equal to 626 - * DebugIo.u.PrintString.LengthOfString, or to 627 - * DebugIo.u.GetString.LengthOfPromptString */ 609 + if (PacketType != PACKET_TYPE_KD_DEBUG_IO) 610 + { 611 + KdIoPrintf("%s: PacketType %d is UNIMPLEMENTED\n", __FUNCTION__, PacketType); 612 + return; 613 + } 628 614 629 - if (!KdpDebugMode.Value) 630 - return; 615 + DebugIo = (PDBGKD_DEBUG_IO)MessageHeader->Buffer; 631 616 632 - /* Print the string proper */ 633 - KdIoPrintString(MessageData->Buffer, MessageData->Length); 617 + /* Validate API call */ 618 + if (MessageHeader->Length != sizeof(DBGKD_DEBUG_IO)) 634 619 return; 635 - } 636 - else if (PacketType == PACKET_TYPE_KD_STATE_CHANGE64) 620 + if ((DebugIo->ApiNumber != DbgKdPrintStringApi) && 621 + (DebugIo->ApiNumber != DbgKdGetStringApi)) 637 622 { 638 - PDBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange = (PDBGKD_ANY_WAIT_STATE_CHANGE)MessageHeader->Buffer; 639 - if (WaitStateChange->NewState == DbgKdLoadSymbolsStateChange) 640 - { 641 - #ifdef KDBG 642 - PLDR_DATA_TABLE_ENTRY LdrEntry; 643 - /* Load symbols. Currently implemented only for KDBG! */ 644 - if (KdbpSymFindModule((PVOID)(ULONG_PTR)WaitStateChange->u.LoadSymbols.BaseOfDll, -1, &LdrEntry)) 645 - { 646 - KdbSymProcessSymbols(LdrEntry, !WaitStateChange->u.LoadSymbols.UnloadSymbols); 647 - } 648 - #endif 649 - return; 650 - } 651 - else if (WaitStateChange->NewState == DbgKdExceptionStateChange) 652 - { 653 - KdbgNextApiNumber = DbgKdGetContextApi; 654 - KdbgExceptionRecord = WaitStateChange->u.Exception.ExceptionRecord; 655 - KdbgFirstChanceException = WaitStateChange->u.Exception.FirstChance; 656 - return; 657 - } 623 + return; 658 624 } 659 - else if (PacketType == PACKET_TYPE_KD_STATE_MANIPULATE) 660 - { 661 - PDBGKD_MANIPULATE_STATE64 ManipulateState = (PDBGKD_MANIPULATE_STATE64)MessageHeader->Buffer; 662 - if (ManipulateState->ApiNumber == DbgKdGetContextApi) 663 - { 664 - KD_CONTINUE_TYPE Result; 625 + if (!MessageData) 626 + return; 665 627 666 - #ifdef KDBG 667 - /* Check if this is an assertion failure */ 668 - if (KdbgExceptionRecord.ExceptionCode == STATUS_ASSERTION_FAILURE) 669 - { 670 - /* Bump EIP to the instruction following the int 2C */ 671 - KeSetContextPc(&KdbgContext, KeGetContextPc(&KdbgContext) + 2); 672 - } 628 + /* NOTE: MessageData->Length should be equal to 629 + * DebugIo.u.PrintString.LengthOfString, or to 630 + * DebugIo.u.GetString.LengthOfPromptString */ 673 631 674 - Result = KdbEnterDebuggerException(&KdbgExceptionRecord, 675 - KdbgContext.SegCs & 1, 676 - &KdbgContext, 677 - KdbgFirstChanceException); 678 - #else 679 - /* We'll manually dump the stack for the user... */ 680 - KeRosDumpStackFrames(NULL, 0); 681 - Result = kdHandleException; 682 - #endif 683 - if (Result != kdHandleException) 684 - KdbgContinueStatus = STATUS_SUCCESS; 685 - else 686 - KdbgContinueStatus = STATUS_UNSUCCESSFUL; 687 - KdbgNextApiNumber = DbgKdSetContextApi; 688 - return; 689 - } 690 - else if (ManipulateState->ApiNumber == DbgKdSetContextApi) 691 - { 692 - KdbgNextApiNumber = DbgKdContinueApi; 693 - return; 694 - } 695 - } 696 - UNIMPLEMENTED; 632 + if (!KdpDebugMode.Value) 633 + return; 634 + 635 + /* Print the string proper */ 636 + KdIoPrintString(MessageData->Buffer, MessageData->Length); 697 637 } 698 638 699 639 KDSTATUS ··· 705 645 _Out_ PULONG DataLength, 706 646 _Inout_ PKD_CONTEXT Context) 707 647 { 708 - #ifdef KDBG 648 + PDBGKD_DEBUG_IO DebugIo; 709 649 STRING ResponseString; 710 - PDBGKD_DEBUG_IO DebugIo; 711 650 CHAR MessageBuffer[512]; 712 - #endif 713 651 714 - if (PacketType == PACKET_TYPE_KD_STATE_MANIPULATE) 652 + if (PacketType != PACKET_TYPE_KD_DEBUG_IO) 715 653 { 716 - PDBGKD_MANIPULATE_STATE64 ManipulateState = (PDBGKD_MANIPULATE_STATE64)MessageHeader->Buffer; 717 - RtlZeroMemory(MessageHeader->Buffer, MessageHeader->MaximumLength); 718 - if (KdbgNextApiNumber == DbgKdGetContextApi) 719 - { 720 - ManipulateState->ApiNumber = DbgKdGetContextApi; 721 - MessageData->Length = 0; 722 - MessageData->Buffer = (PCHAR)&KdbgContext; 723 - return KdPacketReceived; 724 - } 725 - else if (KdbgNextApiNumber == DbgKdSetContextApi) 726 - { 727 - ManipulateState->ApiNumber = DbgKdSetContextApi; 728 - MessageData->Length = sizeof(KdbgContext); 729 - MessageData->Buffer = (PCHAR)&KdbgContext; 730 - return KdPacketReceived; 731 - } 732 - else if (KdbgNextApiNumber != DbgKdContinueApi) 733 - { 734 - UNIMPLEMENTED; 735 - } 736 - ManipulateState->ApiNumber = DbgKdContinueApi; 737 - ManipulateState->u.Continue.ContinueStatus = KdbgContinueStatus; 738 - 739 - /* Prepare for next time */ 740 - KdbgNextApiNumber = DbgKdContinueApi; 741 - KdbgContinueStatus = STATUS_SUCCESS; 742 - 743 - return KdPacketReceived; 654 + KdIoPrintf("%s: PacketType %d is UNIMPLEMENTED\n", __FUNCTION__, PacketType); 655 + return KdPacketTimedOut; 744 656 } 745 657 746 - if (PacketType != PACKET_TYPE_KD_DEBUG_IO) 747 - return KdPacketTimedOut; 748 - 749 - #ifdef KDBG 750 658 DebugIo = (PDBGKD_DEBUG_IO)MessageHeader->Buffer; 751 659 752 660 /* Validate API call */ ··· 795 703 796 704 /* Only now we can copy back the data into MessageData->Buffer */ 797 705 RtlCopyMemory(MessageData->Buffer, ResponseString.Buffer, *DataLength); 798 - #endif 799 706 800 707 return KdPacketReceived; 801 708 }
+19 -9
ntoskrnl/kdbg/kdb.h
··· 51 51 KdbEnterFromUmode 52 52 } KDB_ENTER_CONDITION; 53 53 54 + typedef enum _KD_CONTINUE_TYPE 55 + { 56 + kdContinue = 0, 57 + kdDoNotHandleException, 58 + kdHandleException 59 + } KD_CONTINUE_TYPE; 60 + 61 + 62 + /* GLOBALS *******************************************************************/ 63 + 64 + extern PCHAR KdbInitFileBuffer; 65 + 66 + extern PEPROCESS KdbCurrentProcess; 67 + extern PETHREAD KdbCurrentThread; 68 + extern LONG KdbLastBreakPointNr; 69 + extern ULONG KdbNumSingleSteps; 70 + extern BOOLEAN KdbSingleStepOver; 71 + extern PKDB_KTRAP_FRAME KdbCurrentTrapFrame; 72 + 54 73 55 74 /* FUNCTIONS *****************************************************************/ 56 75 ··· 73 92 IN VOID (*Function)(VOID)); 74 93 75 94 /* from kdb_cli.c */ 76 - 77 - extern PCHAR KdbInitFileBuffer; 78 95 79 96 NTSTATUS 80 97 NTAPI ··· 174 191 _In_ ULONG BootPhase); 175 192 176 193 /* from kdb.c */ 177 - 178 - extern PEPROCESS KdbCurrentProcess; 179 - extern PETHREAD KdbCurrentThread; 180 - extern LONG KdbLastBreakPointNr; 181 - extern ULONG KdbNumSingleSteps; 182 - extern BOOLEAN KdbSingleStepOver; 183 - extern PKDB_KTRAP_FRAME KdbCurrentTrapFrame; 184 194 185 195 LONG 186 196 KdbpGetNextBreakPointNr(
+16 -6
ntoskrnl/kdbg/kdb_print.c
··· 13 13 14 14 /* FUNCTIONS *****************************************************************/ 15 15 16 + static KD_CONTEXT KdbgKdContext; 17 + 18 + #undef KdSendPacket 19 + #define pKdSendPacket KdSendPacket 20 + 21 + #undef KdReceivePacket 22 + #define pKdReceivePacket KdReceivePacket 23 + 16 24 static VOID 17 25 KdbPrintStringWorker( 18 26 _In_ const CSTRING* Output, ··· 48 56 Data->Buffer = (PCHAR)Output->Buffer; 49 57 50 58 /* Send the packet */ 51 - KdSendPacket(PACKET_TYPE_KD_DEBUG_IO, Header, Data, &KdpContext); 59 + /* IO packet: call KdTerm */ 60 + pKdSendPacket(PACKET_TYPE_KD_DEBUG_IO, Header, Data, &KdbgKdContext); 52 61 } 53 62 54 63 VOID ··· 88 97 do 89 98 { 90 99 /* Get our reply */ 91 - Status = KdReceivePacket(PACKET_TYPE_KD_DEBUG_IO, 92 - &Header, 93 - &Data, 94 - &Length, 95 - &KdpContext); 100 + /* IO packet: call KdTerm */ 101 + Status = pKdReceivePacket(PACKET_TYPE_KD_DEBUG_IO, 102 + &Header, 103 + &Data, 104 + &Length, 105 + &KdbgKdContext); 96 106 97 107 /* Return TRUE if we need to resend */ 98 108 if (Status == KdPacketNeedsResend)
+170
ntoskrnl/kdbg/kdbg.c
··· 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 + VOID 26 + NTAPI 27 + KdSendPacket( 28 + _In_ ULONG PacketType, 29 + _In_ PSTRING MessageHeader, 30 + _In_opt_ PSTRING MessageData, 31 + _Inout_ PKD_CONTEXT Context) 32 + #undef KdSendPacket 33 + #define pKdSendPacket KdSendPacket 34 + { 35 + if (PacketType == PACKET_TYPE_KD_DEBUG_IO) 36 + { 37 + /* Call KdTerm */ 38 + pKdSendPacket(PacketType, MessageHeader, MessageData, Context); 39 + return; 40 + } 41 + 42 + /* Debugger-only packets */ 43 + if (PacketType == PACKET_TYPE_KD_STATE_CHANGE64) 44 + { 45 + PDBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange = (PDBGKD_ANY_WAIT_STATE_CHANGE)MessageHeader->Buffer; 46 + if (WaitStateChange->NewState == DbgKdLoadSymbolsStateChange) 47 + { 48 + /* Load or unload symbols */ 49 + PLDR_DATA_TABLE_ENTRY LdrEntry; 50 + if (KdbpSymFindModule((PVOID)(ULONG_PTR)WaitStateChange->u.LoadSymbols.BaseOfDll, -1, &LdrEntry)) 51 + { 52 + KdbSymProcessSymbols(LdrEntry, !WaitStateChange->u.LoadSymbols.UnloadSymbols); 53 + } 54 + return; 55 + } 56 + else if (WaitStateChange->NewState == DbgKdExceptionStateChange) 57 + { 58 + KdbgNextApiNumber = DbgKdGetContextApi; 59 + KdbgExceptionRecord = WaitStateChange->u.Exception.ExceptionRecord; 60 + KdbgFirstChanceException = WaitStateChange->u.Exception.FirstChance; 61 + return; 62 + } 63 + } 64 + else if (PacketType == PACKET_TYPE_KD_STATE_MANIPULATE) 65 + { 66 + PDBGKD_MANIPULATE_STATE64 ManipulateState = (PDBGKD_MANIPULATE_STATE64)MessageHeader->Buffer; 67 + if (ManipulateState->ApiNumber == DbgKdGetContextApi) 68 + { 69 + KD_CONTINUE_TYPE Result; 70 + 71 + /* Check if this is an assertion failure */ 72 + if (KdbgExceptionRecord.ExceptionCode == STATUS_ASSERTION_FAILURE) 73 + { 74 + /* Bump EIP to the instruction following the int 2C */ 75 + KeSetContextPc(&KdbgContext, KeGetContextPc(&KdbgContext) + 2); 76 + } 77 + 78 + Result = KdbEnterDebuggerException(&KdbgExceptionRecord, 79 + KdbgContext.SegCs & 1, 80 + &KdbgContext, 81 + KdbgFirstChanceException); 82 + #if 0 83 + /* Manually dump the stack for the user */ 84 + KeRosDumpStackFrames(NULL, 0); 85 + Result = kdHandleException; 86 + #endif 87 + if (Result != kdHandleException) 88 + KdbgContinueStatus = STATUS_SUCCESS; 89 + else 90 + KdbgContinueStatus = STATUS_UNSUCCESSFUL; 91 + KdbgNextApiNumber = DbgKdSetContextApi; 92 + return; 93 + } 94 + else if (ManipulateState->ApiNumber == DbgKdSetContextApi) 95 + { 96 + KdbgNextApiNumber = DbgKdContinueApi; 97 + return; 98 + } 99 + } 100 + 101 + KdbPrintf("%s: PacketType %d is UNIMPLEMENTED\n", __FUNCTION__, PacketType); 102 + return; 103 + } 104 + 105 + KDSTATUS 106 + NTAPI 107 + KdReceivePacket( 108 + _In_ ULONG PacketType, 109 + _Out_ PSTRING MessageHeader, 110 + _Out_ PSTRING MessageData, 111 + _Out_ PULONG DataLength, 112 + _Inout_ PKD_CONTEXT Context) 113 + #undef KdReceivePacket 114 + #define pKdReceivePacket KdReceivePacket 115 + { 116 + if (PacketType == PACKET_TYPE_KD_POLL_BREAKIN) 117 + { 118 + // FIXME TODO: Implement break-in for the debugger 119 + // and return KdPacketReceived when handled properly. 120 + return KdPacketTimedOut; 121 + } 122 + 123 + if (PacketType == PACKET_TYPE_KD_DEBUG_IO) 124 + { 125 + /* Call KdTerm */ 126 + return pKdReceivePacket(PacketType, 127 + MessageHeader, 128 + MessageData, 129 + DataLength, 130 + Context); 131 + } 132 + 133 + /* Debugger-only packets */ 134 + if (PacketType == PACKET_TYPE_KD_STATE_MANIPULATE) 135 + { 136 + PDBGKD_MANIPULATE_STATE64 ManipulateState = (PDBGKD_MANIPULATE_STATE64)MessageHeader->Buffer; 137 + RtlZeroMemory(MessageHeader->Buffer, MessageHeader->MaximumLength); 138 + if (KdbgNextApiNumber == DbgKdGetContextApi) 139 + { 140 + ManipulateState->ApiNumber = DbgKdGetContextApi; 141 + MessageData->Length = 0; 142 + MessageData->Buffer = (PCHAR)&KdbgContext; 143 + return KdPacketReceived; 144 + } 145 + else if (KdbgNextApiNumber == DbgKdSetContextApi) 146 + { 147 + ManipulateState->ApiNumber = DbgKdSetContextApi; 148 + MessageData->Length = sizeof(KdbgContext); 149 + MessageData->Buffer = (PCHAR)&KdbgContext; 150 + return KdPacketReceived; 151 + } 152 + else if (KdbgNextApiNumber != DbgKdContinueApi) 153 + { 154 + KdbPrintf("%s:%d is UNIMPLEMENTED\n", __FUNCTION__, __LINE__); 155 + } 156 + ManipulateState->ApiNumber = DbgKdContinueApi; 157 + ManipulateState->u.Continue.ContinueStatus = KdbgContinueStatus; 158 + 159 + /* Prepare for next time */ 160 + KdbgNextApiNumber = DbgKdContinueApi; 161 + KdbgContinueStatus = STATUS_SUCCESS; 162 + 163 + return KdPacketReceived; 164 + } 165 + 166 + KdbPrintf("%s: PacketType %d is UNIMPLEMENTED\n", __FUNCTION__, PacketType); 167 + return KdPacketTimedOut; 168 + } 169 + 170 + /* EOF */
+1
ntoskrnl/ntos.cmake
··· 404 404 405 405 if(KDBG) 406 406 list(APPEND SOURCE 407 + ${REACTOS_SOURCE_DIR}/ntoskrnl/kdbg/kdbg.c 407 408 ${REACTOS_SOURCE_DIR}/ntoskrnl/kdbg/kdb.c 408 409 ${REACTOS_SOURCE_DIR}/ntoskrnl/kdbg/kdb_cli.c 409 410 ${REACTOS_SOURCE_DIR}/ntoskrnl/kdbg/kdb_cmdhist.c