]> Git Repo - binutils.git/blob - gdb/arm-netbsd-nat.c
gdb: remove SYMBOL_CLASS macro, add getter
[binutils.git] / gdb / arm-netbsd-nat.c
1 /* Native-dependent code for BSD Unix running on ARM's, for GDB.
2
3    Copyright (C) 1988-2022 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-netbsd-tdep.h"
35 #include "aarch32-tdep.h"
36 #include "inf-ptrace.h"
37 #include "netbsd-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   arm_gdbarch_tdep *tdep = (arm_gdbarch_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   arm_gdbarch_tdep *tdep = (arm_gdbarch_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   arm_gdbarch_tdep *tdep = (arm_gdbarch_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   arm_gdbarch_tdep *tdep = (arm_gdbarch_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.043114 seconds and 4 git commands to generate.