1 /* Native-dependent code for BSD Unix running on ARM's, for GDB.
2 
3    Copyright (C) 1988-2021 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
arm_supply_vfpregset(struct regcache * regcache,struct fpreg * fpregset)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
fetch_register(struct regcache * regcache,int regno)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
fetch_fp_register(struct regcache * regcache,int regno)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
fetch_fp_regs(struct regcache * regcache)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
fetch_registers(struct regcache * regcache,int regno)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
store_register(const struct regcache * regcache,int regno)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
store_regs(const struct regcache * regcache)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
store_fp_register(const struct regcache * regcache,int regno)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
store_fp_regs(const struct regcache * regcache)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
store_registers(struct regcache * regcache,int regno)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 *
read_description()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
_initialize_arm_netbsd_nat()360 _initialize_arm_netbsd_nat ()
361 {
362   add_inf_child_target (&the_arm_netbsd_nat_target);
363 }
364