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