ReactOS 0.4.15-dev-7953-g1f49173
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
19VOID
21PspDumpThreads(BOOLEAN IncludeSystem)
22{
23 PLIST_ENTRY CurrentThread, CurrentProcess;
26 ULONG nThreads = 0;
27
28 /* Loop all Active Processes */
29 CurrentProcess = PsActiveProcessHead.Flink;
30 while(CurrentProcess != &PsActiveProcessHead)
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",
55 Thread->ThreadsProcess->ImageFileName);
56
57 /* Make sure it's not running */
58 if(Thread->Tcb.State == Ready ||
59 Thread->Tcb.State == Standby ||
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 */
107 CurrentProcess = CurrentProcess->Flink;
108 }
109}
110#endif
111
112/* PUBLIC FUNCTIONS **********************************************************/
113
114/*
115 * @implemented
116 */
118NTAPI
120 IN OUT PCONTEXT ThreadContext,
122{
123 GET_SET_CTX_CONTEXT GetSetContext;
124 ULONG Size = 0, Flags = 0;
126
127 /* Enter SEH */
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 */
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 */
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,
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,
215 FALSE,
216 NULL);
217 }
218 }
219
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 */
240NTAPI
242 IN OUT PCONTEXT ThreadContext,
244{
245 GET_SET_CTX_CONTEXT GetSetContext;
246 ULONG Size = 0, Flags = 0;
248
249 /* Enter SEH */
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 */
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 */
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,
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,
339 FALSE,
340 NULL);
341 }
342 }
343
344 /* Return status */
345 return Status;
346}
347
349NTAPI
351 IN OUT PCONTEXT ThreadContext)
352{
356 PAGED_CODE();
357
358 /* Get the Thread Object */
359 Status = ObReferenceObjectByHandle(ThreadHandle,
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
386NTAPI
388 IN PCONTEXT ThreadContext)
389{
393 PAGED_CODE();
394
395 /* Get the Thread Object */
396 Status = ObReferenceObjectByHandle(ThreadHandle,
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 */
#define PAGED_CODE()
unsigned char BOOLEAN
LONG NTSTATUS
Definition: precomp.h:26
#define NULL
Definition: types.h:112
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define UlongToPtr(u)
Definition: config.h:106
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define ExGetPreviousMode
Definition: ex.h:140
VOID NTAPI ProbeForRead(IN CONST VOID *Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:102
VOID NTAPI ProbeForWrite(IN PVOID Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:143
#define _SEH2_END
Definition: filesup.c:22
#define _SEH2_TRY
Definition: filesup.c:19
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:223
Status
Definition: gdiplustypes.h:25
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
#define DbgPrint
Definition: hal.h:12
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
#define THREAD_SET_CONTEXT
#define THREAD_GET_CONTEXT
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:55
VOID NTAPI PspDumpThreads(BOOLEAN SystemThreads)
#define KeLeaveGuardedRegion()
Definition: ke_x.h:68
#define KeEnterGuardedRegion()
Definition: ke_x.h:39
unsigned __int64 ULONG64
Definition: imports.h:198
#define KernelMode
Definition: asm.h:34
@ Ready
Definition: ketypes.h:389
@ Standby
Definition: ketypes.h:391
@ Waiting
Definition: ketypes.h:393
@ OriginalApcEnvironment
Definition: ketypes.h:767
struct _CONTEXT CONTEXT
@ NotificationEvent
#define MMDBG_COPY_UNSAFE
Definition: mm.h:77
BOOLEAN NTAPI KeInsertQueueApc(IN PKAPC Apc, IN PVOID SystemArgument1, IN PVOID SystemArgument2, IN KPRIORITY PriorityBoost)
Definition: apc.c:735
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
NTSTATUS NTAPI PsSetContextThread(IN PETHREAD Thread, IN OUT PCONTEXT ThreadContext, IN KPROCESSOR_MODE PreviousMode)
Definition: debug.c:241
NTSTATUS NTAPI PsGetContextThread(IN PETHREAD Thread, IN OUT PCONTEXT ThreadContext, IN KPROCESSOR_MODE PreviousMode)
Definition: debug.c:119
NTSTATUS NTAPI NtSetContextThread(IN HANDLE ThreadHandle, IN PCONTEXT ThreadContext)
Definition: debug.c:387
NTSTATUS NTAPI NtGetContextThread(IN HANDLE ThreadHandle, IN OUT PCONTEXT ThreadContext)
Definition: debug.c:350
POBJECT_TYPE PsThreadType
Definition: thread.c:20
#define STATUS_INVALID_HANDLE
Definition: ntstatus.h:245
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
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
LIST_ENTRY PsActiveProcessHead
Definition: process.c:22
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:159
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:34
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:162
PEPROCESS PsInitialSystemProcess
Definition: psmgr.c:50
#define ProbeForReadUlong(Ptr)
Definition: probe.h:65
#define CONTEXT_EXTENDED_REGISTERS
#define STATUS_SUCCESS
Definition: shellext.h:65
HANDLE UniqueThread
Definition: compat.h:826
HANDLE UniqueProcess
Definition: compat.h:825
ULONG ContextFlags
Definition: nt_native.h:1426
KTHREAD Tcb
Definition: pstypes.h:1103
CLIENT_ID Cid
Definition: pstypes.h:1128
ULONG SystemThread
Definition: pstypes.h:1182
CONTEXT Context
Definition: ps.h:87
KEVENT Event
Definition: ps.h:85
KPROCESSOR_MODE Mode
Definition: ps.h:86
PVOID SystemArgument1
Definition: ketypes.h:563
PVOID SystemArgument2
Definition: ketypes.h:564
GROUP_AFFINITY Affinity
Definition: ketypes.h:1938
SCHAR Priority
Definition: ketypes.h:1782
PVOID KernelStack
Definition: ketypes.h:1675
volatile VOID * StackLimit
Definition: ketypes.h:1665
volatile UCHAR State
Definition: ketypes.h:1789
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
uint32_t * PULONG
Definition: typedefs.h:59
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
#define NTAPI
Definition: typedefs.h:36
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define IN
Definition: typedefs.h:39
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4533
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
#define ObDereferenceObject
Definition: obfuncs.h:203
_In_ KPROCESSOR_MODE PreviousMode
Definition: sefuncs.h:103