ReactOS  0.4.14-dev-77-gd9e7c48
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 ength */
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  GetSetContext.Context.ContextFlags = Flags;
150  GetSetContext.Mode = PreviousMode;
151 
152  /* Check if we're running in the same thread */
153  if (Thread == PsGetCurrentThread())
154  {
155  /* Setup APC parameters manually */
156  GetSetContext.Apc.SystemArgument1 = NULL;
157  GetSetContext.Apc.SystemArgument2 = Thread;
158 
159  /* Enter a guarded region to simulate APC_LEVEL */
161 
162  /* Manually call the APC */
163  PspGetOrSetContextKernelRoutine(&GetSetContext.Apc,
164  NULL,
165  NULL,
166  &GetSetContext.Apc.SystemArgument1,
167  &GetSetContext.Apc.SystemArgument2);
168 
169  /* Leave the guarded region */
171 
172  /* We are done */
174  }
175  else
176  {
177  /* Initialize the APC */
178  KeInitializeApc(&GetSetContext.Apc,
179  &Thread->Tcb,
182  NULL,
183  NULL,
184  KernelMode,
185  NULL);
186 
187  /* Queue it as a Get APC */
188  if (!KeInsertQueueApc(&GetSetContext.Apc, NULL, Thread, 2))
189  {
190  /* It was already queued, so fail */
192  }
193  else
194  {
195  /* Wait for the APC to complete */
196  Status = KeWaitForSingleObject(&GetSetContext.Event,
197  0,
198  KernelMode,
199  FALSE,
200  NULL);
201  }
202  }
203 
204  _SEH2_TRY
205  {
206  /* Copy the context */
207  RtlCopyMemory(ThreadContext, &GetSetContext.Context, Size);
208  }
210  {
211  /* Get the exception code */
213  }
214  _SEH2_END;
215 
216  /* Return status */
217  return Status;
218 }
219 
220 /*
221  * @implemented
222  */
223 NTSTATUS
224 NTAPI
226  IN OUT PCONTEXT ThreadContext,
228 {
229  GET_SET_CTX_CONTEXT GetSetContext;
230  ULONG Size = 0, Flags = 0;
232 
233  /* Enter SEH */
234  _SEH2_TRY
235  {
236  /* Set default length */
237  Size = sizeof(CONTEXT);
238 
239  /* Read the flags */
240  Flags = ProbeForReadUlong(&ThreadContext->ContextFlags);
241 
242 #ifdef _M_IX86
243  /* Check if the caller wanted extended registers */
246  {
247  /* Cut them out of the size */
248  Size = FIELD_OFFSET(CONTEXT, ExtendedRegisters);
249  }
250 #endif
251 
252  /* Check if we came from user mode */
253  if (PreviousMode != KernelMode)
254  {
255  /* Probe the context */
256  ProbeForRead(ThreadContext, Size, sizeof(ULONG));
257  }
258 
259  /* Copy the context */
260  RtlCopyMemory(&GetSetContext.Context, ThreadContext, Size);
261  }
263  {
264  /* Return the exception code */
266  }
267  _SEH2_END;
268 
269  /* Initialize the wait event */
271 
272  /* Set the flags and previous mode */
273  GetSetContext.Context.ContextFlags = Flags;
274  GetSetContext.Mode = PreviousMode;
275 
276  /* Check if we're running in the same thread */
277  if (Thread == PsGetCurrentThread())
278  {
279  /* Setup APC parameters manually */
280  GetSetContext.Apc.SystemArgument1 = UlongToPtr(1);
281  GetSetContext.Apc.SystemArgument2 = Thread;
282 
283  /* Enter a guarded region to simulate APC_LEVEL */
285 
286  /* Manually call the APC */
287  PspGetOrSetContextKernelRoutine(&GetSetContext.Apc,
288  NULL,
289  NULL,
290  &GetSetContext.Apc.SystemArgument1,
291  &GetSetContext.Apc.SystemArgument2);
292 
293  /* Leave the guarded region */
295 
296  /* We are done */
298  }
299  else
300  {
301  /* Initialize the APC */
302  KeInitializeApc(&GetSetContext.Apc,
303  &Thread->Tcb,
306  NULL,
307  NULL,
308  KernelMode,
309  NULL);
310 
311  /* Queue it as a Get APC */
312  if (!KeInsertQueueApc(&GetSetContext.Apc, UlongToPtr(1), Thread, 2))
313  {
314  /* It was already queued, so fail */
316  }
317  else
318  {
319  /* Wait for the APC to complete */
320  Status = KeWaitForSingleObject(&GetSetContext.Event,
321  0,
322  KernelMode,
323  FALSE,
324  NULL);
325  }
326  }
327 
328  /* Return status */
329  return Status;
330 }
331 
332 NTSTATUS
333 NTAPI
335  IN OUT PCONTEXT ThreadContext)
336 {
340  PAGED_CODE();
341 
342  /* Get the Thread Object */
343  Status = ObReferenceObjectByHandle(ThreadHandle,
345  PsThreadType,
346  PreviousMode,
347  (PVOID*)&Thread,
348  NULL);
349 
350  if (!NT_SUCCESS(Status)) return Status;
351 
352  /* Make sure it's not a system thread */
353  if (Thread->SystemThread)
354  {
355  /* Fail */
357  }
358  else
359  {
360  /* Call the kernel API */
361  Status = PsGetContextThread(Thread, ThreadContext, PreviousMode);
362  }
363 
364  /* Dereference it and return */
366  return Status;
367 }
368 
369 NTSTATUS
370 NTAPI
372  IN PCONTEXT ThreadContext)
373 {
377  PAGED_CODE();
378 
379  /* Get the Thread Object */
380  Status = ObReferenceObjectByHandle(ThreadHandle,
382  PsThreadType,
383  PreviousMode,
384  (PVOID*)&Thread,
385  NULL);
386 
387  if (!NT_SUCCESS(Status)) return Status;
388 
389  /* Make sure it's not a system thread */
390  if (Thread->SystemThread)
391  {
392  /* Fail */
394  }
395  else
396  {
397  /* Call the kernel API */
398  Status = PsSetContextThread(Thread, ThreadContext, PreviousMode);
399  }
400 
401  /* Dereference it and return */
403  return Status;
404 }
405 
406 /* EOF */
ULONG DbgPrint(PCCH Format,...)
Definition: debug.c:416
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:38
struct _CONTEXT CONTEXT
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:1034
SCHAR Priority
Definition: ketypes.h:1672
NTSTATUS NTAPI PsSetContextThread(IN PETHREAD Thread, IN OUT PCONTEXT ThreadContext, IN KPROCESSOR_MODE PreviousMode)
Definition: debug.c:225
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:474
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
VOID NTAPI ProbeForWrite(IN PVOID Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:143
#define STATUS_INVALID_HANDLE
Definition: ntstatus.h:231
#define PAGED_CODE()
Definition: video.h:57
_SEH2_TRY
Definition: create.c:4250
_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
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: compat.h:331
#define THREAD_SET_CONTEXT
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
_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:1059
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:475
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
POBJECT_TYPE PsThreadType
Definition: thread.c:20
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:117
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:359
ULONG SystemThread
Definition: pstypes.h:1113
NTSTATUS NTAPI PsGetContextThread(IN PETHREAD Thread, IN OUT PCONTEXT ThreadContext, IN KPROCESSOR_MODE PreviousMode)
Definition: debug.c:104
Status
Definition: gdiplustypes.h:24
_SEH2_END
Definition: create.c:4424
#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:371
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:254
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:39
volatile UCHAR State
Definition: ketypes.h:1679
GROUP_AFFINITY Affinity
Definition: ketypes.h:1828
unsigned int ULONG
Definition: retypes.h:1
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:12
return STATUS_SUCCESS
Definition: btrfs.c:2966
CONTEXT Context
Definition: ps.h:81
NTSTATUS NTAPI NtGetContextThread(IN HANDLE ThreadHandle, IN OUT PCONTEXT ThreadContext)
Definition: debug.c:334
PVOID SystemArgument2
Definition: ketypes.h:552
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