2 * i386 register context support
4 * Copyright (C) 1999 Alexandre Julliard
13 #include <sys/ptrace.h>
22 #ifndef PTRACE_PEEKUSER
23 #define PTRACE_PEEKUSER PT_READ_U
25 #ifndef PTRACE_POKEUSER
26 #define PTRACE_POKEUSER PT_WRITE_U
28 #ifndef PTRACE_GETREGS
29 #define PTRACE_GETREGS PT_GETREGS
31 #ifndef PTRACE_GETFPREGS
32 #define PTRACE_GETFPREGS PT_GETFPREGS
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
)
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, ®s
) == -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 */
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, ®s
) == -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, ®s
) == -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 */
169 #error You must implement get/set_thread_context for your platform
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
)
181 to
->SegCs
= from
->SegCs
;
182 to
->SegSs
= from
->SegSs
;
183 to
->EFlags
= from
->EFlags
;
185 if (flags
& CONTEXT_INTEGER
)
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
)
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
;
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
);
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
;
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
);
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__ */