1130803Smarcel/* Target-dependent code for NetBSD/sparc.
2130803Smarcel
3130803Smarcel   Copyright 2002, 2003, 2004 Free Software Foundation, Inc.
4130803Smarcel   Contributed by Wasabi Systems, Inc.
5130803Smarcel
6130803Smarcel   This file is part of GDB.
7130803Smarcel
8130803Smarcel   This program is free software; you can redistribute it and/or modify
9130803Smarcel   it under the terms of the GNU General Public License as published by
10130803Smarcel   the Free Software Foundation; either version 2 of the License, or
11130803Smarcel   (at your option) any later version.
12130803Smarcel
13130803Smarcel   This program is distributed in the hope that it will be useful,
14130803Smarcel   but WITHOUT ANY WARRANTY; without even the implied warranty of
15130803Smarcel   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16130803Smarcel   GNU General Public License for more details.
17130803Smarcel
18130803Smarcel   You should have received a copy of the GNU General Public License
19130803Smarcel   along with this program; if not, write to the Free Software
20130803Smarcel   Foundation, Inc., 59 Temple Place - Suite 330,
21130803Smarcel   Boston, MA 02111-1307, USA.  */
22130803Smarcel
23130803Smarcel#include "defs.h"
24130803Smarcel#include "floatformat.h"
25130803Smarcel#include "frame.h"
26130803Smarcel#include "frame-unwind.h"
27130803Smarcel#include "gdbcore.h"
28130803Smarcel#include "osabi.h"
29130803Smarcel#include "regcache.h"
30130803Smarcel#include "regset.h"
31130803Smarcel#include "solib-svr4.h"
32130803Smarcel#include "symtab.h"
33130803Smarcel#include "trad-frame.h"
34130803Smarcel
35130803Smarcel#include "gdb_assert.h"
36130803Smarcel#include "gdb_string.h"
37130803Smarcel
38130803Smarcel#include "sparc-tdep.h"
39130803Smarcel#include "nbsd-tdep.h"
40130803Smarcel
41130803Smarcelconst struct sparc_gregset sparc32nbsd_gregset =
42130803Smarcel{
43130803Smarcel  0 * 4,			/* %psr */
44130803Smarcel  1 * 4,			/* %pc */
45130803Smarcel  2 * 4,			/* %npc */
46130803Smarcel  3 * 4,			/* %y */
47130803Smarcel  -1,				/* %wim */
48130803Smarcel  -1,				/* %tbr */
49130803Smarcel  5 * 4,			/* %g1 */
50130803Smarcel  -1				/* %l0 */
51130803Smarcel};
52130803Smarcel
53130803Smarcelstatic void
54130803Smarcelsparc32nbsd_supply_gregset (const struct regset *regset,
55130803Smarcel			    struct regcache *regcache,
56130803Smarcel			    int regnum, const void *gregs, size_t len)
57130803Smarcel{
58130803Smarcel  sparc32_supply_gregset (regset->descr, regcache, regnum, gregs);
59130803Smarcel
60130803Smarcel  /* Traditional NetBSD core files don't use multiple register sets.
61130803Smarcel     Instead, the general-purpose and floating-point registers are
62130803Smarcel     lumped together in a single section.  */
63130803Smarcel  if (len >= 212)
64130803Smarcel    sparc32_supply_fpregset (regcache, regnum, (const char *) gregs + 80);
65130803Smarcel}
66130803Smarcel
67130803Smarcelstatic void
68130803Smarcelsparc32nbsd_supply_fpregset (const struct regset *regset,
69130803Smarcel			     struct regcache *regcache,
70130803Smarcel			     int regnum, const void *fpregs, size_t len)
71130803Smarcel{
72130803Smarcel  sparc32_supply_fpregset (regcache, regnum, fpregs);
73130803Smarcel}
74130803Smarcel
75130803Smarcel
76130803Smarcel/* Signal trampolines.  */
77130803Smarcel
78130803Smarcel/* The following variables describe the location of an on-stack signal
79130803Smarcel   trampoline.  The current values correspond to the memory layout for
80130803Smarcel   NetBSD 1.3 and up.  These shouldn't be necessary for NetBSD 2.0 and
81130803Smarcel   up, since NetBSD uses signal trampolines provided by libc now.  */
82130803Smarcel
83130803Smarcelstatic const CORE_ADDR sparc32nbsd_sigtramp_start = 0xeffffef0;
84130803Smarcelstatic const CORE_ADDR sparc32nbsd_sigtramp_end = 0xeffffff0;
85130803Smarcel
86130803Smarcelstatic int
87130803Smarcelsparc32nbsd_pc_in_sigtramp (CORE_ADDR pc, char *name)
88130803Smarcel{
89130803Smarcel  if (pc >= sparc32nbsd_sigtramp_start && pc < sparc32nbsd_sigtramp_end)
90130803Smarcel    return 1;
91130803Smarcel
92130803Smarcel  return nbsd_pc_in_sigtramp (pc, name);
93130803Smarcel}
94130803Smarcel
95130803Smarcelstruct trad_frame_saved_reg *
96130803Smarcelsparc32nbsd_sigcontext_saved_regs (struct frame_info *next_frame)
97130803Smarcel{
98130803Smarcel  struct trad_frame_saved_reg *saved_regs;
99130803Smarcel  CORE_ADDR addr, sigcontext_addr;
100130803Smarcel  int regnum, delta;
101130803Smarcel  ULONGEST psr;
102130803Smarcel
103130803Smarcel  saved_regs = trad_frame_alloc_saved_regs (next_frame);
104130803Smarcel
105130803Smarcel  /* We find the appropriate instance of `struct sigcontext' at a
106130803Smarcel     fixed offset in the signal frame.  */
107130803Smarcel  addr = frame_unwind_register_unsigned (next_frame, SPARC_FP_REGNUM);
108130803Smarcel  sigcontext_addr = addr + 64 + 16;
109130803Smarcel
110130803Smarcel  /* The registers are saved in bits and pieces scattered all over the
111130803Smarcel     place.  The code below records their location on the assumption
112130803Smarcel     that the part of the signal trampoline that saves the state has
113130803Smarcel     been executed.  */
114130803Smarcel
115130803Smarcel  saved_regs[SPARC_SP_REGNUM].addr = sigcontext_addr + 8;
116130803Smarcel  saved_regs[SPARC32_PC_REGNUM].addr = sigcontext_addr + 12;
117130803Smarcel  saved_regs[SPARC32_NPC_REGNUM].addr = sigcontext_addr + 16;
118130803Smarcel  saved_regs[SPARC32_PSR_REGNUM].addr = sigcontext_addr + 20;
119130803Smarcel  saved_regs[SPARC_G1_REGNUM].addr = sigcontext_addr + 24;
120130803Smarcel  saved_regs[SPARC_O0_REGNUM].addr = sigcontext_addr + 28;
121130803Smarcel
122130803Smarcel  /* The remaining `global' registers and %y are saved in the `local'
123130803Smarcel     registers.  */
124130803Smarcel  delta = SPARC_L0_REGNUM - SPARC_G0_REGNUM;
125130803Smarcel  for (regnum = SPARC_G2_REGNUM; regnum <= SPARC_G7_REGNUM; regnum++)
126130803Smarcel    saved_regs[regnum].realreg = regnum + delta;
127130803Smarcel  saved_regs[SPARC32_Y_REGNUM].realreg = SPARC_L1_REGNUM;
128130803Smarcel
129130803Smarcel  /* The remaining `out' registers can be found in the current frame's
130130803Smarcel     `in' registers.  */
131130803Smarcel  delta = SPARC_I0_REGNUM - SPARC_O0_REGNUM;
132130803Smarcel  for (regnum = SPARC_O1_REGNUM; regnum <= SPARC_O5_REGNUM; regnum++)
133130803Smarcel    saved_regs[regnum].realreg = regnum + delta;
134130803Smarcel  saved_regs[SPARC_O7_REGNUM].realreg = SPARC_I7_REGNUM;
135130803Smarcel
136130803Smarcel  /* The `local' and `in' registers have been saved in the register
137130803Smarcel     save area.  */
138130803Smarcel  addr = saved_regs[SPARC_SP_REGNUM].addr;
139130803Smarcel  addr = get_frame_memory_unsigned (next_frame, addr, 4);
140130803Smarcel  for (regnum = SPARC_L0_REGNUM;
141130803Smarcel       regnum <= SPARC_I7_REGNUM; regnum++, addr += 4)
142130803Smarcel    saved_regs[regnum].addr = addr;
143130803Smarcel
144130803Smarcel  /* Handle StackGhost.  */
145130803Smarcel  {
146130803Smarcel    ULONGEST wcookie = sparc_fetch_wcookie ();
147130803Smarcel
148130803Smarcel    if (wcookie != 0)
149130803Smarcel      {
150130803Smarcel	ULONGEST i7;
151130803Smarcel
152130803Smarcel	addr = saved_regs[SPARC_I7_REGNUM].addr;
153130803Smarcel	i7 = get_frame_memory_unsigned (next_frame, addr, 4);
154130803Smarcel	trad_frame_set_value (saved_regs, SPARC_I7_REGNUM, i7 ^ wcookie);
155130803Smarcel      }
156130803Smarcel  }
157130803Smarcel
158130803Smarcel  /* The floating-point registers are only saved if the EF bit in %prs
159130803Smarcel     has been set.  */
160130803Smarcel
161130803Smarcel#define PSR_EF	0x00001000
162130803Smarcel
163130803Smarcel  addr = saved_regs[SPARC32_PSR_REGNUM].addr;
164130803Smarcel  psr = get_frame_memory_unsigned (next_frame, addr, 4);
165130803Smarcel  if (psr & PSR_EF)
166130803Smarcel    {
167130803Smarcel      CORE_ADDR sp;
168130803Smarcel
169130803Smarcel      sp = frame_unwind_register_unsigned (next_frame, SPARC_SP_REGNUM);
170130803Smarcel      saved_regs[SPARC32_FSR_REGNUM].addr = sp + 96;
171130803Smarcel      for (regnum = SPARC_F0_REGNUM, addr = sp + 96 + 8;
172130803Smarcel	   regnum <= SPARC_F31_REGNUM; regnum++, addr += 4)
173130803Smarcel	saved_regs[regnum].addr = addr;
174130803Smarcel    }
175130803Smarcel
176130803Smarcel  return saved_regs;
177130803Smarcel}
178130803Smarcel
179130803Smarcelstatic struct sparc_frame_cache *
180130803Smarcelsparc32nbsd_sigcontext_frame_cache (struct frame_info *next_frame,
181130803Smarcel				    void **this_cache)
182130803Smarcel{
183130803Smarcel  struct sparc_frame_cache *cache;
184130803Smarcel  CORE_ADDR addr;
185130803Smarcel
186130803Smarcel  if (*this_cache)
187130803Smarcel    return *this_cache;
188130803Smarcel
189130803Smarcel  cache = sparc_frame_cache (next_frame, this_cache);
190130803Smarcel  gdb_assert (cache == *this_cache);
191130803Smarcel
192130803Smarcel  /* If we couldn't find the frame's function, we're probably dealing
193130803Smarcel     with an on-stack signal trampoline.  */
194130803Smarcel  if (cache->pc == 0)
195130803Smarcel    {
196130803Smarcel      cache->pc = sparc32nbsd_sigtramp_start;
197130803Smarcel
198130803Smarcel      /* Since we couldn't find the frame's function, the cache was
199130803Smarcel         initialized under the assumption that we're frameless.  */
200130803Smarcel      cache->frameless_p = 0;
201130803Smarcel      addr = frame_unwind_register_unsigned (next_frame, SPARC_FP_REGNUM);
202130803Smarcel      cache->base = addr;
203130803Smarcel    }
204130803Smarcel
205130803Smarcel  cache->saved_regs = sparc32nbsd_sigcontext_saved_regs (next_frame);
206130803Smarcel
207130803Smarcel  return cache;
208130803Smarcel}
209130803Smarcel
210130803Smarcelstatic void
211130803Smarcelsparc32nbsd_sigcontext_frame_this_id (struct frame_info *next_frame,
212130803Smarcel				      void **this_cache,
213130803Smarcel				      struct frame_id *this_id)
214130803Smarcel{
215130803Smarcel  struct sparc_frame_cache *cache =
216130803Smarcel    sparc32nbsd_sigcontext_frame_cache (next_frame, this_cache);
217130803Smarcel
218130803Smarcel  (*this_id) = frame_id_build (cache->base, cache->pc);
219130803Smarcel}
220130803Smarcel
221130803Smarcelstatic void
222130803Smarcelsparc32nbsd_sigcontext_frame_prev_register (struct frame_info *next_frame,
223130803Smarcel					    void **this_cache,
224130803Smarcel					    int regnum, int *optimizedp,
225130803Smarcel					    enum lval_type *lvalp,
226130803Smarcel					    CORE_ADDR *addrp,
227130803Smarcel					    int *realnump, void *valuep)
228130803Smarcel{
229130803Smarcel  struct sparc_frame_cache *cache =
230130803Smarcel    sparc32nbsd_sigcontext_frame_cache (next_frame, this_cache);
231130803Smarcel
232130803Smarcel  trad_frame_prev_register (next_frame, cache->saved_regs, regnum,
233130803Smarcel			    optimizedp, lvalp, addrp, realnump, valuep);
234130803Smarcel}
235130803Smarcel
236130803Smarcelstatic const struct frame_unwind sparc32nbsd_sigcontext_frame_unwind =
237130803Smarcel{
238130803Smarcel  SIGTRAMP_FRAME,
239130803Smarcel  sparc32nbsd_sigcontext_frame_this_id,
240130803Smarcel  sparc32nbsd_sigcontext_frame_prev_register
241130803Smarcel};
242130803Smarcel
243130803Smarcelstatic const struct frame_unwind *
244130803Smarcelsparc32nbsd_sigtramp_frame_sniffer (struct frame_info *next_frame)
245130803Smarcel{
246130803Smarcel  CORE_ADDR pc = frame_pc_unwind (next_frame);
247130803Smarcel  char *name;
248130803Smarcel
249130803Smarcel  find_pc_partial_function (pc, &name, NULL, NULL);
250130803Smarcel  if (sparc32nbsd_pc_in_sigtramp (pc, name))
251130803Smarcel    {
252130803Smarcel      if (name == NULL || strncmp (name, "__sigtramp_sigcontext", 21))
253130803Smarcel	return &sparc32nbsd_sigcontext_frame_unwind;
254130803Smarcel    }
255130803Smarcel
256130803Smarcel  return NULL;
257130803Smarcel}
258130803Smarcel
259130803Smarcel
260130803Smarcel/* Return non-zero if we are in a shared library trampoline code stub.  */
261130803Smarcel
262130803Smarcelstatic int
263130803Smarcelsparcnbsd_aout_in_solib_call_trampoline (CORE_ADDR pc, char *name)
264130803Smarcel{
265130803Smarcel  return (name && !strcmp (name, "_DYNAMIC"));
266130803Smarcel}
267130803Smarcel
268130803Smarcelstatic void
269130803Smarcelsparc32nbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
270130803Smarcel{
271130803Smarcel  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
272130803Smarcel
273130803Smarcel  /* NetBSD doesn't support the 128-bit `long double' from the psABI.  */
274130803Smarcel  set_gdbarch_long_double_bit (gdbarch, 64);
275130803Smarcel  set_gdbarch_long_double_format (gdbarch, &floatformat_ieee_double_big);
276130803Smarcel
277130803Smarcel  tdep->gregset = XMALLOC (struct regset);
278130803Smarcel  tdep->gregset->descr = &sparc32nbsd_gregset;
279130803Smarcel  tdep->gregset->supply_regset = sparc32nbsd_supply_gregset;
280130803Smarcel  tdep->sizeof_gregset = 20 * 4;
281130803Smarcel
282130803Smarcel  tdep->fpregset = XMALLOC (struct regset);
283130803Smarcel  tdep->fpregset->supply_regset = sparc32nbsd_supply_fpregset;
284130803Smarcel  tdep->sizeof_fpregset = 33 * 4;
285130803Smarcel
286130803Smarcel  set_gdbarch_pc_in_sigtramp (gdbarch, sparc32nbsd_pc_in_sigtramp);
287130803Smarcel  frame_unwind_append_sniffer (gdbarch, sparc32nbsd_sigtramp_frame_sniffer);
288130803Smarcel}
289130803Smarcel
290130803Smarcelstatic void
291130803Smarcelsparc32nbsd_aout_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
292130803Smarcel{
293130803Smarcel  sparc32nbsd_init_abi (info, gdbarch);
294130803Smarcel
295130803Smarcel  set_gdbarch_in_solib_call_trampoline
296130803Smarcel    (gdbarch, sparcnbsd_aout_in_solib_call_trampoline);
297130803Smarcel}
298130803Smarcel
299130803Smarcelstatic void
300130803Smarcelsparc32nbsd_elf_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
301130803Smarcel{
302130803Smarcel  sparc32nbsd_init_abi (info, gdbarch);
303130803Smarcel
304130803Smarcel  set_solib_svr4_fetch_link_map_offsets
305130803Smarcel    (gdbarch, nbsd_ilp32_solib_svr4_fetch_link_map_offsets);
306130803Smarcel}
307130803Smarcel
308130803Smarcelstatic enum gdb_osabi
309130803Smarcelsparcnbsd_aout_osabi_sniffer (bfd *abfd)
310130803Smarcel{
311130803Smarcel  if (strcmp (bfd_get_target (abfd), "a.out-sparc-netbsd") == 0)
312130803Smarcel    return GDB_OSABI_NETBSD_AOUT;
313130803Smarcel
314130803Smarcel  return GDB_OSABI_UNKNOWN;
315130803Smarcel}
316130803Smarcel
317130803Smarcel/* OpenBSD uses the traditional NetBSD core file format, even for
318130803Smarcel   ports that use ELF.  Therefore, if the default OS ABI is OpenBSD
319130803Smarcel   ELF, we return that instead of NetBSD a.out.  This is mainly for
320130803Smarcel   the benfit of OpenBSD/sparc64, which inherits the sniffer below
321130803Smarcel   since we include this file for an OpenBSD/sparc64 target.  For
322130803Smarcel   OpenBSD/sparc, the NetBSD a.out OS ABI is probably similar enough
323130803Smarcel   to both the OpenBSD a.out and the OpenBSD ELF OS ABI.  */
324130803Smarcel#if defined (GDB_OSABI_DEFAULT) && (GDB_OSABI_DEFAULT == GDB_OSABI_OPENBSD_ELF)
325130803Smarcel#define GDB_OSABI_NETBSD_CORE GDB_OSABI_OPENBSD_ELF
326130803Smarcel#else
327130803Smarcel#define GDB_OSABI_NETBSD_CORE GDB_OSABI_NETBSD_AOUT
328130803Smarcel#endif
329130803Smarcel
330130803Smarcelstatic enum gdb_osabi
331130803Smarcelsparcnbsd_core_osabi_sniffer (bfd *abfd)
332130803Smarcel{
333130803Smarcel  if (strcmp (bfd_get_target (abfd), "netbsd-core") == 0)
334130803Smarcel    return GDB_OSABI_NETBSD_CORE;
335130803Smarcel
336130803Smarcel  return GDB_OSABI_UNKNOWN;
337130803Smarcel}
338130803Smarcel
339130803Smarcel
340130803Smarcel/* Provide a prototype to silence -Wmissing-prototypes.  */
341130803Smarcelvoid _initialize_sparcnbsd_tdep (void);
342130803Smarcel
343130803Smarcelvoid
344130803Smarcel_initialize_sparnbsd_tdep (void)
345130803Smarcel{
346130803Smarcel  gdbarch_register_osabi_sniffer (bfd_arch_sparc, bfd_target_aout_flavour,
347130803Smarcel				  sparcnbsd_aout_osabi_sniffer);
348130803Smarcel
349130803Smarcel  /* BFD doesn't set the architecture for NetBSD style a.out core
350130803Smarcel     files.  */
351130803Smarcel  gdbarch_register_osabi_sniffer (bfd_arch_unknown, bfd_target_unknown_flavour,
352130803Smarcel                                  sparcnbsd_core_osabi_sniffer);
353130803Smarcel
354130803Smarcel  gdbarch_register_osabi (bfd_arch_sparc, 0, GDB_OSABI_NETBSD_AOUT,
355130803Smarcel			  sparc32nbsd_aout_init_abi);
356130803Smarcel  gdbarch_register_osabi (bfd_arch_sparc, 0, GDB_OSABI_NETBSD_ELF,
357130803Smarcel			  sparc32nbsd_elf_init_abi);
358130803Smarcel}
359