xref: /openbsd-src/gnu/usr.bin/binutils/gdb/sparc64nbsd-tdep.c (revision 62d8eb4962d00a0e27fc98307464172b2ba45f2a)
1b725ae77Skettenis /* Target-dependent code for NetBSD/sparc64.
2b725ae77Skettenis 
3b725ae77Skettenis    Copyright 2002, 2003, 2004 Free Software Foundation, Inc.
4b725ae77Skettenis    Based on code contributed by Wasabi Systems, Inc.
5b725ae77Skettenis 
6b725ae77Skettenis    This file is part of GDB.
7b725ae77Skettenis 
8b725ae77Skettenis    This program is free software; you can redistribute it and/or modify
9b725ae77Skettenis    it under the terms of the GNU General Public License as published by
10b725ae77Skettenis    the Free Software Foundation; either version 2 of the License, or
11b725ae77Skettenis    (at your option) any later version.
12b725ae77Skettenis 
13b725ae77Skettenis    This program is distributed in the hope that it will be useful,
14b725ae77Skettenis    but WITHOUT ANY WARRANTY; without even the implied warranty of
15b725ae77Skettenis    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16b725ae77Skettenis    GNU General Public License for more details.
17b725ae77Skettenis 
18b725ae77Skettenis    You should have received a copy of the GNU General Public License
19b725ae77Skettenis    along with this program; if not, write to the Free Software
20b725ae77Skettenis    Foundation, Inc., 59 Temple Place - Suite 330,
21b725ae77Skettenis    Boston, MA 02111-1307, USA.  */
22b725ae77Skettenis 
23b725ae77Skettenis #include "defs.h"
24b725ae77Skettenis #include "frame.h"
25b725ae77Skettenis #include "frame-unwind.h"
26b725ae77Skettenis #include "gdbcore.h"
27b725ae77Skettenis #include "osabi.h"
28b725ae77Skettenis #include "regcache.h"
29b725ae77Skettenis #include "regset.h"
30b725ae77Skettenis #include "symtab.h"
3111efff7fSkettenis #include "objfiles.h"
32b725ae77Skettenis #include "solib-svr4.h"
33b725ae77Skettenis #include "trad-frame.h"
34b725ae77Skettenis 
35b725ae77Skettenis #include "gdb_assert.h"
36b725ae77Skettenis #include "gdb_string.h"
37b725ae77Skettenis 
38b725ae77Skettenis #include "sparc64-tdep.h"
39b725ae77Skettenis #include "nbsd-tdep.h"
40b725ae77Skettenis 
41b725ae77Skettenis /* From <machine/reg.h>.  */
42b725ae77Skettenis const struct sparc_gregset sparc64nbsd_gregset =
43b725ae77Skettenis {
44b725ae77Skettenis   0 * 8,			/* "tstate" */
45b725ae77Skettenis   1 * 8,			/* %pc */
46b725ae77Skettenis   2 * 8,			/* %npc */
47b725ae77Skettenis   3 * 8,			/* %y */
48b725ae77Skettenis   -1,				/* %fprs */
49b725ae77Skettenis   -1,
50b725ae77Skettenis   5 * 8,			/* %g1 */
51b725ae77Skettenis   -1,				/* %l0 */
52b725ae77Skettenis   4				/* sizeof (%y) */
53b725ae77Skettenis };
54b725ae77Skettenis 
55b725ae77Skettenis 
56b725ae77Skettenis static void
sparc64nbsd_supply_gregset(const struct regset * regset,struct regcache * regcache,int regnum,const void * gregs,size_t len)57b725ae77Skettenis sparc64nbsd_supply_gregset (const struct regset *regset,
58b725ae77Skettenis 			    struct regcache *regcache,
59b725ae77Skettenis 			    int regnum, const void *gregs, size_t len)
60b725ae77Skettenis {
6111efff7fSkettenis   sparc64_supply_gregset (&sparc64nbsd_gregset, regcache, regnum, gregs);
62b725ae77Skettenis }
63b725ae77Skettenis 
64b725ae77Skettenis static void
sparc64nbsd_supply_fpregset(const struct regset * regset,struct regcache * regcache,int regnum,const void * fpregs,size_t len)65b725ae77Skettenis sparc64nbsd_supply_fpregset (const struct regset *regset,
66b725ae77Skettenis 			     struct regcache *regcache,
67b725ae77Skettenis 			     int regnum, const void *fpregs, size_t len)
68b725ae77Skettenis {
69b725ae77Skettenis   sparc64_supply_fpregset (regcache, regnum, fpregs);
70b725ae77Skettenis }
71b725ae77Skettenis 
72b725ae77Skettenis 
73b725ae77Skettenis /* Signal trampolines.  */
74b725ae77Skettenis 
75b725ae77Skettenis /* The following variables describe the location of an on-stack signal
76b725ae77Skettenis    trampoline.  The current values correspond to the memory layout for
77b725ae77Skettenis    NetBSD 1.3 and up.  These shouldn't be necessary for NetBSD 2.0 and
78b725ae77Skettenis    up, since NetBSD uses signal trampolines provided by libc now.  */
79b725ae77Skettenis 
80b725ae77Skettenis static const CORE_ADDR sparc64nbsd_sigtramp_start = 0xffffffffffffdee4ULL;
81b725ae77Skettenis static const CORE_ADDR sparc64nbsd_sigtramp_end = 0xffffffffffffe000ULL;
82b725ae77Skettenis 
83b725ae77Skettenis static int
sparc64nbsd_pc_in_sigtramp(CORE_ADDR pc,char * name)84b725ae77Skettenis sparc64nbsd_pc_in_sigtramp (CORE_ADDR pc, char *name)
85b725ae77Skettenis {
86b725ae77Skettenis   if (pc >= sparc64nbsd_sigtramp_start && pc < sparc64nbsd_sigtramp_end)
87b725ae77Skettenis     return 1;
88b725ae77Skettenis 
89b725ae77Skettenis   return nbsd_pc_in_sigtramp (pc, name);
90b725ae77Skettenis }
91b725ae77Skettenis 
92b725ae77Skettenis struct trad_frame_saved_reg *
sparc64nbsd_sigcontext_saved_regs(CORE_ADDR sigcontext_addr,struct frame_info * next_frame)93b725ae77Skettenis sparc64nbsd_sigcontext_saved_regs (CORE_ADDR sigcontext_addr,
94b725ae77Skettenis 				   struct frame_info *next_frame)
95b725ae77Skettenis {
96b725ae77Skettenis   struct trad_frame_saved_reg *saved_regs;
97b725ae77Skettenis   CORE_ADDR addr, sp;
98b725ae77Skettenis   int regnum, delta;
99b725ae77Skettenis 
100b725ae77Skettenis   saved_regs = trad_frame_alloc_saved_regs (next_frame);
101b725ae77Skettenis 
102b725ae77Skettenis   /* The registers are saved in bits and pieces scattered all over the
103b725ae77Skettenis      place.  The code below records their location on the assumption
104b725ae77Skettenis      that the part of the signal trampoline that saves the state has
105b725ae77Skettenis      been executed.  */
106b725ae77Skettenis 
107b725ae77Skettenis   saved_regs[SPARC_SP_REGNUM].addr = sigcontext_addr + 8;
108b725ae77Skettenis   saved_regs[SPARC64_PC_REGNUM].addr = sigcontext_addr + 16;
109b725ae77Skettenis   saved_regs[SPARC64_NPC_REGNUM].addr = sigcontext_addr + 24;
110b725ae77Skettenis   saved_regs[SPARC64_STATE_REGNUM].addr = sigcontext_addr + 32;
111b725ae77Skettenis   saved_regs[SPARC_G1_REGNUM].addr = sigcontext_addr + 40;
112b725ae77Skettenis   saved_regs[SPARC_O0_REGNUM].addr = sigcontext_addr + 48;
113b725ae77Skettenis 
114b725ae77Skettenis   /* The remaining `global' registers and %y are saved in the `local'
115b725ae77Skettenis      registers.  */
116b725ae77Skettenis   delta = SPARC_L0_REGNUM - SPARC_G0_REGNUM;
117b725ae77Skettenis   for (regnum = SPARC_G2_REGNUM; regnum <= SPARC_G7_REGNUM; regnum++)
118b725ae77Skettenis     saved_regs[regnum].realreg = regnum + delta;
119b725ae77Skettenis   saved_regs[SPARC64_Y_REGNUM].realreg = SPARC_L1_REGNUM;
120b725ae77Skettenis 
121b725ae77Skettenis   /* The remaining `out' registers can be found in the current frame's
122b725ae77Skettenis      `in' registers.  */
123b725ae77Skettenis   delta = SPARC_I0_REGNUM - SPARC_O0_REGNUM;
124b725ae77Skettenis   for (regnum = SPARC_O1_REGNUM; regnum <= SPARC_O5_REGNUM; regnum++)
125b725ae77Skettenis     saved_regs[regnum].realreg = regnum + delta;
126b725ae77Skettenis   saved_regs[SPARC_O7_REGNUM].realreg = SPARC_I7_REGNUM;
127b725ae77Skettenis 
128b725ae77Skettenis   /* The `local' and `in' registers have been saved in the register
129b725ae77Skettenis      save area.  */
130b725ae77Skettenis   addr = saved_regs[SPARC_SP_REGNUM].addr;
131b725ae77Skettenis   sp = get_frame_memory_unsigned (next_frame, addr, 8);
132b725ae77Skettenis   for (regnum = SPARC_L0_REGNUM, addr = sp + BIAS;
133b725ae77Skettenis        regnum <= SPARC_I7_REGNUM; regnum++, addr += 8)
134b725ae77Skettenis     saved_regs[regnum].addr = addr;
135b725ae77Skettenis 
136*62d8eb49Skettenis   /* Handle StackGhost.  */
137*62d8eb49Skettenis   {
138*62d8eb49Skettenis     ULONGEST wcookie = sparc_fetch_wcookie ();
139*62d8eb49Skettenis 
140*62d8eb49Skettenis     if (wcookie != 0)
141*62d8eb49Skettenis       {
142*62d8eb49Skettenis 	ULONGEST i7;
143*62d8eb49Skettenis 
144*62d8eb49Skettenis 	addr = saved_regs[SPARC_I7_REGNUM].addr;
145*62d8eb49Skettenis 	i7 = get_frame_memory_unsigned (next_frame, addr, 8);
146*62d8eb49Skettenis 	trad_frame_set_value (saved_regs, SPARC_I7_REGNUM, i7 ^ wcookie);
147*62d8eb49Skettenis       }
148*62d8eb49Skettenis   }
149*62d8eb49Skettenis 
150b725ae77Skettenis   /* TODO: Handle the floating-point registers.  */
151b725ae77Skettenis 
152b725ae77Skettenis   return saved_regs;
153b725ae77Skettenis }
154b725ae77Skettenis 
155b725ae77Skettenis static struct sparc_frame_cache *
sparc64nbsd_sigcontext_frame_cache(struct frame_info * next_frame,void ** this_cache)156b725ae77Skettenis sparc64nbsd_sigcontext_frame_cache (struct frame_info *next_frame,
157b725ae77Skettenis 				    void **this_cache)
158b725ae77Skettenis {
159b725ae77Skettenis   struct sparc_frame_cache *cache;
160b725ae77Skettenis   CORE_ADDR addr;
161b725ae77Skettenis 
162b725ae77Skettenis   if (*this_cache)
163b725ae77Skettenis     return *this_cache;
164b725ae77Skettenis 
165b725ae77Skettenis   cache = sparc_frame_cache (next_frame, this_cache);
166b725ae77Skettenis   gdb_assert (cache == *this_cache);
167b725ae77Skettenis 
168b725ae77Skettenis   /* If we couldn't find the frame's function, we're probably dealing
169b725ae77Skettenis      with an on-stack signal trampoline.  */
170b725ae77Skettenis   if (cache->pc == 0)
171b725ae77Skettenis     {
172b725ae77Skettenis       cache->pc = sparc64nbsd_sigtramp_start;
173b725ae77Skettenis 
174b725ae77Skettenis       /* Since we couldn't find the frame's function, the cache was
175b725ae77Skettenis          initialized under the assumption that we're frameless.  */
176b725ae77Skettenis       cache->frameless_p = 0;
177b725ae77Skettenis       addr = frame_unwind_register_unsigned (next_frame, SPARC_FP_REGNUM);
178b725ae77Skettenis       cache->base = addr;
179b725ae77Skettenis     }
180b725ae77Skettenis 
181b725ae77Skettenis   /* We find the appropriate instance of `struct sigcontext' at a
182b725ae77Skettenis      fixed offset in the signal frame.  */
183b725ae77Skettenis   addr = cache->base + BIAS + 128 + 8;
184b725ae77Skettenis   cache->saved_regs = sparc64nbsd_sigcontext_saved_regs (addr, next_frame);
185b725ae77Skettenis 
186b725ae77Skettenis   return cache;
187b725ae77Skettenis }
188b725ae77Skettenis 
189b725ae77Skettenis static void
sparc64nbsd_sigcontext_frame_this_id(struct frame_info * next_frame,void ** this_cache,struct frame_id * this_id)190b725ae77Skettenis sparc64nbsd_sigcontext_frame_this_id (struct frame_info *next_frame,
191b725ae77Skettenis 				      void **this_cache,
192b725ae77Skettenis 				      struct frame_id *this_id)
193b725ae77Skettenis {
194b725ae77Skettenis   struct sparc_frame_cache *cache =
195b725ae77Skettenis     sparc64nbsd_sigcontext_frame_cache (next_frame, this_cache);
196b725ae77Skettenis 
197b725ae77Skettenis   (*this_id) = frame_id_build (cache->base, cache->pc);
198b725ae77Skettenis }
199b725ae77Skettenis 
200b725ae77Skettenis static void
sparc64nbsd_sigcontext_frame_prev_register(struct frame_info * next_frame,void ** this_cache,int regnum,int * optimizedp,enum lval_type * lvalp,CORE_ADDR * addrp,int * realnump,void * valuep)201b725ae77Skettenis sparc64nbsd_sigcontext_frame_prev_register (struct frame_info *next_frame,
202b725ae77Skettenis 					    void **this_cache,
203b725ae77Skettenis 					    int regnum, int *optimizedp,
204b725ae77Skettenis 					    enum lval_type *lvalp,
205b725ae77Skettenis 					    CORE_ADDR *addrp,
206b725ae77Skettenis 					    int *realnump, void *valuep)
207b725ae77Skettenis {
208b725ae77Skettenis   struct sparc_frame_cache *cache =
209b725ae77Skettenis     sparc64nbsd_sigcontext_frame_cache (next_frame, this_cache);
210b725ae77Skettenis 
21111efff7fSkettenis   trad_frame_get_prev_register (next_frame, cache->saved_regs, regnum,
212b725ae77Skettenis 				optimizedp, lvalp, addrp, realnump, valuep);
213b725ae77Skettenis }
214b725ae77Skettenis 
215b725ae77Skettenis static const struct frame_unwind sparc64nbsd_sigcontext_frame_unwind =
216b725ae77Skettenis {
217b725ae77Skettenis   SIGTRAMP_FRAME,
218b725ae77Skettenis   sparc64nbsd_sigcontext_frame_this_id,
219b725ae77Skettenis   sparc64nbsd_sigcontext_frame_prev_register
220b725ae77Skettenis };
221b725ae77Skettenis 
222b725ae77Skettenis static const struct frame_unwind *
sparc64nbsd_sigtramp_frame_sniffer(struct frame_info * next_frame)223b725ae77Skettenis sparc64nbsd_sigtramp_frame_sniffer (struct frame_info *next_frame)
224b725ae77Skettenis {
225b725ae77Skettenis   CORE_ADDR pc = frame_pc_unwind (next_frame);
226b725ae77Skettenis   char *name;
227b725ae77Skettenis 
228b725ae77Skettenis   find_pc_partial_function (pc, &name, NULL, NULL);
229b725ae77Skettenis   if (sparc64nbsd_pc_in_sigtramp (pc, name))
230b725ae77Skettenis     {
231b725ae77Skettenis       if (name == NULL || strncmp (name, "__sigtramp_sigcontext", 21))
232b725ae77Skettenis 	return &sparc64nbsd_sigcontext_frame_unwind;
233b725ae77Skettenis     }
234b725ae77Skettenis 
235b725ae77Skettenis   return NULL;
236b725ae77Skettenis }
237b725ae77Skettenis 
238b725ae77Skettenis 
239b725ae77Skettenis static void
sparc64nbsd_init_abi(struct gdbarch_info info,struct gdbarch * gdbarch)240b725ae77Skettenis sparc64nbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
241b725ae77Skettenis {
242b725ae77Skettenis   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
243b725ae77Skettenis 
24411efff7fSkettenis   tdep->gregset = regset_alloc (gdbarch, sparc64nbsd_supply_gregset, NULL);
245b725ae77Skettenis   tdep->sizeof_gregset = 160;
246b725ae77Skettenis 
24711efff7fSkettenis   tdep->fpregset = regset_alloc (gdbarch, sparc64nbsd_supply_fpregset, NULL);
248b725ae77Skettenis   tdep->sizeof_fpregset = 272;
249b725ae77Skettenis 
250b725ae77Skettenis   frame_unwind_append_sniffer (gdbarch, sparc64nbsd_sigtramp_frame_sniffer);
251b725ae77Skettenis 
252b725ae77Skettenis   sparc64_init_abi (info, gdbarch);
253b725ae77Skettenis 
25411efff7fSkettenis   /* NetBSD/sparc64 has SVR4-style shared libraries...  */
25511efff7fSkettenis   set_gdbarch_in_solib_call_trampoline (gdbarch, in_plt_section);
25611efff7fSkettenis   set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
257b725ae77Skettenis   set_solib_svr4_fetch_link_map_offsets
25811efff7fSkettenis     (gdbarch, svr4_lp64_fetch_link_map_offsets);
259b725ae77Skettenis }
260b725ae77Skettenis 
261b725ae77Skettenis 
262b725ae77Skettenis /* Provide a prototype to silence -Wmissing-prototypes.  */
263b725ae77Skettenis void _initialize_sparc64nbsd_tdep (void);
264b725ae77Skettenis 
265b725ae77Skettenis void
_initialize_sparc64nbsd_tdep(void)266b725ae77Skettenis _initialize_sparc64nbsd_tdep (void)
267b725ae77Skettenis {
268b725ae77Skettenis   gdbarch_register_osabi (bfd_arch_sparc, bfd_mach_sparc_v9,
269b725ae77Skettenis 			  GDB_OSABI_NETBSD_ELF, sparc64nbsd_init_abi);
270b725ae77Skettenis }
271