[gdb/testsuite] Add untested case in gdb.gdb/complaints.exp
[deliverable/binutils-gdb.git] / gdb / sparc-netbsd-tdep.c
CommitLineData
386c036b
MK
1/* Target-dependent code for NetBSD/sparc.
2
3666a048 3 Copyright (C) 2002-2021 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"
0d12e84c 32#include "gdbarch.h"
9ce5c36a 33
c139e7d9 34#include "sparc-tdep.h"
1b71cfcf 35#include "netbsd-tdep.h"
9ce5c36a 36
c893be75
MK
37/* Macros to extract fields from SPARC instructions. */
38#define X_RS1(i) (((i) >> 14) & 0x1f)
39#define X_RS2(i) ((i) & 0x1f)
40#define X_I(i) (((i) >> 13) & 1)
41
b4fd25c9 42const struct sparc_gregmap sparc32nbsd_gregmap =
9ce5c36a 43{
386c036b
MK
44 0 * 4, /* %psr */
45 1 * 4, /* %pc */
46 2 * 4, /* %npc */
47 3 * 4, /* %y */
48 -1, /* %wim */
49 -1, /* %tbr */
50 5 * 4, /* %g1 */
51 -1 /* %l0 */
52};
9ce5c36a 53
9ce5c36a 54static void
4e7b0cd3
MK
55sparc32nbsd_supply_gregset (const struct regset *regset,
56 struct regcache *regcache,
57 int regnum, const void *gregs, size_t len)
9ce5c36a 58{
b4fd25c9 59 sparc32_supply_gregset (&sparc32nbsd_gregmap, regcache, regnum, gregs);
c8e737d5
MK
60
61 /* Traditional NetBSD core files don't use multiple register sets.
62 Instead, the general-purpose and floating-point registers are
63 lumped together in a single section. */
64 if (len >= 212)
b4fd25c9 65 sparc32_supply_fpregset (&sparc32_bsd_fpregmap, regcache, regnum,
db75c717 66 (const char *) gregs + 80);
9ce5c36a
JT
67}
68
4e7b0cd3
MK
69static void
70sparc32nbsd_supply_fpregset (const struct regset *regset,
71 struct regcache *regcache,
72 int regnum, const void *fpregs, size_t len)
9ce5c36a 73{
b4fd25c9 74 sparc32_supply_fpregset (&sparc32_bsd_fpregmap, regcache, regnum, fpregs);
4e7b0cd3 75}
9ce5c36a 76
386c036b
MK
77\f
78/* Signal trampolines. */
79
80/* The following variables describe the location of an on-stack signal
81 trampoline. The current values correspond to the memory layout for
82 NetBSD 1.3 and up. These shouldn't be necessary for NetBSD 2.0 and
83 up, since NetBSD uses signal trampolines provided by libc now. */
9ce5c36a 84
386c036b
MK
85static const CORE_ADDR sparc32nbsd_sigtramp_start = 0xeffffef0;
86static const CORE_ADDR sparc32nbsd_sigtramp_end = 0xeffffff0;
9ce5c36a
JT
87
88static int
2c02bd72 89sparc32nbsd_pc_in_sigtramp (CORE_ADDR pc, const char *name)
386c036b
MK
90{
91 if (pc >= sparc32nbsd_sigtramp_start && pc < sparc32nbsd_sigtramp_end)
92 return 1;
93
94 return nbsd_pc_in_sigtramp (pc, name);
95}
96
098caef4 97trad_frame_saved_reg *
7ea566be 98sparc32nbsd_sigcontext_saved_regs (struct frame_info *this_frame)
9ce5c36a 99{
e17a4113 100 struct gdbarch *gdbarch = get_frame_arch (this_frame);
098caef4 101 trad_frame_saved_reg *saved_regs;
386c036b 102 CORE_ADDR addr, sigcontext_addr;
386c036b 103 int regnum, delta;
566626fa 104 ULONGEST psr;
9ce5c36a 105
7ea566be 106 saved_regs = trad_frame_alloc_saved_regs (this_frame);
9ce5c36a 107
566626fa
MK
108 /* We find the appropriate instance of `struct sigcontext' at a
109 fixed offset in the signal frame. */
7ea566be 110 addr = get_frame_register_unsigned (this_frame, SPARC_FP_REGNUM);
566626fa 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
098caef4
LM
118 saved_regs[SPARC_SP_REGNUM].set_addr (sigcontext_addr + 8);
119 saved_regs[SPARC32_PC_REGNUM].set_addr (sigcontext_addr + 12);
120 saved_regs[SPARC32_NPC_REGNUM].set_addr (sigcontext_addr + 16);
121 saved_regs[SPARC32_PSR_REGNUM].set_addr (sigcontext_addr + 20);
122 saved_regs[SPARC_G1_REGNUM].set_addr (sigcontext_addr + 24);
123 saved_regs[SPARC_O0_REGNUM].set_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++)
098caef4
LM
129 saved_regs[regnum].set_realreg (regnum + delta);
130 saved_regs[SPARC32_Y_REGNUM].set_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++)
098caef4
LM
136 saved_regs[regnum].set_realreg (regnum + delta);
137 saved_regs[SPARC_O7_REGNUM].set_realreg (SPARC_I7_REGNUM);
386c036b
MK
138
139 /* The `local' and `in' registers have been saved in the register
140 save area. */
098caef4 141 addr = saved_regs[SPARC_SP_REGNUM].addr ();
7ea566be 142 addr = get_frame_memory_unsigned (this_frame, addr, 4);
386c036b
MK
143 for (regnum = SPARC_L0_REGNUM;
144 regnum <= SPARC_I7_REGNUM; regnum++, addr += 4)
098caef4 145 saved_regs[regnum].set_addr (addr);
386c036b 146
1c800673
MK
147 /* Handle StackGhost. */
148 {
e17a4113 149 ULONGEST wcookie = sparc_fetch_wcookie (gdbarch);
1c800673
MK
150
151 if (wcookie != 0)
152 {
153 ULONGEST i7;
154
098caef4 155 addr = saved_regs[SPARC_I7_REGNUM].addr ();
7ea566be 156 i7 = get_frame_memory_unsigned (this_frame, addr, 4);
a9a87d35 157 saved_regs[SPARC_I7_REGNUM].set_value (i7 ^ wcookie);
1c800673
MK
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
098caef4 166 addr = saved_regs[SPARC32_PSR_REGNUM].addr ();
7ea566be 167 psr = get_frame_memory_unsigned (this_frame, addr, 4);
386c036b
MK
168 if (psr & PSR_EF)
169 {
170 CORE_ADDR sp;
171
7ea566be 172 sp = get_frame_register_unsigned (this_frame, SPARC_SP_REGNUM);
098caef4 173 saved_regs[SPARC32_FSR_REGNUM].set_addr (sp + 96);
386c036b
MK
174 for (regnum = SPARC_F0_REGNUM, addr = sp + 96 + 8;
175 regnum <= SPARC_F31_REGNUM; regnum++, addr += 4)
098caef4 176 saved_regs[regnum].set_addr (addr);
566626fa
MK
177 }
178
179 return saved_regs;
180}
181
182static struct sparc_frame_cache *
7ea566be 183sparc32nbsd_sigcontext_frame_cache (struct frame_info *this_frame,
566626fa
MK
184 void **this_cache)
185{
186 struct sparc_frame_cache *cache;
187 CORE_ADDR addr;
188
189 if (*this_cache)
19ba03f4 190 return (struct sparc_frame_cache *) *this_cache;
566626fa 191
7ea566be 192 cache = sparc_frame_cache (this_frame, this_cache);
566626fa
MK
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
dda83cd7 202 initialized under the assumption that we're frameless. */
369c397b 203 sparc_record_save_insn (cache);
7ea566be 204 addr = get_frame_register_unsigned (this_frame, SPARC_FP_REGNUM);
566626fa 205 cache->base = addr;
386c036b
MK
206 }
207
7ea566be 208 cache->saved_regs = sparc32nbsd_sigcontext_saved_regs (this_frame);
566626fa 209
386c036b 210 return cache;
9ce5c36a
JT
211}
212
386c036b 213static void
7ea566be 214sparc32nbsd_sigcontext_frame_this_id (struct frame_info *this_frame,
386c036b
MK
215 void **this_cache,
216 struct frame_id *this_id)
217{
218 struct sparc_frame_cache *cache =
7ea566be 219 sparc32nbsd_sigcontext_frame_cache (this_frame, this_cache);
386c036b
MK
220
221 (*this_id) = frame_id_build (cache->base, cache->pc);
222}
223
7ea566be
MK
224static struct value *
225sparc32nbsd_sigcontext_frame_prev_register (struct frame_info *this_frame,
226 void **this_cache, int regnum)
9ce5c36a 227{
386c036b 228 struct sparc_frame_cache *cache =
7ea566be 229 sparc32nbsd_sigcontext_frame_cache (this_frame, this_cache);
9ce5c36a 230
7ea566be 231 return trad_frame_get_prev_register (this_frame, cache->saved_regs, regnum);
386c036b 232}
9ce5c36a 233
7ea566be
MK
234static int
235sparc32nbsd_sigcontext_frame_sniffer (const struct frame_unwind *self,
236 struct frame_info *this_frame,
237 void **this_cache)
386c036b 238{
7ea566be 239 CORE_ADDR pc = get_frame_pc (this_frame);
2c02bd72 240 const char *name;
9ce5c36a 241
386c036b
MK
242 find_pc_partial_function (pc, &name, NULL, NULL);
243 if (sparc32nbsd_pc_in_sigtramp (pc, name))
244 {
61012eef 245 if (name == NULL || !startswith (name, "__sigtramp_sigcontext"))
7ea566be 246 return 1;
386c036b
MK
247 }
248
7ea566be 249 return 0;
9ce5c36a 250}
7ea566be
MK
251
252static const struct frame_unwind sparc32nbsd_sigcontext_frame_unwind =
253{
a154d838 254 "sparc32 netbsd sigcontext",
7ea566be 255 SIGTRAMP_FRAME,
8fbca658 256 default_frame_unwind_stop_reason,
7ea566be
MK
257 sparc32nbsd_sigcontext_frame_this_id,
258 sparc32nbsd_sigcontext_frame_prev_register,
259 NULL,
260 sparc32nbsd_sigcontext_frame_sniffer
261};
386c036b 262\f
c893be75
MK
263/* Return the address of a system call's alternative return
264 address. */
265
266CORE_ADDR
0b1b3e42 267sparcnbsd_step_trap (struct frame_info *frame, unsigned long insn)
c893be75
MK
268{
269 if ((X_I (insn) == 0 && X_RS1 (insn) == 0 && X_RS2 (insn) == 0)
270 || (X_I (insn) == 1 && X_RS1 (insn) == 0 && (insn & 0x7f) == 0))
271 {
272 /* "New" system call. */
0b1b3e42 273 ULONGEST number = get_frame_register_unsigned (frame, SPARC_G1_REGNUM);
c893be75
MK
274
275 if (number & 0x400)
0b1b3e42 276 return get_frame_register_unsigned (frame, SPARC_G2_REGNUM);
c893be75 277 if (number & 0x800)
0b1b3e42 278 return get_frame_register_unsigned (frame, SPARC_G7_REGNUM);
c893be75
MK
279 }
280
281 return 0;
282}
283\f
386c036b 284
b13feb94
AA
285static const struct regset sparc32nbsd_gregset =
286 {
287 NULL, sparc32nbsd_supply_gregset, NULL
288 };
289
290static const struct regset sparc32nbsd_fpregset =
291 {
292 NULL, sparc32nbsd_supply_fpregset, NULL
293 };
294
1736a7bd 295void
386c036b 296sparc32nbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
9ce5c36a 297{
4e7b0cd3
MK
298 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
299
79743962
KR
300 nbsd_init_abi (info, gdbarch);
301
386c036b
MK
302 /* NetBSD doesn't support the 128-bit `long double' from the psABI. */
303 set_gdbarch_long_double_bit (gdbarch, 64);
8da61cc4 304 set_gdbarch_long_double_format (gdbarch, floatformats_ieee_double);
386c036b 305
b13feb94 306 tdep->gregset = &sparc32nbsd_gregset;
c8e737d5 307 tdep->sizeof_gregset = 20 * 4;
4e7b0cd3 308
b13feb94 309 tdep->fpregset = &sparc32nbsd_fpregset;
c8e737d5 310 tdep->sizeof_fpregset = 33 * 4;
4e7b0cd3 311
c893be75
MK
312 /* Make sure we can single-step "new" syscalls. */
313 tdep->step_trap = sparcnbsd_step_trap;
314
7ea566be 315 frame_unwind_append_unwinder (gdbarch, &sparc32nbsd_sigcontext_frame_unwind);
9ce5c36a 316
386c036b 317 set_solib_svr4_fetch_link_map_offsets
be24b061 318 (gdbarch, svr4_ilp32_fetch_link_map_offsets);
9ce5c36a
JT
319}
320
6c265988 321void _initialize_sparcnbsd_tdep ();
9ce5c36a 322void
6c265988 323_initialize_sparcnbsd_tdep ()
9ce5c36a 324{
1736a7bd
PA
325 gdbarch_register_osabi (bfd_arch_sparc, 0, GDB_OSABI_NETBSD,
326 sparc32nbsd_init_abi);
9ce5c36a 327}
This page took 2.18836 seconds and 4 git commands to generate.