Make a distinction between the thread Unix pid and the process wide
[wine] / server / context_powerpc.c
1 /*
2  * PowerPC register context support
3  *
4  * Copyright (C) 2002 Marcus Meissner, SuSE Linux AG.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include "config.h"
22
23 #ifdef __powerpc__
24
25 #include <assert.h>
26 #include <errno.h>
27 #include <sys/types.h>
28 #ifdef HAVE_SYS_REG_H
29 # include <sys/reg.h>
30 #endif
31 #include <unistd.h>
32 #ifdef HAVE_SYS_PTRACE_H
33 # include <sys/ptrace.h>
34 #endif
35
36 #include "winbase.h"
37
38 #include "file.h"
39 #include "thread.h"
40 #include "request.h"
41
42 /* retrieve a thread context */
43 static void get_thread_context( struct thread *thread, unsigned int flags, CONTEXT *context )
44 {
45     int pid = get_ptrace_pid(thread);
46     if (flags & CONTEXT_FULL)
47     {
48         if (flags & CONTEXT_INTEGER)
49         {
50 #define XREG(x,y) if (ptrace( PTRACE_PEEKUSER, pid, (void*)(x<<2), &context->y) == -1) goto error;
51 #define IREG(x) if (ptrace( PTRACE_PEEKUSER, pid, (void*)(x<<2), &context->Gpr##x) == -1) goto error;
52             IREG(0); IREG(1); IREG(2); IREG(3); IREG(4); IREG(5); IREG(6);
53             IREG(7); IREG(8); IREG(9); IREG(10); IREG(11); IREG(12); IREG(13);
54             IREG(14); IREG(15); IREG(16); IREG(17); IREG(18); IREG(19);
55             IREG(20); IREG(21); IREG(22); IREG(23); IREG(24); IREG(25);
56             IREG(26); IREG(27); IREG(28); IREG(29); IREG(30); IREG(31);
57 #undef IREG
58             XREG(37,Xer);
59             XREG(38,Cr);
60         }
61         if (flags & CONTEXT_CONTROL)
62         {
63             XREG(32,Iar);
64             XREG(33,Msr);
65             XREG(35,Ctr);
66             XREG(36,Lr); /* 36 is LNK ... probably Lr ? */
67         }
68     }
69     if (flags & CONTEXT_FLOATING_POINT)
70     {
71 #define FREG(x) if (ptrace( PTRACE_PEEKUSER, pid, (void*)((48+x*2)<<2), &context->Fpr##x) == -1) goto error;
72         FREG(0);
73         FREG(1);
74         FREG(2);
75         FREG(3);
76         FREG(4);
77         FREG(5);
78         FREG(6);
79         FREG(7);
80         FREG(8);
81         FREG(9);
82         FREG(10);
83         FREG(11);
84         FREG(12);
85         FREG(13);
86         FREG(14);
87         FREG(15);
88         FREG(16);
89         FREG(17);
90         FREG(18);
91         FREG(19);
92         FREG(20);
93         FREG(21);
94         FREG(22);
95         FREG(23);
96         FREG(24);
97         FREG(25);
98         FREG(26);
99         FREG(27);
100         FREG(28);
101         FREG(29);
102         FREG(30);
103         FREG(31);
104         XREG((48+32*2),Fpscr);
105     }
106     return;
107  error:
108     file_set_error();
109 }
110 #undef XREG
111 #undef IREG
112 #undef FREG
113
114 #define XREG(x,y) if (ptrace( PTRACE_POKEUSER, pid, (void*)(x<<2), &context->y) == -1) goto error;
115 #define IREG(x) if (ptrace( PTRACE_POKEUSER, pid, (void*)(x<<2), &context->Gpr##x) == -1) goto error;
116 #define FREG(x) if (ptrace( PTRACE_POKEUSER, pid, (void*)((48+x*2)<<2), &context->Fpr##x) == -1) goto error;
117 /* set a thread context */
118 static void set_thread_context( struct thread *thread, unsigned int flags, const CONTEXT *context )
119 {
120     int pid = get_ptrace_pid(thread);
121     if (flags & CONTEXT_FULL)
122     {
123         if (flags & CONTEXT_INTEGER)
124         {
125             IREG(0); IREG(1); IREG(2); IREG(3); IREG(4); IREG(5); IREG(6);
126             IREG(7); IREG(8); IREG(9); IREG(10); IREG(11); IREG(12); IREG(13);
127             IREG(14); IREG(15); IREG(16); IREG(17); IREG(18); IREG(19);
128             IREG(20); IREG(21); IREG(22); IREG(23); IREG(24); IREG(25);
129             IREG(26); IREG(27); IREG(28); IREG(29); IREG(30); IREG(31);
130             XREG(37,Xer);
131             XREG(38,Cr);
132
133         }
134         if (flags & CONTEXT_CONTROL)
135         {
136             XREG(32,Iar);
137             XREG(33,Msr);
138             XREG(35,Ctr);
139             XREG(36,Lr);
140         }
141     }
142     if (flags & CONTEXT_FLOATING_POINT)
143     {
144         FREG(0);
145         FREG(1);
146         FREG(2);
147         FREG(3);
148         FREG(4);
149         FREG(5);
150         FREG(6);
151         FREG(7);
152         FREG(8);
153         FREG(9);
154         FREG(10);
155         FREG(11);
156         FREG(12);
157         FREG(13);
158         FREG(14);
159         FREG(15);
160         FREG(16);
161         FREG(17);
162         FREG(18);
163         FREG(19);
164         FREG(20);
165         FREG(21);
166         FREG(22);
167         FREG(23);
168         FREG(24);
169         FREG(25);
170         FREG(26);
171         FREG(27);
172         FREG(28);
173         FREG(29);
174         FREG(30);
175         FREG(31);
176 #undef FREG
177         XREG((48+32*2),Fpscr);
178     }
179     return;
180  error:
181     file_set_error();
182 }
183 #undef XREG
184 #undef IREG
185 #undef FREG
186
187 #define IREG(x) to->Gpr##x = from->Gpr##x;
188 #define FREG(x) to->Fpr##x = from->Fpr##x;
189 #define CREG(x) to->x = from->x;
190 /* copy a context structure according to the flags */
191 static void copy_context( CONTEXT *to, const CONTEXT *from, int flags )
192 {
193     if (flags & CONTEXT_CONTROL)
194     {
195         CREG(Msr);
196         CREG(Ctr);
197         CREG(Iar);
198     }
199     if (flags & CONTEXT_INTEGER)
200     {
201         IREG(0); IREG(1); IREG(2); IREG(3); IREG(4); IREG(5); IREG(6);
202         IREG(7); IREG(8); IREG(9); IREG(10); IREG(11); IREG(12); IREG(13);
203         IREG(14); IREG(15); IREG(16); IREG(17); IREG(18); IREG(19);
204         IREG(20); IREG(21); IREG(22); IREG(23); IREG(24); IREG(25);
205         IREG(26); IREG(27); IREG(28); IREG(29); IREG(30); IREG(31);
206         CREG(Xer);
207         CREG(Cr);
208     }
209     if (flags & CONTEXT_FLOATING_POINT)
210     {
211         FREG(0);
212         FREG(1);
213         FREG(2);
214         FREG(3);
215         FREG(4);
216         FREG(5);
217         FREG(6);
218         FREG(7);
219         FREG(8);
220         FREG(9);
221         FREG(10);
222         FREG(11);
223         FREG(12);
224         FREG(13);
225         FREG(14);
226         FREG(15);
227         FREG(16);
228         FREG(17);
229         FREG(18);
230         FREG(19);
231         FREG(20);
232         FREG(21);
233         FREG(22);
234         FREG(23);
235         FREG(24);
236         FREG(25);
237         FREG(26);
238         FREG(27);
239         FREG(28);
240         FREG(29);
241         FREG(30);
242         FREG(31);
243         CREG(Fpscr);
244     }
245 }
246
247 /* retrieve the current instruction pointer of a thread */
248 void *get_thread_ip( struct thread *thread )
249 {
250     CONTEXT context;
251     context.Iar = 0;
252     if (suspend_for_ptrace( thread ))
253     {
254         get_thread_context( thread, CONTEXT_CONTROL, &context );
255         resume_after_ptrace( thread );
256     }
257     return (void *)context.Iar;
258 }
259
260 /* determine if we should continue the thread in single-step mode */
261 int get_thread_single_step( struct thread *thread )
262 {
263     CONTEXT context;
264     if (thread->context) return 0;
265     get_thread_context( thread, CONTEXT_CONTROL, &context );
266 #ifndef MSR_SE
267 # define MSR_SE (1<<10)
268 #endif
269     return (context.Msr & MSR_SE) != 0;
270 }
271
272 /* send a signal to a specific thread */
273 int tkill( int pid, int sig )
274 {
275     /* FIXME: should do something here */
276     errno = ENOSYS;
277     return -1;
278 }
279
280 /* retrieve the current context of a thread */
281 DECL_HANDLER(get_thread_context)
282 {
283     struct thread *thread;
284     void *data;
285     int flags = req->flags;
286
287     if (get_reply_max_size() < sizeof(CONTEXT))
288     {
289         set_error( STATUS_INVALID_PARAMETER );
290         return;
291     }
292     if (!(thread = get_thread_from_handle( req->handle, THREAD_GET_CONTEXT ))) return;
293
294     if ((data = set_reply_data_size( sizeof(CONTEXT) )))
295     {
296         if (thread->context)  /* thread is inside an exception event */
297         {
298             copy_context( data, thread->context, flags );
299             flags = 0;
300         }
301         if (flags && suspend_for_ptrace( thread ))
302         {
303             get_thread_context( thread, flags, data );
304             resume_after_ptrace( thread );
305         }
306     }
307     release_object( thread );
308 }
309
310
311 /* set the current context of a thread */
312 DECL_HANDLER(set_thread_context)
313 {
314     struct thread *thread;
315     int flags = req->flags;
316
317     if (get_req_data_size() < sizeof(CONTEXT))
318     {
319         set_error( STATUS_INVALID_PARAMETER );
320         return;
321     }
322     if ((thread = get_thread_from_handle( req->handle, THREAD_SET_CONTEXT )))
323     {
324         if (thread->context)  /* thread is inside an exception event */
325         {
326             copy_context( thread->context, get_req_data(), flags );
327             flags = 0;
328         }
329         if (flags && suspend_for_ptrace( thread ))
330         {
331             set_thread_context( thread, flags, get_req_data() );
332             resume_after_ptrace( thread );
333         }
334         release_object( thread );
335     }
336 }
337
338 #endif  /* __powerpc__ */