GDB (xrefs)
/tmp/gdb-7.10/gdb/sparc64obsd-tdep.c
Go to the documentation of this file.
1 /* Target-dependent code for OpenBSD/sparc64.
2 
3  Copyright (C) 2004-2015 Free Software Foundation, Inc.
4 
5  This file is part of GDB.
6 
7  This program is free software; you can redistribute it and/or modify
8  it under the terms of the GNU General Public License as published by
9  the Free Software Foundation; either version 3 of the License, or
10  (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program. If not, see <http://www.gnu.org/licenses/>. */
19 
20 #include "defs.h"
21 #include "frame.h"
22 #include "frame-unwind.h"
23 #include "gdbcore.h"
24 #include "osabi.h"
25 #include "regcache.h"
26 #include "regset.h"
27 #include "symtab.h"
28 #include "objfiles.h"
29 #include "trad-frame.h"
30 
31 #include "obsd-tdep.h"
32 #include "sparc64-tdep.h"
33 #include "solib-svr4.h"
34 #include "bsd-uthread.h"
35 
36 /* Older OpenBSD versions used the traditional NetBSD core file
37  format, even for ports that use ELF. These core files don't use
38  multiple register sets. Instead, the general-purpose and
39  floating-point registers are lumped together in a single section.
40  Unlike on NetBSD, OpenBSD uses a different layout for its
41  general-purpose registers than the layout used for ptrace(2).
42 
43  Newer OpenBSD versions use ELF core files. Here the register sets
44  match the ptrace(2) layout. */
45 
46 /* From <machine/reg.h>. */
47 const struct sparc_gregmap sparc64obsd_gregmap =
48 {
49  0 * 8, /* "tstate" */
50  1 * 8, /* %pc */
51  2 * 8, /* %npc */
52  3 * 8, /* %y */
53  -1, /* %fprs */
54  -1,
55  5 * 8, /* %g1 */
56  20 * 8, /* %l0 */
57  4 /* sizeof (%y) */
58 };
59 
60 const struct sparc_gregmap sparc64obsd_core_gregmap =
61 {
62  0 * 8, /* "tstate" */
63  1 * 8, /* %pc */
64  2 * 8, /* %npc */
65  3 * 8, /* %y */
66  -1, /* %fprs */
67  -1,
68  7 * 8, /* %g1 */
69  22 * 8, /* %l0 */
70  4 /* sizeof (%y) */
71 };
72 
73 static void
75  struct regcache *regcache,
76  int regnum, const void *gregs, size_t len)
77 {
78  const void *fpregs = (char *)gregs + 288;
79 
80  if (len < 832)
81  {
82  sparc64_supply_gregset (&sparc64obsd_gregmap, regcache, regnum, gregs);
83  return;
84  }
85 
86  sparc64_supply_gregset (&sparc64obsd_core_gregmap, regcache, regnum, gregs);
87  sparc64_supply_fpregset (&sparc64_bsd_fpregmap, regcache, regnum, fpregs);
88 }
89 
90 static void
92  struct regcache *regcache,
93  int regnum, const void *fpregs, size_t len)
94 {
95  sparc64_supply_fpregset (&sparc64_bsd_fpregmap, regcache, regnum, fpregs);
96 }
97 
98 
99 /* Signal trampolines. */
100 
101 /* Since OpenBSD 3.2, the sigtramp routine is mapped at a random page
102  in virtual memory. The randomness makes it somewhat tricky to
103  detect it, but fortunately we can rely on the fact that the start
104  of the sigtramp routine is page-aligned. We recognize the
105  trampoline by looking for the code that invokes the sigreturn
106  system call. The offset where we can find that code varies from
107  release to release.
108 
109  By the way, the mapping mentioned above is read-only, so you cannot
110  place a breakpoint in the signal trampoline. */
111 
112 /* Default page size. */
113 static const int sparc64obsd_page_size = 8192;
114 
115 /* Offset for sigreturn(2). */
116 static const int sparc64obsd_sigreturn_offset[] = {
117  0xf0, /* OpenBSD 3.8 */
118  0xec, /* OpenBSD 3.6 */
119  0xe8, /* OpenBSD 3.2 */
120  -1
121 };
122 
123 static int
125 {
126  CORE_ADDR start_pc = (pc & ~(sparc64obsd_page_size - 1));
127  unsigned long insn;
128  const int *offset;
129 
130  if (name)
131  return 0;
132 
133  for (offset = sparc64obsd_sigreturn_offset; *offset != -1; offset++)
134  {
135  /* Check for "restore %g0, SYS_sigreturn, %g1". */
136  insn = sparc_fetch_instruction (start_pc + *offset);
137  if (insn != 0x83e82067)
138  continue;
139 
140  /* Check for "t ST_SYSCALL". */
141  insn = sparc_fetch_instruction (start_pc + *offset + 8);
142  if (insn != 0x91d02000)
143  continue;
144 
145  return 1;
146  }
147 
148  return 0;
149 }
150 
151 static struct sparc_frame_cache *
152 sparc64obsd_frame_cache (struct frame_info *this_frame, void **this_cache)
153 {
154  struct sparc_frame_cache *cache;
155  CORE_ADDR addr;
156 
157  if (*this_cache)
158  return *this_cache;
159 
160  cache = sparc_frame_cache (this_frame, this_cache);
161  gdb_assert (cache == *this_cache);
162 
163  /* If we couldn't find the frame's function, we're probably dealing
164  with an on-stack signal trampoline. */
165  if (cache->pc == 0)
166  {
167  cache->pc = get_frame_pc (this_frame);
168  cache->pc &= ~(sparc64obsd_page_size - 1);
169 
170  /* Since we couldn't find the frame's function, the cache was
171  initialized under the assumption that we're frameless. */
172  sparc_record_save_insn (cache);
173  addr = get_frame_register_unsigned (this_frame, SPARC_FP_REGNUM);
174  if (addr & 1)
175  addr += BIAS;
176  cache->base = addr;
177  }
178 
179  /* We find the appropriate instance of `struct sigcontext' at a
180  fixed offset in the signal frame. */
181  addr = cache->base + 128 + 16;
182  cache->saved_regs = sparc64nbsd_sigcontext_saved_regs (addr, this_frame);
183 
184  return cache;
185 }
186 
187 static void
188 sparc64obsd_frame_this_id (struct frame_info *this_frame, void **this_cache,
189  struct frame_id *this_id)
190 {
191  struct sparc_frame_cache *cache =
192  sparc64obsd_frame_cache (this_frame, this_cache);
193 
194  (*this_id) = frame_id_build (cache->base, cache->pc);
195 }
196 
197 static struct value *
199  void **this_cache, int regnum)
200 {
201  struct sparc_frame_cache *cache =
202  sparc64obsd_frame_cache (this_frame, this_cache);
203 
204  return trad_frame_get_prev_register (this_frame, cache->saved_regs, regnum);
205 }
206 
207 static int
209  struct frame_info *this_frame,
210  void **this_cache)
211 {
212  CORE_ADDR pc = get_frame_pc (this_frame);
213  const char *name;
214 
215  find_pc_partial_function (pc, &name, NULL, NULL);
216  if (sparc64obsd_pc_in_sigtramp (pc, name))
217  return 1;
218 
219  return 0;
220 }
221 
222 static const struct frame_unwind sparc64obsd_frame_unwind =
223 {
228  NULL,
230 };
231 
232 /* Kernel debugging support. */
233 
234 static struct sparc_frame_cache *
235 sparc64obsd_trapframe_cache (struct frame_info *this_frame, void **this_cache)
236 {
237  struct sparc_frame_cache *cache;
238  CORE_ADDR sp, trapframe_addr;
239  int regnum;
240 
241  if (*this_cache)
242  return *this_cache;
243 
244  cache = sparc_frame_cache (this_frame, this_cache);
245  gdb_assert (cache == *this_cache);
246 
247  sp = get_frame_register_unsigned (this_frame, SPARC_SP_REGNUM);
248  trapframe_addr = sp + BIAS + 176;
249 
250  cache->saved_regs = trad_frame_alloc_saved_regs (this_frame);
251 
252  cache->saved_regs[SPARC64_STATE_REGNUM].addr = trapframe_addr;
253  cache->saved_regs[SPARC64_PC_REGNUM].addr = trapframe_addr + 8;
254  cache->saved_regs[SPARC64_NPC_REGNUM].addr = trapframe_addr + 16;
255 
256  for (regnum = SPARC_G0_REGNUM; regnum <= SPARC_I7_REGNUM; regnum++)
257  cache->saved_regs[regnum].addr =
258  trapframe_addr + 48 + (regnum - SPARC_G0_REGNUM) * 8;
259 
260  return cache;
261 }
262 
263 static void
265  void **this_cache, struct frame_id *this_id)
266 {
267  struct sparc_frame_cache *cache =
268  sparc64obsd_trapframe_cache (this_frame, this_cache);
269 
270  (*this_id) = frame_id_build (cache->base, cache->pc);
271 }
272 
273 static struct value *
275  void **this_cache, int regnum)
276 {
277  struct sparc_frame_cache *cache =
278  sparc64obsd_trapframe_cache (this_frame, this_cache);
279 
280  return trad_frame_get_prev_register (this_frame, cache->saved_regs, regnum);
281 }
282 
283 static int
285  struct frame_info *this_frame,
286  void **this_cache)
287 {
288  CORE_ADDR pc;
290  const char *name;
291 
292  /* Check whether we are in privileged mode, and bail out if we're not. */
293  pstate = get_frame_register_unsigned (this_frame, SPARC64_PSTATE_REGNUM);
294  if ((pstate & SPARC64_PSTATE_PRIV) == 0)
295  return 0;
296 
297  pc = get_frame_address_in_block (this_frame);
298  find_pc_partial_function (pc, &name, NULL, NULL);
299  if (name && strcmp (name, "Lslowtrap_reenter") == 0)
300  return 1;
301 
302  return 0;
303 }
304 
305 static const struct frame_unwind sparc64obsd_trapframe_unwind =
306 {
307  NORMAL_FRAME,
311  NULL,
313 };
314 
315 
316 /* Threads support. */
317 
318 /* Offset wthin the thread structure where we can find %fp and %i7. */
319 #define SPARC64OBSD_UTHREAD_FP_OFFSET 232
320 #define SPARC64OBSD_UTHREAD_PC_OFFSET 240
321 
322 static void
324  int regnum, CORE_ADDR addr)
325 {
326  struct gdbarch *gdbarch = get_regcache_arch (regcache);
327  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
328  CORE_ADDR fp, fp_addr = addr + SPARC64OBSD_UTHREAD_FP_OFFSET;
329  gdb_byte buf[8];
330 
331  gdb_assert (regnum >= -1);
332 
333  fp = read_memory_unsigned_integer (fp_addr, 8, byte_order);
334  if (regnum == SPARC_SP_REGNUM || regnum == -1)
335  {
336  store_unsigned_integer (buf, 8, byte_order, fp);
337  regcache_raw_supply (regcache, SPARC_SP_REGNUM, buf);
338 
339  if (regnum == SPARC_SP_REGNUM)
340  return;
341  }
342 
343  if (regnum == SPARC64_PC_REGNUM || regnum == SPARC64_NPC_REGNUM
344  || regnum == -1)
345  {
346  CORE_ADDR i7, i7_addr = addr + SPARC64OBSD_UTHREAD_PC_OFFSET;
347 
348  i7 = read_memory_unsigned_integer (i7_addr, 8, byte_order);
349  if (regnum == SPARC64_PC_REGNUM || regnum == -1)
350  {
351  store_unsigned_integer (buf, 8, byte_order, i7 + 8);
352  regcache_raw_supply (regcache, SPARC64_PC_REGNUM, buf);
353  }
354  if (regnum == SPARC64_NPC_REGNUM || regnum == -1)
355  {
356  store_unsigned_integer (buf, 8, byte_order, i7 + 12);
357  regcache_raw_supply (regcache, SPARC64_NPC_REGNUM, buf);
358  }
359 
360  if (regnum == SPARC64_PC_REGNUM || regnum == SPARC64_NPC_REGNUM)
361  return;
362  }
363 
364  sparc_supply_rwindow (regcache, fp, regnum);
365 }
366 
367 static void
369  int regnum, CORE_ADDR addr)
370 {
371  struct gdbarch *gdbarch = get_regcache_arch (regcache);
372  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
373  CORE_ADDR sp;
374  gdb_byte buf[8];
375 
376  gdb_assert (regnum >= -1);
377 
378  if (regnum == SPARC_SP_REGNUM || regnum == -1)
379  {
380  CORE_ADDR fp_addr = addr + SPARC64OBSD_UTHREAD_FP_OFFSET;
381 
382  regcache_raw_collect (regcache, SPARC_SP_REGNUM, buf);
383  write_memory (fp_addr,buf, 8);
384  }
385 
386  if (regnum == SPARC64_PC_REGNUM || regnum == -1)
387  {
388  CORE_ADDR i7, i7_addr = addr + SPARC64OBSD_UTHREAD_PC_OFFSET;
389 
390  regcache_raw_collect (regcache, SPARC64_PC_REGNUM, buf);
391  i7 = extract_unsigned_integer (buf, 8, byte_order) - 8;
392  write_memory_unsigned_integer (i7_addr, 8, byte_order, i7);
393 
394  if (regnum == SPARC64_PC_REGNUM)
395  return;
396  }
397 
398  regcache_raw_collect (regcache, SPARC_SP_REGNUM, buf);
399  sp = extract_unsigned_integer (buf, 8, byte_order);
400  sparc_collect_rwindow (regcache, sp, regnum);
401 }
402 
403 
404 static const struct regset sparc64obsd_gregset =
405  {
406  NULL, sparc64obsd_supply_gregset, NULL
407  };
408 
409 static const struct regset sparc64obsd_fpregset =
410  {
411  NULL, sparc64obsd_supply_fpregset, NULL
412  };
413 
414 static void
416 {
417  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
418 
419  tdep->gregset = &sparc64obsd_gregset;
420  tdep->sizeof_gregset = 288;
422  tdep->sizeof_fpregset = 272;
423 
424  /* Make sure we can single-step "new" syscalls. */
426 
427  frame_unwind_append_unwinder (gdbarch, &sparc64obsd_frame_unwind);
428  frame_unwind_append_unwinder (gdbarch, &sparc64obsd_trapframe_unwind);
429 
430  sparc64_init_abi (info, gdbarch);
431  obsd_init_abi (info, gdbarch);
432 
433  /* OpenBSD/sparc64 has SVR4-style shared libraries. */
437 
438  /* OpenBSD provides a user-level threads implementation. */
441 }
442 
443 
444 /* Provide a prototype to silence -Wmissing-prototypes. */
445 void _initialize_sparc64obsd_tdep (void);
446 
447 void
449 {
450  gdbarch_register_osabi (bfd_arch_sparc, bfd_mach_sparc_v9,
452 }
static void sparc64obsd_collect_uthread(const struct regcache *regcache, int regnum, CORE_ADDR addr)
void sparc64_init_abi(struct gdbarch_info info, struct gdbarch *gdbarch)
ULONGEST extract_unsigned_integer(const gdb_byte *, int, enum bfd_endian)
Definition: findvar.c:84
struct frame_id frame_id_build(CORE_ADDR stack_addr, CORE_ADDR code_addr)
Definition: frame.c:554
static const int sparc64obsd_sigreturn_offset[]
CORE_ADDR get_frame_address_in_block(struct frame_info *this_frame)
Definition: frame.c:2248
CORE_ADDR get_frame_pc(struct frame_info *frame)
Definition: frame.c:2217
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
struct value * trad_frame_get_prev_register(struct frame_info *this_frame, struct trad_frame_saved_reg this_saved_regs[], int regnum)
Definition: trad-frame.c:135
struct gdbarch * get_regcache_arch(const struct regcache *regcache)
Definition: regcache.c:297
void sparc_record_save_insn(struct sparc_frame_cache *cache)
Definition: sparc-tdep.c:866
void write_memory_unsigned_integer(CORE_ADDR addr, int len, enum bfd_endian byte_order, ULONGEST value)
Definition: corefile.c:412
const struct regset * gregset
Definition: sparc-tdep.h:61
struct sparc_frame_cache * sparc_frame_cache(struct frame_info *this_frame, void **this_cache)
Definition: sparc-tdep.c:1098
#define BIAS
Definition: sparc-tdep.c:70
static struct value * sparc64obsd_frame_prev_register(struct frame_info *this_frame, void **this_cache, int regnum)
CORE_ADDR(* step_trap)(struct frame_info *frame, unsigned long insn)
Definition: sparc-tdep.h:74
static void sparc64obsd_init_abi(struct gdbarch_info info, struct gdbarch *gdbarch)
void bsd_uthread_set_collect_uthread(struct gdbarch *gdbarch, void(*collect_uthread)(const struct regcache *, int, CORE_ADDR))
Definition: bsd-uthread.c:79
size_t sizeof_fpregset
Definition: i386-tdep.h:64
void sparc64_supply_gregset(const struct sparc_gregmap *gregmap, struct regcache *regcache, int regnum, const void *gregs)
struct gdbarch_tdep * gdbarch_tdep(struct gdbarch *gdbarch)
Definition: gdbarch.c:1402
void sparc_supply_rwindow(struct regcache *regcache, CORE_ADDR sp, int regnum)
Definition: sparc-tdep.c:1750
void obsd_init_abi(struct gdbarch_info info, struct gdbarch *gdbarch)
Definition: obsd-tdep.c:319
void frame_unwind_append_unwinder(struct gdbarch *gdbarch, const struct frame_unwind *unwinder)
Definition: frame-unwind.c:78
#define SPARC64_PSTATE_PRIV
Definition: sparc64-tdep.h:88
void store_unsigned_integer(gdb_byte *, int, enum bfd_endian, ULONGEST)
Definition: findvar.c:212
static const struct regset sparc64obsd_fpregset
struct trad_frame_saved_reg * sparc64nbsd_sigcontext_saved_regs(CORE_ADDR sigcontext_addr, struct frame_info *next_frame)
struct trad_frame_saved_reg * saved_regs
Definition: sparc-tdep.h:173
Definition: regset.h:34
const struct sparc_fpregmap sparc64_bsd_fpregmap
static int sparc64obsd_trapframe_sniffer(const struct frame_unwind *self, struct frame_info *this_frame, void **this_cache)
const char *const name
Definition: aarch64-tdep.c:68
#define SPARC64OBSD_UTHREAD_FP_OFFSET
static struct parser_state * pstate
Definition: ada-exp.c:149
unsigned long sparc_fetch_instruction(CORE_ADDR pc)
Definition: sparc-tdep.c:96
void sparc_collect_rwindow(const struct regcache *regcache, CORE_ADDR sp, int regnum)
Definition: sparc-tdep.c:1823
CORE_ADDR base
Definition: sparc-tdep.h:154
void sparc64_supply_fpregset(const struct sparc_fpregmap *fpregmap, struct regcache *regcache, int regnum, const void *fpregs)
static int sparc64obsd_sigtramp_frame_sniffer(const struct frame_unwind *self, struct frame_info *this_frame, void **this_cache)
enum bfd_endian gdbarch_byte_order(struct gdbarch *gdbarch)
Definition: gdbarch.c:1420
static const int sparc64obsd_page_size
void set_solib_svr4_fetch_link_map_offsets(struct gdbarch *gdbarch, struct link_map_offsets *(*flmo)(void))
Definition: solib-svr4.c:3108
int find_pc_partial_function(CORE_ADDR pc, const char **name, CORE_ADDR *address, CORE_ADDR *endaddr)
Definition: blockframe.c:321
#define gdb_assert(expr)
Definition: gdb_assert.h:33
void _initialize_sparc64obsd_tdep(void)
static void sparc64obsd_supply_fpregset(const struct regset *regset, struct regcache *regcache, int regnum, const void *fpregs, size_t len)
static struct sparc_frame_cache * sparc64obsd_trapframe_cache(struct frame_info *this_frame, void **this_cache)
int regnum
Definition: aarch64-tdep.c:69
static void sparc64obsd_supply_uthread(struct regcache *regcache, int regnum, CORE_ADDR addr)
ULONGEST get_frame_register_unsigned(struct frame_info *frame, int regnum)
Definition: frame.c:1194
Definition: value.c:172
static void sparc64obsd_frame_this_id(struct frame_info *this_frame, void **this_cache, struct frame_id *this_id)
static struct sparc_frame_cache * sparc64obsd_frame_cache(struct frame_info *this_frame, void **this_cache)
struct trad_frame_saved_reg * trad_frame_alloc_saved_regs(struct frame_info *this_frame)
Definition: trad-frame.c:52
bfd_byte gdb_byte
Definition: common-types.h:38
static struct value * sparc64obsd_trapframe_prev_register(struct frame_info *this_frame, void **this_cache, int regnum)
int offset
Definition: agent.c:65
size_t sizeof_gregset
Definition: i386-tdep.h:61
#define SPARC64OBSD_UTHREAD_PC_OFFSET
const struct regset * fpregset
Definition: i386-tdep.h:242
void regcache_raw_supply(struct regcache *regcache, int regnum, const void *buf)
Definition: regcache.c:1041
static const struct regset sparc64obsd_gregset
unsigned long long ULONGEST
Definition: common-types.h:53
enum unwind_stop_reason default_frame_unwind_stop_reason(struct frame_info *this_frame, void **this_cache)
Definition: frame-unwind.c:180
static int sparc64obsd_pc_in_sigtramp(CORE_ADDR pc, const char *name)
CORE_ADDR obsd_skip_solib_resolver(struct gdbarch *gdbarch, CORE_ADDR pc)
Definition: obsd-tdep.c:28
void regcache_raw_collect(const struct regcache *regcache, int regnum, void *buf)
Definition: regcache.c:1071
static void sparc64obsd_trapframe_this_id(struct frame_info *this_frame, void **this_cache, struct frame_id *this_id)
ULONGEST read_memory_unsigned_integer(CORE_ADDR memaddr, int len, enum bfd_endian byte_order)
Definition: corefile.c:321
void write_memory(CORE_ADDR memaddr, const bfd_byte *myaddr, ssize_t len)
Definition: corefile.c:389
void set_gdbarch_skip_solib_resolver(struct gdbarch *gdbarch, gdbarch_skip_solib_resolver_ftype skip_solib_resolver)
Definition: gdbarch.c:3101
void bsd_uthread_set_supply_uthread(struct gdbarch *gdbarch, void(*supply_uthread)(struct regcache *, int, CORE_ADDR))
Definition: bsd-uthread.c:67
enum bfd_endian byte_order
Definition: gdbarch.c:128
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 void sparc64obsd_supply_gregset(const struct regset *regset, struct regcache *regcache, int regnum, const void *gregs, size_t len)
CORE_ADDR sparcnbsd_step_trap(struct frame_info *frame, unsigned long insn)
const ULONGEST const LONGEST len
Definition: target.h:309