Author: hbelusca
Date: Sat Aug 29 13:53:55 2015
New Revision: 68855
URL: http://svn.reactos.org/svn/reactos?rev=68855&view=rev
Log:
[i8042prt]
Improve debugging experience when pressing Tab+k, at least with WinDBG, by breaking with a suitable control code (adopt the SysRq one even if we don't use SysRq key for breaking, but instead, Tab+k).
Modified:
trunk/reactos/drivers/input/i8042prt/keyboard.c
Modified: trunk/reactos/drivers/input/i8042prt/keyboard.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/input/i8042prt/key…
==============================================================================
--- trunk/reactos/drivers/input/i8042prt/keyboard.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/input/i8042prt/keyboard.c [iso-8859-1] Sat Aug 29 13:53:55 2015
@@ -855,7 +855,7 @@
if (InputData->MakeCode == 0x25)
{
/* k - Breakpoint */
- DbgBreakPoint();
+ DbgBreakPointWithStatus(DBG_STATUS_SYSRQ);
}
else if (InputData->MakeCode == 0x30)
{
Author: hbelusca
Date: Sat Aug 29 12:53:08 2015
New Revision: 68854
URL: http://svn.reactos.org/svn/reactos?rev=68854&view=rev
Log:
[NTOS]
Addendum to r68851:
- Reset the state of the worker thread *after* having captured the data, not before.
- Fix the explanations given in comments.
Modified:
trunk/reactos/ntoskrnl/ex/dbgctrl.c
trunk/reactos/ntoskrnl/ex/work.c
trunk/reactos/ntoskrnl/include/internal/ex.h
Modified: trunk/reactos/ntoskrnl/ex/dbgctrl.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ex/dbgctrl.c?rev=…
==============================================================================
--- trunk/reactos/ntoskrnl/ex/dbgctrl.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/ex/dbgctrl.c [iso-8859-1] Sat Aug 29 12:53:08 2015
@@ -16,7 +16,7 @@
// #ifdef _WINKD_
/*
- * WinDBG Debugger Worker Thread data
+ * WinDBG Debugger Worker State Machine data
*/
WORK_QUEUE_ITEM ExpDebuggerWorkItem;
/*
@@ -33,19 +33,22 @@
// #ifdef _WINKD_
/*
- * WinDBG Debugger Worker Thread
- *
- * A worker thread is queued whenever WinDBG wants to attach or kill a user-mode
+ * WinDBG Debugger Worker State Machine
+ *
+ * This functionality is used whenever WinDBG wants to attach or kill a user-mode
* process from within live kernel-mode session, and/or page-in an address region.
+ * It is implemented as a state machine: when it is in "Ready" state, WinDBG can
+ * initialize the data for the state machine, then switch its state to "Start".
+ * The worker thread balance manager detects this, switches the state to "Initialized"
+ * and queues a worker thread. As long as the state is not "Ready" again, WinDBG
+ * prevents from requeuing a new thread. When the thread is started, it captures
+ * all the data, then resets the machine state to "Ready", thus allowing WinDBG
+ * to requeue another worker thread.
*
* WinDBG commands:
* .process /i <addr> (where <addr> is the address of the EPROCESS block for this process)
* .kill <addr> ( " " " " )
* .pagein <addr> (where <addr> is the address to page in)
- *
- * The implementation is very naive because the same data is reused, so that if
- * the worker thread has not started before WinDBG sends fresh new data again,
- * then only the latest data is taken into account.
*/
VOID
NTAPI
@@ -59,22 +62,25 @@
UNREFERENCED_PARAMETER(Context);
/* Be sure we were started in an initialized state */
- ASSERTMSG("ExpDebuggerWorker being entered with state != 2\n",
+ ASSERTMSG("ExpDebuggerWorker being entered in non-initialized state!\n",
ExpDebuggerWork == WinKdWorkerInitialized);
- if (ExpDebuggerWork != WinKdWorkerInitialized) return;
-
- /* Reset the worker flag to the disabled state */
- ExpDebuggerWork = WinKdWorkerDisabled;
+ if (ExpDebuggerWork != WinKdWorkerInitialized)
+ {
+ /* An error happened, so get a chance to restart proper */
+ ExpDebuggerWork = WinKdWorkerReady;
+ return;
+ }
/* Get the processes to be attached or killed, and the address to page in */
ProcessToAttach = ExpDebuggerProcessAttach;
ProcessToKill = ExpDebuggerProcessKill;
PageInAddress = ExpDebuggerPageIn;
- /* Reset to their default values */
+ /* Reset the state machine to its ready state */
ExpDebuggerProcessAttach = NULL;
ExpDebuggerProcessKill = NULL;
ExpDebuggerPageIn = (ULONG_PTR)NULL;
+ ExpDebuggerWork = WinKdWorkerReady;
/* Default to the current process if we don't find the process to be attached or killed */
Process = NULL;
Modified: trunk/reactos/ntoskrnl/ex/work.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ex/work.c?rev=688…
==============================================================================
--- trunk/reactos/ntoskrnl/ex/work.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/ex/work.c [iso-8859-1] Sat Aug 29 12:53:08 2015
@@ -491,7 +491,7 @@
* If WinDBG wants to attach or kill a user-mode process, and/or
* page-in an address region, queue a debugger worker thread.
*/
- if (ExpDebuggerWork == WinKdWorkerActivate)
+ if (ExpDebuggerWork == WinKdWorkerStart)
{
ExInitializeWorkItem(&ExpDebuggerWorkItem, ExpDebuggerWorker, NULL);
ExpDebuggerWork = WinKdWorkerInitialized;
Modified: trunk/reactos/ntoskrnl/include/internal/ex.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/…
==============================================================================
--- trunk/reactos/ntoskrnl/include/internal/ex.h [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/include/internal/ex.h [iso-8859-1] Sat Aug 29 12:53:08 2015
@@ -44,12 +44,12 @@
// #ifdef _WINKD_
/*
- * WinDBG Debugger Worker Thread data (see dbgctrl.c)
+ * WinDBG Debugger Worker State Machine data (see dbgctrl.c)
*/
typedef enum _WINKD_WORKER_STATE
{
- WinKdWorkerDisabled = 0,
- WinKdWorkerActivate,
+ WinKdWorkerReady = 0,
+ WinKdWorkerStart,
WinKdWorkerInitialized
} WINKD_WORKER_STATE;
Author: hbelusca
Date: Sat Aug 29 02:03:56 2015
New Revision: 68851
URL: http://svn.reactos.org/svn/reactos?rev=68851&view=rev
Log:
[NTOS]
Implement the WinDBG Debugger Worker Thread, which is created inside a target process whenever one uses the ".process /i <addr>" (invasive debugging) command using WinDBG in kernel-mode debugging.
See https://www.microsoftpressstore.com/articles/article.aspx?p=2201303&seqNum=2 section "Switching the Current Process Context" (from the book "Inside Windows Debugging" by Tarik Soulami, pp.101-102) for more details.
The names of the variables must be kept as they are, because WinDBG (more exactly, dbgeng.dll) searches for them within the kernel symbols and retrieves their addresses (since those variables are not publicly exported).
Modified:
trunk/reactos/ntoskrnl/ex/dbgctrl.c
trunk/reactos/ntoskrnl/ex/work.c
trunk/reactos/ntoskrnl/include/internal/dbgk.h
trunk/reactos/ntoskrnl/include/internal/ex.h
Modified: trunk/reactos/ntoskrnl/ex/dbgctrl.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ex/dbgctrl.c?rev=…
==============================================================================
--- trunk/reactos/ntoskrnl/ex/dbgctrl.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/ex/dbgctrl.c [iso-8859-1] Sat Aug 29 02:03:56 2015
@@ -12,7 +12,131 @@
#define NDEBUG
#include <debug.h>
+/* DATA **********************************************************************/
+
+// #ifdef _WINKD_
+/*
+ * WinDBG Debugger Worker Thread data
+ */
+WORK_QUEUE_ITEM ExpDebuggerWorkItem;
+/*
+ * The following global variables must be visible through all the kernel
+ * because WinDBG explicitely search for them inside our symbols.
+ */
+WINKD_WORKER_STATE ExpDebuggerWork;
+PEPROCESS ExpDebuggerProcessAttach;
+PEPROCESS ExpDebuggerProcessKill;
+ULONG_PTR ExpDebuggerPageIn;
+// #endif /* _WINKD_ */
+
/* FUNCTIONS *****************************************************************/
+
+// #ifdef _WINKD_
+/*
+ * WinDBG Debugger Worker Thread
+ *
+ * A worker thread is queued whenever WinDBG wants to attach or kill a user-mode
+ * process from within live kernel-mode session, and/or page-in an address region.
+ *
+ * WinDBG commands:
+ * .process /i <addr> (where <addr> is the address of the EPROCESS block for this process)
+ * .kill <addr> ( " " " " )
+ * .pagein <addr> (where <addr> is the address to page in)
+ *
+ * The implementation is very naive because the same data is reused, so that if
+ * the worker thread has not started before WinDBG sends fresh new data again,
+ * then only the latest data is taken into account.
+ */
+VOID
+NTAPI
+ExpDebuggerWorker(IN PVOID Context)
+{
+ PEPROCESS ProcessToAttach, ProcessToKill;
+ ULONG_PTR PageInAddress;
+ PEPROCESS Process;
+ KAPC_STATE ApcState;
+
+ UNREFERENCED_PARAMETER(Context);
+
+ /* Be sure we were started in an initialized state */
+ ASSERTMSG("ExpDebuggerWorker being entered with state != 2\n",
+ ExpDebuggerWork == WinKdWorkerInitialized);
+ if (ExpDebuggerWork != WinKdWorkerInitialized) return;
+
+ /* Reset the worker flag to the disabled state */
+ ExpDebuggerWork = WinKdWorkerDisabled;
+
+ /* Get the processes to be attached or killed, and the address to page in */
+ ProcessToAttach = ExpDebuggerProcessAttach;
+ ProcessToKill = ExpDebuggerProcessKill;
+ PageInAddress = ExpDebuggerPageIn;
+
+ /* Reset to their default values */
+ ExpDebuggerProcessAttach = NULL;
+ ExpDebuggerProcessKill = NULL;
+ ExpDebuggerPageIn = (ULONG_PTR)NULL;
+
+ /* Default to the current process if we don't find the process to be attached or killed */
+ Process = NULL;
+
+ /* Check if we need to attach or kill some process */
+ if (ProcessToAttach != NULL || ProcessToKill != NULL)
+ {
+ /* Find the process in the list */
+ Process = PsGetNextProcess(Process);
+ while (Process)
+ {
+ /* Is this the process we want to attach to? */
+ if (Process == ProcessToAttach)
+ {
+ /* Yes, attach ourselves to it */
+ KeStackAttachProcess(&Process->Pcb, &ApcState);
+ break;
+ }
+ /* Or is this the process we want to kill? */
+ else if (Process == ProcessToKill)
+ {
+ /* Yes, kill and dereference it, then return */
+ PsTerminateProcess(Process, DBG_TERMINATE_PROCESS);
+ ObDereferenceObject(Process);
+ return;
+ }
+
+ /* Get the next process */
+ Process = PsGetNextProcess(Process);
+ }
+
+ /* We either have found a process, or we default to the current process */
+ }
+
+ /* If we have an address to page in... */
+ if (PageInAddress)
+ {
+ /* ... try to do it by attempting to read at this address */
+ _SEH2_TRY
+ {
+ ProbeForReadUchar(PageInAddress);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ DPRINT1("Failed to page in address 0x%p, Status 0x%08lx\n", PageInAddress, _SEH2_GetExceptionCode());
+ }
+ _SEH2_END;
+ }
+
+ /* Break into the process (or the current one if Process == NULL) */
+ DbgBreakPointWithStatus(DBG_STATUS_WORKER);
+
+ /* If we are attached to a process, not the current one... */
+ if (Process)
+ {
+ /* ... we can detach from the process */
+ KeUnstackDetachProcess(&ApcState);
+ /* Dereference the process which was referenced for us by PsGetNextProcess */
+ ObDereferenceObject(Process);
+ }
+}
+// #endif /* _WINKD_ */
/*++
* @name NtSystemDebugControl
Modified: trunk/reactos/ntoskrnl/ex/work.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ex/work.c?rev=688…
==============================================================================
--- trunk/reactos/ntoskrnl/ex/work.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/ex/work.c [iso-8859-1] Sat Aug 29 02:03:56 2015
@@ -485,6 +485,19 @@
ObDereferenceObject(ExpLastWorkerThread);
PsTerminateSystemThread(STATUS_SYSTEM_SHUTDOWN);
}
+
+// #ifdef _WINKD_
+ /*
+ * If WinDBG wants to attach or kill a user-mode process, and/or
+ * page-in an address region, queue a debugger worker thread.
+ */
+ if (ExpDebuggerWork == WinKdWorkerActivate)
+ {
+ ExInitializeWorkItem(&ExpDebuggerWorkItem, ExpDebuggerWorker, NULL);
+ ExpDebuggerWork = WinKdWorkerInitialized;
+ ExQueueWorkItem(&ExpDebuggerWorkItem, DelayedWorkQueue);
+ }
+// #endif /* _WINKD_ */
}
}
@@ -744,4 +757,3 @@
}
/* EOF */
-
Modified: trunk/reactos/ntoskrnl/include/internal/dbgk.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/…
==============================================================================
--- trunk/reactos/ntoskrnl/include/internal/dbgk.h [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/include/internal/dbgk.h [iso-8859-1] Sat Aug 29 02:03:56 2015
@@ -141,7 +141,7 @@
IN KPROCESSOR_MODE PreviousMode,
OUT HANDLE *DebugHandle
);
-
+
extern ULONG DbgkpTraceLevel;
extern POBJECT_TYPE DbgkDebugObjectType;
Modified: trunk/reactos/ntoskrnl/include/internal/ex.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/…
==============================================================================
--- trunk/reactos/ntoskrnl/include/internal/ex.h [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/include/internal/ex.h [iso-8859-1] Sat Aug 29 02:03:56 2015
@@ -42,6 +42,25 @@
extern UNICODE_STRING CmCSDVersionString;
extern CHAR NtBuildLab[];
+// #ifdef _WINKD_
+/*
+ * WinDBG Debugger Worker Thread data (see dbgctrl.c)
+ */
+typedef enum _WINKD_WORKER_STATE
+{
+ WinKdWorkerDisabled = 0,
+ WinKdWorkerActivate,
+ WinKdWorkerInitialized
+} WINKD_WORKER_STATE;
+
+extern WORK_QUEUE_ITEM ExpDebuggerWorkItem;
+extern WINKD_WORKER_STATE ExpDebuggerWork;
+extern PEPROCESS ExpDebuggerProcessAttach;
+extern PEPROCESS ExpDebuggerProcessKill;
+extern ULONG_PTR ExpDebuggerPageIn;
+VOID NTAPI ExpDebuggerWorker(IN PVOID Context);
+// #endif /* _WINKD_ */
+
#ifdef _WIN64
#define HANDLE_LOW_BITS (PAGE_SHIFT - 4)
#define HANDLE_HIGH_BITS (PAGE_SHIFT - 3)