]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gdb/armnbsd-nat.c
0779c144bd07548e11ccec5af08acc5ed345cc48
[thirdparty/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-2013 Free Software Foundation, Inc.
4
5 This file is part of GDB.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19
20 #include "defs.h"
21 #include "gdbcore.h"
22 #include "inferior.h"
23 #include "regcache.h"
24 #include "target.h"
25
26 #include <string.h>
27 #include <sys/types.h>
28 #include <sys/ptrace.h>
29 #include <machine/reg.h>
30 #include <machine/frame.h>
31
32 #include "arm-tdep.h"
33 #include "inf-ptrace.h"
34
35 extern int arm_apcs_32;
36
37 static void
38 arm_supply_gregset (struct regcache *regcache, struct reg *gregset)
39 {
40 int regno;
41 CORE_ADDR r_pc;
42
43 /* Integer registers. */
44 for (regno = ARM_A1_REGNUM; regno < ARM_SP_REGNUM; regno++)
45 regcache_raw_supply (regcache, regno, (char *) &gregset->r[regno]);
46
47 regcache_raw_supply (regcache, ARM_SP_REGNUM,
48 (char *) &gregset->r_sp);
49 regcache_raw_supply (regcache, ARM_LR_REGNUM,
50 (char *) &gregset->r_lr);
51 /* This is ok: we're running native... */
52 r_pc = gdbarch_addr_bits_remove (get_regcache_arch (regcache), gregset->r_pc);
53 regcache_raw_supply (regcache, ARM_PC_REGNUM, (char *) &r_pc);
54
55 if (arm_apcs_32)
56 regcache_raw_supply (regcache, ARM_PS_REGNUM,
57 (char *) &gregset->r_cpsr);
58 else
59 regcache_raw_supply (regcache, ARM_PS_REGNUM,
60 (char *) &gregset->r_pc);
61 }
62
63 static void
64 arm_supply_fparegset (struct regcache *regcache, struct fpreg *fparegset)
65 {
66 int regno;
67
68 for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++)
69 regcache_raw_supply (regcache, regno,
70 (char *) &fparegset->fpr[regno - ARM_F0_REGNUM]);
71
72 regcache_raw_supply (regcache, ARM_FPS_REGNUM,
73 (char *) &fparegset->fpr_fpsr);
74 }
75
76 static void
77 fetch_register (struct regcache *regcache, int regno)
78 {
79 struct reg inferior_registers;
80 int ret;
81
82 ret = ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid),
83 (PTRACE_TYPE_ARG3) &inferior_registers, 0);
84
85 if (ret < 0)
86 {
87 warning (_("unable to fetch general register"));
88 return;
89 }
90
91 switch (regno)
92 {
93 case ARM_SP_REGNUM:
94 regcache_raw_supply (regcache, ARM_SP_REGNUM,
95 (char *) &inferior_registers.r_sp);
96 break;
97
98 case ARM_LR_REGNUM:
99 regcache_raw_supply (regcache, ARM_LR_REGNUM,
100 (char *) &inferior_registers.r_lr);
101 break;
102
103 case ARM_PC_REGNUM:
104 /* This is ok: we're running native... */
105 inferior_registers.r_pc = gdbarch_addr_bits_remove
106 (get_regcache_arch (regcache),
107 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, ptid_get_pid (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, ptid_get_pid (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, ptid_get_pid (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 target_ops *ops,
197 struct regcache *regcache, int regno)
198 {
199 if (regno >= 0)
200 {
201 if (regno < ARM_F0_REGNUM || regno > ARM_FPS_REGNUM)
202 fetch_register (regcache, regno);
203 else
204 fetch_fp_register (regcache, regno);
205 }
206 else
207 {
208 fetch_regs (regcache);
209 fetch_fp_regs (regcache);
210 }
211 }
212
213
214 static void
215 store_register (const struct regcache *regcache, int regno)
216 {
217 struct gdbarch *gdbarch = get_regcache_arch (regcache);
218 struct reg inferior_registers;
219 int ret;
220
221 ret = ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid),
222 (PTRACE_TYPE_ARG3) &inferior_registers, 0);
223
224 if (ret < 0)
225 {
226 warning (_("unable to fetch general registers"));
227 return;
228 }
229
230 switch (regno)
231 {
232 case ARM_SP_REGNUM:
233 regcache_raw_collect (regcache, ARM_SP_REGNUM,
234 (char *) &inferior_registers.r_sp);
235 break;
236
237 case ARM_LR_REGNUM:
238 regcache_raw_collect (regcache, ARM_LR_REGNUM,
239 (char *) &inferior_registers.r_lr);
240 break;
241
242 case ARM_PC_REGNUM:
243 if (arm_apcs_32)
244 regcache_raw_collect (regcache, ARM_PC_REGNUM,
245 (char *) &inferior_registers.r_pc);
246 else
247 {
248 unsigned pc_val;
249
250 regcache_raw_collect (regcache, ARM_PC_REGNUM,
251 (char *) &pc_val);
252
253 pc_val = gdbarch_addr_bits_remove (gdbarch, pc_val);
254 inferior_registers.r_pc ^= gdbarch_addr_bits_remove
255 (gdbarch, inferior_registers.r_pc);
256 inferior_registers.r_pc |= pc_val;
257 }
258 break;
259
260 case ARM_PS_REGNUM:
261 if (arm_apcs_32)
262 regcache_raw_collect (regcache, ARM_PS_REGNUM,
263 (char *) &inferior_registers.r_cpsr);
264 else
265 {
266 unsigned psr_val;
267
268 regcache_raw_collect (regcache, ARM_PS_REGNUM,
269 (char *) &psr_val);
270
271 psr_val ^= gdbarch_addr_bits_remove (gdbarch, psr_val);
272 inferior_registers.r_pc = gdbarch_addr_bits_remove
273 (gdbarch, 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, ptid_get_pid (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 gdbarch *gdbarch = get_regcache_arch (regcache);
295 struct reg inferior_registers;
296 int ret;
297 int regno;
298
299
300 for (regno = ARM_A1_REGNUM; regno < ARM_SP_REGNUM; regno++)
301 regcache_raw_collect (regcache, regno,
302 (char *) &inferior_registers.r[regno]);
303
304 regcache_raw_collect (regcache, ARM_SP_REGNUM,
305 (char *) &inferior_registers.r_sp);
306 regcache_raw_collect (regcache, ARM_LR_REGNUM,
307 (char *) &inferior_registers.r_lr);
308
309 if (arm_apcs_32)
310 {
311 regcache_raw_collect (regcache, ARM_PC_REGNUM,
312 (char *) &inferior_registers.r_pc);
313 regcache_raw_collect (regcache, ARM_PS_REGNUM,
314 (char *) &inferior_registers.r_cpsr);
315 }
316 else
317 {
318 unsigned pc_val;
319 unsigned psr_val;
320
321 regcache_raw_collect (regcache, ARM_PC_REGNUM,
322 (char *) &pc_val);
323 regcache_raw_collect (regcache, ARM_PS_REGNUM,
324 (char *) &psr_val);
325
326 pc_val = gdbarch_addr_bits_remove (gdbarch, pc_val);
327 psr_val ^= gdbarch_addr_bits_remove (gdbarch, psr_val);
328
329 inferior_registers.r_pc = pc_val | psr_val;
330 }
331
332 ret = ptrace (PT_SETREGS, ptid_get_pid (inferior_ptid),
333 (PTRACE_TYPE_ARG3) &inferior_registers, 0);
334
335 if (ret < 0)
336 warning (_("unable to store general registers"));
337 }
338
339 static void
340 store_fp_register (const struct regcache *regcache, int regno)
341 {
342 struct fpreg inferior_fp_registers;
343 int ret;
344
345 ret = ptrace (PT_GETFPREGS, ptid_get_pid (inferior_ptid),
346 (PTRACE_TYPE_ARG3) &inferior_fp_registers, 0);
347
348 if (ret < 0)
349 {
350 warning (_("unable to fetch floating-point registers"));
351 return;
352 }
353
354 switch (regno)
355 {
356 case ARM_FPS_REGNUM:
357 regcache_raw_collect (regcache, ARM_FPS_REGNUM,
358 (char *) &inferior_fp_registers.fpr_fpsr);
359 break;
360
361 default:
362 regcache_raw_collect (regcache, regno,
363 (char *) &inferior_fp_registers.fpr[regno - ARM_F0_REGNUM]);
364 break;
365 }
366
367 ret = ptrace (PT_SETFPREGS, ptid_get_pid (inferior_ptid),
368 (PTRACE_TYPE_ARG3) &inferior_fp_registers, 0);
369
370 if (ret < 0)
371 warning (_("unable to write register %d to inferior"), regno);
372 }
373
374 static void
375 store_fp_regs (const struct regcache *regcache)
376 {
377 struct fpreg inferior_fp_registers;
378 int ret;
379 int regno;
380
381
382 for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++)
383 regcache_raw_collect (regcache, regno,
384 (char *) &inferior_fp_registers.fpr[regno - ARM_F0_REGNUM]);
385
386 regcache_raw_collect (regcache, ARM_FPS_REGNUM,
387 (char *) &inferior_fp_registers.fpr_fpsr);
388
389 ret = ptrace (PT_SETFPREGS, ptid_get_pid (inferior_ptid),
390 (PTRACE_TYPE_ARG3) &inferior_fp_registers, 0);
391
392 if (ret < 0)
393 warning (_("unable to store floating-point registers"));
394 }
395
396 static void
397 armnbsd_store_registers (struct target_ops *ops,
398 struct regcache *regcache, int regno)
399 {
400 if (regno >= 0)
401 {
402 if (regno < ARM_F0_REGNUM || regno > ARM_FPS_REGNUM)
403 store_register (regcache, regno);
404 else
405 store_fp_register (regcache, regno);
406 }
407 else
408 {
409 store_regs (regcache);
410 store_fp_regs (regcache);
411 }
412 }
413
414 struct md_core
415 {
416 struct reg intreg;
417 struct fpreg freg;
418 };
419
420 static void
421 fetch_core_registers (struct regcache *regcache,
422 char *core_reg_sect, unsigned core_reg_size,
423 int which, CORE_ADDR ignore)
424 {
425 struct md_core *core_reg = (struct md_core *) core_reg_sect;
426 int regno;
427 CORE_ADDR r_pc;
428
429 arm_supply_gregset (regcache, &core_reg->intreg);
430 arm_supply_fparegset (regcache, &core_reg->freg);
431 }
432
433 static void
434 fetch_elfcore_registers (struct regcache *regcache,
435 char *core_reg_sect, unsigned core_reg_size,
436 int which, CORE_ADDR ignore)
437 {
438 struct reg gregset;
439 struct fpreg fparegset;
440
441 switch (which)
442 {
443 case 0: /* Integer registers. */
444 if (core_reg_size != sizeof (struct reg))
445 warning (_("wrong size of register set in core file"));
446 else
447 {
448 /* The memcpy may be unnecessary, but we can't really be sure
449 of the alignment of the data in the core file. */
450 memcpy (&gregset, core_reg_sect, sizeof (gregset));
451 arm_supply_gregset (regcache, &gregset);
452 }
453 break;
454
455 case 2:
456 if (core_reg_size != sizeof (struct fpreg))
457 warning (_("wrong size of FPA register set in core file"));
458 else
459 {
460 /* The memcpy may be unnecessary, but we can't really be sure
461 of the alignment of the data in the core file. */
462 memcpy (&fparegset, core_reg_sect, sizeof (fparegset));
463 arm_supply_fparegset (regcache, &fparegset);
464 }
465 break;
466
467 default:
468 /* Don't know what kind of register request this is; just ignore it. */
469 break;
470 }
471 }
472
473 static struct core_fns arm_netbsd_core_fns =
474 {
475 bfd_target_unknown_flavour, /* core_flovour. */
476 default_check_format, /* check_format. */
477 default_core_sniffer, /* core_sniffer. */
478 fetch_core_registers, /* core_read_registers. */
479 NULL
480 };
481
482 static struct core_fns arm_netbsd_elfcore_fns =
483 {
484 bfd_target_elf_flavour, /* core_flovour. */
485 default_check_format, /* check_format. */
486 default_core_sniffer, /* core_sniffer. */
487 fetch_elfcore_registers, /* core_read_registers. */
488 NULL
489 };
490
491 void
492 _initialize_arm_netbsd_nat (void)
493 {
494 struct target_ops *t;
495
496 t = inf_ptrace_target ();
497 t->to_fetch_registers = armnbsd_fetch_registers;
498 t->to_store_registers = armnbsd_store_registers;
499 add_target (t);
500
501 deprecated_add_core_fns (&arm_netbsd_core_fns);
502 deprecated_add_core_fns (&arm_netbsd_elfcore_fns);
503 }