AARCH64: Migrate from 'regset_from_core_section' to 'iterate_over_regset_sections'
[deliverable/binutils-gdb.git] / gdb / alphanbsd-tdep.c
CommitLineData
789f3b5f
MK
1/* Target-dependent code for NetBSD/alpha.
2
ecd75fc8 3 Copyright (C) 2002-2014 Free Software Foundation, Inc.
2031c21a 4
da8ca43d
JT
5 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
a9762ec7 11 the Free Software Foundation; either version 3 of the License, or
da8ca43d
JT
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
a9762ec7 20 along with this program. If not, see <http://www.gnu.org/licenses/>. */
da8ca43d
JT
21
22#include "defs.h"
2ca8ae21 23#include "frame.h"
3beabdb2
MK
24#include "gdbcore.h"
25#include "osabi.h"
8513dd2d 26#include "regcache.h"
3beabdb2 27#include "regset.h"
da8ca43d 28#include "value.h"
da8ca43d
JT
29
30#include "alpha-tdep.h"
8513dd2d 31#include "alphabsd-tdep.h"
ea5bc2a6 32#include "nbsd-tdep.h"
527ca6bb 33#include "solib-svr4.h"
effa26a9 34#include "target.h"
8513dd2d 35
3beabdb2
MK
36/* Core file support. */
37
38/* Even though NetBSD/alpha used ELF since day one, it used the
39 traditional a.out-style core dump format before NetBSD 1.6. */
40
41/* Sizeof `struct reg' in <machine/reg.h>. */
42#define ALPHANBSD_SIZEOF_GREGS (32 * 8)
43
44/* Sizeof `struct fpreg' in <machine/reg.h. */
45#define ALPHANBSD_SIZEOF_FPREGS ((32 * 8) + 8)
46
47/* Supply register REGNUM from the buffer specified by FPREGS and LEN
48 in the floating-point register set REGSET to register cache
49 REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */
50
8513dd2d 51static void
3beabdb2
MK
52alphanbsd_supply_fpregset (const struct regset *regset,
53 struct regcache *regcache,
54 int regnum, const void *fpregs, size_t len)
8513dd2d 55{
3beabdb2
MK
56 const gdb_byte *regs = fpregs;
57 int i;
58
59 gdb_assert (len >= ALPHANBSD_SIZEOF_FPREGS);
60
61 for (i = ALPHA_FP0_REGNUM; i < ALPHA_FP0_REGNUM + 31; i++)
62 {
63 if (regnum == i || regnum == -1)
64 regcache_raw_supply (regcache, i, regs + (i - ALPHA_FP0_REGNUM) * 8);
65 }
66
67 if (regnum == ALPHA_FPCR_REGNUM || regnum == -1)
68 regcache_raw_supply (regcache, ALPHA_FPCR_REGNUM, regs + 32 * 8);
69}
70
71/* Supply register REGNUM from the buffer specified by GREGS and LEN
72 in the general-purpose register set REGSET to register cache
73 REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */
8513dd2d 74
3beabdb2
MK
75static void
76alphanbsd_supply_gregset (const struct regset *regset,
77 struct regcache *regcache,
78 int regnum, const void *gregs, size_t len)
79{
80 const gdb_byte *regs = gregs;
81 int i;
82
83 gdb_assert (len >= ALPHANBSD_SIZEOF_GREGS);
84
85 for (i = 0; i < ALPHA_ZERO_REGNUM; i++)
86 {
87 if (regnum == i || regnum == -1)
88 regcache_raw_supply (regcache, i, regs + i * 8);
89 }
90
91 if (regnum == ALPHA_PC_REGNUM || regnum == -1)
92 regcache_raw_supply (regcache, ALPHA_PC_REGNUM, regs + 31 * 8);
93}
94
95/* Supply register REGNUM from the buffer specified by GREGS and LEN
96 in the general-purpose register set REGSET to register cache
97 REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */
98
99static void
100alphanbsd_aout_supply_gregset (const struct regset *regset,
101 struct regcache *regcache,
102 int regnum, const void *gregs, size_t len)
103{
104 const gdb_byte *regs = gregs;
105 int i;
106
107 /* Table to map a GDB register number to a trapframe register index. */
8513dd2d
JT
108 static const int regmap[] =
109 {
110 0, 1, 2, 3,
111 4, 5, 6, 7,
112 8, 9, 10, 11,
113 12, 13, 14, 15,
114 30, 31, 32, 16,
115 17, 18, 19, 20,
116 21, 22, 23, 24,
117 25, 29, 26
118 };
8513dd2d 119
3beabdb2 120 gdb_assert (len >= ALPHANBSD_SIZEOF_GREGS);
8513dd2d 121
3beabdb2 122 for (i = 0; i < ARRAY_SIZE(regmap); i++)
8513dd2d 123 {
3beabdb2
MK
124 if (regnum == i || regnum == -1)
125 regcache_raw_supply (regcache, i, regs + regmap[i] * 8);
8513dd2d
JT
126 }
127
3beabdb2
MK
128 if (regnum == ALPHA_PC_REGNUM || regnum == -1)
129 regcache_raw_supply (regcache, ALPHA_PC_REGNUM, regs + 31 * 8);
8513dd2d 130
3beabdb2 131 if (len >= ALPHANBSD_SIZEOF_GREGS + ALPHANBSD_SIZEOF_FPREGS)
8513dd2d 132 {
3beabdb2
MK
133 regs += ALPHANBSD_SIZEOF_GREGS;
134 len -= ALPHANBSD_SIZEOF_GREGS;
135 alphanbsd_supply_fpregset (regset, regcache, regnum, regs, len);
8513dd2d
JT
136 }
137}
138
3beabdb2
MK
139/* NetBSD/alpha register sets. */
140
3ca7dae4 141static const struct regset alphanbsd_gregset =
8513dd2d 142{
3beabdb2
MK
143 NULL,
144 alphanbsd_supply_gregset
8513dd2d
JT
145};
146
3ca7dae4 147static const struct regset alphanbsd_fpregset =
8513dd2d 148{
3beabdb2
MK
149 NULL,
150 alphanbsd_supply_fpregset
8513dd2d 151};
da8ca43d 152
3ca7dae4 153static const struct regset alphanbsd_aout_gregset =
3beabdb2
MK
154{
155 NULL,
156 alphanbsd_aout_supply_gregset
157};
158
159/* Return the appropriate register set for the core section identified
160 by SECT_NAME and SECT_SIZE. */
161
b0ca8573 162const struct regset *
3beabdb2
MK
163alphanbsd_regset_from_core_section (struct gdbarch *gdbarch,
164 const char *sect_name, size_t sect_size)
165{
166 if (strcmp (sect_name, ".reg") == 0 && sect_size >= ALPHANBSD_SIZEOF_GREGS)
b0ca8573
MK
167 {
168 if (sect_size >= ALPHANBSD_SIZEOF_GREGS + ALPHANBSD_SIZEOF_FPREGS)
169 return &alphanbsd_aout_gregset;
170 else
171 return &alphanbsd_gregset;
172 }
3beabdb2
MK
173
174 if (strcmp (sect_name, ".reg2") == 0 && sect_size >= ALPHANBSD_SIZEOF_FPREGS)
175 return &alphanbsd_fpregset;
176
177 return NULL;
178}
3beabdb2
MK
179\f
180
181/* Signal trampolines. */
182
da8ca43d
JT
183/* Under NetBSD/alpha, signal handler invocations can be identified by the
184 designated code sequence that is used to return from a signal handler.
185 In particular, the return address of a signal handler points to the
186 following code sequence:
187
188 ldq a0, 0(sp)
189 lda sp, 16(sp)
190 lda v0, 295(zero) # __sigreturn14
191 call_pal callsys
192
193 Each instruction has a unique encoding, so we simply attempt to match
194 the instruction the PC is pointing to with any of the above instructions.
195 If there is a hit, we know the offset to the start of the designated
196 sequence and can then check whether we really are executing in the
197 signal trampoline. If not, -1 is returned, otherwise the offset from the
198 start of the return sequence is returned. */
948f8e3d 199static const gdb_byte sigtramp_retcode[] =
da8ca43d 200{
cfef91e4
JT
201 0x00, 0x00, 0x1e, 0xa6, /* ldq a0, 0(sp) */
202 0x10, 0x00, 0xde, 0x23, /* lda sp, 16(sp) */
203 0x27, 0x01, 0x1f, 0x20, /* lda v0, 295(zero) */
204 0x83, 0x00, 0x00, 0x00, /* call_pal callsys */
da8ca43d 205};
cfef91e4
JT
206#define RETCODE_NWORDS 4
207#define RETCODE_SIZE (RETCODE_NWORDS * 4)
da8ca43d 208
b0ca8573 209static LONGEST
e17a4113 210alphanbsd_sigtramp_offset (struct gdbarch *gdbarch, CORE_ADDR pc)
da8ca43d 211{
948f8e3d 212 gdb_byte ret[RETCODE_SIZE], w[4];
da8ca43d
JT
213 LONGEST off;
214 int i;
215
948f8e3d 216 if (target_read_memory (pc, w, 4) != 0)
da8ca43d
JT
217 return -1;
218
219 for (i = 0; i < RETCODE_NWORDS; i++)
220 {
cfef91e4 221 if (memcmp (w, sigtramp_retcode + (i * 4), 4) == 0)
da8ca43d
JT
222 break;
223 }
224 if (i == RETCODE_NWORDS)
225 return (-1);
226
227 off = i * 4;
228 pc -= off;
229
948f8e3d 230 if (target_read_memory (pc, ret, sizeof (ret)) != 0)
da8ca43d
JT
231 return -1;
232
cfef91e4 233 if (memcmp (ret, sigtramp_retcode, RETCODE_SIZE) == 0)
da8ca43d
JT
234 return off;
235
236 return -1;
237}
238
6c72f9f9 239static int
e17a4113 240alphanbsd_pc_in_sigtramp (struct gdbarch *gdbarch,
2c02bd72 241 CORE_ADDR pc, const char *func_name)
6c72f9f9 242{
3d9b49b0 243 return (nbsd_pc_in_sigtramp (pc, func_name)
e17a4113 244 || alphanbsd_sigtramp_offset (gdbarch, pc) >= 0);
6c72f9f9
JT
245}
246
2ca8ae21
JT
247static CORE_ADDR
248alphanbsd_sigcontext_addr (struct frame_info *frame)
249{
250 /* FIXME: This is not correct for all versions of NetBSD/alpha.
251 We will probably need to disassemble the trampoline to figure
252 out which trampoline frame type we have. */
94afd7a6
UW
253 if (!get_next_frame (frame))
254 return 0;
255 return get_frame_base (get_next_frame (frame));
2ca8ae21 256}
b0ca8573 257\f
2ca8ae21 258
da8ca43d
JT
259static void
260alphanbsd_init_abi (struct gdbarch_info info,
261 struct gdbarch *gdbarch)
262{
263 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
264
baa490c4
RH
265 /* Hook into the DWARF CFI frame unwinder. */
266 alpha_dwarf2_init_abi (info, gdbarch);
267
268 /* Hook into the MDEBUG frame unwinder. */
269 alpha_mdebug_init_abi (info, gdbarch);
270
da8ca43d
JT
271 /* NetBSD/alpha does not provide single step support via ptrace(2); we
272 must use software single-stepping. */
273 set_gdbarch_software_single_step (gdbarch, alpha_software_single_step);
274
789f3b5f
MK
275 /* NetBSD/alpha has SVR4-style shared libraries. */
276 set_solib_svr4_fetch_link_map_offsets
277 (gdbarch, svr4_lp64_fetch_link_map_offsets);
da8ca43d
JT
278
279 tdep->dynamic_sigtramp_offset = alphanbsd_sigtramp_offset;
f2524b93 280 tdep->pc_in_sigtramp = alphanbsd_pc_in_sigtramp;
2ca8ae21 281 tdep->sigcontext_addr = alphanbsd_sigcontext_addr;
accc6d1f
JT
282
283 tdep->jb_pc = 2;
284 tdep->jb_elt_size = 8;
3beabdb2
MK
285
286 set_gdbarch_regset_from_core_section
287 (gdbarch, alphanbsd_regset_from_core_section);
288}
3beabdb2
MK
289\f
290
291static enum gdb_osabi
292alphanbsd_core_osabi_sniffer (bfd *abfd)
293{
294 if (strcmp (bfd_get_target (abfd), "netbsd-core") == 0)
b0ca8573 295 return GDB_OSABI_NETBSD_ELF;
3beabdb2
MK
296
297 return GDB_OSABI_UNKNOWN;
298}
299\f
300
301/* Provide a prototype to silence -Wmissing-prototypes. */
302void _initialize_alphanbsd_tdep (void);
da8ca43d
JT
303
304void
305_initialize_alphanbsd_tdep (void)
306{
3beabdb2
MK
307 /* BFD doesn't set a flavour for NetBSD style a.out core files. */
308 gdbarch_register_osabi_sniffer (bfd_arch_alpha, bfd_target_unknown_flavour,
309 alphanbsd_core_osabi_sniffer);
310
05816f70 311 gdbarch_register_osabi (bfd_arch_alpha, 0, GDB_OSABI_NETBSD_ELF,
70f80edf 312 alphanbsd_init_abi);
da8ca43d 313}
This page took 0.704349 seconds and 4 git commands to generate.