server: Moved the tkill function to ptrace.c.
[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 <stdarg.h>
32 #include <unistd.h>
33 #ifdef HAVE_SYS_PTRACE_H
34 # include <sys/ptrace.h>
35 #endif
36
37 #ifndef PTRACE_PEEKUSER
38 # ifdef PT_READ_D
39 #  define PTRACE_PEEKUSER PT_READ_D
40 # endif
41 #endif /* PTRACE_PEEKUSER */
42
43 #ifndef PTRACE_POKEUSER
44 # ifdef PT_WRITE_D
45 #  define PTRACE_POKEUSER PT_WRITE_D
46 # endif
47 #endif /* PTRACE_POKEUSER */
48
49 #include "windef.h"
50
51 #include "file.h"
52 #include "thread.h"
53 #include "request.h"
54
55 /* retrieve a thread context */
56 static void get_thread_context_ptrace( struct thread *thread, unsigned int flags, CONTEXT *context )
57 {
58     int pid = get_ptrace_pid(thread);
59     if (flags & CONTEXT_INTEGER)
60     {
61 #define XREG(x,y) if (ptrace( PTRACE_PEEKUSER, pid, (void*)(x<<2), &context->y) == -1) goto error;
62 #define IREG(x) if (ptrace( PTRACE_PEEKUSER, pid, (void*)(x<<2), &context->Gpr##x) == -1) goto error;
63         IREG(0); IREG(1); IREG(2); IREG(3); IREG(4); IREG(5); IREG(6);
64         IREG(7); IREG(8); IREG(9); IREG(10); IREG(11); IREG(12); IREG(13);
65         IREG(14); IREG(15); IREG(16); IREG(17); IREG(18); IREG(19);
66         IREG(20); IREG(21); IREG(22); IREG(23); IREG(24); IREG(25);
67         IREG(26); IREG(27); IREG(28); IREG(29); IREG(30); IREG(31);
68 #undef IREG
69         XREG(37,Xer);
70         XREG(38,Cr);
71         context->ContextFlags |= CONTEXT_INTEGER;
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         context->ContextFlags |= CONTEXT_CONTROL;
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         context->ContextFlags |= CONTEXT_FLOATING_POINT;
118     }
119     return;
120  error:
121     file_set_error();
122 }
123 #undef XREG
124 #undef IREG
125 #undef FREG
126
127 #define XREG(x,y) if (ptrace( PTRACE_POKEUSER, pid, (void*)(x<<2), &context->y) == -1) goto error;
128 #define IREG(x) if (ptrace( PTRACE_POKEUSER, pid, (void*)(x<<2), &context->Gpr##x) == -1) goto error;
129 #define FREG(x) if (ptrace( PTRACE_POKEUSER, pid, (void*)((48+x*2)<<2), &context->Fpr##x) == -1) goto error;
130 /* set a thread context */
131 static void set_thread_context_ptrace( struct thread *thread, unsigned int flags, const CONTEXT *context )
132 {
133     int pid = get_ptrace_pid(thread);
134     if (flags & CONTEXT_FULL)
135     {
136         if (flags & CONTEXT_INTEGER)
137         {
138             IREG(0); IREG(1); IREG(2); IREG(3); IREG(4); IREG(5); IREG(6);
139             IREG(7); IREG(8); IREG(9); IREG(10); IREG(11); IREG(12); IREG(13);
140             IREG(14); IREG(15); IREG(16); IREG(17); IREG(18); IREG(19);
141             IREG(20); IREG(21); IREG(22); IREG(23); IREG(24); IREG(25);
142             IREG(26); IREG(27); IREG(28); IREG(29); IREG(30); IREG(31);
143             XREG(37,Xer);
144             XREG(38,Cr);
145
146         }
147         if (flags & CONTEXT_CONTROL)
148         {
149             XREG(32,Iar);
150             XREG(33,Msr);
151             XREG(35,Ctr);
152             XREG(36,Lr);
153         }
154     }
155     if (flags & CONTEXT_FLOATING_POINT)
156     {
157         FREG(0);
158         FREG(1);
159         FREG(2);
160         FREG(3);
161         FREG(4);
162         FREG(5);
163         FREG(6);
164         FREG(7);
165         FREG(8);
166         FREG(9);
167         FREG(10);
168         FREG(11);
169         FREG(12);
170         FREG(13);
171         FREG(14);
172         FREG(15);
173         FREG(16);
174         FREG(17);
175         FREG(18);
176         FREG(19);
177         FREG(20);
178         FREG(21);
179         FREG(22);
180         FREG(23);
181         FREG(24);
182         FREG(25);
183         FREG(26);
184         FREG(27);
185         FREG(28);
186         FREG(29);
187         FREG(30);
188         FREG(31);
189 #undef FREG
190         XREG((48+32*2),Fpscr);
191     }
192     return;
193  error:
194     file_set_error();
195 }
196 #undef XREG
197 #undef IREG
198 #undef FREG
199
200 #define IREG(x) to->Gpr##x = from->Gpr##x;
201 #define FREG(x) to->Fpr##x = from->Fpr##x;
202 #define CREG(x) to->x = from->x;
203 /* copy a context structure according to the flags */
204 static void copy_context( CONTEXT *to, const CONTEXT *from, unsigned int flags )
205 {
206     if (flags & CONTEXT_CONTROL)
207     {
208         CREG(Msr);
209         CREG(Ctr);
210         CREG(Iar);
211         to->ContextFlags |= CONTEXT_CONTROL;
212     }
213     if (flags & CONTEXT_INTEGER)
214     {
215         IREG(0); IREG(1); IREG(2); IREG(3); IREG(4); IREG(5); IREG(6);
216         IREG(7); IREG(8); IREG(9); IREG(10); IREG(11); IREG(12); IREG(13);
217         IREG(14); IREG(15); IREG(16); IREG(17); IREG(18); IREG(19);
218         IREG(20); IREG(21); IREG(22); IREG(23); IREG(24); IREG(25);
219         IREG(26); IREG(27); IREG(28); IREG(29); IREG(30); IREG(31);
220         CREG(Xer);
221         CREG(Cr);
222         to->ContextFlags |= CONTEXT_INTEGER;
223     }
224     if (flags & CONTEXT_FLOATING_POINT)
225     {
226         FREG(0);
227         FREG(1);
228         FREG(2);
229         FREG(3);
230         FREG(4);
231         FREG(5);
232         FREG(6);
233         FREG(7);
234         FREG(8);
235         FREG(9);
236         FREG(10);
237         FREG(11);
238         FREG(12);
239         FREG(13);
240         FREG(14);
241         FREG(15);
242         FREG(16);
243         FREG(17);
244         FREG(18);
245         FREG(19);
246         FREG(20);
247         FREG(21);
248         FREG(22);
249         FREG(23);
250         FREG(24);
251         FREG(25);
252         FREG(26);
253         FREG(27);
254         FREG(28);
255         FREG(29);
256         FREG(30);
257         FREG(31);
258         CREG(Fpscr);
259         to->ContextFlags |= CONTEXT_FLOATING_POINT;
260     }
261 }
262
263 /* retrieve the current instruction pointer of a thread */
264 void *get_thread_ip( struct thread *thread )
265 {
266     CONTEXT context;
267     context.Iar = 0;
268     if (suspend_for_ptrace( thread ))
269     {
270         get_thread_context_ptrace( thread, CONTEXT_CONTROL, &context );
271         resume_after_ptrace( thread );
272     }
273     return (void *)context.Iar;
274 }
275
276 /* retrieve the thread context */
277 void get_thread_context( struct thread *thread, CONTEXT *context, unsigned int flags )
278 {
279     if (thread->context)  /* thread is inside an exception event or suspended */
280     {
281         copy_context( context, thread->context, flags );
282     }
283     else if (flags && suspend_for_ptrace( thread ))
284     {
285         get_thread_context_ptrace( thread, flags, context );
286         resume_after_ptrace( thread );
287     }
288 }
289
290 /* set the thread context */
291 void set_thread_context( struct thread *thread, const CONTEXT *context, unsigned int flags )
292 {
293     if (thread->context)  /* thread is inside an exception event or suspended */
294     {
295         copy_context( thread->context, context, flags );
296     }
297     else if (flags && suspend_for_ptrace( thread ))
298     {
299         set_thread_context_ptrace( thread, flags, context );
300         resume_after_ptrace( thread );
301     }
302 }
303
304 #endif  /* __powerpc__ */