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