correctly regenerate configure
[deliverable/binutils-gdb.git] / gdb / alphanbsd-tdep.c
CommitLineData
789f3b5f
MK
1/* Target-dependent code for NetBSD/alpha.
2
9b254dd1
DJ
3 Copyright (C) 2002, 2003, 2004, 2006, 2007, 2008
4 Free Software Foundation, Inc.
2031c21a 5
da8ca43d
JT
6 Contributed by Wasabi Systems, Inc.
7
8 This file is part of GDB.
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
a9762ec7 12 the Free Software Foundation; either version 3 of the License, or
da8ca43d
JT
13 (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
a9762ec7 21 along with this program. If not, see <http://www.gnu.org/licenses/>. */
da8ca43d
JT
22
23#include "defs.h"
2ca8ae21 24#include "frame.h"
3beabdb2
MK
25#include "gdbcore.h"
26#include "osabi.h"
8513dd2d 27#include "regcache.h"
3beabdb2 28#include "regset.h"
da8ca43d 29#include "value.h"
da8ca43d 30
3beabdb2 31#include "gdb_assert.h"
cca0d3b0 32#include "gdb_string.h"
9964235a 33
da8ca43d 34#include "alpha-tdep.h"
8513dd2d 35#include "alphabsd-tdep.h"
ea5bc2a6 36#include "nbsd-tdep.h"
527ca6bb 37#include "solib-svr4.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. */
cfef91e4 202static const unsigned char 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
da8ca43d
JT
213alphanbsd_sigtramp_offset (CORE_ADDR pc)
214{
cfef91e4 215 unsigned char ret[RETCODE_SIZE], w[4];
da8ca43d
JT
216 LONGEST off;
217 int i;
218
8defab1a 219 if (target_read_memory (pc, (char *) 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
8defab1a 233 if (target_read_memory (pc, (char *) 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
JT
242static int
243alphanbsd_pc_in_sigtramp (CORE_ADDR pc, char *func_name)
244{
3d9b49b0
JT
245 return (nbsd_pc_in_sigtramp (pc, func_name)
246 || alphanbsd_sigtramp_offset (pc) >= 0);
6c72f9f9
JT
247}
248
2ca8ae21
JT
249static CORE_ADDR
250alphanbsd_sigcontext_addr (struct frame_info *frame)
251{
252 /* FIXME: This is not correct for all versions of NetBSD/alpha.
253 We will probably need to disassemble the trampoline to figure
254 out which trampoline frame type we have. */
f534e522 255 return get_frame_base (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.361226 seconds and 4 git commands to generate.