xref: /netbsd-src/external/gpl3/gdb.old/dist/gdb/ppc-netbsd-nat.c (revision 4439cfd0acf9c7dc90625e5cd83b2317a9ab8967)
1 /* Native-dependent code for NetBSD/powerpc.
2 
3    Copyright (C) 2002-2023 Free Software Foundation, Inc.
4 
5    Contributed by Wasabi Systems, Inc.
6 
7    This file is part of GDB.
8 
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13 
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18 
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
21 
22 /* We define this to get types like register_t.  */
23 #include "defs.h"
24 
25 #include <sys/types.h>
26 #include <sys/ptrace.h>
27 #include <machine/reg.h>
28 #include <machine/frame.h>
29 #include <machine/pcb.h>
30 
31 #include "gdbcore.h"
32 #include "inferior.h"
33 #include "regcache.h"
34 
35 #include "ppc-tdep.h"
36 #include "ppc-netbsd-tdep.h"
37 #include "bsd-kvm.h"
38 #include "inf-ptrace.h"
39 #include "netbsd-nat.h"
40 
41 struct ppc_nbsd_nat_target final : public nbsd_nat_target
42 {
43   void fetch_registers (struct regcache *, int) override;
44   void store_registers (struct regcache *, int) override;
45 };
46 
47 static ppc_nbsd_nat_target the_ppc_nbsd_nat_target;
48 
49 /* Returns true if PT_GETREGS fetches this register.  */
50 
51 static int
52 getregs_supplies (struct gdbarch *gdbarch, int regnum)
53 {
54   ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
55 
56   return ((regnum >= tdep->ppc_gp0_regnum
57 	   && regnum < tdep->ppc_gp0_regnum + ppc_num_gprs)
58 	  || regnum == tdep->ppc_lr_regnum
59 	  || regnum == tdep->ppc_cr_regnum
60 	  || regnum == tdep->ppc_xer_regnum
61 	  || regnum == tdep->ppc_ctr_regnum
62 	  || regnum == gdbarch_pc_regnum (gdbarch));
63 }
64 
65 /* Like above, but for PT_GETFPREGS.  */
66 
67 static int
68 getfpregs_supplies (struct gdbarch *gdbarch, int regnum)
69 {
70   ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
71 
72   /* FIXME: jimb/2004-05-05: Some PPC variants don't have floating
73      point registers.  Traditionally, GDB's register set has still
74      listed the floating point registers for such machines, so this
75      code is harmless.  However, the new E500 port actually omits the
76      floating point registers entirely from the register set --- they
77      don't even have register numbers assigned to them.
78 
79      It's not clear to me how best to update this code, so this assert
80      will alert the first person to encounter the NetBSD/E500
81      combination to the problem.  */
82   gdb_assert (ppc_floating_point_unit_p (gdbarch));
83 
84   return ((regnum >= tdep->ppc_fp0_regnum
85 	   && regnum < tdep->ppc_fp0_regnum + ppc_num_fprs)
86 	  || regnum == tdep->ppc_fpscr_regnum);
87 }
88 
89 void
90 ppc_nbsd_nat_target::fetch_registers (struct regcache *regcache, int regnum)
91 {
92   struct gdbarch *gdbarch = regcache->arch ();
93   pid_t pid = regcache->ptid ().pid ();
94   int lwp = regcache->ptid ().lwp ();
95 
96   if (regnum == -1 || getregs_supplies (gdbarch, regnum))
97     {
98       struct reg regs;
99 
100       if (ptrace (PT_GETREGS, pid, (PTRACE_TYPE_ARG3) &regs, lwp) == -1)
101 	perror_with_name (_("Couldn't get registers"));
102 
103       ppc_supply_gregset (&ppcnbsd_gregset, regcache,
104 			  regnum, &regs, sizeof regs);
105     }
106 
107   if (regnum == -1 || getfpregs_supplies (gdbarch, regnum))
108     {
109       struct fpreg fpregs;
110 
111       if (ptrace (PT_GETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, lwp) == -1)
112 	perror_with_name (_("Couldn't get FP registers"));
113 
114       ppc_supply_fpregset (&ppcnbsd_fpregset, regcache,
115 			   regnum, &fpregs, sizeof fpregs);
116     }
117 }
118 
119 void
120 ppc_nbsd_nat_target::store_registers (struct regcache *regcache, int regnum)
121 {
122   struct gdbarch *gdbarch = regcache->arch ();
123   pid_t pid = regcache->ptid ().pid ();
124   int lwp = regcache->ptid ().lwp ();
125 
126   if (regnum == -1 || getregs_supplies (gdbarch, regnum))
127     {
128       struct reg regs;
129 
130       if (ptrace (PT_GETREGS, pid, (PTRACE_TYPE_ARG3) &regs, lwp) == -1)
131 	perror_with_name (_("Couldn't get registers"));
132 
133       ppc_collect_gregset (&ppcnbsd_gregset, regcache,
134 			   regnum, &regs, sizeof regs);
135 
136       if (ptrace (PT_SETREGS, pid, (PTRACE_TYPE_ARG3) &regs, lwp) == -1)
137 	perror_with_name (_("Couldn't write registers"));
138     }
139 
140   if (regnum == -1 || getfpregs_supplies (gdbarch, regnum))
141     {
142       struct fpreg fpregs;
143 
144       if (ptrace (PT_GETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, lwp) == -1)
145 	perror_with_name (_("Couldn't get FP registers"));
146 
147       ppc_collect_fpregset (&ppcnbsd_fpregset, regcache,
148 			    regnum, &fpregs, sizeof fpregs);
149 
150       if (ptrace (PT_SETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, lwp) == -1)
151 	perror_with_name (_("Couldn't set FP registers"));
152     }
153 }
154 
155 static int
156 ppcnbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb)
157 {
158   struct switchframe sf;
159   struct callframe cf;
160   struct gdbarch *gdbarch = regcache->arch ();
161   ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
162   int i;
163 
164   /* The stack pointer shouldn't be zero.  */
165   if (pcb->pcb_sp == 0)
166     return 0;
167 
168   read_memory (pcb->pcb_sp, (gdb_byte *)&sf, sizeof sf);
169   regcache->raw_supply (tdep->ppc_cr_regnum, &sf.sf_cr);
170   regcache->raw_supply (tdep->ppc_gp0_regnum + 2, &sf.sf_fixreg2);
171   for (i = 0 ; i < 19 ; i++)
172     regcache->raw_supply (tdep->ppc_gp0_regnum + 13 + i, &sf.sf_fixreg[i]);
173 
174   read_memory(sf.sf_sp, (gdb_byte *)&cf, sizeof(cf));
175   regcache->raw_supply (tdep->ppc_gp0_regnum + 30, &cf.cf_r30);
176   regcache->raw_supply (tdep->ppc_gp0_regnum + 31, &cf.cf_r31);
177   regcache->raw_supply (tdep->ppc_gp0_regnum + 1, &cf.cf_sp);
178 
179   read_memory(cf.cf_sp, (gdb_byte *)&cf, sizeof(cf));
180   regcache->raw_supply (tdep->ppc_lr_regnum, &cf.cf_lr);
181   regcache->raw_supply (gdbarch_pc_regnum (gdbarch), &cf.cf_lr);
182 
183   return 1;
184 }
185 
186 void _initialize_ppcnbsd_nat ();
187 void
188 _initialize_ppcnbsd_nat ()
189 {
190   /* Support debugging kernel virtual memory images.  */
191   bsd_kvm_add_target (ppcnbsd_supply_pcb);
192 
193   add_inf_child_target (&the_ppc_nbsd_nat_target);
194 }
195