ReactOS  0.4.15-dev-1201-gb2cf5a4
debug.c
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS Kernel
3  * LICENSE: GPL - See COPYING in the top level directory
4  * FILE: ntoskrnl/ps/debug.c
5  * PURPOSE: Process Manager: Debugging Support (Set/Get Context)
6  * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7  * Thomas Weidenmueller (w3seek@reactos.org)
8  */
9 
10 /* INCLUDES ****************************************************************/
11 
12 #include <ntoskrnl.h>
13 #define NDEBUG
14 #include <debug.h>
15 
16 /* PRIVATE FUNCTIONS *********************************************************/
17 
18 #if DBG
19 VOID
20 NTAPI
21 PspDumpThreads(BOOLEAN IncludeSystem)
22 {
23  PLIST_ENTRY CurrentThread, CurrentProcess;
26  ULONG nThreads = 0;
27 
28  /* Loop all Active Processes */
31  {
32  /* Get the process */
33  Process = CONTAINING_RECORD(CurrentProcess, EPROCESS, ActiveProcessLinks);
34 
35  /* Skip the Initial Process if requested */
37  (Process == PsInitialSystemProcess && IncludeSystem))
38  {
39  /* Loop all its threads */
40  CurrentThread = Process->ThreadListHead.Flink;
41  while(CurrentThread != &Process->ThreadListHead)
42  {
43 
44  /* Get teh Thread */
45  Thread = CONTAINING_RECORD(CurrentThread, ETHREAD, ThreadListEntry);
46  nThreads++;
47 
48  /* Print the Info */
49  DbgPrint("State %u Affinity %08x Priority %d PID.TID %d.%d Name %.8s Stack: \n",
50  Thread->Tcb.State,
55  Thread->ThreadsProcess->ImageFileName);
56 
57  /* Make sure it's not running */
58  if(Thread->Tcb.State == Ready ||
59  Thread->Tcb.State == Standby ||
60  Thread->Tcb.State == Waiting)
61  {
62 #ifdef _M_IX86
63  ULONG i = 0;
65  PULONG Ebp = (PULONG)Esp[4];
66 
67  /* Print EBP */
68  DbgPrint("Ebp %p\n", Ebp);
69 
70  /* Walk it */
71  while(Ebp != 0 && Ebp >= (PULONG)Thread->Tcb.StackLimit)
72  {
73  /* Print what's on the stack */
74  DbgPrint("%.8X %.8X%s", Ebp[0], Ebp[1], (i % 8) == 7 ? "\n" : " ");
75  Ebp = (PULONG)Ebp[0];
76  i++;
77  }
78 
79  /* Print a new line if there's nothing */
80  if((i % 8) != 0) DbgPrint("\n");
81 #else
82  DbgPrint("FIXME: Backtrace skipped on non-x86\n");
83 #endif
84  }
85 
86  /* Move to the next Thread */
87  CurrentThread = CurrentThread->Flink;
88  }
89  }
90 
91  /* Move to the next Process */
93  }
94 }
95 #endif
96 
97 /* PUBLIC FUNCTIONS **********************************************************/
98 
99 /*
100  * @implemented
101  */
102 NTSTATUS
103 NTAPI
105  IN OUT PCONTEXT ThreadContext,
107 {
108  GET_SET_CTX_CONTEXT GetSetContext;
109  ULONG Size = 0, Flags = 0;
111 
112  /* Enter SEH */
113  _SEH2_TRY
114  {
115  /* Set default length */
116  Size = sizeof(CONTEXT);
117 
118  /* Read the flags */
119  Flags = ProbeForReadUlong(&ThreadContext->ContextFlags);
120 
121 #ifdef _M_IX86
122  /* Check if the caller wanted extended registers */
125  {
126  /* Cut them out of the size */
127  Size = FIELD_OFFSET(CONTEXT, ExtendedRegisters);
128  }
129 #endif
130 
131  /* Check if we came from user mode */
132  if (PreviousMode != KernelMode)
133  {
134  /* Probe the context */
135  ProbeForWrite(ThreadContext, Size, sizeof(ULONG));
136  }
137  }
139  {
140  /* Return the exception code */
142  }
143  _SEH2_END;
144 
145  /* Initialize the wait event */
147 
148  /* Set the flags and previous mode */
149  RtlZeroMemory(&GetSetContext.Context, Size);
150  GetSetContext.Context.ContextFlags = Flags;
151  GetSetContext.Mode = PreviousMode;
152 
153  /* Check if we're running in the same thread */
154  if (Thread == PsGetCurrentThread())
155  {
156  /* Setup APC parameters manually */
157  GetSetContext.Apc.SystemArgument1 = NULL;
158  GetSetContext.Apc.SystemArgument2 = Thread;
159 
160  /* Enter a guarded region to simulate APC_LEVEL */
162 
163  /* Manually call the APC */
164  PspGetOrSetContextKernelRoutine(&GetSetContext.Apc,
165  NULL,
166  NULL,
167  &GetSetContext.Apc.SystemArgument1,
168  &GetSetContext.Apc.SystemArgument2);
169 
170  /* Leave the guarded region */
172 
173  /* We are done */
175  }
176  else
177  {
178  /* Initialize the APC */
179  KeInitializeApc(&GetSetContext.Apc,
180  &Thread->Tcb,
183  NULL,
184  NULL,
185  KernelMode,
186  NULL);
187 
188  /* Queue it as a Get APC */
189  if (!KeInsertQueueApc(&GetSetContext.Apc, NULL, Thread, 2))
190  {
191  /* It was already queued, so fail */
193  }
194  else
195  {
196  /* Wait for the APC to complete */
197  Status = KeWaitForSingleObject(&GetSetContext.Event,
198  0,
199  KernelMode,
200  FALSE,
201  NULL);
202  }
203  }
204 
205  _SEH2_TRY
206  {
207  /* Copy the context */
208  RtlCopyMemory(ThreadContext, &GetSetContext.Context, Size);
209  }
211  {
212  /* Get the exception code */
214  }
215  _SEH2_END;
216 
217  /* Return status */
218  return Status;
219 }
220 
221 /*
222  * @implemented
223  */
224 NTSTATUS
225 NTAPI
227  IN OUT PCONTEXT ThreadContext,
229 {
230  GET_SET_CTX_CONTEXT GetSetContext;
231  ULONG Size = 0, Flags = 0;
233 
234  /* Enter SEH */
235  _SEH2_TRY
236  {
237  /* Set default length */
238  Size = sizeof(CONTEXT);
239 
240  /* Read the flags */
241  Flags = ProbeForReadUlong(&ThreadContext->ContextFlags);
242 
243 #ifdef _M_IX86
244  /* Check if the caller wanted extended registers */
247  {
248  /* Cut them out of the size */
249  Size = FIELD_OFFSET(CONTEXT, ExtendedRegisters);
250  }
251 #endif
252 
253  /* Check if we came from user mode */
254  if (PreviousMode != KernelMode)
255  {
256  /* Probe the context */
257  ProbeForRead(ThreadContext, Size, sizeof(ULONG));
258  }
259 
260  /* Copy the context */
261  RtlCopyMemory(&GetSetContext.Context, ThreadContext, Size);
262  }
264  {
265  /* Return the exception code */
267  }
268  _SEH2_END;
269 
270  /* Initialize the wait event */
272 
273  /* Set the flags and previous mode */
274  GetSetContext.Context.ContextFlags = Flags;
275  GetSetContext.Mode = PreviousMode;
276 
277  /* Check if we're running in the same thread */
278  if (Thread == PsGetCurrentThread())
279  {
280  /* Setup APC parameters manually */
281  GetSetContext.Apc.SystemArgument1 = UlongToPtr(1);
282  GetSetContext.Apc.SystemArgument2 = Thread;
283 
284  /* Enter a guarded region to simulate APC_LEVEL */
286 
287  /* Manually call the APC */
288  PspGetOrSetContextKernelRoutine(&GetSetContext.Apc,
289  NULL,
290  NULL,
291  &GetSetContext.Apc.SystemArgument1,
292  &GetSetContext.Apc.SystemArgument2);
293 
294  /* Leave the guarded region */
296 
297  /* We are done */
299  }
300  else
301  {
302  /* Initialize the APC */
303  KeInitializeApc(&GetSetContext.Apc,
304  &Thread->Tcb,
307  NULL,
308  NULL,
309  KernelMode,
310  NULL);
311 
312  /* Queue it as a Get APC */
313  if (!KeInsertQueueApc(&GetSetContext.Apc, UlongToPtr(1), Thread, 2))
314  {
315  /* It was already queued, so fail */
317  }
318  else
319  {
320  /* Wait for the APC to complete */
321  Status = KeWaitForSingleObject(&GetSetContext.Event,
322  0,
323  KernelMode,
324  FALSE,
325  NULL);
326  }
327  }
328 
329  /* Return status */
330  return Status;
331 }
332 
333 NTSTATUS
334 NTAPI
336  IN OUT PCONTEXT ThreadContext)
337 {
341  PAGED_CODE();
342 
343  /* Get the Thread Object */
344  Status = ObReferenceObjectByHandle(ThreadHandle,
346  PsThreadType,
347  PreviousMode,
348  (PVOID*)&Thread,
349  NULL);
350 
351  if (!NT_SUCCESS(Status)) return Status;
352 
353  /* Make sure it's not a system thread */
354  if (Thread->SystemThread)
355  {
356  /* Fail */
358  }
359  else
360  {
361  /* Call the kernel API */
362  Status = PsGetContextThread(Thread, ThreadContext, PreviousMode);
363  }
364 
365  /* Dereference it and return */
367  return Status;
368 }
369 
370 NTSTATUS
371 NTAPI
373  IN PCONTEXT ThreadContext)
374 {
378  PAGED_CODE();
379 
380  /* Get the Thread Object */
381  Status = ObReferenceObjectByHandle(ThreadHandle,
383  PsThreadType,
384  PreviousMode,
385  (PVOID*)&Thread,
386  NULL);
387 
388  if (!NT_SUCCESS(Status)) return Status;
389 
390  /* Make sure it's not a system thread */
391  if (Thread->SystemThread)
392  {
393  /* Fail */
395  }
396  else
397  {
398  /* Call the kernel API */
399  Status = PsSetContextThread(Thread, ThreadContext, PreviousMode);
400  }
401 
402  /* Dereference it and return */
404  return Status;
405 }
406 
407 /* EOF */
ULONG DbgPrint(PCCH Format,...)
Definition: debug.c:427
VOID NTAPI KeInitializeApc(IN PKAPC Apc, IN PKTHREAD Thread, IN KAPC_ENVIRONMENT TargetEnvironment, IN PKKERNEL_ROUTINE KernelRoutine, IN PKRUNDOWN_ROUTINE RundownRoutine OPTIONAL, IN PKNORMAL_ROUTINE NormalRoutine, IN KPROCESSOR_MODE Mode, IN PVOID Context)
Definition: apc.c:651
#define IN
Definition: typedefs.h:39
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define CONTEXT_EXTENDED_REGISTERS
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
LONG NTSTATUS
Definition: precomp.h:26
KTHREAD Tcb
Definition: pstypes.h:1045
SCHAR Priority
Definition: ketypes.h:1672
NTSTATUS NTAPI PsSetContextThread(IN PETHREAD Thread, IN OUT PCONTEXT ThreadContext, IN KPROCESSOR_MODE PreviousMode)
Definition: debug.c:226
VOID NTAPI PspDumpThreads(BOOLEAN SystemThreads)
KPROCESSOR_MODE NTAPI ExGetPreviousMode(VOID)
Definition: sysinfo.c:3066
VOID NTAPI ObDereferenceObject(IN PVOID Object)
Definition: obref.c:375
LIST_ENTRY PsActiveProcessHead
Definition: process.c:22
HANDLE UniqueProcess
Definition: compat.h:684
NTSTATUS NTAPI KeWaitForSingleObject(IN PVOID Object, IN KWAIT_REASON WaitReason, IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL)
Definition: wait.c:416
struct _CONTEXT CONTEXT
VOID NTAPI ProbeForWrite(IN PVOID Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:143
#define STATUS_INVALID_HANDLE
Definition: ntstatus.h:245
_SEH2_TRY
Definition: create.c:4226
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
NTSTATUS NTAPI ObReferenceObjectByHandle(IN HANDLE Handle, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, OUT PVOID *Object, OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL)
Definition: obref.c:496
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define FALSE
Definition: types.h:117
PEPROCESS PsInitialSystemProcess
Definition: psmgr.c:50
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
#define KeLeaveGuardedRegion()
Definition: ke_x.h:63
PVOID KernelStack
Definition: ketypes.h:1565
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
#define UlongToPtr(u)
Definition: config.h:106
ULONG ContextFlags
Definition: nt_native.h:1426
#define THREAD_SET_CONTEXT
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
_In_ KPROCESSOR_MODE PreviousMode
Definition: sefuncs.h:103
ULONG CurrentProcess
Definition: shell.c:125
#define _SEH2_YIELD(STMT_)
Definition: pseh2_64.h:8
PVOID SystemArgument1
Definition: ketypes.h:551
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
CLIENT_ID Cid
Definition: pstypes.h:1070
KPROCESSOR_MODE Mode
Definition: ps.h:80
volatile VOID * StackLimit
Definition: ketypes.h:1555
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
#define KeEnterGuardedRegion()
Definition: ke_x.h:34
#define ProbeForReadUlong(Ptr)
Definition: probe.h:65
HANDLE UniqueThread
Definition: compat.h:685
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
POBJECT_TYPE PsThreadType
Definition: thread.c:20
Status
Definition: gdiplustypes.h:24
VOID NTAPI ProbeForRead(IN CONST VOID *Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:102
Definition: ketypes.h:370
Definition: typedefs.h:119
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:361
ULONG SystemThread
Definition: pstypes.h:1124
NTSTATUS NTAPI PsGetContextThread(IN PETHREAD Thread, IN OUT PCONTEXT ThreadContext, IN KPROCESSOR_MODE PreviousMode)
Definition: debug.c:104
_SEH2_END
Definition: create.c:4400
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
KEVENT Event
Definition: ps.h:79
NTSTATUS NTAPI NtSetContextThread(IN HANDLE ThreadHandle, IN PCONTEXT ThreadContext)
Definition: debug.c:372
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
unsigned int * PULONG
Definition: retypes.h:1
BOOLEAN NTAPI KeInsertQueueApc(IN PKAPC Apc, IN PVOID SystemArgument1, IN PVOID SystemArgument2, IN KPRIORITY PriorityBoost)
Definition: apc.c:735
#define THREAD_GET_CONTEXT
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219
#define OUT
Definition: typedefs.h:40
volatile UCHAR State
Definition: ketypes.h:1679
GROUP_AFFINITY Affinity
Definition: ketypes.h:1828
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:12
return STATUS_SUCCESS
Definition: btrfs.c:3014
CONTEXT Context
Definition: ps.h:81
NTSTATUS NTAPI NtGetContextThread(IN HANDLE ThreadHandle, IN OUT PCONTEXT ThreadContext)
Definition: debug.c:335
PVOID SystemArgument2
Definition: ketypes.h:552
#define PAGED_CODE()
VOID NTAPI PspGetOrSetContextKernelRoutine(IN PKAPC Apc, IN OUT PKNORMAL_ROUTINE *NormalRoutine, IN OUT PVOID *NormalContext, IN OUT PVOID *SystemArgument1, IN OUT PVOID *SystemArgument2)
Definition: psctx.c:45