gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / gdb / arm-nbsd-nat.c
1 /* Native-dependent code for BSD Unix running on ARM's, for GDB.
2
3 Copyright (C) 1988-2020 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 /* We define this to get types like register_t. */
21 #define _KERNTYPES
22 #include "defs.h"
23 #include "gdbcore.h"
24 #include "inferior.h"
25 #include "regcache.h"
26 #include "target.h"
27 #include <sys/types.h>
28 #include <sys/ptrace.h>
29 #include <sys/sysctl.h>
30 #include <machine/reg.h>
31 #include <machine/frame.h>
32
33 #include "arm-tdep.h"
34 #include "arm-nbsd-tdep.h"
35 #include "aarch32-tdep.h"
36 #include "inf-ptrace.h"
37 #include "nbsd-nat.h"
38
39 class arm_netbsd_nat_target final : public nbsd_nat_target
40 {
41 public:
42 /* Add our register access methods. */
43 void fetch_registers (struct regcache *, int) override;
44 void store_registers (struct regcache *, int) override;
45 const struct target_desc *read_description () override;
46 };
47
48 static arm_netbsd_nat_target the_arm_netbsd_nat_target;
49
50 static void
51 arm_supply_vfpregset (struct regcache *regcache, struct fpreg *fpregset)
52 {
53 struct gdbarch_tdep *tdep = gdbarch_tdep (regcache->arch ());
54 if (tdep->vfp_register_count == 0)
55 return;
56
57 struct vfpreg &vfp = fpregset->fpr_vfp;
58 for (int regno = 0; regno <= tdep->vfp_register_count; regno++)
59 regcache->raw_supply (regno + ARM_D0_REGNUM, (char *) &vfp.vfp_regs[regno]);
60
61 regcache->raw_supply (ARM_FPSCR_REGNUM, (char *) &vfp.vfp_fpscr);
62 }
63
64 static void
65 fetch_register (struct regcache *regcache, int regno)
66 {
67 struct reg inferior_registers;
68 int ret;
69 int lwp = regcache->ptid ().lwp ();
70
71 ret = ptrace (PT_GETREGS, regcache->ptid ().pid (),
72 (PTRACE_TYPE_ARG3) &inferior_registers, lwp);
73
74 if (ret < 0)
75 {
76 warning (_("unable to fetch general register"));
77 return;
78 }
79 arm_nbsd_supply_gregset (nullptr, regcache, regno, &inferior_registers,
80 sizeof (inferior_registers));
81 }
82
83 static void
84 fetch_fp_register (struct regcache *regcache, int regno)
85 {
86 struct fpreg inferior_fp_registers;
87 int lwp = regcache->ptid ().lwp ();
88
89 int ret = ptrace (PT_GETFPREGS, regcache->ptid ().pid (),
90 (PTRACE_TYPE_ARG3) &inferior_fp_registers, lwp);
91
92 struct vfpreg &vfp = inferior_fp_registers.fpr_vfp;
93
94 if (ret < 0)
95 {
96 warning (_("unable to fetch floating-point register"));
97 return;
98 }
99
100 struct gdbarch_tdep *tdep = gdbarch_tdep (regcache->arch ());
101 if (regno == ARM_FPSCR_REGNUM && tdep->vfp_register_count != 0)
102 regcache->raw_supply (ARM_FPSCR_REGNUM, (char *) &vfp.vfp_fpscr);
103 else if (regno >= ARM_D0_REGNUM
104 && regno <= ARM_D0_REGNUM + tdep->vfp_register_count)
105 {
106 regcache->raw_supply (regno,
107 (char *) &vfp.vfp_regs[regno - ARM_D0_REGNUM]);
108 }
109 else
110 warning (_("Invalid register number."));
111 }
112
113 static void
114 fetch_fp_regs (struct regcache *regcache)
115 {
116 struct fpreg inferior_fp_registers;
117 int lwp = regcache->ptid ().lwp ();
118 int ret;
119 int regno;
120
121 ret = ptrace (PT_GETFPREGS, regcache->ptid ().pid (),
122 (PTRACE_TYPE_ARG3) &inferior_fp_registers, lwp);
123
124 if (ret < 0)
125 {
126 warning (_("unable to fetch general registers"));
127 return;
128 }
129
130 arm_supply_vfpregset (regcache, &inferior_fp_registers);
131 }
132
133 void
134 arm_netbsd_nat_target::fetch_registers (struct regcache *regcache, int regno)
135 {
136 if (regno >= 0)
137 {
138 if (regno < ARM_F0_REGNUM || regno > ARM_FPS_REGNUM)
139 fetch_register (regcache, regno);
140 else
141 fetch_fp_register (regcache, regno);
142 }
143 else
144 {
145 fetch_register (regcache, -1);
146 fetch_fp_regs (regcache);
147 }
148 }
149
150
151 static void
152 store_register (const struct regcache *regcache, int regno)
153 {
154 struct gdbarch *gdbarch = regcache->arch ();
155 struct reg inferior_registers;
156 int lwp = regcache->ptid ().lwp ();
157 int ret;
158
159 ret = ptrace (PT_GETREGS, regcache->ptid ().pid (),
160 (PTRACE_TYPE_ARG3) &inferior_registers, lwp);
161
162 if (ret < 0)
163 {
164 warning (_("unable to fetch general registers"));
165 return;
166 }
167
168 switch (regno)
169 {
170 case ARM_SP_REGNUM:
171 regcache->raw_collect (ARM_SP_REGNUM, (char *) &inferior_registers.r_sp);
172 break;
173
174 case ARM_LR_REGNUM:
175 regcache->raw_collect (ARM_LR_REGNUM, (char *) &inferior_registers.r_lr);
176 break;
177
178 case ARM_PC_REGNUM:
179 if (arm_apcs_32)
180 regcache->raw_collect (ARM_PC_REGNUM,
181 (char *) &inferior_registers.r_pc);
182 else
183 {
184 unsigned pc_val;
185
186 regcache->raw_collect (ARM_PC_REGNUM, (char *) &pc_val);
187
188 pc_val = gdbarch_addr_bits_remove (gdbarch, pc_val);
189 inferior_registers.r_pc ^= gdbarch_addr_bits_remove
190 (gdbarch, inferior_registers.r_pc);
191 inferior_registers.r_pc |= pc_val;
192 }
193 break;
194
195 case ARM_PS_REGNUM:
196 if (arm_apcs_32)
197 regcache->raw_collect (ARM_PS_REGNUM,
198 (char *) &inferior_registers.r_cpsr);
199 else
200 {
201 unsigned psr_val;
202
203 regcache->raw_collect (ARM_PS_REGNUM, (char *) &psr_val);
204
205 psr_val ^= gdbarch_addr_bits_remove (gdbarch, psr_val);
206 inferior_registers.r_pc = gdbarch_addr_bits_remove
207 (gdbarch, inferior_registers.r_pc);
208 inferior_registers.r_pc |= psr_val;
209 }
210 break;
211
212 default:
213 regcache->raw_collect (regno, (char *) &inferior_registers.r[regno]);
214 break;
215 }
216
217 ret = ptrace (PT_SETREGS, regcache->ptid ().pid (),
218 (PTRACE_TYPE_ARG3) &inferior_registers, lwp);
219
220 if (ret < 0)
221 warning (_("unable to write register %d to inferior"), regno);
222 }
223
224 static void
225 store_regs (const struct regcache *regcache)
226 {
227 struct gdbarch *gdbarch = regcache->arch ();
228 struct reg inferior_registers;
229 int lwp = regcache->ptid ().lwp ();
230 int ret;
231 int regno;
232
233
234 for (regno = ARM_A1_REGNUM; regno < ARM_SP_REGNUM; regno++)
235 regcache->raw_collect (regno, (char *) &inferior_registers.r[regno]);
236
237 regcache->raw_collect (ARM_SP_REGNUM, (char *) &inferior_registers.r_sp);
238 regcache->raw_collect (ARM_LR_REGNUM, (char *) &inferior_registers.r_lr);
239
240 if (arm_apcs_32)
241 {
242 regcache->raw_collect (ARM_PC_REGNUM, (char *) &inferior_registers.r_pc);
243 regcache->raw_collect (ARM_PS_REGNUM,
244 (char *) &inferior_registers.r_cpsr);
245 }
246 else
247 {
248 unsigned pc_val;
249 unsigned psr_val;
250
251 regcache->raw_collect (ARM_PC_REGNUM, (char *) &pc_val);
252 regcache->raw_collect (ARM_PS_REGNUM, (char *) &psr_val);
253
254 pc_val = gdbarch_addr_bits_remove (gdbarch, pc_val);
255 psr_val ^= gdbarch_addr_bits_remove (gdbarch, psr_val);
256
257 inferior_registers.r_pc = pc_val | psr_val;
258 }
259
260 ret = ptrace (PT_SETREGS, regcache->ptid ().pid (),
261 (PTRACE_TYPE_ARG3) &inferior_registers, lwp);
262
263 if (ret < 0)
264 warning (_("unable to store general registers"));
265 }
266
267 static void
268 store_fp_register (const struct regcache *regcache, int regno)
269 {
270 struct fpreg inferior_fp_registers;
271 int lwp = regcache->ptid ().lwp ();
272 int ret = ptrace (PT_GETFPREGS, regcache->ptid ().pid (),
273 (PTRACE_TYPE_ARG3) &inferior_fp_registers, lwp);
274 struct vfpreg &vfp = inferior_fp_registers.fpr_vfp;
275
276 if (ret < 0)
277 {
278 warning (_("unable to fetch floating-point registers"));
279 return;
280 }
281
282 struct gdbarch_tdep *tdep = gdbarch_tdep (regcache->arch ());
283 if (regno == ARM_FPSCR_REGNUM && tdep->vfp_register_count != 0)
284 regcache->raw_collect (ARM_FPSCR_REGNUM, (char *) &vfp.vfp_fpscr);
285 else if (regno >= ARM_D0_REGNUM
286 && regno <= ARM_D0_REGNUM + tdep->vfp_register_count)
287 {
288 regcache->raw_collect (regno,
289 (char *) &vfp.vfp_regs[regno - ARM_D0_REGNUM]);
290 }
291 else
292 warning (_("Invalid register number."));
293
294 ret = ptrace (PT_SETFPREGS, regcache->ptid ().pid (),
295 (PTRACE_TYPE_ARG3) &inferior_fp_registers, lwp);
296
297 if (ret < 0)
298 warning (_("unable to write register %d to inferior"), regno);
299 }
300
301 static void
302 store_fp_regs (const struct regcache *regcache)
303 {
304 struct gdbarch_tdep *tdep = gdbarch_tdep (regcache->arch ());
305 int lwp = regcache->ptid ().lwp ();
306 if (tdep->vfp_register_count == 0)
307 return;
308
309 struct fpreg fpregs;
310 for (int regno = 0; regno <= tdep->vfp_register_count; regno++)
311 regcache->raw_collect
312 (regno + ARM_D0_REGNUM, (char *) &fpregs.fpr_vfp.vfp_regs[regno]);
313
314 regcache->raw_collect (ARM_FPSCR_REGNUM,
315 (char *) &fpregs.fpr_vfp.vfp_fpscr);
316
317 int ret = ptrace (PT_SETFPREGS, regcache->ptid ().pid (),
318 (PTRACE_TYPE_ARG3) &fpregs, lwp);
319
320 if (ret < 0)
321 warning (_("unable to store floating-point registers"));
322 }
323
324 void
325 arm_netbsd_nat_target::store_registers (struct regcache *regcache, int regno)
326 {
327 if (regno >= 0)
328 {
329 if (regno < ARM_F0_REGNUM || regno > ARM_FPS_REGNUM)
330 store_register (regcache, regno);
331 else
332 store_fp_register (regcache, regno);
333 }
334 else
335 {
336 store_regs (regcache);
337 store_fp_regs (regcache);
338 }
339 }
340
341 const struct target_desc *
342 arm_netbsd_nat_target::read_description ()
343 {
344 int flag;
345 size_t len = sizeof (flag);
346
347 if (sysctlbyname("machdep.fpu_present", &flag, &len, NULL, 0) != 0
348 || !flag)
349 return arm_read_description (ARM_FP_TYPE_NONE);
350
351 len = sizeof(flag);
352 if (sysctlbyname("machdep.neon_present", &flag, &len, NULL, 0) == 0 && flag)
353 return aarch32_read_description ();
354
355 return arm_read_description (ARM_FP_TYPE_VFPV3);
356 }
357
358 void _initialize_arm_netbsd_nat ();
359 void
360 _initialize_arm_netbsd_nat ()
361 {
362 add_inf_child_target (&the_arm_netbsd_nat_target);
363 }
This page took 0.036786 seconds and 4 git commands to generate.