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