2 * Alpha register context support
4 * Copyright (C) 2004 Vincent BĂ©ron
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.
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.
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
32 #ifdef HAVE_SYS_PTRACE_H
33 # include <sys/ptrace.h>
40 #ifdef HAVE_SYS_USER_H
41 # include <sys/user.h>
44 /* user definitions from asm/user.h */
45 struct kernel_user_struct
47 unsigned long regs[EF_SIZE/8+32];
51 unsigned long start_code;
52 unsigned long start_data;
53 unsigned long start_stack;
60 /* get thread context */
61 static void get_thread_context( struct thread *thread, unsigned int flags, CONTEXT *context )
63 int pid = get_ptrace_pid(thread);
64 if (flags & CONTEXT_FULL)
66 struct kernel_user_struct regs;
67 if (ptrace( PTRACE_GETREGS, pid, 0, ®s ) == -1) goto error;
68 if (flags & CONTEXT_INTEGER)
70 context->IntV0 = regs.regs[EF_V0];
71 context->IntT0 = regs.regs[EF_T0];
72 context->IntT1 = regs.regs[EF_T1];
73 context->IntT2 = regs.regs[EF_T2];
74 context->IntT3 = regs.regs[EF_T3];
75 context->IntT4 = regs.regs[EF_T4];
76 context->IntT5 = regs.regs[EF_T5];
77 context->IntT6 = regs.regs[EF_T6];
78 context->IntT7 = regs.regs[EF_T7];
79 context->IntS0 = regs.regs[EF_S0];
80 context->IntS1 = regs.regs[EF_S1];
81 context->IntS2 = regs.regs[EF_S2];
82 context->IntS3 = regs.regs[EF_S3];
83 context->IntS4 = regs.regs[EF_S4];
84 context->IntS5 = regs.regs[EF_S5];
85 context->IntFp = regs.regs[EF_S6];
86 context->IntA0 = regs.regs[EF_A0];
87 context->IntA1 = regs.regs[EF_A1];
88 context->IntA2 = regs.regs[EF_A2];
89 context->IntA3 = regs.regs[EF_A3];
90 context->IntA4 = regs.regs[EF_A4];
91 context->IntA5 = regs.regs[EF_A5];
92 context->IntT8 = regs.regs[EF_T8];
93 context->IntT9 = regs.regs[EF_T9];
94 context->IntT10 = regs.regs[EF_T10];
95 context->IntT11 = regs.regs[EF_T11];
96 context->IntT12 = regs.regs[EF_T12];
97 context->IntAt = regs.regs[EF_AT];
100 if (flags & CONTEXT_CONTROL)
102 context->IntRa = regs.regs[EF_RA];
103 context->IntGp = regs.regs[EF_GP];
104 context->IntSp = regs.regs[EF_SP];
105 context->Fir = regs.regs[EF_PC];
106 context->Psr = regs.regs[EF_PS];
108 if (flags & CONTEXT_FLOATING_POINT)
110 context->FltF0 = regs.regs[EF_SIZE/8+0];
111 context->FltF1 = regs.regs[EF_SIZE/8+1];
112 context->FltF2 = regs.regs[EF_SIZE/8+2];
113 context->FltF3 = regs.regs[EF_SIZE/8+3];
114 context->FltF4 = regs.regs[EF_SIZE/8+4];
115 context->FltF5 = regs.regs[EF_SIZE/8+5];
116 context->FltF6 = regs.regs[EF_SIZE/8+6];
117 context->FltF7 = regs.regs[EF_SIZE/8+7];
118 context->FltF8 = regs.regs[EF_SIZE/8+8];
119 context->FltF9 = regs.regs[EF_SIZE/8+9];
120 context->FltF10 = regs.regs[EF_SIZE/8+10];
121 context->FltF11 = regs.regs[EF_SIZE/8+11];
122 context->FltF12 = regs.regs[EF_SIZE/8+12];
123 context->FltF13 = regs.regs[EF_SIZE/8+13];
124 context->FltF14 = regs.regs[EF_SIZE/8+14];
125 context->FltF15 = regs.regs[EF_SIZE/8+15];
126 context->FltF16 = regs.regs[EF_SIZE/8+16];
127 context->FltF17 = regs.regs[EF_SIZE/8+17];
128 context->FltF18 = regs.regs[EF_SIZE/8+18];
129 context->FltF19 = regs.regs[EF_SIZE/8+19];
130 context->FltF20 = regs.regs[EF_SIZE/8+20];
131 context->FltF21 = regs.regs[EF_SIZE/8+21];
132 context->FltF22 = regs.regs[EF_SIZE/8+22];
133 context->FltF23 = regs.regs[EF_SIZE/8+23];
134 context->FltF24 = regs.regs[EF_SIZE/8+24];
135 context->FltF25 = regs.regs[EF_SIZE/8+25];
136 context->FltF26 = regs.regs[EF_SIZE/8+26];
137 context->FltF27 = regs.regs[EF_SIZE/8+27];
138 context->FltF28 = regs.regs[EF_SIZE/8+28];
139 context->FltF29 = regs.regs[EF_SIZE/8+29];
140 context->FltF30 = regs.regs[EF_SIZE/8+30];
142 context->Fpcr = regs.regs[EF_SIZE/8+31];
143 context->SoftFpcr = 0; /* FIXME */
145 if (ptrace( PTRACE_SETREGS, pid, 0, ®s ) == -1) goto error;
152 /* set a thread context */
153 static void set_thread_context( struct thread *thread, unsigned int flags, const CONTEXT *context )
155 int pid = get_ptrace_pid(thread);
156 if (flags & CONTEXT_FULL)
158 struct kernel_user_struct regs;
159 if (ptrace( PTRACE_GETREGS, pid, 0, ®s ) == -1) goto error;
160 if (flags & CONTEXT_INTEGER)
162 regs.regs[EF_V0] = context->IntV0;
163 regs.regs[EF_T0] = context->IntT0;
164 regs.regs[EF_T1] = context->IntT1;
165 regs.regs[EF_T2] = context->IntT2;
166 regs.regs[EF_T3] = context->IntT3;
167 regs.regs[EF_T4] = context->IntT4;
168 regs.regs[EF_T5] = context->IntT5;
169 regs.regs[EF_T6] = context->IntT6;
170 regs.regs[EF_T7] = context->IntT7;
171 regs.regs[EF_S0] = context->IntS0;
172 regs.regs[EF_S1] = context->IntS1;
173 regs.regs[EF_S2] = context->IntS2;
174 regs.regs[EF_S3] = context->IntS3;
175 regs.regs[EF_S4] = context->IntS4;
176 regs.regs[EF_S5] = context->IntS5;
177 regs.regs[EF_S6] = context->IntFp;
178 regs.regs[EF_A0] = context->IntA0;
179 regs.regs[EF_A1] = context->IntA1;
180 regs.regs[EF_A2] = context->IntA2;
181 regs.regs[EF_A3] = context->IntA3;
182 regs.regs[EF_A4] = context->IntA4;
183 regs.regs[EF_A5] = context->IntA5;
184 regs.regs[EF_T8] = context->IntT8;
185 regs.regs[EF_T9] = context->IntT9;
186 regs.regs[EF_T10] = context->IntT10;
187 regs.regs[EF_T11] = context->IntT11;
188 regs.regs[EF_T12] = context->IntT12;
189 regs.regs[EF_AT] = context->IntAt;
191 if (flags & CONTEXT_CONTROL)
193 regs.regs[EF_RA] = context->IntRa;
194 regs.regs[EF_GP] = context->IntGp;
195 regs.regs[EF_SP] = context->IntSp;
196 regs.regs[EF_PC] = context->Fir;
197 regs.regs[EF_PS] = context->Psr;
199 if (flags & CONTEXT_FLOATING_POINT)
201 regs.regs[EF_SIZE/8+0] = context->FltF0;
202 regs.regs[EF_SIZE/8+1] = context->FltF1;
203 regs.regs[EF_SIZE/8+2] = context->FltF2;
204 regs.regs[EF_SIZE/8+3] = context->FltF3;
205 regs.regs[EF_SIZE/8+4] = context->FltF4;
206 regs.regs[EF_SIZE/8+5] = context->FltF5;
207 regs.regs[EF_SIZE/8+6] = context->FltF6;
208 regs.regs[EF_SIZE/8+7] = context->FltF7;
209 regs.regs[EF_SIZE/8+8] = context->FltF8;
210 regs.regs[EF_SIZE/8+9] = context->FltF9;
211 regs.regs[EF_SIZE/8+10] = context->FltF10;
212 regs.regs[EF_SIZE/8+11] = context->FltF11;
213 regs.regs[EF_SIZE/8+12] = context->FltF12;
214 regs.regs[EF_SIZE/8+13] = context->FltF13;
215 regs.regs[EF_SIZE/8+14] = context->FltF14;
216 regs.regs[EF_SIZE/8+15] = context->FltF15;
217 regs.regs[EF_SIZE/8+16] = context->FltF16;
218 regs.regs[EF_SIZE/8+17] = context->FltF17;
219 regs.regs[EF_SIZE/8+18] = context->FltF18;
220 regs.regs[EF_SIZE/8+19] = context->FltF19;
221 regs.regs[EF_SIZE/8+20] = context->FltF20;
222 regs.regs[EF_SIZE/8+21] = context->FltF21;
223 regs.regs[EF_SIZE/8+22] = context->FltF22;
224 regs.regs[EF_SIZE/8+23] = context->FltF23;
225 regs.regs[EF_SIZE/8+24] = context->FltF24;
226 regs.regs[EF_SIZE/8+25] = context->FltF25;
227 regs.regs[EF_SIZE/8+26] = context->FltF26;
228 regs.regs[EF_SIZE/8+27] = context->FltF27;
229 regs.regs[EF_SIZE/8+28] = context->FltF28;
230 regs.regs[EF_SIZE/8+29] = context->FltF29;
231 regs.regs[EF_SIZE/8+30] = context->FltF30;
232 regs.regs[EF_SIZE/8+31] = context->Fpcr;
240 /* copy a context structure according to the flags */
241 static void copy_context( CONTEXT *to, const CONTEXT *from, int flags )
243 if (flags & CONTEXT_CONTROL)
245 to->IntRa = from->IntRa;
246 to->IntGp = from->IntGp;
247 to->IntSp = from->IntSp;
251 if (flags & CONTEXT_INTEGER)
253 to->IntV0 = from->IntV0;
254 to->IntT0 = from->IntT0;
255 to->IntT1 = from->IntT1;
256 to->IntT2 = from->IntT2;
257 to->IntT3 = from->IntT3;
258 to->IntT4 = from->IntT4;
259 to->IntT5 = from->IntT5;
260 to->IntT6 = from->IntT6;
261 to->IntT7 = from->IntT7;
262 to->IntS0 = from->IntS0;
263 to->IntS1 = from->IntS1;
264 to->IntS2 = from->IntS2;
265 to->IntS3 = from->IntS3;
266 to->IntS4 = from->IntS4;
267 to->IntS5 = from->IntS5;
268 to->IntFp = from->IntFp;
269 to->IntA0 = from->IntA0;
270 to->IntA1 = from->IntA1;
271 to->IntA2 = from->IntA2;
272 to->IntA3 = from->IntA3;
273 to->IntA4 = from->IntA4;
274 to->IntA5 = from->IntA5;
275 to->IntT8 = from->IntT8;
276 to->IntT9 = from->IntT9;
277 to->IntT10 = from->IntT10;
278 to->IntT11 = from->IntT11;
279 to->IntT12 = from->IntT12;
280 to->IntAt = from->IntAt;
281 to->IntZero = from->IntZero;
283 if (flags & CONTEXT_FLOATING_POINT)
285 to->FltF0 = from->FltF0;
286 to->FltF1 = from->FltF1;
287 to->FltF2 = from->FltF2;
288 to->FltF3 = from->FltF3;
289 to->FltF4 = from->FltF4;
290 to->FltF5 = from->FltF5;
291 to->FltF6 = from->FltF6;
292 to->FltF7 = from->FltF7;
293 to->FltF8 = from->FltF8;
294 to->FltF9 = from->FltF9;
295 to->FltF10 = from->FltF10;
296 to->FltF11 = from->FltF11;
297 to->FltF12 = from->FltF12;
298 to->FltF13 = from->FltF13;
299 to->FltF14 = from->FltF14;
300 to->FltF15 = from->FltF15;
301 to->FltF16 = from->FltF16;
302 to->FltF17 = from->FltF17;
303 to->FltF18 = from->FltF18;
304 to->FltF19 = from->FltF19;
305 to->FltF20 = from->FltF20;
306 to->FltF21 = from->FltF21;
307 to->FltF22 = from->FltF22;
308 to->FltF23 = from->FltF23;
309 to->FltF24 = from->FltF24;
310 to->FltF25 = from->FltF25;
311 to->FltF26 = from->FltF26;
312 to->FltF27 = from->FltF27;
313 to->FltF28 = from->FltF28;
314 to->FltF29 = from->FltF29;
315 to->FltF30 = from->FltF30;
316 to->FltF31 = from->FltF31;
317 to->Fpcr = from->Fpcr;
318 to->SoftFpcr = from->SoftFpcr;
322 /* retrieve the current instruction pointer of a thread */
323 void *get_thread_ip( struct thread *thread )
327 if (suspend_for_ptrace( thread ))
329 get_thread_context( thread, CONTEXT_CONTROL, &context );
330 resume_after_ptrace( thread );
332 return (void *)context.Fir;
335 /* determine if we should continue the thread in single-step mode */
336 int get_thread_single_step( struct thread *thread )
338 return 0; /* FIXME */
341 /* send a signal to a specific thread */
342 int tkill( int pid, int sig )
344 /* FIXME: should do something here */
349 /* retrieve the current context of a thread */
350 DECL_HANDLER(get_thread_context)
352 struct thread *thread;
354 int flags = req->flags & ~CONTEXT_ALPHA; /* get rid of CPU id */
356 if (get_reply_max_size() < sizeof(CONTEXT))
358 set_error( STATUS_INVALID_PARAMETER );
361 if (!(thread = get_thread_from_handle( req->handle, THREAD_GET_CONTEXT ))) return;
363 if ((data = set_reply_data_size( sizeof(CONTEXT) )))
365 if (thread->context) /* thread is inside an exception event */
367 copy_context( data, thread->context, flags );
370 if (flags && suspend_for_ptrace( thread ))
372 get_thread_context( thread, flags, data );
373 resume_after_ptrace( thread );
376 release_object( thread );
379 /* set the current context of a thread */
380 DECL_HANDLER(set_thread_context)
382 struct thread *thread;
383 int flags = req->flags & ~CONTEXT_ALPHA; /* get rid of CPU id */
385 if (get_req_data_size() < sizeof(CONTEXT))
387 set_error( STATUS_INVALID_PARAMETER );
390 if ((thread = get_thread_from_handle( req->handle, THREAD_SET_CONTEXT )))
392 if (thread->context) /* thread is inside an exception event */
394 copy_context( thread->context, get_req_data(), flags );
397 if (flags && suspend_for_ptrace( thread ))
399 set_thread_context( thread, flags, get_req_data() );
400 resume_after_ptrace( thread );
402 release_object( thread );
406 #endif /* __ALPHA__ */