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 /* user_regs definitions from asm/user.h */
38 struct kernel_user_regs_struct
40 long ebx
, ecx
, edx
, esi
, edi
, ebp
, eax
;
41 unsigned short ds
, __ds
, es
, __es
;
42 unsigned short fs
, __fs
, gs
, __gs
;
44 unsigned short cs
, __cs
;
46 unsigned short ss
, __ss
;
49 /* debug register offset in struct user */
50 #define DR_OFFSET(dr) ((int)((((struct user *)0)->u_debugreg) + (dr)))
52 /* retrieve a debug register */
53 static inline int get_debug_reg( int pid
, int num
, DWORD
*data
)
55 int res
= ptrace( PTRACE_PEEKUSER
, pid
, DR_OFFSET(num
), 0 );
56 if ((res
== -1) && errno
)
65 /* retrieve a thread context */
66 static void get_thread_context( struct thread
*thread
, unsigned int flags
, CONTEXT
*context
)
68 int pid
= thread
->unix_pid
;
69 if (flags
& CONTEXT_FULL
)
71 struct kernel_user_regs_struct regs
;
72 if (ptrace( PTRACE_GETREGS
, pid
, 0, ®s
) == -1) goto error
;
73 if (flags
& CONTEXT_INTEGER
)
75 context
->Eax
= regs
.eax
;
76 context
->Ebx
= regs
.ebx
;
77 context
->Ecx
= regs
.ecx
;
78 context
->Edx
= regs
.edx
;
79 context
->Esi
= regs
.esi
;
80 context
->Edi
= regs
.edi
;
82 if (flags
& CONTEXT_CONTROL
)
84 context
->Ebp
= regs
.ebp
;
85 context
->Esp
= regs
.esp
;
86 context
->Eip
= regs
.eip
;
87 context
->SegCs
= regs
.cs
;
88 context
->SegSs
= regs
.ss
;
89 context
->EFlags
= regs
.eflags
;
91 if (flags
& CONTEXT_SEGMENTS
)
93 context
->SegDs
= regs
.ds
;
94 context
->SegEs
= regs
.es
;
95 context
->SegFs
= regs
.fs
;
96 context
->SegGs
= regs
.gs
;
99 if (flags
& CONTEXT_DEBUG_REGISTERS
)
101 if (get_debug_reg( pid
, 0, &context
->Dr0
) == -1) goto error
;
102 if (get_debug_reg( pid
, 1, &context
->Dr1
) == -1) goto error
;
103 if (get_debug_reg( pid
, 2, &context
->Dr2
) == -1) goto error
;
104 if (get_debug_reg( pid
, 3, &context
->Dr3
) == -1) goto error
;
105 if (get_debug_reg( pid
, 6, &context
->Dr6
) == -1) goto error
;
106 if (get_debug_reg( pid
, 7, &context
->Dr7
) == -1) goto error
;
108 if (flags
& CONTEXT_FLOATING_POINT
)
110 /* we can use context->FloatSave directly as it is using the */
111 /* correct structure (the same as fsave/frstor) */
112 if (ptrace( PTRACE_GETFPREGS
, pid
, 0, &context
->FloatSave
) == -1) goto error
;
113 context
->FloatSave
.Cr0NpxState
= 0; /* FIXME */
121 /* set a thread context */
122 static void set_thread_context( struct thread
*thread
, unsigned int flags
, CONTEXT
*context
)
124 int pid
= thread
->unix_pid
;
125 if (flags
& CONTEXT_FULL
)
127 struct kernel_user_regs_struct regs
;
128 if ((flags
& CONTEXT_FULL
) != CONTEXT_FULL
) /* need to preserve some registers */
130 if (ptrace( PTRACE_GETREGS
, pid
, 0, ®s
) == -1) goto error
;
132 if (flags
& CONTEXT_INTEGER
)
134 regs
.eax
= context
->Eax
;
135 regs
.ebx
= context
->Ebx
;
136 regs
.ecx
= context
->Ecx
;
137 regs
.edx
= context
->Edx
;
138 regs
.esi
= context
->Esi
;
139 regs
.edi
= context
->Edi
;
141 if (flags
& CONTEXT_CONTROL
)
143 regs
.ebp
= context
->Ebp
;
144 regs
.esp
= context
->Esp
;
145 regs
.eip
= context
->Eip
;
146 regs
.cs
= context
->SegCs
;
147 regs
.ss
= context
->SegSs
;
148 regs
.eflags
= context
->EFlags
;
150 if (flags
& CONTEXT_SEGMENTS
)
152 regs
.ds
= context
->SegDs
;
153 regs
.es
= context
->SegEs
;
154 regs
.fs
= context
->SegFs
;
155 regs
.gs
= context
->SegGs
;
157 if (ptrace( PTRACE_SETREGS
, pid
, 0, ®s
) == -1) goto error
;
159 if (flags
& CONTEXT_DEBUG_REGISTERS
)
161 if (ptrace( PTRACE_POKEUSER
, pid
, DR_OFFSET(0), context
->Dr0
) == -1) goto error
;
162 if (ptrace( PTRACE_POKEUSER
, pid
, DR_OFFSET(1), context
->Dr1
) == -1) goto error
;
163 if (ptrace( PTRACE_POKEUSER
, pid
, DR_OFFSET(2), context
->Dr2
) == -1) goto error
;
164 if (ptrace( PTRACE_POKEUSER
, pid
, DR_OFFSET(3), context
->Dr3
) == -1) goto error
;
165 if (ptrace( PTRACE_POKEUSER
, pid
, DR_OFFSET(6), context
->Dr6
) == -1) goto error
;
166 if (ptrace( PTRACE_POKEUSER
, pid
, DR_OFFSET(7), context
->Dr7
) == -1) goto error
;
168 if (flags
& CONTEXT_FLOATING_POINT
)
170 /* we can use context->FloatSave directly as it is using the */
171 /* correct structure (the same as fsave/frstor) */
172 if (ptrace( PTRACE_SETFPREGS
, pid
, 0, &context
->FloatSave
) == -1) goto error
;
173 context
->FloatSave
.Cr0NpxState
= 0; /* FIXME */
181 #error You must implement get/set_thread_context for your platform
185 /* copy a context structure according to the flags */
186 static void copy_context( CONTEXT
*to
, CONTEXT
*from
, int flags
)
188 if (flags
& CONTEXT_CONTROL
)
193 to
->SegCs
= from
->SegCs
;
194 to
->SegSs
= from
->SegSs
;
195 to
->EFlags
= from
->EFlags
;
197 if (flags
& CONTEXT_INTEGER
)
206 if (flags
& CONTEXT_SEGMENTS
)
208 to
->SegDs
= from
->SegDs
;
209 to
->SegEs
= from
->SegEs
;
210 to
->SegFs
= from
->SegFs
;
211 to
->SegGs
= from
->SegGs
;
213 if (flags
& CONTEXT_DEBUG_REGISTERS
)
222 if (flags
& CONTEXT_FLOATING_POINT
)
224 to
->FloatSave
= from
->FloatSave
;
228 /* retrieve the current context of a thread */
229 DECL_HANDLER(get_thread_context
)
231 struct thread
*thread
;
234 if ((thread
= get_thread_from_handle( req
->handle
, THREAD_GET_CONTEXT
)))
236 if ((context
= get_debug_context( thread
))) /* thread is inside an exception event */
238 copy_context( &req
->context
, context
, req
->flags
);
242 suspend_thread( thread
, 0 );
243 if (thread
->attached
) get_thread_context( thread
, req
->flags
, &req
->context
);
244 else set_error( STATUS_ACCESS_DENIED
);
245 resume_thread( thread
);
247 release_object( thread
);
252 /* set the current context of a thread */
253 DECL_HANDLER(set_thread_context
)
255 struct thread
*thread
;
258 if ((thread
= get_thread_from_handle( req
->handle
, THREAD_SET_CONTEXT
)))
260 if ((context
= get_debug_context( thread
))) /* thread is inside an exception event */
262 copy_context( context
, &req
->context
, req
->flags
);
266 suspend_thread( thread
, 0 );
267 if (thread
->attached
) set_thread_context( thread
, req
->flags
, &req
->context
);
268 else set_error( STATUS_ACCESS_DENIED
);
269 resume_thread( thread
);
271 release_object( thread
);
275 #endif /* __i386__ */