diff --git a/ntoskrnl/kdbg/kdb.c b/ntoskrnl/kdbg/kdb.c index d8dbeea978a52..50f65538f951f 100644 --- a/ntoskrnl/kdbg/kdb.c +++ b/ntoskrnl/kdbg/kdb.c @@ -1141,20 +1141,29 @@ KdbpAttachToProcess( return KdbpAttachToThread(Thread->Cid.UniqueThread); } -/*!\brief Calls the main loop ... - */ +/** + * @brief Calls the main interactive debugger loop. + **/ static VOID KdbpCallMainLoop(VOID) { KdbpCliMainLoop(KdbEnteredOnSingleStep); } -/*!\brief Internal function to enter KDB. +/** + * @brief + * Internal function to enter KDBG and run the specified procedure. * * Disables interrupts, releases display ownership, ... - */ + * + * @param[in] Function + * The procedure to execute under the KDBG environment. + * Either execute the the main interactive debugger loop (KdbpCallMainLoop) + * or run the KDBinit file (KdbpCliInterpretInitFile). + **/ static VOID -KdbpInternalEnter(VOID) +KdbpInternalEnter( + _In_ VOID (*Function)(VOID)) { PETHREAD Thread; PVOID SavedInitialStack, SavedStackBase, SavedKernelStack; @@ -1178,7 +1187,7 @@ KdbpInternalEnter(VOID) // KdbPrintf("Switching to KDB stack 0x%08x-0x%08x (Current Stack is 0x%08x)\n", Thread->Tcb.StackLimit, Thread->Tcb.StackBase, Esp); - KdbpStackSwitchAndCall(KdbStack + KDB_STACK_SIZE - KDB_STACK_RESERVE, KdbpCallMainLoop); + KdbpStackSwitchAndCall(KdbStack + KDB_STACK_SIZE - KDB_STACK_RESERVE, Function); Thread->Tcb.InitialStack = SavedInitialStack; Thread->Tcb.StackBase = SavedStackBase; @@ -1275,6 +1284,7 @@ KdbEnterDebuggerException( ULONG OldEflags; KIRQL OldIrql; NTSTATUS ExceptionCode; + VOID (*EnterFunction)(VOID) = KdbpCallMainLoop; ExceptionCode = (ExceptionRecord ? ExceptionRecord->ExceptionCode : STATUS_BREAKPOINT); @@ -1333,7 +1343,6 @@ KdbEnterDebuggerException( { Resume = TRUE; /* Set the resume flag when continuing execution */ } - /* * When a temporary breakpoint is hit we have to make sure that we are * in the same context in which it was set, otherwise it could happen @@ -1360,7 +1369,6 @@ KdbEnterDebuggerException( KdbEnteredOnSingleStep = TRUE; } - /* * If we hit a breakpoint set by the debugger we set the single step flag, * ignore the next single step and reenable the breakpoint. @@ -1482,16 +1490,16 @@ KdbEnterDebuggerException( } else if (ExceptionCode == STATUS_BREAKPOINT) { + /* Do the condition check and banner display only if we are entering + * because of a true code breakpoint. Running the KDBinit file is also + * done via a breakpoint, but it is artificial, so we skip the check + * and the banner in this case. */ if (KdbInitFileBuffer) { - // FIXME? Should we do that call at the same place - // where we currently call KdbpInternalEnter? - // InterlockedIncrement(&KdbEntryCount); - KdbpCliInterpretInitFile(); - // InterlockedDecrement(&KdbEntryCount); - EnterConditionMet = FALSE; - goto continue_execution; /* return */ + EnterFunction = KdbpCliInterpretInitFile; + goto EnterKdbg; } + if (!EnterConditionMet) { return kdHandleException; @@ -1499,6 +1507,7 @@ KdbEnterDebuggerException( KdbPrintf("\nEntered debugger on embedded INT3 at 0x%04x:0x%p.\n", Context->SegCs & 0xffff, KeGetContextPc(Context)); +EnterKdbg:; } else { @@ -1549,8 +1558,8 @@ KdbEnterDebuggerException( return kdHandleException; } - /* Call the main loop */ - KdbpInternalEnter(); + /* Enter KDBG proper and either run the KDBinit file or call the main loop */ + KdbpInternalEnter(EnterFunction); /* Check if we should single step */ if (KdbNumSingleSteps > 0) diff --git a/ntoskrnl/kdbg/kdb.h b/ntoskrnl/kdbg/kdb.h index df2945a7d9c64..b76c4706bc57e 100644 --- a/ntoskrnl/kdbg/kdb.h +++ b/ntoskrnl/kdbg/kdb.h @@ -61,7 +61,7 @@ typedef enum _KD_CONTINUE_TYPE /* GLOBALS *******************************************************************/ -extern PCHAR KdbInitFileBuffer; +extern volatile PCHAR KdbInitFileBuffer; extern PEPROCESS KdbCurrentProcess; extern PETHREAD KdbCurrentThread; diff --git a/ntoskrnl/kdbg/kdb_cli.c b/ntoskrnl/kdbg/kdb_cli.c index 7752526eb8f63..898e9bbb053db 100644 --- a/ntoskrnl/kdbg/kdb_cli.c +++ b/ntoskrnl/kdbg/kdb_cli.c @@ -134,7 +134,7 @@ static ULONG KdbNumberOfColsPrinted = 0; static BOOLEAN KdbOutputAborted = FALSE; static BOOLEAN KdbRepeatLastCommand = FALSE; -PCHAR KdbInitFileBuffer = NULL; /* Buffer where KDBinit file is loaded into during initialization */ +volatile PCHAR KdbInitFileBuffer = NULL; /* Buffer where KDBinit file is loaded into during initialization */ BOOLEAN KdbpBugCheckRequested = FALSE; /* Variables for Dmesg */ @@ -3339,7 +3339,7 @@ KdbpCliMainLoop( /** * @brief - * Interprets the KDBinit file from the SystemRoot\System32\drivers\etc + * Interprets the KDBinit file from the \SystemRoot\System32\drivers\etc * directory, that has been loaded by KdbpCliInit(). * * This function is used to interpret the init file in the debugger context @@ -3352,21 +3352,19 @@ VOID KdbpCliInterpretInitFile(VOID) { PCHAR p1, p2; - INT_PTR i; - CHAR c; - if (!KdbInitFileBuffer) + p1 = InterlockedExchangePointer((PVOID*)&KdbInitFileBuffer, NULL); + if (!p1) return; /* Execute the commands in the init file */ - KdpDprintf("KDB: Executing KDBinit file...\n"); - p1 = KdbInitFileBuffer; + KdbPuts("KDB: Executing KDBinit file...\n"); while (p1[0] != '\0') { - i = strcspn(p1, "\r\n"); + INT_PTR i = strcspn(p1, "\r\n"); if (i > 0) { - c = p1[i]; + CHAR c = p1[i]; p1[i] = '\0'; /* Look for "break" command and comments */ @@ -3378,8 +3376,8 @@ KdbpCliInterpretInitFile(VOID) if (strncmp(p2, "break", sizeof("break")-1) == 0 && (p2[sizeof("break")-1] == '\0' || isspace(p2[sizeof("break")-1]))) { - /* Break into the debugger */ - KdbpCliMainLoop(FALSE); // KdbpInternalEnter(); + /* Run the debugger loop (we have already broken into the debugger) */ + KdbpCliMainLoop(FALSE); } else if (p2[0] != '#' && p2[0] != '\0') /* Ignore empty lines and comments */ { @@ -3393,15 +3391,14 @@ KdbpCliInterpretInitFile(VOID) while (p1[0] == '\r' || p1[0] == '\n') p1++; } - KdpDprintf("KDB: KDBinit executed\n"); - KdbInitFileBuffer = NULL; + KdbPuts("KDB: KDBinit executed\n"); } /** * @brief Called when KDB is initialized. * - * Reads the KDBinit file from the SystemRoot\System32\drivers\etc directory - * and executes it, by calling back into the debugger. + * Loads the KDBinit file from the \SystemRoot\System32\drivers\etc + * directory and interprets it, by calling back into the debugger. **/ NTSTATUS KdbpCliInit(VOID) @@ -3412,7 +3409,7 @@ KdbpCliInit(VOID) IO_STATUS_BLOCK Iosb; FILE_STANDARD_INFORMATION FileStdInfo; HANDLE hFile = NULL; - INT FileSize; + ULONG FileSize; PCHAR FileBuffer; /* Don't load the KDBinit file if its buffer is already lying around */ @@ -3434,7 +3431,7 @@ KdbpCliInit(VOID) FILE_NO_INTERMEDIATE_BUFFERING); if (!NT_SUCCESS(Status)) { - DPRINT1("Could not open \\SystemRoot\\System32\\drivers\\etc\\KDBinit (Status 0x%lx)\n", Status); + DPRINT("Could not open \\SystemRoot\\System32\\drivers\\etc\\KDBinit (Status 0x%lx)\n", Status); return Status; } @@ -3451,16 +3448,17 @@ KdbpCliInit(VOID) FileSize = FileStdInfo.EndOfFile.u.LowPart; /* Allocate memory for the file */ - FileBuffer = ExAllocatePool(PagedPool, FileSize + 1); /* add 1 byte for terminating '\0' */ + FileBuffer = ExAllocatePool(NonPagedPool, FileSize + 1); /* Add 1 byte for terminating NUL */ if (!FileBuffer) { ZwClose(hFile); - DPRINT1("Could not allocate %d bytes for KDBinit file\n", FileSize); + DPRINT1("Could not allocate %lu bytes for KDBinit file\n", FileSize); return Status; } /* Load file into memory */ - Status = ZwReadFile(hFile, NULL, NULL, NULL, &Iosb, FileBuffer, FileSize, NULL, NULL); + Status = ZwReadFile(hFile, NULL, NULL, NULL, &Iosb, + FileBuffer, FileSize, NULL, NULL); ZwClose(hFile); if (!NT_SUCCESS(Status) && (Status != STATUS_END_OF_FILE)) @@ -3473,10 +3471,10 @@ KdbpCliInit(VOID) FileSize = min(FileSize, (INT)Iosb.Information); FileBuffer[FileSize] = '\0'; - /* Interpret the init file by calling back into the debugger */ - KdbInitFileBuffer = FileBuffer; + /* Interpret the KDBinit file by calling back into the debugger */ + InterlockedExchangePointer((PVOID*)&KdbInitFileBuffer, FileBuffer); DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C); - KdbInitFileBuffer = NULL; + InterlockedExchangePointer((PVOID*)&KdbInitFileBuffer, NULL); ExFreePool(FileBuffer); @@ -3618,7 +3616,7 @@ KdbInitialize( if (BootPhase >= 2) { - /* I/O is now set up for disk access: Read KDB Data */ + /* I/O is now set up for disk access: load the KDBinit file */ NTSTATUS Status = KdbpCliInit(); /* Schedule an I/O reinitialization if needed */