GDB (xrefs)
/tmp/gdb-7.10/gdb/alphanbsd-tdep.c
Go to the documentation of this file.
1 /* Target-dependent code for NetBSD/alpha.
2 
3  Copyright (C) 2002-2015 Free Software Foundation, Inc.
4 
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
11  the Free Software Foundation; either version 3 of the License, or
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
20  along with this program. If not, see <http://www.gnu.org/licenses/>. */
21 
22 #include "defs.h"
23 #include "frame.h"
24 #include "gdbcore.h"
25 #include "osabi.h"
26 #include "regcache.h"
27 #include "regset.h"
28 #include "value.h"
29 
30 #include "alpha-tdep.h"
31 #include "alphabsd-tdep.h"
32 #include "nbsd-tdep.h"
33 #include "solib-svr4.h"
34 #include "target.h"
35 
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 
51 static void
53  struct regcache *regcache,
54  int regnum, const void *fpregs, size_t len)
55 {
56  const gdb_byte *regs = fpregs;
57  int i;
58 
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. */
74 
75 static void
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  /* Table to map a GDB register number to a trapframe register index. */
84  static const int regmap[] =
85  {
86  0, 1, 2, 3,
87  4, 5, 6, 7,
88  8, 9, 10, 11,
89  12, 13, 14, 15,
90  30, 31, 32, 16,
91  17, 18, 19, 20,
92  21, 22, 23, 24,
93  25, 29, 26
94  };
95 
97 
98  for (i = 0; i < ARRAY_SIZE(regmap); i++)
99  {
100  if (regnum == i || regnum == -1)
101  regcache_raw_supply (regcache, i, regs + regmap[i] * 8);
102  }
103 
104  if (regnum == ALPHA_PC_REGNUM || regnum == -1)
105  regcache_raw_supply (regcache, ALPHA_PC_REGNUM, regs + 31 * 8);
106 
108  {
109  regs += ALPHANBSD_SIZEOF_GREGS;
110  len -= ALPHANBSD_SIZEOF_GREGS;
111  alphanbsd_supply_fpregset (regset, regcache, regnum, regs, len);
112  }
113 }
114 
115 /* Supply register REGNUM from the buffer specified by GREGS and LEN
116  in the general-purpose register set REGSET to register cache
117  REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */
118 
119 static void
121  struct regcache *regcache,
122  int regnum, const void *gregs, size_t len)
123 {
124  const gdb_byte *regs = gregs;
125  int i;
126 
128  {
129  alphanbsd_aout_supply_gregset (regset, regcache, regnum, gregs, len);
130  return;
131  }
132 
133  for (i = 0; i < ALPHA_ZERO_REGNUM; i++)
134  {
135  if (regnum == i || regnum == -1)
136  regcache_raw_supply (regcache, i, regs + i * 8);
137  }
138 
139  if (regnum == ALPHA_PC_REGNUM || regnum == -1)
140  regcache_raw_supply (regcache, ALPHA_PC_REGNUM, regs + 31 * 8);
141 }
142 
143 /* NetBSD/alpha register sets. */
144 
145 static const struct regset alphanbsd_gregset =
146 {
147  NULL,
149  NULL,
151 };
152 
153 static const struct regset alphanbsd_fpregset =
154 {
155  NULL,
157 };
158 
159 /* Iterate over supported core file register note sections. */
160 
161 void
164  void *cb_data,
165  const struct regcache *regcache)
166 {
167  cb (".reg", ALPHANBSD_SIZEOF_GREGS, &alphanbsd_gregset, NULL, cb_data);
168  cb (".reg2", ALPHANBSD_SIZEOF_FPREGS, &alphanbsd_fpregset, NULL, cb_data);
169 }
170 
171 
172 /* Signal trampolines. */
173 
174 /* Under NetBSD/alpha, signal handler invocations can be identified by the
175  designated code sequence that is used to return from a signal handler.
176  In particular, the return address of a signal handler points to the
177  following code sequence:
178 
179  ldq a0, 0(sp)
180  lda sp, 16(sp)
181  lda v0, 295(zero) # __sigreturn14
182  call_pal callsys
183 
184  Each instruction has a unique encoding, so we simply attempt to match
185  the instruction the PC is pointing to with any of the above instructions.
186  If there is a hit, we know the offset to the start of the designated
187  sequence and can then check whether we really are executing in the
188  signal trampoline. If not, -1 is returned, otherwise the offset from the
189  start of the return sequence is returned. */
190 static const gdb_byte sigtramp_retcode[] =
191 {
192  0x00, 0x00, 0x1e, 0xa6, /* ldq a0, 0(sp) */
193  0x10, 0x00, 0xde, 0x23, /* lda sp, 16(sp) */
194  0x27, 0x01, 0x1f, 0x20, /* lda v0, 295(zero) */
195  0x83, 0x00, 0x00, 0x00, /* call_pal callsys */
196 };
197 #define RETCODE_NWORDS 4
198 #define RETCODE_SIZE (RETCODE_NWORDS * 4)
199 
200 static LONGEST
202 {
203  gdb_byte ret[RETCODE_SIZE], w[4];
204  LONGEST off;
205  int i;
206 
207  if (target_read_memory (pc, w, 4) != 0)
208  return -1;
209 
210  for (i = 0; i < RETCODE_NWORDS; i++)
211  {
212  if (memcmp (w, sigtramp_retcode + (i * 4), 4) == 0)
213  break;
214  }
215  if (i == RETCODE_NWORDS)
216  return (-1);
217 
218  off = i * 4;
219  pc -= off;
220 
221  if (target_read_memory (pc, ret, sizeof (ret)) != 0)
222  return -1;
223 
224  if (memcmp (ret, sigtramp_retcode, RETCODE_SIZE) == 0)
225  return off;
226 
227  return -1;
228 }
229 
230 static int
232  CORE_ADDR pc, const char *func_name)
233 {
234  return (nbsd_pc_in_sigtramp (pc, func_name)
235  || alphanbsd_sigtramp_offset (gdbarch, pc) >= 0);
236 }
237 
238 static CORE_ADDR
240 {
241  /* FIXME: This is not correct for all versions of NetBSD/alpha.
242  We will probably need to disassemble the trampoline to figure
243  out which trampoline frame type we have. */
244  if (!get_next_frame (frame))
245  return 0;
246  return get_frame_base (get_next_frame (frame));
247 }
248 
249 
250 static void
252  struct gdbarch *gdbarch)
253 {
254  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
255 
256  /* Hook into the DWARF CFI frame unwinder. */
257  alpha_dwarf2_init_abi (info, gdbarch);
258 
259  /* Hook into the MDEBUG frame unwinder. */
260  alpha_mdebug_init_abi (info, gdbarch);
261 
262  /* NetBSD/alpha does not provide single step support via ptrace(2); we
263  must use software single-stepping. */
265 
266  /* NetBSD/alpha has SVR4-style shared libraries. */
269 
273 
274  tdep->jb_pc = 2;
275  tdep->jb_elt_size = 8;
276 
279 }
280 
281 
282 static enum gdb_osabi
284 {
285  if (strcmp (bfd_get_target (abfd), "netbsd-core") == 0)
286  return GDB_OSABI_NETBSD_ELF;
287 
288  return GDB_OSABI_UNKNOWN;
289 }
290 
291 
292 /* Provide a prototype to silence -Wmissing-prototypes. */
293 void _initialize_alphanbsd_tdep (void);
294 
295 void
297 {
298  /* BFD doesn't set a flavour for NetBSD style a.out core files. */
299  gdbarch_register_osabi_sniffer (bfd_arch_alpha, bfd_target_unknown_flavour,
301 
302  gdbarch_register_osabi (bfd_arch_alpha, 0, GDB_OSABI_NETBSD_ELF,
304 }
static enum gdb_osabi alphanbsd_core_osabi_sniffer(bfd *abfd)
void alpha_mdebug_init_abi(struct gdbarch_info info, struct gdbarch *gdbarch)
bfd_vma CORE_ADDR
Definition: common-types.h:41
struct link_map_offsets * svr4_lp64_fetch_link_map_offsets(void)
Definition: solib-svr4.c:3180
#define ALPHANBSD_SIZEOF_FPREGS
#define ALPHA_FP0_REGNUM
Definition: alpha-tdep.h:47
LONGEST(* dynamic_sigtramp_offset)(struct gdbarch *, CORE_ADDR)
Definition: alpha-tdep.h:78
int nbsd_pc_in_sigtramp(CORE_ADDR pc, const char *func_name)
Definition: nbsd-tdep.c:42
void alpha_dwarf2_init_abi(struct gdbarch_info info, struct gdbarch *gdbarch)
Definition: alpha-tdep.c:1849
void gdbarch_register_osabi_sniffer(enum bfd_architecture arch, enum bfd_flavour flavour, enum gdb_osabi(*sniffer_fn)(bfd *))
Definition: osabi.c:225
CORE_ADDR(* sigcontext_addr)(struct frame_info *)
Definition: alpha-tdep.h:82
static LONGEST alphanbsd_sigtramp_offset(struct gdbarch *gdbarch, CORE_ADDR pc)
static int regmap[]
struct gdbarch_tdep * gdbarch_tdep(struct gdbarch *gdbarch)
Definition: gdbarch.c:1402
static CORE_ADDR alphanbsd_sigcontext_addr(struct frame_info *frame)
#define ALPHANBSD_SIZEOF_GREGS
Definition: regset.h:34
static void alphanbsd_supply_fpregset(const struct regset *regset, struct regcache *regcache, int regnum, const void *fpregs, size_t len)
#define ALPHA_PC_REGNUM
Definition: alpha-tdep.h:50
static void alphanbsd_init_abi(struct gdbarch_info info, struct gdbarch *gdbarch)
void set_solib_svr4_fetch_link_map_offsets(struct gdbarch *gdbarch, struct link_map_offsets *(*flmo)(void))
Definition: solib-svr4.c:3108
#define REGSET_VARIABLE_SIZE
Definition: regset.h:52
#define gdb_assert(expr)
Definition: gdb_assert.h:33
#define ALPHA_FPCR_REGNUM
Definition: alpha-tdep.h:49
void _initialize_alphanbsd_tdep(void)
int regnum
Definition: aarch64-tdep.c:69
void( iterate_over_regset_sections_cb)(const char *sect_name, int size, const struct regset *regset, const char *human_name, void *cb_data)
Definition: gdbarch.h:98
size_t jb_elt_size
Definition: aarch64-tdep.h:83
#define ALPHA_ZERO_REGNUM
Definition: alpha-tdep.h:46
void set_gdbarch_software_single_step(struct gdbarch *gdbarch, gdbarch_software_single_step_ftype software_single_step)
Definition: gdbarch.c:3026
int alpha_software_single_step(struct frame_info *frame)
Definition: alpha-tdep.c:1725
bfd_byte gdb_byte
Definition: common-types.h:38
struct frame_info * get_next_frame(struct frame_info *this_frame)
Definition: frame.c:1668
#define RETCODE_SIZE
int(* pc_in_sigtramp)(struct gdbarch *gdbarch, CORE_ADDR pc, const char *name)
Definition: alpha-tdep.h:88
#define RETCODE_NWORDS
CORE_ADDR get_frame_base(struct frame_info *fi)
Definition: frame.c:2388
int target_read_memory(CORE_ADDR memaddr, gdb_byte *myaddr, ssize_t len)
Definition: target.c:1393
static void alphanbsd_aout_supply_gregset(const struct regset *regset, struct regcache *regcache, int regnum, const void *gregs, size_t len)
struct m32c_reg regs[M32C_MAX_NUM_REGS]
Definition: m32c-tdep.c:105
void regcache_raw_supply(struct regcache *regcache, int regnum, const void *buf)
Definition: regcache.c:1041
static void alphanbsd_supply_gregset(const struct regset *regset, struct regcache *regcache, int regnum, const void *gregs, size_t len)
void alphanbsd_iterate_over_regset_sections(struct gdbarch *gdbarch, iterate_over_regset_sections_cb *cb, void *cb_data, const struct regcache *regcache)
void set_gdbarch_iterate_over_regset_sections(struct gdbarch *gdbarch, gdbarch_iterate_over_regset_sections_ftype iterate_over_regset_sections)
Definition: gdbarch.c:3398
static const gdb_byte sigtramp_retcode[]
void gdbarch_register_osabi(enum bfd_architecture arch, unsigned long machine, enum gdb_osabi osabi, void(*init_osabi)(struct gdbarch_info, struct gdbarch *))
Definition: osabi.c:148
static int alphanbsd_pc_in_sigtramp(struct gdbarch *gdbarch, CORE_ADDR pc, const char *func_name)
long long LONGEST
Definition: common-types.h:52
gdb_osabi
Definition: defs.h:540
const ULONGEST const LONGEST len
Definition: target.h:309