2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/ex/dbgctrl.c
5 * PURPOSE: System debug control
6 * PROGRAMMERS: Alex Ionescu
9 /* INCLUDES *****************************************************************/
15 /* DATA **********************************************************************/
19 * WinDBG Debugger Worker State Machine data
21 WORK_QUEUE_ITEM ExpDebuggerWorkItem
;
23 * The following global variables must be visible through all the kernel
24 * because WinDBG explicitely search for them inside our symbols.
26 WINKD_WORKER_STATE ExpDebuggerWork
;
27 PEPROCESS ExpDebuggerProcessAttach
;
28 PEPROCESS ExpDebuggerProcessKill
;
29 ULONG_PTR ExpDebuggerPageIn
;
30 // #endif /* _WINKD_ */
32 /* FUNCTIONS *****************************************************************/
36 * WinDBG Debugger Worker State Machine
38 * This functionality is used whenever WinDBG wants to attach or kill a user-mode
39 * process from within live kernel-mode session, and/or page-in an address region.
40 * It is implemented as a state machine: when it is in "Ready" state, WinDBG can
41 * initialize the data for the state machine, then switch its state to "Start".
42 * The worker thread balance manager detects this, switches the state to "Initialized"
43 * and queues a worker thread. As long as the state is not "Ready" again, WinDBG
44 * prevents from requeuing a new thread. When the thread is started, it captures
45 * all the data, then resets the machine state to "Ready", thus allowing WinDBG
46 * to requeue another worker thread.
49 * .process /i <addr> (where <addr> is the address of the EPROCESS block for this process)
50 * .kill <addr> ( " " " " )
51 * .pagein <addr> (where <addr> is the address to page in)
55 ExpDebuggerWorker(IN PVOID Context
)
57 PEPROCESS ProcessToAttach
, ProcessToKill
;
58 ULONG_PTR PageInAddress
;
62 UNREFERENCED_PARAMETER(Context
);
64 /* Be sure we were started in an initialized state */
65 ASSERTMSG("ExpDebuggerWorker being entered in non-initialized state!\n",
66 ExpDebuggerWork
== WinKdWorkerInitialized
);
67 if (ExpDebuggerWork
!= WinKdWorkerInitialized
)
69 /* An error happened, so get a chance to restart proper */
70 ExpDebuggerWork
= WinKdWorkerReady
;
74 /* Get the processes to be attached or killed, and the address to page in */
75 ProcessToAttach
= ExpDebuggerProcessAttach
;
76 ProcessToKill
= ExpDebuggerProcessKill
;
77 PageInAddress
= ExpDebuggerPageIn
;
79 /* Reset the state machine to its ready state */
80 ExpDebuggerProcessAttach
= NULL
;
81 ExpDebuggerProcessKill
= NULL
;
82 ExpDebuggerPageIn
= (ULONG_PTR
)NULL
;
83 ExpDebuggerWork
= WinKdWorkerReady
;
85 /* Default to the current process if we don't find the process to be attached or killed */
88 /* Check if we need to attach or kill some process */
89 if (ProcessToAttach
!= NULL
|| ProcessToKill
!= NULL
)
91 /* Find the process in the list */
92 Process
= PsGetNextProcess(Process
);
95 /* Is this the process we want to attach to? */
96 if (Process
== ProcessToAttach
)
98 /* Yes, attach ourselves to it */
99 KeStackAttachProcess(&Process
->Pcb
, &ApcState
);
102 /* Or is this the process we want to kill? */
103 else if (Process
== ProcessToKill
)
105 /* Yes, kill and dereference it, then return */
106 PsTerminateProcess(Process
, DBG_TERMINATE_PROCESS
);
107 ObDereferenceObject(Process
);
111 /* Get the next process */
112 Process
= PsGetNextProcess(Process
);
115 /* We either have found a process, or we default to the current process */
118 /* If we have an address to page in... */
121 /* ... try to do it by attempting to read at this address */
124 ProbeForReadUchar(PageInAddress
);
126 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
128 DPRINT1("Failed to page in address 0x%p, Status 0x%08lx\n", PageInAddress
, _SEH2_GetExceptionCode());
133 /* Break into the process (or the current one if Process == NULL) */
134 DbgBreakPointWithStatus(DBG_STATUS_WORKER
);
136 /* If we are attached to a process, not the current one... */
139 /* ... we can detach from the process */
140 KeUnstackDetachProcess(&ApcState
);
141 /* Dereference the process which was referenced for us by PsGetNextProcess */
142 ObDereferenceObject(Process
);
145 // #endif /* _WINKD_ */
148 * @name NtSystemDebugControl
151 * Perform various queries to debugger.
152 * This API is subject to test-case creation to further evaluate its
153 * abilities (if needed to at all)
155 * See: http://www.osronline.com/showthread.cfm?link=93915
156 * http://void.ru/files/Ntexapi.h
157 * http://www.codeguru.com/code/legacy/system/ntexapi.zip
158 * http://www.securityfocus.com/bid/9694
161 * Description of the parameter. Wrapped to more lines on ~70th
167 * @param InputBufferLength
170 * @param OutputBuffer
173 * @param OutputBufferLength
176 * @param ReturnLength
179 * @return STATUS_SUCCESS in case of success, proper error code otherwise
186 NtSystemDebugControl(SYSDBG_COMMAND ControlCode
,
188 ULONG InputBufferLength
,
190 ULONG OutputBufferLength
,
195 case SysDbgQueryModuleInformation
:
196 case SysDbgQueryTraceInformation
:
197 case SysDbgSetTracepoint
:
198 case SysDbgSetSpecialCall
:
199 case SysDbgClearSpecialCalls
:
200 case SysDbgQuerySpecialCalls
:
201 case SysDbgQueryVersion
:
202 case SysDbgReadVirtual
:
203 case SysDbgWriteVirtual
:
204 case SysDbgReadPhysical
:
205 case SysDbgWritePhysical
:
206 case SysDbgReadControlSpace
:
207 case SysDbgWriteControlSpace
:
208 case SysDbgReadIoSpace
:
209 case SysDbgWriteIoSpace
:
212 case SysDbgReadBusData
:
213 case SysDbgWriteBusData
:
214 case SysDbgCheckLowMemory
:
215 case SysDbgGetTriageDump
:
216 return STATUS_NOT_IMPLEMENTED
;
217 case SysDbgBreakPoint
:
218 case SysDbgEnableKernelDebugger
:
219 case SysDbgDisableKernelDebugger
:
220 case SysDbgGetAutoKdEnable
:
221 case SysDbgSetAutoKdEnable
:
222 case SysDbgGetPrintBufferSize
:
223 case SysDbgSetPrintBufferSize
:
224 case SysDbgGetKdUmExceptionEnable
:
225 case SysDbgSetKdUmExceptionEnable
:
226 case SysDbgGetKdBlockEnable
:
227 case SysDbgSetKdBlockEnable
:
228 return KdSystemDebugControl(
230 InputBuffer
, InputBufferLength
,
231 OutputBuffer
, OutputBufferLength
,
232 ReturnLength
, KeGetPreviousMode());
234 return STATUS_INVALID_INFO_CLASS
;