Removed debugstr.h.
[wine/hacks.git] / server / context_i386.c
blobcb62b09f013c80b5aef77fe721e9fad8b1bcf225
1 /*
2 * i386 register context support
4 * Copyright (C) 1999 Alexandre Julliard
5 */
7 #include "config.h"
9 #ifdef __i386__
11 #include <assert.h>
12 #include <errno.h>
13 #include <sys/ptrace.h>
14 #include <sys/user.h>
16 #include "winbase.h"
18 #include "thread.h"
19 #include "request.h"
22 #ifndef PTRACE_PEEKUSER
23 #define PTRACE_PEEKUSER PT_READ_U
24 #endif
25 #ifndef PTRACE_POKEUSER
26 #define PTRACE_POKEUSER PT_WRITE_U
27 #endif
28 #ifndef PTRACE_GETREGS
29 #define PTRACE_GETREGS PT_GETREGS
30 #endif
31 #ifndef PTRACE_GETFPREGS
32 #define PTRACE_GETFPREGS PT_GETFPREGS
33 #endif
35 #ifdef linux
37 /* debug register offset in struct user */
38 #define DR_OFFSET(dr) ((int)((((struct user *)0)->u_debugreg) + (dr)))
40 /* retrieve a debug register */
41 static inline int get_debug_reg( int pid, int num, DWORD *data )
43 int res = ptrace( PTRACE_PEEKUSER, pid, DR_OFFSET(num), 0 );
44 if ((res == -1) && errno)
46 file_set_error();
47 return -1;
49 *data = res;
50 return 0;
53 /* retrieve a thread context */
54 static void get_thread_context( struct thread *thread, unsigned int flags, CONTEXT *context )
56 int pid = thread->unix_pid;
57 if (flags & CONTEXT_FULL)
59 struct user_regs_struct regs;
60 if (ptrace( PTRACE_GETREGS, pid, 0, &regs ) == -1) goto error;
61 if (flags & CONTEXT_INTEGER)
63 context->Eax = regs.eax;
64 context->Ebx = regs.ebx;
65 context->Ecx = regs.ecx;
66 context->Edx = regs.edx;
67 context->Esi = regs.esi;
68 context->Edi = regs.edi;
70 if (flags & CONTEXT_CONTROL)
72 context->Ebp = regs.ebp;
73 context->Esp = regs.esp;
74 context->Eip = regs.eip;
75 context->SegCs = regs.xcs & 0xffff;
76 context->SegSs = regs.xss & 0xffff;
77 context->EFlags = regs.eflags;
79 if (flags & CONTEXT_SEGMENTS)
81 context->SegDs = regs.xds & 0xffff;
82 context->SegEs = regs.xes & 0xffff;
83 context->SegFs = regs.xfs & 0xffff;
84 context->SegGs = regs.xgs & 0xffff;
87 if (flags & CONTEXT_DEBUG_REGISTERS)
89 if (get_debug_reg( pid, 0, &context->Dr0 ) == -1) goto error;
90 if (get_debug_reg( pid, 1, &context->Dr1 ) == -1) goto error;
91 if (get_debug_reg( pid, 2, &context->Dr2 ) == -1) goto error;
92 if (get_debug_reg( pid, 3, &context->Dr3 ) == -1) goto error;
93 if (get_debug_reg( pid, 6, &context->Dr6 ) == -1) goto error;
94 if (get_debug_reg( pid, 7, &context->Dr7 ) == -1) goto error;
96 if (flags & CONTEXT_FLOATING_POINT)
98 /* we can use context->FloatSave directly as it is using the */
99 /* correct structure (the same as fsave/frstor) */
100 if (ptrace( PTRACE_GETFPREGS, pid, 0, &context->FloatSave ) == -1) goto error;
101 context->FloatSave.Cr0NpxState = 0; /* FIXME */
103 return;
104 error:
105 file_set_error();
109 /* set a thread context */
110 static void set_thread_context( struct thread *thread, unsigned int flags, CONTEXT *context )
112 int pid = thread->unix_pid;
113 if (flags & CONTEXT_FULL)
115 struct user_regs_struct regs;
116 if ((flags & CONTEXT_FULL) != CONTEXT_FULL) /* need to preserve some registers */
118 if (ptrace( PTRACE_GETREGS, pid, 0, &regs ) == -1) goto error;
120 if (flags & CONTEXT_INTEGER)
122 regs.eax = context->Eax;
123 regs.ebx = context->Ebx;
124 regs.ecx = context->Ecx;
125 regs.edx = context->Edx;
126 regs.esi = context->Esi;
127 regs.edi = context->Edi;
129 if (flags & CONTEXT_CONTROL)
131 regs.ebp = context->Ebp;
132 regs.esp = context->Esp;
133 regs.eip = context->Eip;
134 regs.xcs = context->SegCs;
135 regs.xss = context->SegSs;
136 regs.eflags = context->EFlags;
138 if (flags & CONTEXT_SEGMENTS)
140 regs.xds = context->SegDs;
141 regs.xes = context->SegEs;
142 regs.xfs = context->SegFs;
143 regs.xgs = context->SegGs;
145 if (ptrace( PTRACE_SETREGS, pid, 0, &regs ) == -1) goto error;
147 if (flags & CONTEXT_DEBUG_REGISTERS)
149 if (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(0), context->Dr0 ) == -1) goto error;
150 if (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(1), context->Dr1 ) == -1) goto error;
151 if (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(2), context->Dr2 ) == -1) goto error;
152 if (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(3), context->Dr3 ) == -1) goto error;
153 if (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(6), context->Dr6 ) == -1) goto error;
154 if (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(7), context->Dr7 ) == -1) goto error;
156 if (flags & CONTEXT_FLOATING_POINT)
158 /* we can use context->FloatSave directly as it is using the */
159 /* correct structure (the same as fsave/frstor) */
160 if (ptrace( PTRACE_SETFPREGS, pid, 0, &context->FloatSave ) == -1) goto error;
161 context->FloatSave.Cr0NpxState = 0; /* FIXME */
163 return;
164 error:
165 file_set_error();
168 #else /* linux */
169 #error You must implement get/set_thread_context for your platform
170 #endif /* linux */
173 /* copy a context structure according to the flags */
174 static void copy_context( CONTEXT *to, CONTEXT *from, int flags )
176 if (flags & CONTEXT_CONTROL)
178 to->Ebp = from->Ebp;
179 to->Eip = from->Eip;
180 to->Esp = from->Esp;
181 to->SegCs = from->SegCs;
182 to->SegSs = from->SegSs;
183 to->EFlags = from->EFlags;
185 if (flags & CONTEXT_INTEGER)
187 to->Eax = from->Eax;
188 to->Ebx = from->Ebx;
189 to->Ecx = from->Ecx;
190 to->Edx = from->Edx;
191 to->Esi = from->Esi;
192 to->Edi = from->Edi;
194 if (flags & CONTEXT_SEGMENTS)
196 to->SegDs = from->SegDs;
197 to->SegEs = from->SegEs;
198 to->SegFs = from->SegFs;
199 to->SegGs = from->SegGs;
201 if (flags & CONTEXT_DEBUG_REGISTERS)
203 to->Dr0 = from->Dr0;
204 to->Dr1 = from->Dr1;
205 to->Dr2 = from->Dr2;
206 to->Dr3 = from->Dr3;
207 to->Dr6 = from->Dr6;
208 to->Dr7 = from->Dr7;
210 if (flags & CONTEXT_FLOATING_POINT)
212 to->FloatSave = from->FloatSave;
216 /* retrieve the current context of a thread */
217 DECL_HANDLER(get_thread_context)
219 struct thread *thread;
220 CONTEXT *context;
222 if ((thread = get_thread_from_handle( req->handle, THREAD_GET_CONTEXT )))
224 if ((context = get_debug_context( thread ))) /* thread is inside an exception event */
226 copy_context( &req->context, context, req->flags );
228 else
230 suspend_thread( thread, 0 );
231 if (thread->attached) get_thread_context( thread, req->flags, &req->context );
232 else set_error( STATUS_ACCESS_DENIED );
233 resume_thread( thread );
235 release_object( thread );
240 /* set the current context of a thread */
241 DECL_HANDLER(set_thread_context)
243 struct thread *thread;
244 CONTEXT *context;
246 if ((thread = get_thread_from_handle( req->handle, THREAD_SET_CONTEXT )))
248 if ((context = get_debug_context( thread ))) /* thread is inside an exception event */
250 copy_context( context, &req->context, req->flags );
252 else
254 suspend_thread( thread, 0 );
255 if (thread->attached) set_thread_context( thread, req->flags, &req->context );
256 else set_error( STATUS_ACCESS_DENIED );
257 resume_thread( thread );
259 release_object( thread );
263 #endif /* __i386__ */