ReactOS  0.4.15-dev-3453-gff89651
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  ULONG EbpContent[2];
74  ULONG MemoryCopied;
76 
77  /* Get stack frame content */
79  EbpContent,
80  sizeof(EbpContent),
81  sizeof(EbpContent),
83  &MemoryCopied);
84  if (!NT_SUCCESS(Status) || (MemoryCopied < sizeof(EbpContent)))
85  {
86  break;
87  }
88 
89  DbgPrint("%.8X %.8X%s", EbpContent[0], EbpContent[1], (i % 8) == 7 ? "\n" : " ");
90  Ebp = (PULONG)EbpContent[0];
91  i++;
92  }
93 
94  /* Print a new line if there's nothing */
95  if((i % 8) != 0) DbgPrint("\n");
96 #else
97  DbgPrint("FIXME: Backtrace skipped on non-x86\n");
98 #endif
99  }
100 
101  /* Move to the next Thread */
102  CurrentThread = CurrentThread->Flink;
103  }
104  }
105 
106  /* Move to the next Process */
108  }
109 }
110 #endif
111 
112 /* PUBLIC FUNCTIONS **********************************************************/
113 
114 /*
115  * @implemented
116  */
117 NTSTATUS
118 NTAPI
120  IN OUT PCONTEXT ThreadContext,
122 {
123  GET_SET_CTX_CONTEXT GetSetContext;
124  ULONG Size = 0, Flags = 0;
126 
127  /* Enter SEH */
128  _SEH2_TRY
129  {
130  /* Set default length */
131  Size = sizeof(CONTEXT);
132 
133  /* Read the flags */
134  Flags = ProbeForReadUlong(&ThreadContext->ContextFlags);
135 
136 #ifdef _M_IX86
137  /* Check if the caller wanted extended registers */
140  {
141  /* Cut them out of the size */
142  Size = FIELD_OFFSET(CONTEXT, ExtendedRegisters);
143  }
144 #endif
145 
146  /* Check if we came from user mode */
147  if (PreviousMode != KernelMode)
148  {
149  /* Probe the context */
150  ProbeForWrite(ThreadContext, Size, sizeof(ULONG));
151  }
152  }
154  {
155  /* Return the exception code */
157  }
158  _SEH2_END;
159 
160  /* Initialize the wait event */
162 
163  /* Set the flags and previous mode */
164  RtlZeroMemory(&GetSetContext.Context, Size);
165  GetSetContext.Context.ContextFlags = Flags;
166  GetSetContext.Mode = PreviousMode;
167 
168  /* Check if we're running in the same thread */
169  if (Thread == PsGetCurrentThread())
170  {
171  /* Setup APC parameters manually */
172  GetSetContext.Apc.SystemArgument1 = NULL;
173  GetSetContext.Apc.SystemArgument2 = Thread;
174 
175  /* Enter a guarded region to simulate APC_LEVEL */
177 
178  /* Manually call the APC */
179  PspGetOrSetContextKernelRoutine(&GetSetContext.Apc,
180  NULL,
181  NULL,
182  &GetSetContext.Apc.SystemArgument1,
183  &GetSetContext.Apc.SystemArgument2);
184 
185  /* Leave the guarded region */
187 
188  /* We are done */
190  }
191  else
192  {
193  /* Initialize the APC */
194  KeInitializeApc(&GetSetContext.Apc,
195  &Thread->Tcb,
198  NULL,
199  NULL,
200  KernelMode,
201  NULL);
202 
203  /* Queue it as a Get APC */
204  if (!KeInsertQueueApc(&GetSetContext.Apc, NULL, Thread, 2))
205  {
206  /* It was already queued, so fail */
208  }
209  else
210  {
211  /* Wait for the APC to complete */
212  Status = KeWaitForSingleObject(&GetSetContext.Event,
213  0,
214  KernelMode,
215  FALSE,
216  NULL);
217  }
218  }
219 
220  _SEH2_TRY
221  {
222  /* Copy the context */
223  RtlCopyMemory(ThreadContext, &GetSetContext.Context, Size);
224  }
226  {
227  /* Get the exception code */
229  }
230  _SEH2_END;
231 
232  /* Return status */
233  return Status;
234 }
235 
236 /*
237  * @implemented
238  */
239 NTSTATUS
240 NTAPI
242  IN OUT PCONTEXT ThreadContext,
244 {
245  GET_SET_CTX_CONTEXT GetSetContext;
246  ULONG Size = 0, Flags = 0;
248 
249  /* Enter SEH */
250  _SEH2_TRY
251  {
252  /* Set default length */
253  Size = sizeof(CONTEXT);
254 
255  /* Read the flags */
256  Flags = ProbeForReadUlong(&ThreadContext->ContextFlags);
257 
258 #ifdef _M_IX86
259  /* Check if the caller wanted extended registers */
262  {
263  /* Cut them out of the size */
264  Size = FIELD_OFFSET(CONTEXT, ExtendedRegisters);
265  }
266 #endif
267 
268  /* Check if we came from user mode */
269  if (PreviousMode != KernelMode)
270  {
271  /* Probe the context */
272  ProbeForRead(ThreadContext, Size, sizeof(ULONG));
273  }
274 
275  /* Copy the context */
276  RtlCopyMemory(&GetSetContext.Context, ThreadContext, Size);
277  }
279  {
280  /* Return the exception code */
282  }
283  _SEH2_END;
284 
285  /* Initialize the wait event */
287 
288  /* Set the flags and previous mode */
289  GetSetContext.Context.ContextFlags = Flags;
290  GetSetContext.Mode = PreviousMode;
291 
292  /* Check if we're running in the same thread */
293  if (Thread == PsGetCurrentThread())
294  {
295  /* Setup APC parameters manually */
296  GetSetContext.Apc.SystemArgument1 = UlongToPtr(1);
297  GetSetContext.Apc.SystemArgument2 = Thread;
298 
299  /* Enter a guarded region to simulate APC_LEVEL */
301 
302  /* Manually call the APC */
303  PspGetOrSetContextKernelRoutine(&GetSetContext.Apc,
304  NULL,
305  NULL,
306  &GetSetContext.Apc.SystemArgument1,
307  &GetSetContext.Apc.SystemArgument2);
308 
309  /* Leave the guarded region */
311 
312  /* We are done */
314  }
315  else
316  {
317  /* Initialize the APC */
318  KeInitializeApc(&GetSetContext.Apc,
319  &Thread->Tcb,
322  NULL,
323  NULL,
324  KernelMode,
325  NULL);
326 
327  /* Queue it as a Get APC */
328  if (!KeInsertQueueApc(&GetSetContext.Apc, UlongToPtr(1), Thread, 2))
329  {
330  /* It was already queued, so fail */
332  }
333  else
334  {
335  /* Wait for the APC to complete */
336  Status = KeWaitForSingleObject(&GetSetContext.Event,
337  0,
338  KernelMode,
339  FALSE,
340  NULL);
341  }
342  }
343 
344  /* Return status */
345  return Status;
346 }
347 
348 NTSTATUS
349 NTAPI
351  IN OUT PCONTEXT ThreadContext)
352 {
356  PAGED_CODE();
357 
358  /* Get the Thread Object */
359  Status = ObReferenceObjectByHandle(ThreadHandle,
361  PsThreadType,
362  PreviousMode,
363  (PVOID*)&Thread,
364  NULL);
365 
366  if (!NT_SUCCESS(Status)) return Status;
367 
368  /* Make sure it's not a system thread */
369  if (Thread->SystemThread)
370  {
371  /* Fail */
373  }
374  else
375  {
376  /* Call the kernel API */
377  Status = PsGetContextThread(Thread, ThreadContext, PreviousMode);
378  }
379 
380  /* Dereference it and return */
382  return Status;
383 }
384 
385 NTSTATUS
386 NTAPI
388  IN PCONTEXT ThreadContext)
389 {
393  PAGED_CODE();
394 
395  /* Get the Thread Object */
396  Status = ObReferenceObjectByHandle(ThreadHandle,
398  PsThreadType,
399  PreviousMode,
400  (PVOID*)&Thread,
401  NULL);
402 
403  if (!NT_SUCCESS(Status)) return Status;
404 
405  /* Make sure it's not a system thread */
406  if (Thread->SystemThread)
407  {
408  /* Fail */
410  }
411  else
412  {
413  /* Call the kernel API */
414  Status = PsSetContextThread(Thread, ThreadContext, PreviousMode);
415  }
416 
417  /* Dereference it and return */
419  return Status;
420 }
421 
422 /* 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
#define CONTEXT_EXTENDED_REGISTERS
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
NTSTATUS NTAPI KdpCopyMemoryChunks(_In_ ULONG64 Address, _In_ PVOID Buffer, _In_ ULONG TotalSize, _In_ ULONG ChunkSize, _In_ ULONG Flags, _Out_opt_ PULONG ActualSize)
Definition: kdapi.c:50
LONG NTSTATUS
Definition: precomp.h:26
KTHREAD Tcb
Definition: pstypes.h:1103
SCHAR Priority
Definition: ketypes.h:1714
NTSTATUS NTAPI PsSetContextThread(IN PETHREAD Thread, IN OUT PCONTEXT ThreadContext, IN KPROCESSOR_MODE PreviousMode)
Definition: debug.c:241
VOID NTAPI PspDumpThreads(BOOLEAN SystemThreads)
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:361
KPROCESSOR_MODE NTAPI ExGetPreviousMode(VOID)
Definition: sysinfo.c:3063
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
uint32_t ULONG_PTR
Definition: typedefs.h:65
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:494
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
unsigned char BOOLEAN
#define KeLeaveGuardedRegion()
Definition: ke_x.h:68
PVOID KernelStack
Definition: ketypes.h:1607
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
Status
Definition: gdiplustypes.h:24
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
_In_ KPROCESSOR_MODE PreviousMode
Definition: sefuncs.h:103
ULONG CurrentProcess
Definition: shell.c:125
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
PVOID SystemArgument1
Definition: ketypes.h:551
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
CLIENT_ID Cid
Definition: pstypes.h:1128
KPROCESSOR_MODE Mode
Definition: ps.h:80
#define ObDereferenceObject
Definition: obfuncs.h:203
volatile VOID * StackLimit
Definition: ketypes.h:1597
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2652
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
#define KeEnterGuardedRegion()
Definition: ke_x.h:39
#define ProbeForReadUlong(Ptr)
Definition: probe.h:65
HANDLE UniqueThread
Definition: compat.h:685
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
unsigned __int64 ULONG64
Definition: imports.h:198
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:412
Definition: typedefs.h:119
ULONG SystemThread
Definition: pstypes.h:1182
NTSTATUS NTAPI PsGetContextThread(IN PETHREAD Thread, IN OUT PCONTEXT ThreadContext, IN KPROCESSOR_MODE PreviousMode)
Definition: debug.c:119
_SEH2_END
Definition: create.c:4400
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
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
KEVENT Event
Definition: ps.h:79
#define MMDBG_COPY_UNSAFE
Definition: mm.h:66
NTSTATUS NTAPI NtSetContextThread(IN HANDLE ThreadHandle, IN PCONTEXT ThreadContext)
Definition: debug.c:387
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
unsigned int * PULONG
Definition: retypes.h:1
#define NULL
Definition: types.h:112
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:1721
GROUP_AFFINITY Affinity
Definition: ketypes.h:1870
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:40
#define STATUS_SUCCESS
Definition: shellext.h:65
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:165
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:168
CONTEXT Context
Definition: ps.h:81
NTSTATUS NTAPI NtGetContextThread(IN HANDLE ThreadHandle, IN OUT PCONTEXT ThreadContext)
Definition: debug.c:350
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:38