1/* Target-dependent code for NetBSD/sparc.
2
3   Copyright 2002, 2003, 2004 Free Software Foundation, Inc.
4   Contributed by Wasabi Systems, Inc.
5
6   This file is part of GDB.
7
8   This program is free software; you can redistribute it and/or modify
9   it under the terms of the GNU General Public License as published by
10   the Free Software Foundation; either version 2 of the License, or
11   (at your option) any later version.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with this program; if not, write to the Free Software
20   Foundation, Inc., 59 Temple Place - Suite 330,
21   Boston, MA 02111-1307, USA.  */
22
23#include "defs.h"
24#include "floatformat.h"
25#include "frame.h"
26#include "frame-unwind.h"
27#include "gdbcore.h"
28#include "osabi.h"
29#include "regcache.h"
30#include "regset.h"
31#include "solib-svr4.h"
32#include "symtab.h"
33#include "trad-frame.h"
34
35#include "gdb_assert.h"
36#include "gdb_string.h"
37
38#include "sparc-tdep.h"
39#include "nbsd-tdep.h"
40
41const struct sparc_gregset sparc32nbsd_gregset =
42{
43  0 * 4,			/* %psr */
44  1 * 4,			/* %pc */
45  2 * 4,			/* %npc */
46  3 * 4,			/* %y */
47  -1,				/* %wim */
48  -1,				/* %tbr */
49  5 * 4,			/* %g1 */
50  -1				/* %l0 */
51};
52
53static void
54sparc32nbsd_supply_gregset (const struct regset *regset,
55			    struct regcache *regcache,
56			    int regnum, const void *gregs, size_t len)
57{
58  sparc32_supply_gregset (&sparc32nbsd_gregset, regcache, regnum, gregs);
59
60  /* Traditional NetBSD core files don't use multiple register sets.
61     Instead, the general-purpose and floating-point registers are
62     lumped together in a single section.  */
63  if (len >= 212)
64    sparc32_supply_fpregset (regcache, regnum, (const char *) gregs + 80);
65}
66
67static void
68sparc32nbsd_supply_fpregset (const struct regset *regset,
69			     struct regcache *regcache,
70			     int regnum, const void *fpregs, size_t len)
71{
72  sparc32_supply_fpregset (regcache, regnum, fpregs);
73}
74
75
76/* Signal trampolines.  */
77
78/* The following variables describe the location of an on-stack signal
79   trampoline.  The current values correspond to the memory layout for
80   NetBSD 1.3 and up.  These shouldn't be necessary for NetBSD 2.0 and
81   up, since NetBSD uses signal trampolines provided by libc now.  */
82
83static const CORE_ADDR sparc32nbsd_sigtramp_start = 0xeffffef0;
84static const CORE_ADDR sparc32nbsd_sigtramp_end = 0xeffffff0;
85
86static int
87sparc32nbsd_pc_in_sigtramp (CORE_ADDR pc, char *name)
88{
89  if (pc >= sparc32nbsd_sigtramp_start && pc < sparc32nbsd_sigtramp_end)
90    return 1;
91
92  return nbsd_pc_in_sigtramp (pc, name);
93}
94
95struct trad_frame_saved_reg *
96sparc32nbsd_sigcontext_saved_regs (struct frame_info *next_frame)
97{
98  struct trad_frame_saved_reg *saved_regs;
99  CORE_ADDR addr, sigcontext_addr;
100  int regnum, delta;
101  ULONGEST psr;
102
103  saved_regs = trad_frame_alloc_saved_regs (next_frame);
104
105  /* We find the appropriate instance of `struct sigcontext' at a
106     fixed offset in the signal frame.  */
107  addr = frame_unwind_register_unsigned (next_frame, SPARC_FP_REGNUM);
108  sigcontext_addr = addr + 64 + 16;
109
110  /* The registers are saved in bits and pieces scattered all over the
111     place.  The code below records their location on the assumption
112     that the part of the signal trampoline that saves the state has
113     been executed.  */
114
115  saved_regs[SPARC_SP_REGNUM].addr = sigcontext_addr + 8;
116  saved_regs[SPARC32_PC_REGNUM].addr = sigcontext_addr + 12;
117  saved_regs[SPARC32_NPC_REGNUM].addr = sigcontext_addr + 16;
118  saved_regs[SPARC32_PSR_REGNUM].addr = sigcontext_addr + 20;
119  saved_regs[SPARC_G1_REGNUM].addr = sigcontext_addr + 24;
120  saved_regs[SPARC_O0_REGNUM].addr = sigcontext_addr + 28;
121
122  /* The remaining `global' registers and %y are saved in the `local'
123     registers.  */
124  delta = SPARC_L0_REGNUM - SPARC_G0_REGNUM;
125  for (regnum = SPARC_G2_REGNUM; regnum <= SPARC_G7_REGNUM; regnum++)
126    saved_regs[regnum].realreg = regnum + delta;
127  saved_regs[SPARC32_Y_REGNUM].realreg = SPARC_L1_REGNUM;
128
129  /* The remaining `out' registers can be found in the current frame's
130     `in' registers.  */
131  delta = SPARC_I0_REGNUM - SPARC_O0_REGNUM;
132  for (regnum = SPARC_O1_REGNUM; regnum <= SPARC_O5_REGNUM; regnum++)
133    saved_regs[regnum].realreg = regnum + delta;
134  saved_regs[SPARC_O7_REGNUM].realreg = SPARC_I7_REGNUM;
135
136  /* The `local' and `in' registers have been saved in the register
137     save area.  */
138  addr = saved_regs[SPARC_SP_REGNUM].addr;
139  addr = get_frame_memory_unsigned (next_frame, addr, 4);
140  for (regnum = SPARC_L0_REGNUM;
141       regnum <= SPARC_I7_REGNUM; regnum++, addr += 4)
142    saved_regs[regnum].addr = addr;
143
144  /* Handle StackGhost.  */
145  {
146    ULONGEST wcookie = sparc_fetch_wcookie ();
147
148    if (wcookie != 0)
149      {
150	ULONGEST i7;
151
152	addr = saved_regs[SPARC_I7_REGNUM].addr;
153	i7 = get_frame_memory_unsigned (next_frame, addr, 4);
154	trad_frame_set_value (saved_regs, SPARC_I7_REGNUM, i7 ^ wcookie);
155      }
156  }
157
158  /* The floating-point registers are only saved if the EF bit in %prs
159     has been set.  */
160
161#define PSR_EF	0x00001000
162
163  addr = saved_regs[SPARC32_PSR_REGNUM].addr;
164  psr = get_frame_memory_unsigned (next_frame, addr, 4);
165  if (psr & PSR_EF)
166    {
167      CORE_ADDR sp;
168
169      sp = frame_unwind_register_unsigned (next_frame, SPARC_SP_REGNUM);
170      saved_regs[SPARC32_FSR_REGNUM].addr = sp + 96;
171      for (regnum = SPARC_F0_REGNUM, addr = sp + 96 + 8;
172	   regnum <= SPARC_F31_REGNUM; regnum++, addr += 4)
173	saved_regs[regnum].addr = addr;
174    }
175
176  return saved_regs;
177}
178
179static struct sparc_frame_cache *
180sparc32nbsd_sigcontext_frame_cache (struct frame_info *next_frame,
181				    void **this_cache)
182{
183  struct sparc_frame_cache *cache;
184  CORE_ADDR addr;
185
186  if (*this_cache)
187    return *this_cache;
188
189  cache = sparc_frame_cache (next_frame, this_cache);
190  gdb_assert (cache == *this_cache);
191
192  /* If we couldn't find the frame's function, we're probably dealing
193     with an on-stack signal trampoline.  */
194  if (cache->pc == 0)
195    {
196      cache->pc = sparc32nbsd_sigtramp_start;
197
198      /* Since we couldn't find the frame's function, the cache was
199         initialized under the assumption that we're frameless.  */
200      cache->frameless_p = 0;
201      addr = frame_unwind_register_unsigned (next_frame, SPARC_FP_REGNUM);
202      cache->base = addr;
203    }
204
205  cache->saved_regs = sparc32nbsd_sigcontext_saved_regs (next_frame);
206
207  return cache;
208}
209
210static void
211sparc32nbsd_sigcontext_frame_this_id (struct frame_info *next_frame,
212				      void **this_cache,
213				      struct frame_id *this_id)
214{
215  struct sparc_frame_cache *cache =
216    sparc32nbsd_sigcontext_frame_cache (next_frame, this_cache);
217
218  (*this_id) = frame_id_build (cache->base, cache->pc);
219}
220
221static void
222sparc32nbsd_sigcontext_frame_prev_register (struct frame_info *next_frame,
223					    void **this_cache,
224					    int regnum, int *optimizedp,
225					    enum lval_type *lvalp,
226					    CORE_ADDR *addrp,
227					    int *realnump, void *valuep)
228{
229  struct sparc_frame_cache *cache =
230    sparc32nbsd_sigcontext_frame_cache (next_frame, this_cache);
231
232  trad_frame_get_prev_register (next_frame, cache->saved_regs, regnum,
233				optimizedp, lvalp, addrp, realnump, valuep);
234}
235
236static const struct frame_unwind sparc32nbsd_sigcontext_frame_unwind =
237{
238  SIGTRAMP_FRAME,
239  sparc32nbsd_sigcontext_frame_this_id,
240  sparc32nbsd_sigcontext_frame_prev_register
241};
242
243static const struct frame_unwind *
244sparc32nbsd_sigtramp_frame_sniffer (struct frame_info *next_frame)
245{
246  CORE_ADDR pc = frame_pc_unwind (next_frame);
247  char *name;
248
249  find_pc_partial_function (pc, &name, NULL, NULL);
250  if (sparc32nbsd_pc_in_sigtramp (pc, name))
251    {
252      if (name == NULL || strncmp (name, "__sigtramp_sigcontext", 21))
253	return &sparc32nbsd_sigcontext_frame_unwind;
254    }
255
256  return NULL;
257}
258
259
260/* Return non-zero if we are in a shared library trampoline code stub.  */
261
262static int
263sparcnbsd_aout_in_solib_call_trampoline (CORE_ADDR pc, char *name)
264{
265  return (name && !strcmp (name, "_DYNAMIC"));
266}
267
268static void
269sparc32nbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
270{
271  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
272
273  /* NetBSD doesn't support the 128-bit `long double' from the psABI.  */
274  set_gdbarch_long_double_bit (gdbarch, 64);
275  set_gdbarch_long_double_format (gdbarch, &floatformat_ieee_double_big);
276
277  tdep->gregset = regset_alloc (gdbarch, sparc32nbsd_supply_gregset, NULL);
278  tdep->sizeof_gregset = 20 * 4;
279
280  tdep->fpregset = regset_alloc (gdbarch, sparc32nbsd_supply_fpregset, NULL);
281  tdep->sizeof_fpregset = 33 * 4;
282
283  frame_unwind_append_sniffer (gdbarch, sparc32nbsd_sigtramp_frame_sniffer);
284}
285
286static void
287sparc32nbsd_aout_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
288{
289  sparc32nbsd_init_abi (info, gdbarch);
290
291  set_gdbarch_in_solib_call_trampoline
292    (gdbarch, sparcnbsd_aout_in_solib_call_trampoline);
293}
294
295static void
296sparc32nbsd_elf_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
297{
298  sparc32nbsd_init_abi (info, gdbarch);
299
300  set_solib_svr4_fetch_link_map_offsets
301    (gdbarch, svr4_ilp32_fetch_link_map_offsets);
302}
303
304static enum gdb_osabi
305sparcnbsd_aout_osabi_sniffer (bfd *abfd)
306{
307  if (strcmp (bfd_get_target (abfd), "a.out-sparc-netbsd") == 0)
308    return GDB_OSABI_NETBSD_AOUT;
309
310  return GDB_OSABI_UNKNOWN;
311}
312
313/* OpenBSD uses the traditional NetBSD core file format, even for
314   ports that use ELF.  Therefore, if the default OS ABI is OpenBSD
315   ELF, we return that instead of NetBSD a.out.  This is mainly for
316   the benfit of OpenBSD/sparc64, which inherits the sniffer below
317   since we include this file for an OpenBSD/sparc64 target.  For
318   OpenBSD/sparc, the NetBSD a.out OS ABI is probably similar enough
319   to both the OpenBSD a.out and the OpenBSD ELF OS ABI.  */
320#if defined (GDB_OSABI_DEFAULT) && (GDB_OSABI_DEFAULT == GDB_OSABI_OPENBSD_ELF)
321#define GDB_OSABI_NETBSD_CORE GDB_OSABI_OPENBSD_ELF
322#else
323#define GDB_OSABI_NETBSD_CORE GDB_OSABI_NETBSD_AOUT
324#endif
325
326static enum gdb_osabi
327sparcnbsd_core_osabi_sniffer (bfd *abfd)
328{
329  if (strcmp (bfd_get_target (abfd), "netbsd-core") == 0)
330    return GDB_OSABI_NETBSD_CORE;
331
332  return GDB_OSABI_UNKNOWN;
333}
334
335
336/* Provide a prototype to silence -Wmissing-prototypes.  */
337void _initialize_sparcnbsd_tdep (void);
338
339void
340_initialize_sparnbsd_tdep (void)
341{
342  gdbarch_register_osabi_sniffer (bfd_arch_sparc, bfd_target_aout_flavour,
343				  sparcnbsd_aout_osabi_sniffer);
344
345  /* BFD doesn't set a flavour for NetBSD style a.out core files.  */
346  gdbarch_register_osabi_sniffer (bfd_arch_sparc, bfd_target_unknown_flavour,
347                                  sparcnbsd_core_osabi_sniffer);
348
349  gdbarch_register_osabi (bfd_arch_sparc, 0, GDB_OSABI_NETBSD_AOUT,
350			  sparc32nbsd_aout_init_abi);
351  gdbarch_register_osabi (bfd_arch_sparc, 0, GDB_OSABI_NETBSD_ELF,
352			  sparc32nbsd_elf_init_abi);
353}
354