Implement anonymous pipes on top of named pipes.
[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 #ifndef PTRACE_PEEKUSER
37 # ifdef PT_READ_D
38 #  define PTRACE_PEEKUSER PT_READ_D
39 # endif
40 #endif /* PTRACE_PEEKUSER */
41
42 #ifndef PTRACE_POKEUSER
43 # ifdef PT_WRITE_D
44 #  define PTRACE_POKEUSER PT_WRITE_D
45 # endif
46 #endif /* PTRACE_POKEUSER */
47
48 #include "winbase.h"
49
50 #include "file.h"
51 #include "thread.h"
52 #include "request.h"
53
54 /* retrieve a thread context */
55 static void get_thread_context( struct thread *thread, unsigned int flags, CONTEXT *context )
56 {
57     int pid = get_ptrace_pid(thread);
58     if (flags & CONTEXT_FULL)
59     {
60         if (flags & CONTEXT_INTEGER)
61         {
62 #define XREG(x,y) if (ptrace( PTRACE_PEEKUSER, pid, (void*)(x<<2), &context->y) == -1) goto error;
63 #define IREG(x) if (ptrace( PTRACE_PEEKUSER, pid, (void*)(x<<2), &context->Gpr##x) == -1) goto error;
64             IREG(0); IREG(1); IREG(2); IREG(3); IREG(4); IREG(5); IREG(6);
65             IREG(7); IREG(8); IREG(9); IREG(10); IREG(11); IREG(12); IREG(13);
66             IREG(14); IREG(15); IREG(16); IREG(17); IREG(18); IREG(19);
67             IREG(20); IREG(21); IREG(22); IREG(23); IREG(24); IREG(25);
68             IREG(26); IREG(27); IREG(28); IREG(29); IREG(30); IREG(31);
69 #undef IREG
70             XREG(37,Xer);
71             XREG(38,Cr);
72         }
73         if (flags & CONTEXT_CONTROL)
74         {
75             XREG(32,Iar);
76             XREG(33,Msr);
77             XREG(35,Ctr);
78             XREG(36,Lr); /* 36 is LNK ... probably Lr ? */
79         }
80     }
81     if (flags & CONTEXT_FLOATING_POINT)
82     {
83 #define FREG(x) if (ptrace( PTRACE_PEEKUSER, pid, (void*)((48+x*2)<<2), &context->Fpr##x) == -1) goto error;
84         FREG(0);
85         FREG(1);
86         FREG(2);
87         FREG(3);
88         FREG(4);
89         FREG(5);
90         FREG(6);
91         FREG(7);
92         FREG(8);
93         FREG(9);
94         FREG(10);
95         FREG(11);
96         FREG(12);
97         FREG(13);
98         FREG(14);
99         FREG(15);
100         FREG(16);
101         FREG(17);
102         FREG(18);
103         FREG(19);
104         FREG(20);
105         FREG(21);
106         FREG(22);
107         FREG(23);
108         FREG(24);
109         FREG(25);
110         FREG(26);
111         FREG(27);
112         FREG(28);
113         FREG(29);
114         FREG(30);
115         FREG(31);
116         XREG((48+32*2),Fpscr);
117     }
118     return;
119  error:
120     file_set_error();
121 }
122 #undef XREG
123 #undef IREG
124 #undef FREG
125
126 #define XREG(x,y) if (ptrace( PTRACE_POKEUSER, pid, (void*)(x<<2), &context->y) == -1) goto error;
127 #define IREG(x) if (ptrace( PTRACE_POKEUSER, pid, (void*)(x<<2), &context->Gpr##x) == -1) goto error;
128 #define FREG(x) if (ptrace( PTRACE_POKEUSER, pid, (void*)((48+x*2)<<2), &context->Fpr##x) == -1) goto error;
129 /* set a thread context */
130 static void set_thread_context( struct thread *thread, unsigned int flags, const CONTEXT *context )
131 {
132     int pid = get_ptrace_pid(thread);
133     if (flags & CONTEXT_FULL)
134     {
135         if (flags & CONTEXT_INTEGER)
136         {
137             IREG(0); IREG(1); IREG(2); IREG(3); IREG(4); IREG(5); IREG(6);
138             IREG(7); IREG(8); IREG(9); IREG(10); IREG(11); IREG(12); IREG(13);
139             IREG(14); IREG(15); IREG(16); IREG(17); IREG(18); IREG(19);
140             IREG(20); IREG(21); IREG(22); IREG(23); IREG(24); IREG(25);
141             IREG(26); IREG(27); IREG(28); IREG(29); IREG(30); IREG(31);
142             XREG(37,Xer);
143             XREG(38,Cr);
144
145         }
146         if (flags & CONTEXT_CONTROL)
147         {
148             XREG(32,Iar);
149             XREG(33,Msr);
150             XREG(35,Ctr);
151             XREG(36,Lr);
152         }
153     }
154     if (flags & CONTEXT_FLOATING_POINT)
155     {
156         FREG(0);
157         FREG(1);
158         FREG(2);
159         FREG(3);
160         FREG(4);
161         FREG(5);
162         FREG(6);
163         FREG(7);
164         FREG(8);
165         FREG(9);
166         FREG(10);
167         FREG(11);
168         FREG(12);
169         FREG(13);
170         FREG(14);
171         FREG(15);
172         FREG(16);
173         FREG(17);
174         FREG(18);
175         FREG(19);
176         FREG(20);
177         FREG(21);
178         FREG(22);
179         FREG(23);
180         FREG(24);
181         FREG(25);
182         FREG(26);
183         FREG(27);
184         FREG(28);
185         FREG(29);
186         FREG(30);
187         FREG(31);
188 #undef FREG
189         XREG((48+32*2),Fpscr);
190     }
191     return;
192  error:
193     file_set_error();
194 }
195 #undef XREG
196 #undef IREG
197 #undef FREG
198
199 #define IREG(x) to->Gpr##x = from->Gpr##x;
200 #define FREG(x) to->Fpr##x = from->Fpr##x;
201 #define CREG(x) to->x = from->x;
202 /* copy a context structure according to the flags */
203 static void copy_context( CONTEXT *to, const CONTEXT *from, int flags )
204 {
205     if (flags & CONTEXT_CONTROL)
206     {
207         CREG(Msr);
208         CREG(Ctr);
209         CREG(Iar);
210     }
211     if (flags & CONTEXT_INTEGER)
212     {
213         IREG(0); IREG(1); IREG(2); IREG(3); IREG(4); IREG(5); IREG(6);
214         IREG(7); IREG(8); IREG(9); IREG(10); IREG(11); IREG(12); IREG(13);
215         IREG(14); IREG(15); IREG(16); IREG(17); IREG(18); IREG(19);
216         IREG(20); IREG(21); IREG(22); IREG(23); IREG(24); IREG(25);
217         IREG(26); IREG(27); IREG(28); IREG(29); IREG(30); IREG(31);
218         CREG(Xer);
219         CREG(Cr);
220     }
221     if (flags & CONTEXT_FLOATING_POINT)
222     {
223         FREG(0);
224         FREG(1);
225         FREG(2);
226         FREG(3);
227         FREG(4);
228         FREG(5);
229         FREG(6);
230         FREG(7);
231         FREG(8);
232         FREG(9);
233         FREG(10);
234         FREG(11);
235         FREG(12);
236         FREG(13);
237         FREG(14);
238         FREG(15);
239         FREG(16);
240         FREG(17);
241         FREG(18);
242         FREG(19);
243         FREG(20);
244         FREG(21);
245         FREG(22);
246         FREG(23);
247         FREG(24);
248         FREG(25);
249         FREG(26);
250         FREG(27);
251         FREG(28);
252         FREG(29);
253         FREG(30);
254         FREG(31);
255         CREG(Fpscr);
256     }
257 }
258
259 /* retrieve the current instruction pointer of a thread */
260 void *get_thread_ip( struct thread *thread )
261 {
262     CONTEXT context;
263     context.Iar = 0;
264     if (suspend_for_ptrace( thread ))
265     {
266         get_thread_context( thread, CONTEXT_CONTROL, &context );
267         resume_after_ptrace( thread );
268     }
269     return (void *)context.Iar;
270 }
271
272 /* determine if we should continue the thread in single-step mode */
273 int get_thread_single_step( struct thread *thread )
274 {
275     CONTEXT context;
276     if (thread->context) return 0;
277     get_thread_context( thread, CONTEXT_CONTROL, &context );
278 #ifndef MSR_SE
279 # define MSR_SE (1<<10)
280 #endif
281     return (context.Msr & MSR_SE) != 0;
282 }
283
284 /* send a signal to a specific thread */
285 int tkill( int pid, int sig )
286 {
287     /* FIXME: should do something here */
288     errno = ENOSYS;
289     return -1;
290 }
291
292 /* retrieve the current context of a thread */
293 DECL_HANDLER(get_thread_context)
294 {
295     struct thread *thread;
296     void *data;
297     int flags = req->flags;
298
299     if (get_reply_max_size() < sizeof(CONTEXT))
300     {
301         set_error( STATUS_INVALID_PARAMETER );
302         return;
303     }
304     if (!(thread = get_thread_from_handle( req->handle, THREAD_GET_CONTEXT ))) return;
305
306     if ((data = set_reply_data_size( sizeof(CONTEXT) )))
307     {
308         if (thread->context)  /* thread is inside an exception event */
309         {
310             copy_context( data, thread->context, flags );
311             flags = 0;
312         }
313         if (flags && suspend_for_ptrace( thread ))
314         {
315             get_thread_context( thread, flags, data );
316             resume_after_ptrace( thread );
317         }
318     }
319     release_object( thread );
320 }
321
322
323 /* set the current context of a thread */
324 DECL_HANDLER(set_thread_context)
325 {
326     struct thread *thread;
327     int flags = req->flags;
328
329     if (get_req_data_size() < sizeof(CONTEXT))
330     {
331         set_error( STATUS_INVALID_PARAMETER );
332         return;
333     }
334     if ((thread = get_thread_from_handle( req->handle, THREAD_SET_CONTEXT )))
335     {
336         if (thread->context)  /* thread is inside an exception event */
337         {
338             copy_context( thread->context, get_req_data(), flags );
339             flags = 0;
340         }
341         if (flags && suspend_for_ptrace( thread ))
342         {
343             set_thread_context( thread, flags, get_req_data() );
344             resume_after_ptrace( thread );
345         }
346         release_object( thread );
347     }
348 }
349
350 #endif  /* __powerpc__ */