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