2007-10-08 Markus Deuling <deuling@de.ibm.com>
[deliverable/binutils-gdb.git] / gdb / armnbsd-nat.c
1 /* Native-dependent code for BSD Unix running on ARM's, for GDB.
2
3 Copyright (C) 1988, 1989, 1991, 1992, 1994, 1996, 1999, 2002, 2004, 2007
4 Free Software Foundation, Inc.
5
6 This file is part of GDB.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
20
21 #include "defs.h"
22 #include "gdbcore.h"
23 #include "inferior.h"
24 #include "regcache.h"
25 #include "target.h"
26
27 #include "gdb_string.h"
28 #include <sys/types.h>
29 #include <sys/ptrace.h>
30 #include <machine/reg.h>
31 #include <machine/frame.h>
32
33 #include "arm-tdep.h"
34 #include "inf-ptrace.h"
35
36 extern int arm_apcs_32;
37
38 static void
39 arm_supply_gregset (struct regcache *regcache, struct reg *gregset)
40 {
41 int regno;
42 CORE_ADDR r_pc;
43
44 /* Integer registers. */
45 for (regno = ARM_A1_REGNUM; regno < ARM_SP_REGNUM; regno++)
46 regcache_raw_supply (regcache, regno, (char *) &gregset->r[regno]);
47
48 regcache_raw_supply (regcache, ARM_SP_REGNUM,
49 (char *) &gregset->r_sp);
50 regcache_raw_supply (regcache, ARM_LR_REGNUM,
51 (char *) &gregset->r_lr);
52 /* This is ok: we're running native... */
53 r_pc = gdbarch_addr_bits_remove (current_gdbarch, gregset->r_pc);
54 regcache_raw_supply (regcache, ARM_PC_REGNUM, (char *) &r_pc);
55
56 if (arm_apcs_32)
57 regcache_raw_supply (regcache, ARM_PS_REGNUM,
58 (char *) &gregset->r_cpsr);
59 else
60 regcache_raw_supply (regcache, ARM_PS_REGNUM,
61 (char *) &gregset->r_pc);
62 }
63
64 static void
65 arm_supply_fparegset (struct regcache *regcache, struct fpreg *fparegset)
66 {
67 int regno;
68
69 for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++)
70 regcache_raw_supply (regcache, regno,
71 (char *) &fparegset->fpr[regno - ARM_F0_REGNUM]);
72
73 regcache_raw_supply (regcache, ARM_FPS_REGNUM,
74 (char *) &fparegset->fpr_fpsr);
75 }
76
77 static void
78 fetch_register (struct regcache *regcache, int regno)
79 {
80 struct reg inferior_registers;
81 int ret;
82
83 ret = ptrace (PT_GETREGS, PIDGET (inferior_ptid),
84 (PTRACE_TYPE_ARG3) &inferior_registers, 0);
85
86 if (ret < 0)
87 {
88 warning (_("unable to fetch general register"));
89 return;
90 }
91
92 switch (regno)
93 {
94 case ARM_SP_REGNUM:
95 regcache_raw_supply (regcache, ARM_SP_REGNUM,
96 (char *) &inferior_registers.r_sp);
97 break;
98
99 case ARM_LR_REGNUM:
100 regcache_raw_supply (regcache, ARM_LR_REGNUM,
101 (char *) &inferior_registers.r_lr);
102 break;
103
104 case ARM_PC_REGNUM:
105 /* This is ok: we're running native... */
106 inferior_registers.r_pc = gdbarch_addr_bits_remove
107 (current_gdbarch, inferior_registers.r_pc);
108 regcache_raw_supply (regcache, ARM_PC_REGNUM,
109 (char *) &inferior_registers.r_pc);
110 break;
111
112 case ARM_PS_REGNUM:
113 if (arm_apcs_32)
114 regcache_raw_supply (regcache, ARM_PS_REGNUM,
115 (char *) &inferior_registers.r_cpsr);
116 else
117 regcache_raw_supply (regcache, ARM_PS_REGNUM,
118 (char *) &inferior_registers.r_pc);
119 break;
120
121 default:
122 regcache_raw_supply (regcache, regno,
123 (char *) &inferior_registers.r[regno]);
124 break;
125 }
126 }
127
128 static void
129 fetch_regs (struct regcache *regcache)
130 {
131 struct reg inferior_registers;
132 int ret;
133 int regno;
134
135 ret = ptrace (PT_GETREGS, PIDGET (inferior_ptid),
136 (PTRACE_TYPE_ARG3) &inferior_registers, 0);
137
138 if (ret < 0)
139 {
140 warning (_("unable to fetch general registers"));
141 return;
142 }
143
144 arm_supply_gregset (regcache, &inferior_registers);
145 }
146
147 static void
148 fetch_fp_register (struct regcache *regcache, int regno)
149 {
150 struct fpreg inferior_fp_registers;
151 int ret;
152
153 ret = ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
154 (PTRACE_TYPE_ARG3) &inferior_fp_registers, 0);
155
156 if (ret < 0)
157 {
158 warning (_("unable to fetch floating-point register"));
159 return;
160 }
161
162 switch (regno)
163 {
164 case ARM_FPS_REGNUM:
165 regcache_raw_supply (regcache, ARM_FPS_REGNUM,
166 (char *) &inferior_fp_registers.fpr_fpsr);
167 break;
168
169 default:
170 regcache_raw_supply (regcache, regno,
171 (char *) &inferior_fp_registers.fpr[regno - ARM_F0_REGNUM]);
172 break;
173 }
174 }
175
176 static void
177 fetch_fp_regs (struct regcache *regcache)
178 {
179 struct fpreg inferior_fp_registers;
180 int ret;
181 int regno;
182
183 ret = ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
184 (PTRACE_TYPE_ARG3) &inferior_fp_registers, 0);
185
186 if (ret < 0)
187 {
188 warning (_("unable to fetch general registers"));
189 return;
190 }
191
192 arm_supply_fparegset (regcache, &inferior_fp_registers);
193 }
194
195 static void
196 armnbsd_fetch_registers (struct regcache *regcache, int regno)
197 {
198 if (regno >= 0)
199 {
200 if (regno < ARM_F0_REGNUM || regno > ARM_FPS_REGNUM)
201 fetch_register (regcache, regno);
202 else
203 fetch_fp_register (regcache, regno);
204 }
205 else
206 {
207 fetch_regs (regcache);
208 fetch_fp_regs (regcache);
209 }
210 }
211
212
213 static void
214 store_register (const struct regcache *regcache, int regno)
215 {
216 struct reg inferior_registers;
217 int ret;
218
219 ret = ptrace (PT_GETREGS, PIDGET (inferior_ptid),
220 (PTRACE_TYPE_ARG3) &inferior_registers, 0);
221
222 if (ret < 0)
223 {
224 warning (_("unable to fetch general registers"));
225 return;
226 }
227
228 switch (regno)
229 {
230 case ARM_SP_REGNUM:
231 regcache_raw_collect (regcache, ARM_SP_REGNUM,
232 (char *) &inferior_registers.r_sp);
233 break;
234
235 case ARM_LR_REGNUM:
236 regcache_raw_collect (regcache, ARM_LR_REGNUM,
237 (char *) &inferior_registers.r_lr);
238 break;
239
240 case ARM_PC_REGNUM:
241 if (arm_apcs_32)
242 regcache_raw_collect (regcache, ARM_PC_REGNUM,
243 (char *) &inferior_registers.r_pc);
244 else
245 {
246 unsigned pc_val;
247
248 regcache_raw_collect (regcache, ARM_PC_REGNUM,
249 (char *) &pc_val);
250
251 pc_val = gdbarch_addr_bits_remove (current_gdbarch, pc_val);
252 inferior_registers.r_pc ^= gdbarch_addr_bits_remove
253 (current_gdbarch,
254 inferior_registers.r_pc);
255 inferior_registers.r_pc |= pc_val;
256 }
257 break;
258
259 case ARM_PS_REGNUM:
260 if (arm_apcs_32)
261 regcache_raw_collect (regcache, ARM_PS_REGNUM,
262 (char *) &inferior_registers.r_cpsr);
263 else
264 {
265 unsigned psr_val;
266
267 regcache_raw_collect (regcache, ARM_PS_REGNUM,
268 (char *) &psr_val);
269
270 psr_val ^= gdbarch_addr_bits_remove (current_gdbarch, psr_val);
271 inferior_registers.r_pc = gdbarch_addr_bits_remove
272 (current_gdbarch,
273 inferior_registers.r_pc);
274 inferior_registers.r_pc |= psr_val;
275 }
276 break;
277
278 default:
279 regcache_raw_collect (regcache, regno,
280 (char *) &inferior_registers.r[regno]);
281 break;
282 }
283
284 ret = ptrace (PT_SETREGS, PIDGET (inferior_ptid),
285 (PTRACE_TYPE_ARG3) &inferior_registers, 0);
286
287 if (ret < 0)
288 warning (_("unable to write register %d to inferior"), regno);
289 }
290
291 static void
292 store_regs (const struct regcache *regcache)
293 {
294 struct reg inferior_registers;
295 int ret;
296 int regno;
297
298
299 for (regno = ARM_A1_REGNUM; regno < ARM_SP_REGNUM; regno++)
300 regcache_raw_collect (regcache, regno,
301 (char *) &inferior_registers.r[regno]);
302
303 regcache_raw_collect (regcache, ARM_SP_REGNUM,
304 (char *) &inferior_registers.r_sp);
305 regcache_raw_collect (regcache, ARM_LR_REGNUM,
306 (char *) &inferior_registers.r_lr);
307
308 if (arm_apcs_32)
309 {
310 regcache_raw_collect (regcache, ARM_PC_REGNUM,
311 (char *) &inferior_registers.r_pc);
312 regcache_raw_collect (regcache, ARM_PS_REGNUM,
313 (char *) &inferior_registers.r_cpsr);
314 }
315 else
316 {
317 unsigned pc_val;
318 unsigned psr_val;
319
320 regcache_raw_collect (regcache, ARM_PC_REGNUM,
321 (char *) &pc_val);
322 regcache_raw_collect (regcache, ARM_PS_REGNUM,
323 (char *) &psr_val);
324
325 pc_val = gdbarch_addr_bits_remove (current_gdbarch, pc_val);
326 psr_val ^= gdbarch_addr_bits_remove (current_gdbarch, psr_val);
327
328 inferior_registers.r_pc = pc_val | psr_val;
329 }
330
331 ret = ptrace (PT_SETREGS, PIDGET (inferior_ptid),
332 (PTRACE_TYPE_ARG3) &inferior_registers, 0);
333
334 if (ret < 0)
335 warning (_("unable to store general registers"));
336 }
337
338 static void
339 store_fp_register (const struct regcache *regcache, int regno)
340 {
341 struct fpreg inferior_fp_registers;
342 int ret;
343
344 ret = ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
345 (PTRACE_TYPE_ARG3) &inferior_fp_registers, 0);
346
347 if (ret < 0)
348 {
349 warning (_("unable to fetch floating-point registers"));
350 return;
351 }
352
353 switch (regno)
354 {
355 case ARM_FPS_REGNUM:
356 regcache_raw_collect (regcache, ARM_FPS_REGNUM,
357 (char *) &inferior_fp_registers.fpr_fpsr);
358 break;
359
360 default:
361 regcache_raw_collect (regcache, regno,
362 (char *) &inferior_fp_registers.fpr[regno - ARM_F0_REGNUM]);
363 break;
364 }
365
366 ret = ptrace (PT_SETFPREGS, PIDGET (inferior_ptid),
367 (PTRACE_TYPE_ARG3) &inferior_fp_registers, 0);
368
369 if (ret < 0)
370 warning (_("unable to write register %d to inferior"), regno);
371 }
372
373 static void
374 store_fp_regs (const struct regcache *regcache)
375 {
376 struct fpreg inferior_fp_registers;
377 int ret;
378 int regno;
379
380
381 for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++)
382 regcache_raw_collect (regcache, regno,
383 (char *) &inferior_fp_registers.fpr[regno - ARM_F0_REGNUM]);
384
385 regcache_raw_collect (regcache, ARM_FPS_REGNUM,
386 (char *) &inferior_fp_registers.fpr_fpsr);
387
388 ret = ptrace (PT_SETFPREGS, PIDGET (inferior_ptid),
389 (PTRACE_TYPE_ARG3) &inferior_fp_registers, 0);
390
391 if (ret < 0)
392 warning (_("unable to store floating-point registers"));
393 }
394
395 static void
396 armnbsd_store_registers (struct regcache *regcache, int regno)
397 {
398 if (regno >= 0)
399 {
400 if (regno < ARM_F0_REGNUM || regno > ARM_FPS_REGNUM)
401 store_register (regcache, regno);
402 else
403 store_fp_register (regcache, regno);
404 }
405 else
406 {
407 store_regs (regcache);
408 store_fp_regs (regcache);
409 }
410 }
411
412 struct md_core
413 {
414 struct reg intreg;
415 struct fpreg freg;
416 };
417
418 static void
419 fetch_core_registers (struct regcache *regcache,
420 char *core_reg_sect, unsigned core_reg_size,
421 int which, CORE_ADDR ignore)
422 {
423 struct md_core *core_reg = (struct md_core *) core_reg_sect;
424 int regno;
425 CORE_ADDR r_pc;
426
427 arm_supply_gregset (regcache, &core_reg->intreg);
428 arm_supply_fparegset (regcache, &core_reg->freg);
429 }
430
431 static void
432 fetch_elfcore_registers (struct regcache *regcache,
433 char *core_reg_sect, unsigned core_reg_size,
434 int which, CORE_ADDR ignore)
435 {
436 struct reg gregset;
437 struct fpreg fparegset;
438
439 switch (which)
440 {
441 case 0: /* Integer registers. */
442 if (core_reg_size != sizeof (struct reg))
443 warning (_("wrong size of register set in core file"));
444 else
445 {
446 /* The memcpy may be unnecessary, but we can't really be sure
447 of the alignment of the data in the core file. */
448 memcpy (&gregset, core_reg_sect, sizeof (gregset));
449 arm_supply_gregset (regcache, &gregset);
450 }
451 break;
452
453 case 2:
454 if (core_reg_size != sizeof (struct fpreg))
455 warning (_("wrong size of FPA register set in core file"));
456 else
457 {
458 /* The memcpy may be unnecessary, but we can't really be sure
459 of the alignment of the data in the core file. */
460 memcpy (&fparegset, core_reg_sect, sizeof (fparegset));
461 arm_supply_fparegset (regcache, &fparegset);
462 }
463 break;
464
465 default:
466 /* Don't know what kind of register request this is; just ignore it. */
467 break;
468 }
469 }
470
471 static struct core_fns arm_netbsd_core_fns =
472 {
473 bfd_target_unknown_flavour, /* core_flovour. */
474 default_check_format, /* check_format. */
475 default_core_sniffer, /* core_sniffer. */
476 fetch_core_registers, /* core_read_registers. */
477 NULL
478 };
479
480 static struct core_fns arm_netbsd_elfcore_fns =
481 {
482 bfd_target_elf_flavour, /* core_flovour. */
483 default_check_format, /* check_format. */
484 default_core_sniffer, /* core_sniffer. */
485 fetch_elfcore_registers, /* core_read_registers. */
486 NULL
487 };
488
489 void
490 _initialize_arm_netbsd_nat (void)
491 {
492 struct target_ops *t;
493
494 t = inf_ptrace_target ();
495 t->to_fetch_registers = armnbsd_fetch_registers;
496 t->to_store_registers = armnbsd_store_registers;
497 add_target (t);
498
499 deprecated_add_core_fns (&arm_netbsd_core_fns);
500 deprecated_add_core_fns (&arm_netbsd_elfcore_fns);
501 }
This page took 0.040545 seconds and 4 git commands to generate.