Commit | Line | Data |
---|---|---|
e7a42bc8 | 1 | /* Native-dependent code for BSD Unix running on ARM's, for GDB. |
9f8e0089 | 2 | |
b811d2c2 | 3 | Copyright (C) 1988-2020 Free Software Foundation, Inc. |
e7a42bc8 FN |
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 | |
a9762ec7 | 9 | the Free Software Foundation; either version 3 of the License, or |
e7a42bc8 FN |
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 | |
a9762ec7 | 18 | along with this program. If not, see <http://www.gnu.org/licenses/>. */ |
e7a42bc8 | 19 | |
73685c7e CB |
20 | /* We define this to get types like register_t. */ |
21 | #define _KERNTYPES | |
e7a42bc8 | 22 | #include "defs.h" |
d55e5aa6 | 23 | #include "gdbcore.h" |
d55e5aa6 TT |
24 | #include "inferior.h" |
25 | #include "regcache.h" | |
26 | #include "target.h" | |
4de283e4 TT |
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" | |
e7a42bc8 | 34 | |
f6ac5f3d PA |
35 | class arm_netbsd_nat_target final : public inf_ptrace_target |
36 | { | |
37 | public: | |
38 | /* Add our register access methods. */ | |
39 | void fetch_registers (struct regcache *, int) override; | |
40 | void store_registers (struct regcache *, int) override; | |
41 | }; | |
42 | ||
43 | static arm_netbsd_nat_target the_arm_netbsd_nat_target; | |
44 | ||
b34db576 | 45 | static void |
d683e2b7 | 46 | arm_supply_gregset (struct regcache *regcache, struct reg *gregset) |
b34db576 RE |
47 | { |
48 | int regno; | |
49 | CORE_ADDR r_pc; | |
50 | ||
51 | /* Integer registers. */ | |
52 | for (regno = ARM_A1_REGNUM; regno < ARM_SP_REGNUM; regno++) | |
73e1c03f | 53 | regcache->raw_supply (regno, (char *) &gregset->r[regno]); |
b34db576 | 54 | |
73e1c03f SM |
55 | regcache->raw_supply (ARM_SP_REGNUM, (char *) &gregset->r_sp); |
56 | regcache->raw_supply (ARM_LR_REGNUM, (char *) &gregset->r_lr); | |
b34db576 | 57 | /* This is ok: we're running native... */ |
ac7936df | 58 | r_pc = gdbarch_addr_bits_remove (regcache->arch (), gregset->r_pc); |
73e1c03f | 59 | regcache->raw_supply (ARM_PC_REGNUM, (char *) &r_pc); |
b34db576 RE |
60 | |
61 | if (arm_apcs_32) | |
73e1c03f | 62 | regcache->raw_supply (ARM_PS_REGNUM, (char *) &gregset->r_cpsr); |
b34db576 | 63 | else |
73e1c03f | 64 | regcache->raw_supply (ARM_PS_REGNUM, (char *) &gregset->r_pc); |
b34db576 RE |
65 | } |
66 | ||
67 | static void | |
d683e2b7 | 68 | arm_supply_fparegset (struct regcache *regcache, struct fpreg *fparegset) |
b34db576 RE |
69 | { |
70 | int regno; | |
71 | ||
72 | for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++) | |
73e1c03f SM |
73 | regcache->raw_supply (regno, |
74 | (char *) &fparegset->fpr[regno - ARM_F0_REGNUM]); | |
b34db576 | 75 | |
73e1c03f | 76 | regcache->raw_supply (ARM_FPS_REGNUM, (char *) &fparegset->fpr_fpsr); |
b34db576 RE |
77 | } |
78 | ||
47221191 | 79 | static void |
56be3814 | 80 | fetch_register (struct regcache *regcache, int regno) |
47221191 RE |
81 | { |
82 | struct reg inferior_registers; | |
83 | int ret; | |
84 | ||
e99b03dc | 85 | ret = ptrace (PT_GETREGS, regcache->ptid ().pid (), |
9f8e0089 | 86 | (PTRACE_TYPE_ARG3) &inferior_registers, 0); |
47221191 RE |
87 | |
88 | if (ret < 0) | |
89 | { | |
edefbb7c | 90 | warning (_("unable to fetch general register")); |
47221191 RE |
91 | return; |
92 | } | |
93 | ||
94 | switch (regno) | |
95 | { | |
96 | case ARM_SP_REGNUM: | |
73e1c03f | 97 | regcache->raw_supply (ARM_SP_REGNUM, (char *) &inferior_registers.r_sp); |
47221191 RE |
98 | break; |
99 | ||
100 | case ARM_LR_REGNUM: | |
73e1c03f | 101 | regcache->raw_supply (ARM_LR_REGNUM, (char *) &inferior_registers.r_lr); |
47221191 RE |
102 | break; |
103 | ||
104 | case ARM_PC_REGNUM: | |
0963b4bd | 105 | /* This is ok: we're running native... */ |
bf6ae464 | 106 | inferior_registers.r_pc = gdbarch_addr_bits_remove |
ac7936df | 107 | (regcache->arch (), |
b2cb219a | 108 | inferior_registers.r_pc); |
73e1c03f | 109 | regcache->raw_supply (ARM_PC_REGNUM, (char *) &inferior_registers.r_pc); |
47221191 RE |
110 | break; |
111 | ||
112 | case ARM_PS_REGNUM: | |
113 | if (arm_apcs_32) | |
73e1c03f SM |
114 | regcache->raw_supply (ARM_PS_REGNUM, |
115 | (char *) &inferior_registers.r_cpsr); | |
47221191 | 116 | else |
73e1c03f SM |
117 | regcache->raw_supply (ARM_PS_REGNUM, |
118 | (char *) &inferior_registers.r_pc); | |
47221191 RE |
119 | break; |
120 | ||
121 | default: | |
73e1c03f | 122 | regcache->raw_supply (regno, (char *) &inferior_registers.r[regno]); |
47221191 RE |
123 | break; |
124 | } | |
125 | } | |
126 | ||
127 | static void | |
56be3814 | 128 | fetch_regs (struct regcache *regcache) |
e7a42bc8 FN |
129 | { |
130 | struct reg inferior_registers; | |
47221191 RE |
131 | int ret; |
132 | int regno; | |
133 | ||
e99b03dc | 134 | ret = ptrace (PT_GETREGS, regcache->ptid ().pid (), |
9f8e0089 | 135 | (PTRACE_TYPE_ARG3) &inferior_registers, 0); |
47221191 RE |
136 | |
137 | if (ret < 0) | |
138 | { | |
edefbb7c | 139 | warning (_("unable to fetch general registers")); |
47221191 RE |
140 | return; |
141 | } | |
142 | ||
56be3814 | 143 | arm_supply_gregset (regcache, &inferior_registers); |
47221191 RE |
144 | } |
145 | ||
146 | static void | |
56be3814 | 147 | fetch_fp_register (struct regcache *regcache, int regno) |
47221191 RE |
148 | { |
149 | struct fpreg inferior_fp_registers; | |
150 | int ret; | |
151 | ||
e99b03dc | 152 | ret = ptrace (PT_GETFPREGS, regcache->ptid ().pid (), |
9f8e0089 | 153 | (PTRACE_TYPE_ARG3) &inferior_fp_registers, 0); |
47221191 RE |
154 | |
155 | if (ret < 0) | |
156 | { | |
edefbb7c | 157 | warning (_("unable to fetch floating-point register")); |
47221191 RE |
158 | return; |
159 | } | |
160 | ||
161 | switch (regno) | |
162 | { | |
163 | case ARM_FPS_REGNUM: | |
73e1c03f SM |
164 | regcache->raw_supply (ARM_FPS_REGNUM, |
165 | (char *) &inferior_fp_registers.fpr_fpsr); | |
47221191 RE |
166 | break; |
167 | ||
168 | default: | |
73e1c03f SM |
169 | regcache->raw_supply |
170 | (regno, (char *) &inferior_fp_registers.fpr[regno - ARM_F0_REGNUM]); | |
47221191 RE |
171 | break; |
172 | } | |
173 | } | |
174 | ||
175 | static void | |
56be3814 | 176 | fetch_fp_regs (struct regcache *regcache) |
47221191 RE |
177 | { |
178 | struct fpreg inferior_fp_registers; | |
179 | int ret; | |
180 | int regno; | |
181 | ||
e99b03dc | 182 | ret = ptrace (PT_GETFPREGS, regcache->ptid ().pid (), |
9f8e0089 | 183 | (PTRACE_TYPE_ARG3) &inferior_fp_registers, 0); |
47221191 RE |
184 | |
185 | if (ret < 0) | |
186 | { | |
edefbb7c | 187 | warning (_("unable to fetch general registers")); |
47221191 RE |
188 | return; |
189 | } | |
190 | ||
56be3814 | 191 | arm_supply_fparegset (regcache, &inferior_fp_registers); |
e7a42bc8 FN |
192 | } |
193 | ||
f6ac5f3d | 194 | void |
3050c6f4 | 195 | arm_netbsd_nat_target::fetch_registers (struct regcache *regcache, int regno) |
47221191 RE |
196 | { |
197 | if (regno >= 0) | |
198 | { | |
199 | if (regno < ARM_F0_REGNUM || regno > ARM_FPS_REGNUM) | |
56be3814 | 200 | fetch_register (regcache, regno); |
47221191 | 201 | else |
56be3814 | 202 | fetch_fp_register (regcache, regno); |
47221191 RE |
203 | } |
204 | else | |
205 | { | |
56be3814 UW |
206 | fetch_regs (regcache); |
207 | fetch_fp_regs (regcache); | |
47221191 RE |
208 | } |
209 | } | |
210 | ||
211 | ||
212 | static void | |
56be3814 | 213 | store_register (const struct regcache *regcache, int regno) |
e7a42bc8 | 214 | { |
ac7936df | 215 | struct gdbarch *gdbarch = regcache->arch (); |
e7a42bc8 | 216 | struct reg inferior_registers; |
47221191 RE |
217 | int ret; |
218 | ||
e99b03dc | 219 | ret = ptrace (PT_GETREGS, regcache->ptid ().pid (), |
9f8e0089 | 220 | (PTRACE_TYPE_ARG3) &inferior_registers, 0); |
47221191 RE |
221 | |
222 | if (ret < 0) | |
223 | { | |
edefbb7c | 224 | warning (_("unable to fetch general registers")); |
47221191 RE |
225 | return; |
226 | } | |
227 | ||
228 | switch (regno) | |
229 | { | |
230 | case ARM_SP_REGNUM: | |
34a79281 | 231 | regcache->raw_collect (ARM_SP_REGNUM, (char *) &inferior_registers.r_sp); |
47221191 RE |
232 | break; |
233 | ||
234 | case ARM_LR_REGNUM: | |
34a79281 | 235 | regcache->raw_collect (ARM_LR_REGNUM, (char *) &inferior_registers.r_lr); |
47221191 | 236 | break; |
e7a42bc8 | 237 | |
47221191 RE |
238 | case ARM_PC_REGNUM: |
239 | if (arm_apcs_32) | |
34a79281 SM |
240 | regcache->raw_collect (ARM_PC_REGNUM, |
241 | (char *) &inferior_registers.r_pc); | |
47221191 RE |
242 | else |
243 | { | |
244 | unsigned pc_val; | |
e7a42bc8 | 245 | |
34a79281 | 246 | regcache->raw_collect (ARM_PC_REGNUM, (char *) &pc_val); |
47221191 | 247 | |
b2cb219a | 248 | pc_val = gdbarch_addr_bits_remove (gdbarch, pc_val); |
bf6ae464 | 249 | inferior_registers.r_pc ^= gdbarch_addr_bits_remove |
b2cb219a | 250 | (gdbarch, inferior_registers.r_pc); |
47221191 RE |
251 | inferior_registers.r_pc |= pc_val; |
252 | } | |
253 | break; | |
254 | ||
255 | case ARM_PS_REGNUM: | |
256 | if (arm_apcs_32) | |
34a79281 SM |
257 | regcache->raw_collect (ARM_PS_REGNUM, |
258 | (char *) &inferior_registers.r_cpsr); | |
47221191 RE |
259 | else |
260 | { | |
261 | unsigned psr_val; | |
262 | ||
34a79281 | 263 | regcache->raw_collect (ARM_PS_REGNUM, (char *) &psr_val); |
47221191 | 264 | |
b2cb219a | 265 | psr_val ^= gdbarch_addr_bits_remove (gdbarch, psr_val); |
bf6ae464 | 266 | inferior_registers.r_pc = gdbarch_addr_bits_remove |
b2cb219a | 267 | (gdbarch, inferior_registers.r_pc); |
47221191 RE |
268 | inferior_registers.r_pc |= psr_val; |
269 | } | |
270 | break; | |
271 | ||
272 | default: | |
34a79281 | 273 | regcache->raw_collect (regno, (char *) &inferior_registers.r[regno]); |
47221191 RE |
274 | break; |
275 | } | |
276 | ||
e99b03dc | 277 | ret = ptrace (PT_SETREGS, regcache->ptid ().pid (), |
9f8e0089 | 278 | (PTRACE_TYPE_ARG3) &inferior_registers, 0); |
47221191 RE |
279 | |
280 | if (ret < 0) | |
edefbb7c | 281 | warning (_("unable to write register %d to inferior"), regno); |
47221191 RE |
282 | } |
283 | ||
284 | static void | |
56be3814 | 285 | store_regs (const struct regcache *regcache) |
47221191 | 286 | { |
ac7936df | 287 | struct gdbarch *gdbarch = regcache->arch (); |
47221191 RE |
288 | struct reg inferior_registers; |
289 | int ret; | |
290 | int regno; | |
291 | ||
292 | ||
293 | for (regno = ARM_A1_REGNUM; regno < ARM_SP_REGNUM; regno++) | |
34a79281 | 294 | regcache->raw_collect (regno, (char *) &inferior_registers.r[regno]); |
47221191 | 295 | |
34a79281 SM |
296 | regcache->raw_collect (ARM_SP_REGNUM, (char *) &inferior_registers.r_sp); |
297 | regcache->raw_collect (ARM_LR_REGNUM, (char *) &inferior_registers.r_lr); | |
47221191 RE |
298 | |
299 | if (arm_apcs_32) | |
300 | { | |
34a79281 SM |
301 | regcache->raw_collect (ARM_PC_REGNUM, (char *) &inferior_registers.r_pc); |
302 | regcache->raw_collect (ARM_PS_REGNUM, | |
303 | (char *) &inferior_registers.r_cpsr); | |
47221191 RE |
304 | } |
305 | else | |
306 | { | |
307 | unsigned pc_val; | |
308 | unsigned psr_val; | |
309 | ||
34a79281 SM |
310 | regcache->raw_collect (ARM_PC_REGNUM, (char *) &pc_val); |
311 | regcache->raw_collect (ARM_PS_REGNUM, (char *) &psr_val); | |
47221191 | 312 | |
b2cb219a UW |
313 | pc_val = gdbarch_addr_bits_remove (gdbarch, pc_val); |
314 | psr_val ^= gdbarch_addr_bits_remove (gdbarch, psr_val); | |
47221191 RE |
315 | |
316 | inferior_registers.r_pc = pc_val | psr_val; | |
317 | } | |
318 | ||
e99b03dc | 319 | ret = ptrace (PT_SETREGS, regcache->ptid ().pid (), |
9f8e0089 | 320 | (PTRACE_TYPE_ARG3) &inferior_registers, 0); |
47221191 RE |
321 | |
322 | if (ret < 0) | |
edefbb7c | 323 | warning (_("unable to store general registers")); |
47221191 RE |
324 | } |
325 | ||
326 | static void | |
56be3814 | 327 | store_fp_register (const struct regcache *regcache, int regno) |
47221191 RE |
328 | { |
329 | struct fpreg inferior_fp_registers; | |
330 | int ret; | |
331 | ||
e99b03dc | 332 | ret = ptrace (PT_GETFPREGS, regcache->ptid ().pid (), |
9f8e0089 | 333 | (PTRACE_TYPE_ARG3) &inferior_fp_registers, 0); |
47221191 RE |
334 | |
335 | if (ret < 0) | |
336 | { | |
edefbb7c | 337 | warning (_("unable to fetch floating-point registers")); |
47221191 RE |
338 | return; |
339 | } | |
340 | ||
341 | switch (regno) | |
342 | { | |
343 | case ARM_FPS_REGNUM: | |
34a79281 SM |
344 | regcache->raw_collect (ARM_FPS_REGNUM, |
345 | (char *) &inferior_fp_registers.fpr_fpsr); | |
47221191 RE |
346 | break; |
347 | ||
348 | default: | |
34a79281 SM |
349 | regcache->raw_collect |
350 | (regno, (char *) &inferior_fp_registers.fpr[regno - ARM_F0_REGNUM]); | |
47221191 RE |
351 | break; |
352 | } | |
353 | ||
e99b03dc | 354 | ret = ptrace (PT_SETFPREGS, regcache->ptid ().pid (), |
9f8e0089 | 355 | (PTRACE_TYPE_ARG3) &inferior_fp_registers, 0); |
47221191 RE |
356 | |
357 | if (ret < 0) | |
edefbb7c | 358 | warning (_("unable to write register %d to inferior"), regno); |
47221191 RE |
359 | } |
360 | ||
361 | static void | |
56be3814 | 362 | store_fp_regs (const struct regcache *regcache) |
47221191 RE |
363 | { |
364 | struct fpreg inferior_fp_registers; | |
365 | int ret; | |
366 | int regno; | |
367 | ||
368 | ||
369 | for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++) | |
34a79281 SM |
370 | regcache->raw_collect |
371 | (regno, (char *) &inferior_fp_registers.fpr[regno - ARM_F0_REGNUM]); | |
47221191 | 372 | |
34a79281 SM |
373 | regcache->raw_collect (ARM_FPS_REGNUM, |
374 | (char *) &inferior_fp_registers.fpr_fpsr); | |
47221191 | 375 | |
e99b03dc | 376 | ret = ptrace (PT_SETFPREGS, regcache->ptid ().pid (), |
9f8e0089 | 377 | (PTRACE_TYPE_ARG3) &inferior_fp_registers, 0); |
47221191 RE |
378 | |
379 | if (ret < 0) | |
edefbb7c | 380 | warning (_("unable to store floating-point registers")); |
47221191 RE |
381 | } |
382 | ||
f6ac5f3d | 383 | void |
3050c6f4 | 384 | arm_netbsd_nat_target::store_registers (struct regcache *regcache, int regno) |
47221191 RE |
385 | { |
386 | if (regno >= 0) | |
387 | { | |
388 | if (regno < ARM_F0_REGNUM || regno > ARM_FPS_REGNUM) | |
56be3814 | 389 | store_register (regcache, regno); |
47221191 | 390 | else |
56be3814 | 391 | store_fp_register (regcache, regno); |
47221191 RE |
392 | } |
393 | else | |
394 | { | |
56be3814 UW |
395 | store_regs (regcache); |
396 | store_fp_regs (regcache); | |
47221191 | 397 | } |
e7a42bc8 FN |
398 | } |
399 | ||
b34db576 | 400 | static void |
9eefc95f | 401 | fetch_elfcore_registers (struct regcache *regcache, |
0cac9354 | 402 | gdb_byte *core_reg_sect, unsigned core_reg_size, |
b34db576 RE |
403 | int which, CORE_ADDR ignore) |
404 | { | |
405 | struct reg gregset; | |
406 | struct fpreg fparegset; | |
e7a42bc8 | 407 | |
b34db576 RE |
408 | switch (which) |
409 | { | |
410 | case 0: /* Integer registers. */ | |
411 | if (core_reg_size != sizeof (struct reg)) | |
edefbb7c | 412 | warning (_("wrong size of register set in core file")); |
b34db576 RE |
413 | else |
414 | { | |
415 | /* The memcpy may be unnecessary, but we can't really be sure | |
416 | of the alignment of the data in the core file. */ | |
417 | memcpy (&gregset, core_reg_sect, sizeof (gregset)); | |
9eefc95f | 418 | arm_supply_gregset (regcache, &gregset); |
b34db576 RE |
419 | } |
420 | break; | |
421 | ||
422 | case 2: | |
423 | if (core_reg_size != sizeof (struct fpreg)) | |
edefbb7c | 424 | warning (_("wrong size of FPA register set in core file")); |
b34db576 RE |
425 | else |
426 | { | |
427 | /* The memcpy may be unnecessary, but we can't really be sure | |
428 | of the alignment of the data in the core file. */ | |
429 | memcpy (&fparegset, core_reg_sect, sizeof (fparegset)); | |
9eefc95f | 430 | arm_supply_fparegset (regcache, &fparegset); |
b34db576 RE |
431 | } |
432 | break; | |
3e56fc4b | 433 | |
b34db576 RE |
434 | default: |
435 | /* Don't know what kind of register request this is; just ignore it. */ | |
436 | break; | |
437 | } | |
e7a42bc8 FN |
438 | } |
439 | ||
b34db576 RE |
440 | static struct core_fns arm_netbsd_elfcore_fns = |
441 | { | |
405feb71 | 442 | bfd_target_elf_flavour, /* core_flavour. */ |
b34db576 RE |
443 | default_check_format, /* check_format. */ |
444 | default_core_sniffer, /* core_sniffer. */ | |
445 | fetch_elfcore_registers, /* core_read_registers. */ | |
446 | NULL | |
447 | }; | |
448 | ||
6c265988 | 449 | void _initialize_arm_netbsd_nat (); |
3e56fc4b | 450 | void |
6c265988 | 451 | _initialize_arm_netbsd_nat () |
3e56fc4b | 452 | { |
d9f719f1 | 453 | add_inf_child_target (&the_arm_netbsd_nat_target); |
2b73aeb1 | 454 | |
00e32a35 | 455 | deprecated_add_core_fns (&arm_netbsd_elfcore_fns); |
3e56fc4b | 456 | } |