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