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 context
->ContextFlags
|= flags
& CONTEXT_FULL
;
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
;
234 if (ptrace( PTRACE_SETREGS
, pid
, 0, ®s
) == -1) goto error
;
241 /* copy a context structure according to the flags */
242 static void copy_context( CONTEXT
*to
, const CONTEXT
*from
, unsigned int flags
)
244 if (flags
& CONTEXT_CONTROL
)
246 to
->IntRa
= from
->IntRa
;
247 to
->IntGp
= from
->IntGp
;
248 to
->IntSp
= from
->IntSp
;
252 if (flags
& CONTEXT_INTEGER
)
254 to
->IntV0
= from
->IntV0
;
255 to
->IntT0
= from
->IntT0
;
256 to
->IntT1
= from
->IntT1
;
257 to
->IntT2
= from
->IntT2
;
258 to
->IntT3
= from
->IntT3
;
259 to
->IntT4
= from
->IntT4
;
260 to
->IntT5
= from
->IntT5
;
261 to
->IntT6
= from
->IntT6
;
262 to
->IntT7
= from
->IntT7
;
263 to
->IntS0
= from
->IntS0
;
264 to
->IntS1
= from
->IntS1
;
265 to
->IntS2
= from
->IntS2
;
266 to
->IntS3
= from
->IntS3
;
267 to
->IntS4
= from
->IntS4
;
268 to
->IntS5
= from
->IntS5
;
269 to
->IntFp
= from
->IntFp
;
270 to
->IntA0
= from
->IntA0
;
271 to
->IntA1
= from
->IntA1
;
272 to
->IntA2
= from
->IntA2
;
273 to
->IntA3
= from
->IntA3
;
274 to
->IntA4
= from
->IntA4
;
275 to
->IntA5
= from
->IntA5
;
276 to
->IntT8
= from
->IntT8
;
277 to
->IntT9
= from
->IntT9
;
278 to
->IntT10
= from
->IntT10
;
279 to
->IntT11
= from
->IntT11
;
280 to
->IntT12
= from
->IntT12
;
281 to
->IntAt
= from
->IntAt
;
282 to
->IntZero
= from
->IntZero
;
284 if (flags
& CONTEXT_FLOATING_POINT
)
286 to
->FltF0
= from
->FltF0
;
287 to
->FltF1
= from
->FltF1
;
288 to
->FltF2
= from
->FltF2
;
289 to
->FltF3
= from
->FltF3
;
290 to
->FltF4
= from
->FltF4
;
291 to
->FltF5
= from
->FltF5
;
292 to
->FltF6
= from
->FltF6
;
293 to
->FltF7
= from
->FltF7
;
294 to
->FltF8
= from
->FltF8
;
295 to
->FltF9
= from
->FltF9
;
296 to
->FltF10
= from
->FltF10
;
297 to
->FltF11
= from
->FltF11
;
298 to
->FltF12
= from
->FltF12
;
299 to
->FltF13
= from
->FltF13
;
300 to
->FltF14
= from
->FltF14
;
301 to
->FltF15
= from
->FltF15
;
302 to
->FltF16
= from
->FltF16
;
303 to
->FltF17
= from
->FltF17
;
304 to
->FltF18
= from
->FltF18
;
305 to
->FltF19
= from
->FltF19
;
306 to
->FltF20
= from
->FltF20
;
307 to
->FltF21
= from
->FltF21
;
308 to
->FltF22
= from
->FltF22
;
309 to
->FltF23
= from
->FltF23
;
310 to
->FltF24
= from
->FltF24
;
311 to
->FltF25
= from
->FltF25
;
312 to
->FltF26
= from
->FltF26
;
313 to
->FltF27
= from
->FltF27
;
314 to
->FltF28
= from
->FltF28
;
315 to
->FltF29
= from
->FltF29
;
316 to
->FltF30
= from
->FltF30
;
317 to
->FltF31
= from
->FltF31
;
318 to
->Fpcr
= from
->Fpcr
;
319 to
->SoftFpcr
= from
->SoftFpcr
;
321 to
->ContextFlags
|= flags
;
324 /* retrieve the current instruction pointer of a context */
325 void *get_context_ip( const CONTEXT
*context
)
327 return (void *)context
->Fir
;
330 /* retrieve the thread context */
331 void get_thread_context( struct thread
*thread
, CONTEXT
*context
, unsigned int flags
)
333 context
->ContextFlags
|= CONTEXT_ALPHA
;
334 flags
&= ~CONTEXT_ALPHA
; /* get rid of CPU id */
336 if (thread
->context
) /* thread is inside an exception event or suspended */
338 copy_context( context
, thread
->context
, flags
);
340 else if (flags
&& suspend_for_ptrace( thread
))
342 get_thread_context_ptrace( thread
, flags
, context
);
343 resume_after_ptrace( thread
);
347 /* set the thread context */
348 void set_thread_context( struct thread
*thread
, const CONTEXT
*context
, unsigned int flags
)
350 flags
&= ~CONTEXT_ALPHA
; /* get rid of CPU id */
352 if (thread
->context
) /* thread is inside an exception event or suspended */
354 copy_context( thread
->context
, context
, flags
);
356 else if (flags
&& suspend_for_ptrace( thread
))
358 set_thread_context_ptrace( thread
, flags
, context
);
359 resume_after_ptrace( thread
);
363 #endif /* __ALPHA__ */