1 /* Target-dependent code for NetBSD/sparc64.
3 Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007
4 Free Software Foundation, Inc.
5 Based on code contributed by Wasabi Systems, Inc.
7 This file is part of GDB.
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.
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.
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
21 Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 Boston, MA 02110-1301, USA. */
26 #include "frame-unwind.h"
33 #include "solib-svr4.h"
34 #include "trad-frame.h"
36 #include "gdb_assert.h"
37 #include "gdb_string.h"
39 #include "sparc64-tdep.h"
40 #include "nbsd-tdep.h"
42 /* From <machine/reg.h>. */
43 const struct sparc_gregset sparc64nbsd_gregset
=
58 sparc64nbsd_supply_gregset (const struct regset
*regset
,
59 struct regcache
*regcache
,
60 int regnum
, const void *gregs
, size_t len
)
62 sparc64_supply_gregset (&sparc64nbsd_gregset
, regcache
, regnum
, gregs
);
66 sparc64nbsd_supply_fpregset (const struct regset
*regset
,
67 struct regcache
*regcache
,
68 int regnum
, const void *fpregs
, size_t len
)
70 sparc64_supply_fpregset (regcache
, regnum
, fpregs
);
74 /* Signal trampolines. */
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. */
81 static const CORE_ADDR sparc64nbsd_sigtramp_start
= 0xffffffffffffdee4ULL
;
82 static const CORE_ADDR sparc64nbsd_sigtramp_end
= 0xffffffffffffe000ULL
;
85 sparc64nbsd_pc_in_sigtramp (CORE_ADDR pc
, char *name
)
87 if (pc
>= sparc64nbsd_sigtramp_start
&& pc
< sparc64nbsd_sigtramp_end
)
90 return nbsd_pc_in_sigtramp (pc
, name
);
93 struct trad_frame_saved_reg
*
94 sparc64nbsd_sigcontext_saved_regs (CORE_ADDR sigcontext_addr
,
95 struct frame_info
*next_frame
)
97 struct trad_frame_saved_reg
*saved_regs
;
101 saved_regs
= trad_frame_alloc_saved_regs (next_frame
);
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
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;
115 /* The remaining `global' registers and %y are saved in the `local'
117 delta
= SPARC_L0_REGNUM
- SPARC_G0_REGNUM
;
118 for (regnum
= SPARC_G2_REGNUM
; regnum
<= SPARC_G7_REGNUM
; regnum
++)
119 saved_regs
[regnum
].realreg
= regnum
+ delta
;
120 saved_regs
[SPARC64_Y_REGNUM
].realreg
= SPARC_L1_REGNUM
;
122 /* The remaining `out' registers can be found in the current frame's
124 delta
= SPARC_I0_REGNUM
- SPARC_O0_REGNUM
;
125 for (regnum
= SPARC_O1_REGNUM
; regnum
<= SPARC_O5_REGNUM
; regnum
++)
126 saved_regs
[regnum
].realreg
= regnum
+ delta
;
127 saved_regs
[SPARC_O7_REGNUM
].realreg
= SPARC_I7_REGNUM
;
129 /* The `local' and `in' registers have been saved in the register
131 addr
= saved_regs
[SPARC_SP_REGNUM
].addr
;
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)
135 saved_regs
[regnum
].addr
= addr
;
137 /* Handle StackGhost. */
139 ULONGEST wcookie
= sparc_fetch_wcookie ();
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
);
151 /* TODO: Handle the floating-point registers. */
156 static struct sparc_frame_cache
*
157 sparc64nbsd_sigcontext_frame_cache (struct frame_info
*next_frame
,
160 struct sparc_frame_cache
*cache
;
166 cache
= sparc_frame_cache (next_frame
, this_cache
);
167 gdb_assert (cache
== *this_cache
);
169 /* If we couldn't find the frame's function, we're probably dealing
170 with an on-stack signal trampoline. */
173 cache
->pc
= sparc64nbsd_sigtramp_start
;
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
);
184 /* We find the appropriate instance of `struct sigcontext' at a
185 fixed offset in the signal frame. */
186 addr
= cache
->base
+ 128 + 8;
187 cache
->saved_regs
= sparc64nbsd_sigcontext_saved_regs (addr
, next_frame
);
193 sparc64nbsd_sigcontext_frame_this_id (struct frame_info
*next_frame
,
195 struct frame_id
*this_id
)
197 struct sparc_frame_cache
*cache
=
198 sparc64nbsd_sigcontext_frame_cache (next_frame
, this_cache
);
200 (*this_id
) = frame_id_build (cache
->base
, cache
->pc
);
204 sparc64nbsd_sigcontext_frame_prev_register (struct frame_info
*next_frame
,
206 int regnum
, int *optimizedp
,
207 enum lval_type
*lvalp
,
209 int *realnump
, gdb_byte
*valuep
)
211 struct sparc_frame_cache
*cache
=
212 sparc64nbsd_sigcontext_frame_cache (next_frame
, this_cache
);
214 trad_frame_get_prev_register (next_frame
, cache
->saved_regs
, regnum
,
215 optimizedp
, lvalp
, addrp
, realnump
, valuep
);
218 static const struct frame_unwind sparc64nbsd_sigcontext_frame_unwind
=
221 sparc64nbsd_sigcontext_frame_this_id
,
222 sparc64nbsd_sigcontext_frame_prev_register
225 static const struct frame_unwind
*
226 sparc64nbsd_sigtramp_frame_sniffer (struct frame_info
*next_frame
)
228 CORE_ADDR pc
= frame_pc_unwind (next_frame
);
231 find_pc_partial_function (pc
, &name
, NULL
, NULL
);
232 if (sparc64nbsd_pc_in_sigtramp (pc
, name
))
234 if (name
== NULL
|| strncmp (name
, "__sigtramp_sigcontext", 21))
235 return &sparc64nbsd_sigcontext_frame_unwind
;
243 sparc64nbsd_init_abi (struct gdbarch_info info
, struct gdbarch
*gdbarch
)
245 struct gdbarch_tdep
*tdep
= gdbarch_tdep (gdbarch
);
247 tdep
->gregset
= regset_alloc (gdbarch
, sparc64nbsd_supply_gregset
, NULL
);
248 tdep
->sizeof_gregset
= 160;
250 tdep
->fpregset
= regset_alloc (gdbarch
, sparc64nbsd_supply_fpregset
, NULL
);
251 tdep
->sizeof_fpregset
= 272;
253 /* Make sure we can single-step "new" syscalls. */
254 tdep
->step_trap
= sparcnbsd_step_trap
;
256 frame_unwind_append_sniffer (gdbarch
, sparc64nbsd_sigtramp_frame_sniffer
);
258 sparc64_init_abi (info
, gdbarch
);
260 /* NetBSD/sparc64 has SVR4-style shared libraries. */
261 set_gdbarch_skip_trampoline_code (gdbarch
, find_solib_trampoline_target
);
262 set_solib_svr4_fetch_link_map_offsets
263 (gdbarch
, svr4_lp64_fetch_link_map_offsets
);
267 /* Provide a prototype to silence -Wmissing-prototypes. */
268 void _initialize_sparc64nbsd_tdep (void);
271 _initialize_sparc64nbsd_tdep (void)
273 gdbarch_register_osabi (bfd_arch_sparc
, bfd_mach_sparc_v9
,
274 GDB_OSABI_NETBSD_ELF
, sparc64nbsd_init_abi
);