Added wine_get_user_name function and got rid of some of the getpwuid
[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 "thread.h"
39 #include "request.h"
40
41 /* retrieve a thread context */
42 static void get_thread_context( struct thread *thread, unsigned int flags, CONTEXT *context )
43 {
44     int pid = thread->unix_pid;
45     if (flags & CONTEXT_FULL)
46     {
47         if (flags & CONTEXT_INTEGER)
48         {
49 #define XREG(x,y) if (ptrace( PTRACE_PEEKUSER, pid, (void*)(x<<2), &context->y) == -1) goto error;
50 #define IREG(x) if (ptrace( PTRACE_PEEKUSER, pid, (void*)(x<<2), &context->Gpr##x) == -1) goto error;
51             IREG(0); IREG(1); IREG(2); IREG(3); IREG(4); IREG(5); IREG(6);
52             IREG(7); IREG(8); IREG(9); IREG(10); IREG(11); IREG(12); IREG(13);
53             IREG(14); IREG(15); IREG(16); IREG(17); IREG(18); IREG(19);
54             IREG(20); IREG(21); IREG(22); IREG(23); IREG(24); IREG(25);
55             IREG(26); IREG(27); IREG(28); IREG(29); IREG(30); IREG(31);
56 #undef IREG
57             XREG(37,Xer);
58             XREG(38,Cr);
59
60         }
61         if (flags & CONTEXT_CONTROL)
62         {
63             XREG(33,Msr);
64             XREG(35,Ctr);
65
66             XREG(32,Fill[0]); /* misused for PC / nip */
67
68         /* what is Iar? Lr? */
69             /*XREG(33*4,Iar);*/
70             /*XREG(33*4,Lr);*/
71         }
72     }
73     if (flags & CONTEXT_FLOATING_POINT)
74     {
75 #define FREG(x) if (ptrace( PTRACE_PEEKUSER, pid, (void*)((48+x*2)<<2), &context->Fpr##x) == -1) goto error;
76         FREG(0);
77         FREG(1);
78         FREG(2);
79         FREG(3);
80         FREG(4);
81         FREG(5);
82         FREG(6);
83         FREG(7);
84         FREG(8);
85         FREG(9);
86         FREG(10);
87         FREG(11);
88         FREG(12);
89         FREG(13);
90         FREG(14);
91         FREG(15);
92         FREG(16);
93         FREG(17);
94         FREG(18);
95         FREG(19);
96         FREG(20);
97         FREG(21);
98         FREG(22);
99         FREG(23);
100         FREG(24);
101         FREG(25);
102         FREG(26);
103         FREG(27);
104         FREG(28);
105         FREG(29);
106         FREG(30);
107         FREG(31);
108         XREG((48+32*2),Fpscr);
109     }
110     return;
111  error:
112     file_set_error();
113 }
114 #undef XREG
115 #undef IREG
116 #undef FREG
117
118 #define XREG(x,y) if (ptrace( PTRACE_POKEUSER, pid, (void*)(x<<2), &context->y) == -1) goto error;
119 #define IREG(x) if (ptrace( PTRACE_POKEUSER, pid, (void*)(x<<2), &context->Gpr##x) == -1) goto error;
120 #define FREG(x) if (ptrace( PTRACE_POKEUSER, pid, (void*)((48+x*2)<<2), &context->Fpr##x) == -1) goto error;
121 /* set a thread context */
122 static void set_thread_context( struct thread *thread, unsigned int flags, const CONTEXT *context )
123 {
124     int pid = thread->unix_pid;
125     if (flags & CONTEXT_FULL)
126     {
127         if (flags & CONTEXT_INTEGER)
128         {
129             IREG(0); IREG(1); IREG(2); IREG(3); IREG(4); IREG(5); IREG(6);
130             IREG(7); IREG(8); IREG(9); IREG(10); IREG(11); IREG(12); IREG(13);
131             IREG(14); IREG(15); IREG(16); IREG(17); IREG(18); IREG(19);
132             IREG(20); IREG(21); IREG(22); IREG(23); IREG(24); IREG(25);
133             IREG(26); IREG(27); IREG(28); IREG(29); IREG(30); IREG(31);
134             XREG(37,Xer);
135             XREG(38,Cr);
136
137         }
138         if (flags & CONTEXT_CONTROL)
139         {
140             XREG(33,Msr);
141             XREG(35,Ctr);
142
143             XREG(32,Fill[0]); /* misused for PC / nip */
144
145         /* what is Iar? Lr? */
146             /*XREG(33*4,Iar);*/
147             /*XREG(33*4,Lr);*/
148         }
149     }
150     if (flags & CONTEXT_FLOATING_POINT)
151     {
152         FREG(0);
153         FREG(1);
154         FREG(2);
155         FREG(3);
156         FREG(4);
157         FREG(5);
158         FREG(6);
159         FREG(7);
160         FREG(8);
161         FREG(9);
162         FREG(10);
163         FREG(11);
164         FREG(12);
165         FREG(13);
166         FREG(14);
167         FREG(15);
168         FREG(16);
169         FREG(17);
170         FREG(18);
171         FREG(19);
172         FREG(20);
173         FREG(21);
174         FREG(22);
175         FREG(23);
176         FREG(24);
177         FREG(25);
178         FREG(26);
179         FREG(27);
180         FREG(28);
181         FREG(29);
182         FREG(30);
183         FREG(31);
184 #undef FREG
185         XREG((48+32*2),Fpscr);
186     }
187     return;
188  error:
189     file_set_error();
190 }
191 #undef XREG
192 #undef IREG
193 #undef FREG
194
195 #define IREG(x) to->Gpr##x = from->Gpr##x;
196 #define FREG(x) to->Fpr##x = from->Fpr##x;
197 #define CREG(x) to->x = from->x;
198 /* copy a context structure according to the flags */
199 static void copy_context( CONTEXT *to, const CONTEXT *from, int flags )
200 {
201     if (flags & CONTEXT_CONTROL)
202     {
203         CREG(Msr);
204         CREG(Ctr);
205         CREG(Fill[0]);
206     }
207     if (flags & CONTEXT_INTEGER)
208     {
209         IREG(0); IREG(1); IREG(2); IREG(3); IREG(4); IREG(5); IREG(6);
210         IREG(7); IREG(8); IREG(9); IREG(10); IREG(11); IREG(12); IREG(13);
211         IREG(14); IREG(15); IREG(16); IREG(17); IREG(18); IREG(19);
212         IREG(20); IREG(21); IREG(22); IREG(23); IREG(24); IREG(25);
213         IREG(26); IREG(27); IREG(28); IREG(29); IREG(30); IREG(31);
214         CREG(Xer);
215         CREG(Cr);
216     }
217     if (flags & CONTEXT_FLOATING_POINT)
218     {
219         FREG(0);
220         FREG(1);
221         FREG(2);
222         FREG(3);
223         FREG(4);
224         FREG(5);
225         FREG(6);
226         FREG(7);
227         FREG(8);
228         FREG(9);
229         FREG(10);
230         FREG(11);
231         FREG(12);
232         FREG(13);
233         FREG(14);
234         FREG(15);
235         FREG(16);
236         FREG(17);
237         FREG(18);
238         FREG(19);
239         FREG(20);
240         FREG(21);
241         FREG(22);
242         FREG(23);
243         FREG(24);
244         FREG(25);
245         FREG(26);
246         FREG(27);
247         FREG(28);
248         FREG(29);
249         FREG(30);
250         FREG(31);
251         CREG(Fpscr);
252     }
253 }
254
255 /* retrieve the current instruction pointer of a thread */
256 void *get_thread_ip( struct thread *thread )
257 {
258     CONTEXT context;
259     context.Fill[0] = 0;
260     if (suspend_for_ptrace( thread ))
261     {
262         get_thread_context( thread, CONTEXT_CONTROL, &context );
263         resume_thread( thread );
264     }
265     return (void *)context.Fill[0];
266 }
267
268 /* determine if we should continue the thread in single-step mode */
269 int get_thread_single_step( struct thread *thread )
270 {
271     CONTEXT context;
272     if (thread->context) return 0;
273     get_thread_context( thread, CONTEXT_CONTROL, &context );
274 #ifndef MSR_SE
275 # define MSR_SE (1<<10)
276 #endif
277     return (context.Msr & MSR_SE) != 0;
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_thread( 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_thread( thread );
333         }
334         release_object( thread );
335     }
336 }
337
338 #endif  /* __powerpc__ */