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&seq…
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)