xref: /netbsd-src/external/gpl3/gdb.old/dist/gdb/mips-netbsd-tdep.c (revision 6881a4007f077b54e5f51159c52b9b25f57deb0d)
1*6881a400Schristos /* Target-dependent code for NetBSD/mips.
2*6881a400Schristos 
3*6881a400Schristos    Copyright (C) 2002-2023 Free Software Foundation, Inc.
4*6881a400Schristos 
5*6881a400Schristos    Contributed by Wasabi Systems, Inc.
6*6881a400Schristos 
7*6881a400Schristos    This file is part of GDB.
8*6881a400Schristos 
9*6881a400Schristos    This program is free software; you can redistribute it and/or modify
10*6881a400Schristos    it under the terms of the GNU General Public License as published by
11*6881a400Schristos    the Free Software Foundation; either version 3 of the License, or
12*6881a400Schristos    (at your option) any later version.
13*6881a400Schristos 
14*6881a400Schristos    This program is distributed in the hope that it will be useful,
15*6881a400Schristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
16*6881a400Schristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17*6881a400Schristos    GNU General Public License for more details.
18*6881a400Schristos 
19*6881a400Schristos    You should have received a copy of the GNU General Public License
20*6881a400Schristos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
21*6881a400Schristos 
22*6881a400Schristos #include "defs.h"
23*6881a400Schristos #include "gdbcore.h"
24*6881a400Schristos #include "regcache.h"
25*6881a400Schristos #include "regset.h"
26*6881a400Schristos #include "target.h"
27*6881a400Schristos #include "value.h"
28*6881a400Schristos #include "osabi.h"
29*6881a400Schristos 
30*6881a400Schristos #include "netbsd-tdep.h"
31*6881a400Schristos #include "mips-netbsd-tdep.h"
32*6881a400Schristos #include "mips-tdep.h"
33*6881a400Schristos 
34*6881a400Schristos #include "solib-svr4.h"
35*6881a400Schristos 
36*6881a400Schristos /* Shorthand for some register numbers used below.  */
37*6881a400Schristos #define MIPS_PC_REGNUM  MIPS_EMBED_PC_REGNUM
38*6881a400Schristos #define MIPS_FP0_REGNUM MIPS_EMBED_FP0_REGNUM
39*6881a400Schristos #define MIPS_FSR_REGNUM MIPS_EMBED_FP0_REGNUM + 32
40*6881a400Schristos 
41*6881a400Schristos /* Core file support.  */
42*6881a400Schristos 
43*6881a400Schristos /* Number of registers in `struct reg' from <machine/reg.h>.  */
44*6881a400Schristos #define MIPSNBSD_NUM_GREGS	38
45*6881a400Schristos 
46*6881a400Schristos /* Number of registers in `struct fpreg' from <machine/reg.h>.  */
47*6881a400Schristos #define MIPSNBSD_NUM_FPREGS	33
48*6881a400Schristos 
49*6881a400Schristos /* Supply register REGNUM from the buffer specified by FPREGS and LEN
50*6881a400Schristos    in the floating-point register set REGSET to register cache
51*6881a400Schristos    REGCACHE.  If REGNUM is -1, do this for all registers in REGSET.  */
52*6881a400Schristos 
53*6881a400Schristos static void
54*6881a400Schristos mipsnbsd_supply_fpregset (const struct regset *regset,
55*6881a400Schristos 			  struct regcache *regcache,
56*6881a400Schristos 			  int regnum, const void *fpregs, size_t len)
57*6881a400Schristos {
58*6881a400Schristos   size_t regsize = mips_isa_regsize (regcache->arch ());
59*6881a400Schristos   const char *regs = (const char *) fpregs;
60*6881a400Schristos   int i;
61*6881a400Schristos 
62*6881a400Schristos   gdb_assert (len >= MIPSNBSD_NUM_FPREGS * regsize);
63*6881a400Schristos 
64*6881a400Schristos   for (i = MIPS_FP0_REGNUM; i <= MIPS_FSR_REGNUM; i++)
65*6881a400Schristos     {
66*6881a400Schristos       if (regnum == i || regnum == -1)
67*6881a400Schristos 	regcache->raw_supply (i, regs + (i - MIPS_FP0_REGNUM) * regsize);
68*6881a400Schristos     }
69*6881a400Schristos }
70*6881a400Schristos 
71*6881a400Schristos /* Supply register REGNUM from the buffer specified by GREGS and LEN
72*6881a400Schristos    in the general-purpose register set REGSET to register cache
73*6881a400Schristos    REGCACHE.  If REGNUM is -1, do this for all registers in REGSET.  */
74*6881a400Schristos 
75*6881a400Schristos static void
76*6881a400Schristos mipsnbsd_supply_gregset (const struct regset *regset,
77*6881a400Schristos 			 struct regcache *regcache, int regnum,
78*6881a400Schristos 			 const void *gregs, size_t len)
79*6881a400Schristos {
80*6881a400Schristos   size_t regsize = mips_isa_regsize (regcache->arch ());
81*6881a400Schristos   const char *regs = (const char *) gregs;
82*6881a400Schristos   int i;
83*6881a400Schristos 
84*6881a400Schristos   gdb_assert (len >= MIPSNBSD_NUM_GREGS * regsize);
85*6881a400Schristos 
86*6881a400Schristos   for (i = 0; i <= MIPS_PC_REGNUM; i++)
87*6881a400Schristos     {
88*6881a400Schristos       if (regnum == i || regnum == -1)
89*6881a400Schristos 	regcache->raw_supply (i, regs + i * regsize);
90*6881a400Schristos     }
91*6881a400Schristos 
92*6881a400Schristos   if (len >= (MIPSNBSD_NUM_GREGS + MIPSNBSD_NUM_FPREGS) * regsize)
93*6881a400Schristos     {
94*6881a400Schristos       regs += MIPSNBSD_NUM_GREGS * regsize;
95*6881a400Schristos       len -= MIPSNBSD_NUM_GREGS * regsize;
96*6881a400Schristos       mipsnbsd_supply_fpregset (regset, regcache, regnum, regs, len);
97*6881a400Schristos     }
98*6881a400Schristos   if (regnum == -1 || regnum == MIPS_ZERO_REGNUM)
99*6881a400Schristos     regcache->raw_supply_zeroed (MIPS_ZERO_REGNUM);
100*6881a400Schristos }
101*6881a400Schristos 
102*6881a400Schristos /* NetBSD/mips register sets.  */
103*6881a400Schristos 
104*6881a400Schristos static const struct regset mipsnbsd_gregset =
105*6881a400Schristos {
106*6881a400Schristos   NULL,
107*6881a400Schristos   mipsnbsd_supply_gregset,
108*6881a400Schristos   NULL,
109*6881a400Schristos   REGSET_VARIABLE_SIZE
110*6881a400Schristos };
111*6881a400Schristos 
112*6881a400Schristos static const struct regset mipsnbsd_fpregset =
113*6881a400Schristos {
114*6881a400Schristos   NULL,
115*6881a400Schristos   mipsnbsd_supply_fpregset
116*6881a400Schristos };
117*6881a400Schristos 
118*6881a400Schristos /* Iterate over core file register note sections.  */
119*6881a400Schristos 
120*6881a400Schristos static void
121*6881a400Schristos mipsnbsd_iterate_over_regset_sections (struct gdbarch *gdbarch,
122*6881a400Schristos 				       iterate_over_regset_sections_cb *cb,
123*6881a400Schristos 				       void *cb_data,
124*6881a400Schristos 				       const struct regcache *regcache)
125*6881a400Schristos {
126*6881a400Schristos   size_t regsize = mips_isa_regsize (gdbarch);
127*6881a400Schristos 
128*6881a400Schristos   cb (".reg", MIPSNBSD_NUM_GREGS * regsize, MIPSNBSD_NUM_GREGS * regsize,
129*6881a400Schristos       &mipsnbsd_gregset, NULL, cb_data);
130*6881a400Schristos   cb (".reg2", MIPSNBSD_NUM_FPREGS * regsize, MIPSNBSD_NUM_FPREGS * regsize,
131*6881a400Schristos       &mipsnbsd_fpregset, NULL, cb_data);
132*6881a400Schristos }
133*6881a400Schristos 
134*6881a400Schristos 
135*6881a400Schristos /* Conveniently, GDB uses the same register numbering as the
136*6881a400Schristos    ptrace register structure used by NetBSD/mips.  */
137*6881a400Schristos 
138*6881a400Schristos void
139*6881a400Schristos mipsnbsd_supply_reg (struct regcache *regcache, const char *regs, int regno)
140*6881a400Schristos {
141*6881a400Schristos   struct gdbarch *gdbarch = regcache->arch ();
142*6881a400Schristos   int i;
143*6881a400Schristos 
144*6881a400Schristos   for (i = 0; i <= gdbarch_pc_regnum (gdbarch); i++)
145*6881a400Schristos     {
146*6881a400Schristos       if (regno == i || regno == -1)
147*6881a400Schristos 	{
148*6881a400Schristos 	  if (gdbarch_cannot_fetch_register (gdbarch, i))
149*6881a400Schristos 	    regcache->raw_supply (i, NULL);
150*6881a400Schristos 	  else
151*6881a400Schristos 	    regcache->raw_supply
152*6881a400Schristos 	      (i, regs + (i * mips_isa_regsize (gdbarch)));
153*6881a400Schristos 	}
154*6881a400Schristos     }
155*6881a400Schristos   if (regno == -1 || regno == MIPS_ZERO_REGNUM)
156*6881a400Schristos     regcache->raw_supply_zeroed (MIPS_ZERO_REGNUM);
157*6881a400Schristos }
158*6881a400Schristos 
159*6881a400Schristos void
160*6881a400Schristos mipsnbsd_fill_reg (const struct regcache *regcache, char *regs, int regno)
161*6881a400Schristos {
162*6881a400Schristos   struct gdbarch *gdbarch = regcache->arch ();
163*6881a400Schristos   int i;
164*6881a400Schristos 
165*6881a400Schristos   for (i = 0; i <= gdbarch_pc_regnum (gdbarch); i++)
166*6881a400Schristos     if ((regno == i || regno == -1)
167*6881a400Schristos 	&& ! gdbarch_cannot_store_register (gdbarch, i))
168*6881a400Schristos       regcache->raw_collect (i, regs + (i * mips_isa_regsize (gdbarch)));
169*6881a400Schristos }
170*6881a400Schristos 
171*6881a400Schristos void
172*6881a400Schristos mipsnbsd_supply_fpreg (struct regcache *regcache,
173*6881a400Schristos 		       const char *fpregs, int regno)
174*6881a400Schristos {
175*6881a400Schristos   struct gdbarch *gdbarch = regcache->arch ();
176*6881a400Schristos   int i;
177*6881a400Schristos 
178*6881a400Schristos   for (i = gdbarch_fp0_regnum (gdbarch);
179*6881a400Schristos        i <= mips_regnum (gdbarch)->fp_implementation_revision;
180*6881a400Schristos        i++)
181*6881a400Schristos     {
182*6881a400Schristos       if (regno == i || regno == -1)
183*6881a400Schristos 	{
184*6881a400Schristos 	  if (gdbarch_cannot_fetch_register (gdbarch, i))
185*6881a400Schristos 	    regcache->raw_supply (i, NULL);
186*6881a400Schristos 	  else
187*6881a400Schristos 	    regcache->raw_supply (i,
188*6881a400Schristos 				 fpregs
189*6881a400Schristos 				 + ((i - gdbarch_fp0_regnum (gdbarch))
190*6881a400Schristos 				    * mips_isa_regsize (gdbarch)));
191*6881a400Schristos 	}
192*6881a400Schristos     }
193*6881a400Schristos }
194*6881a400Schristos 
195*6881a400Schristos void
196*6881a400Schristos mipsnbsd_fill_fpreg (const struct regcache *regcache, char *fpregs, int regno)
197*6881a400Schristos {
198*6881a400Schristos   struct gdbarch *gdbarch = regcache->arch ();
199*6881a400Schristos   int i;
200*6881a400Schristos 
201*6881a400Schristos   for (i = gdbarch_fp0_regnum (gdbarch);
202*6881a400Schristos        i <= mips_regnum (gdbarch)->fp_control_status;
203*6881a400Schristos        i++)
204*6881a400Schristos     if ((regno == i || regno == -1)
205*6881a400Schristos 	&& ! gdbarch_cannot_store_register (gdbarch, i))
206*6881a400Schristos       regcache->raw_collect
207*6881a400Schristos 	(i, (fpregs + ((i - gdbarch_fp0_regnum (gdbarch))
208*6881a400Schristos 	     * mips_isa_regsize (gdbarch))));
209*6881a400Schristos }
210*6881a400Schristos 
211*6881a400Schristos #if 0
212*6881a400Schristos 
213*6881a400Schristos /* Under NetBSD/mips, signal handler invocations can be identified by the
214*6881a400Schristos    designated code sequence that is used to return from a signal handler.
215*6881a400Schristos    In particular, the return address of a signal handler points to the
216*6881a400Schristos    following code sequence:
217*6881a400Schristos 
218*6881a400Schristos 	addu	a0, sp, 16
219*6881a400Schristos 	li	v0, 295			# __sigreturn14
220*6881a400Schristos 	syscall
221*6881a400Schristos 
222*6881a400Schristos    Each instruction has a unique encoding, so we simply attempt to match
223*6881a400Schristos    the instruction the PC is pointing to with any of the above instructions.
224*6881a400Schristos    If there is a hit, we know the offset to the start of the designated
225*6881a400Schristos    sequence and can then check whether we really are executing in the
226*6881a400Schristos    signal trampoline.  If not, -1 is returned, otherwise the offset from the
227*6881a400Schristos    start of the return sequence is returned.  */
228*6881a400Schristos 
229*6881a400Schristos #define RETCODE_NWORDS	3
230*6881a400Schristos #define RETCODE_SIZE	(RETCODE_NWORDS * 4)
231*6881a400Schristos 
232*6881a400Schristos static const unsigned char sigtramp_retcode_mipsel[RETCODE_SIZE] =
233*6881a400Schristos {
234*6881a400Schristos   0x10, 0x00, 0xa4, 0x27,	/* addu a0, sp, 16 */
235*6881a400Schristos   0x27, 0x01, 0x02, 0x24,	/* li v0, 295 */
236*6881a400Schristos   0x0c, 0x00, 0x00, 0x00,	/* syscall */
237*6881a400Schristos };
238*6881a400Schristos 
239*6881a400Schristos static const unsigned char sigtramp_retcode_mipseb[RETCODE_SIZE] =
240*6881a400Schristos {
241*6881a400Schristos   0x27, 0xa4, 0x00, 0x10,	/* addu a0, sp, 16 */
242*6881a400Schristos   0x24, 0x02, 0x01, 0x27,	/* li v0, 295 */
243*6881a400Schristos   0x00, 0x00, 0x00, 0x0c,	/* syscall */
244*6881a400Schristos };
245*6881a400Schristos 
246*6881a400Schristos #endif
247*6881a400Schristos 
248*6881a400Schristos /* Figure out where the longjmp will land.  We expect that we have
249*6881a400Schristos    just entered longjmp and haven't yet setup the stack frame, so the
250*6881a400Schristos    args are still in the argument regs.  MIPS_A0_REGNUM points at the
251*6881a400Schristos    jmp_buf structure from which we extract the PC that we will land
252*6881a400Schristos    at.  The PC is copied into *pc.  This routine returns true on
253*6881a400Schristos    success.  */
254*6881a400Schristos 
255*6881a400Schristos #define NBSD_MIPS_JB_PC			(2 * 4)
256*6881a400Schristos #define NBSD_MIPS_JB_ELEMENT_SIZE(gdbarch)	mips_isa_regsize (gdbarch)
257*6881a400Schristos #define NBSD_MIPS_JB_OFFSET(gdbarch)		(NBSD_MIPS_JB_PC * \
258*6881a400Schristos 					 NBSD_MIPS_JB_ELEMENT_SIZE (gdbarch))
259*6881a400Schristos 
260*6881a400Schristos static int
261*6881a400Schristos mipsnbsd_get_longjmp_target (frame_info_ptr frame, CORE_ADDR *pc)
262*6881a400Schristos {
263*6881a400Schristos   struct gdbarch *gdbarch = get_frame_arch (frame);
264*6881a400Schristos   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
265*6881a400Schristos   CORE_ADDR jb_addr;
266*6881a400Schristos   gdb_byte *buf;
267*6881a400Schristos 
268*6881a400Schristos   buf = (gdb_byte *) alloca (NBSD_MIPS_JB_ELEMENT_SIZE (gdbarch));
269*6881a400Schristos 
270*6881a400Schristos   jb_addr = get_frame_register_unsigned (frame, MIPS_A0_REGNUM);
271*6881a400Schristos 
272*6881a400Schristos   if (target_read_memory (jb_addr + NBSD_MIPS_JB_OFFSET (gdbarch), buf,
273*6881a400Schristos 			  NBSD_MIPS_JB_ELEMENT_SIZE (gdbarch)))
274*6881a400Schristos     return 0;
275*6881a400Schristos 
276*6881a400Schristos   *pc = extract_unsigned_integer (buf, NBSD_MIPS_JB_ELEMENT_SIZE (gdbarch),
277*6881a400Schristos 				  byte_order);
278*6881a400Schristos   return 1;
279*6881a400Schristos }
280*6881a400Schristos 
281*6881a400Schristos static int
282*6881a400Schristos mipsnbsd_cannot_fetch_register (struct gdbarch *gdbarch, int regno)
283*6881a400Schristos {
284*6881a400Schristos   return regno == mips_regnum (gdbarch)->fp_implementation_revision;
285*6881a400Schristos }
286*6881a400Schristos 
287*6881a400Schristos static int
288*6881a400Schristos mipsnbsd_cannot_store_register (struct gdbarch *gdbarch, int regno)
289*6881a400Schristos {
290*6881a400Schristos   return (regno == MIPS_ZERO_REGNUM
291*6881a400Schristos 	  || regno == mips_regnum (gdbarch)->fp_implementation_revision);
292*6881a400Schristos }
293*6881a400Schristos 
294*6881a400Schristos /* Shared library support.  */
295*6881a400Schristos 
296*6881a400Schristos /* NetBSD/mips uses a slightly different `struct link_map' than the
297*6881a400Schristos    other NetBSD platforms.  */
298*6881a400Schristos 
299*6881a400Schristos static struct link_map_offsets *
300*6881a400Schristos mipsnbsd_ilp32_fetch_link_map_offsets (void)
301*6881a400Schristos {
302*6881a400Schristos   static struct link_map_offsets lmo;
303*6881a400Schristos   static struct link_map_offsets *lmp = NULL;
304*6881a400Schristos 
305*6881a400Schristos   if (lmp == NULL)
306*6881a400Schristos     {
307*6881a400Schristos       lmp = &lmo;
308*6881a400Schristos 
309*6881a400Schristos       lmo.r_version_offset = 0;
310*6881a400Schristos       lmo.r_version_size = 4;
311*6881a400Schristos       lmo.r_map_offset = 4;
312*6881a400Schristos       lmo.r_brk_offset = 8;
313*6881a400Schristos       lmo.r_ldsomap_offset = -1;
314*6881a400Schristos       lmo.r_next_offset = -1;
315*6881a400Schristos 
316*6881a400Schristos       /* Everything we need is in the first 24 bytes.  */
317*6881a400Schristos       lmo.link_map_size = 24;
318*6881a400Schristos       lmo.l_addr_offset = 4;
319*6881a400Schristos       lmo.l_name_offset = 8;
320*6881a400Schristos       lmo.l_ld_offset = 12;
321*6881a400Schristos       lmo.l_next_offset = 16;
322*6881a400Schristos       lmo.l_prev_offset = 20;
323*6881a400Schristos     }
324*6881a400Schristos 
325*6881a400Schristos   return lmp;
326*6881a400Schristos }
327*6881a400Schristos 
328*6881a400Schristos static struct link_map_offsets *
329*6881a400Schristos mipsnbsd_lp64_fetch_link_map_offsets (void)
330*6881a400Schristos {
331*6881a400Schristos   static struct link_map_offsets lmo;
332*6881a400Schristos   static struct link_map_offsets *lmp = NULL;
333*6881a400Schristos 
334*6881a400Schristos   if (lmp == NULL)
335*6881a400Schristos     {
336*6881a400Schristos       lmp = &lmo;
337*6881a400Schristos 
338*6881a400Schristos       lmo.r_version_offset = 0;
339*6881a400Schristos       lmo.r_version_size = 4;
340*6881a400Schristos       lmo.r_map_offset = 8;
341*6881a400Schristos       lmo.r_brk_offset = 16;
342*6881a400Schristos       lmo.r_ldsomap_offset = -1;
343*6881a400Schristos       lmo.r_next_offset = -1;
344*6881a400Schristos 
345*6881a400Schristos       /* Everything we need is in the first 40 bytes.  */
346*6881a400Schristos       lmo.link_map_size = 48;
347*6881a400Schristos       lmo.l_addr_offset = 0;
348*6881a400Schristos       lmo.l_name_offset = 16;
349*6881a400Schristos       lmo.l_ld_offset = 24;
350*6881a400Schristos       lmo.l_next_offset = 32;
351*6881a400Schristos       lmo.l_prev_offset = 40;
352*6881a400Schristos     }
353*6881a400Schristos 
354*6881a400Schristos   return lmp;
355*6881a400Schristos }
356*6881a400Schristos 
357*6881a400Schristos 
358*6881a400Schristos static void
359*6881a400Schristos mipsnbsd_init_abi (struct gdbarch_info info,
360*6881a400Schristos 		   struct gdbarch *gdbarch)
361*6881a400Schristos {
362*6881a400Schristos   nbsd_init_abi (info, gdbarch);
363*6881a400Schristos 
364*6881a400Schristos   set_gdbarch_iterate_over_regset_sections
365*6881a400Schristos     (gdbarch, mipsnbsd_iterate_over_regset_sections);
366*6881a400Schristos 
367*6881a400Schristos   set_gdbarch_get_longjmp_target (gdbarch, mipsnbsd_get_longjmp_target);
368*6881a400Schristos 
369*6881a400Schristos   set_gdbarch_cannot_fetch_register (gdbarch, mipsnbsd_cannot_fetch_register);
370*6881a400Schristos   set_gdbarch_cannot_store_register (gdbarch, mipsnbsd_cannot_store_register);
371*6881a400Schristos 
372*6881a400Schristos   set_gdbarch_software_single_step (gdbarch, mips_software_single_step);
373*6881a400Schristos 
374*6881a400Schristos   /* NetBSD/mips has SVR4-style shared libraries.  */
375*6881a400Schristos   set_solib_svr4_fetch_link_map_offsets
376*6881a400Schristos     (gdbarch, (gdbarch_ptr_bit (gdbarch) == 32 ?
377*6881a400Schristos 	       mipsnbsd_ilp32_fetch_link_map_offsets :
378*6881a400Schristos 	       mipsnbsd_lp64_fetch_link_map_offsets));
379*6881a400Schristos }
380*6881a400Schristos 
381*6881a400Schristos void _initialize_mipsnbsd_tdep ();
382*6881a400Schristos void
383*6881a400Schristos _initialize_mipsnbsd_tdep ()
384*6881a400Schristos {
385*6881a400Schristos   gdbarch_register_osabi (bfd_arch_mips, 0, GDB_OSABI_NETBSD,
386*6881a400Schristos 			  mipsnbsd_init_abi);
387*6881a400Schristos }
388