gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / gdb / sparc64-nbsd-tdep.c
CommitLineData
386c036b
MK
1/* Target-dependent code for NetBSD/sparc64.
2
b811d2c2 3 Copyright (C) 2002-2020 Free Software Foundation, Inc.
386c036b
MK
4 Based on code 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
386c036b
MK
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/>. */
386c036b
MK
20
21#include "defs.h"
22#include "frame.h"
23#include "frame-unwind.h"
24#include "gdbcore.h"
25#include "osabi.h"
26#include "regcache.h"
2ca62865 27#include "regset.h"
386c036b 28#include "symtab.h"
3510d1f2 29#include "objfiles.h"
386c036b
MK
30#include "solib-svr4.h"
31#include "trad-frame.h"
32
386c036b
MK
33#include "sparc64-tdep.h"
34#include "nbsd-tdep.h"
35
36/* From <machine/reg.h>. */
b4fd25c9 37const struct sparc_gregmap sparc64nbsd_gregmap =
386c036b
MK
38{
39 0 * 8, /* "tstate" */
40 1 * 8, /* %pc */
41 2 * 8, /* %npc */
42 3 * 8, /* %y */
43 -1, /* %fprs */
44 -1,
45 5 * 8, /* %g1 */
46 -1, /* %l0 */
47 4 /* sizeof (%y) */
48};
2ca62865 49\f
386c036b
MK
50
51static void
2ca62865
MK
52sparc64nbsd_supply_gregset (const struct regset *regset,
53 struct regcache *regcache,
54 int regnum, const void *gregs, size_t len)
386c036b 55{
b4fd25c9 56 sparc64_supply_gregset (&sparc64nbsd_gregmap, regcache, regnum, gregs);
386c036b
MK
57}
58
2ca62865
MK
59static void
60sparc64nbsd_supply_fpregset (const struct regset *regset,
61 struct regcache *regcache,
62 int regnum, const void *fpregs, size_t len)
386c036b 63{
b4fd25c9 64 sparc64_supply_fpregset (&sparc64_bsd_fpregmap, regcache, regnum, fpregs);
2ca62865 65}
386c036b 66\f
2ca62865 67
386c036b
MK
68/* Signal trampolines. */
69
70/* The following variables describe the location of an on-stack signal
71 trampoline. The current values correspond to the memory layout for
72 NetBSD 1.3 and up. These shouldn't be necessary for NetBSD 2.0 and
73 up, since NetBSD uses signal trampolines provided by libc now. */
74
75static const CORE_ADDR sparc64nbsd_sigtramp_start = 0xffffffffffffdee4ULL;
76static const CORE_ADDR sparc64nbsd_sigtramp_end = 0xffffffffffffe000ULL;
77
78static int
2c02bd72 79sparc64nbsd_pc_in_sigtramp (CORE_ADDR pc, const char *name)
386c036b
MK
80{
81 if (pc >= sparc64nbsd_sigtramp_start && pc < sparc64nbsd_sigtramp_end)
82 return 1;
83
84 return nbsd_pc_in_sigtramp (pc, name);
85}
86
1e067c66
MK
87struct trad_frame_saved_reg *
88sparc64nbsd_sigcontext_saved_regs (CORE_ADDR sigcontext_addr,
94afd7a6 89 struct frame_info *this_frame)
386c036b 90{
e17a4113 91 struct gdbarch *gdbarch = get_frame_arch (this_frame);
1e067c66
MK
92 struct trad_frame_saved_reg *saved_regs;
93 CORE_ADDR addr, sp;
386c036b
MK
94 int regnum, delta;
95
94afd7a6 96 saved_regs = trad_frame_alloc_saved_regs (this_frame);
386c036b
MK
97
98 /* The registers are saved in bits and pieces scattered all over the
99 place. The code below records their location on the assumption
100 that the part of the signal trampoline that saves the state has
101 been executed. */
102
1e067c66
MK
103 saved_regs[SPARC_SP_REGNUM].addr = sigcontext_addr + 8;
104 saved_regs[SPARC64_PC_REGNUM].addr = sigcontext_addr + 16;
105 saved_regs[SPARC64_NPC_REGNUM].addr = sigcontext_addr + 24;
106 saved_regs[SPARC64_STATE_REGNUM].addr = sigcontext_addr + 32;
107 saved_regs[SPARC_G1_REGNUM].addr = sigcontext_addr + 40;
108 saved_regs[SPARC_O0_REGNUM].addr = sigcontext_addr + 48;
386c036b
MK
109
110 /* The remaining `global' registers and %y are saved in the `local'
111 registers. */
112 delta = SPARC_L0_REGNUM - SPARC_G0_REGNUM;
113 for (regnum = SPARC_G2_REGNUM; regnum <= SPARC_G7_REGNUM; regnum++)
1e067c66
MK
114 saved_regs[regnum].realreg = regnum + delta;
115 saved_regs[SPARC64_Y_REGNUM].realreg = SPARC_L1_REGNUM;
386c036b
MK
116
117 /* The remaining `out' registers can be found in the current frame's
118 `in' registers. */
119 delta = SPARC_I0_REGNUM - SPARC_O0_REGNUM;
120 for (regnum = SPARC_O1_REGNUM; regnum <= SPARC_O5_REGNUM; regnum++)
1e067c66
MK
121 saved_regs[regnum].realreg = regnum + delta;
122 saved_regs[SPARC_O7_REGNUM].realreg = SPARC_I7_REGNUM;
386c036b
MK
123
124 /* The `local' and `in' registers have been saved in the register
125 save area. */
1e067c66 126 addr = saved_regs[SPARC_SP_REGNUM].addr;
94afd7a6 127 sp = get_frame_memory_unsigned (this_frame, addr, 8);
386c036b
MK
128 for (regnum = SPARC_L0_REGNUM, addr = sp + BIAS;
129 regnum <= SPARC_I7_REGNUM; regnum++, addr += 8)
1e067c66 130 saved_regs[regnum].addr = addr;
386c036b 131
8391b9b1
MK
132 /* Handle StackGhost. */
133 {
e17a4113 134 ULONGEST wcookie = sparc_fetch_wcookie (gdbarch);
8391b9b1
MK
135
136 if (wcookie != 0)
137 {
138 ULONGEST i7;
139
140 addr = saved_regs[SPARC_I7_REGNUM].addr;
94afd7a6 141 i7 = get_frame_memory_unsigned (this_frame, addr, 8);
8391b9b1
MK
142 trad_frame_set_value (saved_regs, SPARC_I7_REGNUM, i7 ^ wcookie);
143 }
144 }
145
386c036b
MK
146 /* TODO: Handle the floating-point registers. */
147
1e067c66
MK
148 return saved_regs;
149}
150
151static struct sparc_frame_cache *
94afd7a6 152sparc64nbsd_sigcontext_frame_cache (struct frame_info *this_frame,
1e067c66
MK
153 void **this_cache)
154{
155 struct sparc_frame_cache *cache;
156 CORE_ADDR addr;
157
158 if (*this_cache)
19ba03f4 159 return (struct sparc_frame_cache *) *this_cache;
1e067c66 160
94afd7a6 161 cache = sparc_frame_cache (this_frame, this_cache);
1e067c66
MK
162 gdb_assert (cache == *this_cache);
163
164 /* If we couldn't find the frame's function, we're probably dealing
165 with an on-stack signal trampoline. */
166 if (cache->pc == 0)
167 {
168 cache->pc = sparc64nbsd_sigtramp_start;
169
170 /* Since we couldn't find the frame's function, the cache was
171 initialized under the assumption that we're frameless. */
369c397b 172 sparc_record_save_insn (cache);
94afd7a6 173 addr = get_frame_register_unsigned (this_frame, SPARC_FP_REGNUM);
5b2d44a0
MK
174 if (addr & 1)
175 addr += BIAS;
1e067c66
MK
176 cache->base = addr;
177 }
178
179 /* We find the appropriate instance of `struct sigcontext' at a
180 fixed offset in the signal frame. */
5b2d44a0 181 addr = cache->base + 128 + 8;
94afd7a6 182 cache->saved_regs = sparc64nbsd_sigcontext_saved_regs (addr, this_frame);
1e067c66 183
386c036b
MK
184 return cache;
185}
186
187static void
94afd7a6 188sparc64nbsd_sigcontext_frame_this_id (struct frame_info *this_frame,
386c036b
MK
189 void **this_cache,
190 struct frame_id *this_id)
191{
192 struct sparc_frame_cache *cache =
94afd7a6 193 sparc64nbsd_sigcontext_frame_cache (this_frame, this_cache);
386c036b
MK
194
195 (*this_id) = frame_id_build (cache->base, cache->pc);
196}
197
94afd7a6
UW
198static struct value *
199sparc64nbsd_sigcontext_frame_prev_register (struct frame_info *this_frame,
200 void **this_cache, int regnum)
386c036b
MK
201{
202 struct sparc_frame_cache *cache =
94afd7a6 203 sparc64nbsd_sigcontext_frame_cache (this_frame, this_cache);
386c036b 204
94afd7a6 205 return trad_frame_get_prev_register (this_frame, cache->saved_regs, regnum);
386c036b
MK
206}
207
94afd7a6
UW
208static int
209sparc64nbsd_sigtramp_frame_sniffer (const struct frame_unwind *self,
210 struct frame_info *this_frame,
211 void **this_cache)
386c036b 212{
94afd7a6 213 CORE_ADDR pc = get_frame_pc (this_frame);
2c02bd72 214 const char *name;
386c036b
MK
215
216 find_pc_partial_function (pc, &name, NULL, NULL);
217 if (sparc64nbsd_pc_in_sigtramp (pc, name))
218 {
61012eef 219 if (name == NULL || !startswith (name, "__sigtramp_sigcontext"))
94afd7a6 220 return 1;
386c036b
MK
221 }
222
94afd7a6 223 return 0;
386c036b 224}
94afd7a6
UW
225
226static const struct frame_unwind sparc64nbsd_sigcontext_frame_unwind =
227{
228 SIGTRAMP_FRAME,
8fbca658 229 default_frame_unwind_stop_reason,
94afd7a6
UW
230 sparc64nbsd_sigcontext_frame_this_id,
231 sparc64nbsd_sigcontext_frame_prev_register,
232 NULL,
233 sparc64nbsd_sigtramp_frame_sniffer
234};
386c036b
MK
235\f
236
b13feb94
AA
237static const struct regset sparc64nbsd_gregset =
238 {
239 NULL, sparc64nbsd_supply_gregset, NULL
240 };
241
242static const struct regset sparc64nbsd_fpregset =
243 {
244 NULL, sparc64nbsd_supply_fpregset, NULL
245 };
246
386c036b
MK
247static void
248sparc64nbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
249{
2ca62865
MK
250 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
251
79743962
KR
252 nbsd_init_abi (info, gdbarch);
253
b13feb94 254 tdep->gregset = &sparc64nbsd_gregset;
2ca62865
MK
255 tdep->sizeof_gregset = 160;
256
b13feb94 257 tdep->fpregset = &sparc64nbsd_fpregset;
2ca62865
MK
258 tdep->sizeof_fpregset = 272;
259
c893be75
MK
260 /* Make sure we can single-step "new" syscalls. */
261 tdep->step_trap = sparcnbsd_step_trap;
262
94afd7a6 263 frame_unwind_append_unwinder (gdbarch, &sparc64nbsd_sigcontext_frame_unwind);
386c036b
MK
264
265 sparc64_init_abi (info, gdbarch);
266
5b2d44a0 267 /* NetBSD/sparc64 has SVR4-style shared libraries. */
3510d1f2 268 set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
386c036b 269 set_solib_svr4_fetch_link_map_offsets
3510d1f2 270 (gdbarch, svr4_lp64_fetch_link_map_offsets);
386c036b 271}
386c036b 272
6c265988 273void _initialize_sparc64nbsd_tdep ();
386c036b 274void
6c265988 275_initialize_sparc64nbsd_tdep ()
386c036b
MK
276{
277 gdbarch_register_osabi (bfd_arch_sparc, bfd_mach_sparc_v9,
1736a7bd 278 GDB_OSABI_NETBSD, sparc64nbsd_init_abi);
386c036b 279}
This page took 1.674889 seconds and 4 git commands to generate.