1/* Target-dependent code for OpenBSD/sparc64.
2
3   Copyright (C) 2004-2020 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>.  */
47const 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
60const 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
73static void
74sparc64obsd_supply_gregset (const struct regset *regset,
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
90static void
91sparc64obsd_supply_fpregset (const struct regset *regset,
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.  */
113static const int sparc64obsd_page_size = 8192;
114
115/* Offset for sigreturn(2).  */
116static const int sparc64obsd_sigreturn_offset[] = {
117  0xf0,				/* OpenBSD 3.8 */
118  0xec,				/* OpenBSD 3.6 */
119  0xe8,				/* OpenBSD 3.2 */
120  -1
121};
122
123static int
124sparc64obsd_pc_in_sigtramp (CORE_ADDR pc, const char *name)
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
151static struct sparc_frame_cache *
152sparc64obsd_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 (struct sparc_frame_cache *) *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
187static void
188sparc64obsd_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
197static struct value *
198sparc64obsd_frame_prev_register (struct frame_info *this_frame,
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
207static int
208sparc64obsd_sigtramp_frame_sniffer (const struct frame_unwind *self,
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
222static const struct frame_unwind sparc64obsd_frame_unwind =
223{
224  SIGTRAMP_FRAME,
225  default_frame_unwind_stop_reason,
226  sparc64obsd_frame_this_id,
227  sparc64obsd_frame_prev_register,
228  NULL,
229  sparc64obsd_sigtramp_frame_sniffer
230};
231
232/* Kernel debugging support.  */
233
234static struct sparc_frame_cache *
235sparc64obsd_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 (struct sparc_frame_cache *) *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
263static void
264sparc64obsd_trapframe_this_id (struct frame_info *this_frame,
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
273static struct value *
274sparc64obsd_trapframe_prev_register (struct frame_info *this_frame,
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
283static int
284sparc64obsd_trapframe_sniffer (const struct frame_unwind *self,
285			       struct frame_info *this_frame,
286			       void **this_cache)
287{
288  CORE_ADDR pc;
289  ULONGEST pstate;
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
305static const struct frame_unwind sparc64obsd_trapframe_unwind =
306{
307  NORMAL_FRAME,
308  default_frame_unwind_stop_reason,
309  sparc64obsd_trapframe_this_id,
310  sparc64obsd_trapframe_prev_register,
311  NULL,
312  sparc64obsd_trapframe_sniffer
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
322static void
323sparc64obsd_supply_uthread (struct regcache *regcache,
324			    int regnum, CORE_ADDR addr)
325{
326  struct gdbarch *gdbarch = regcache->arch ();
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 (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 (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 (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
367static void
368sparc64obsd_collect_uthread(const struct regcache *regcache,
369			    int regnum, CORE_ADDR addr)
370{
371  struct gdbarch *gdbarch = regcache->arch ();
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 (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 (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 (SPARC_SP_REGNUM, buf);
399  sp = extract_unsigned_integer (buf, 8, byte_order);
400  sparc_collect_rwindow (regcache, sp, regnum);
401}
402
403
404static const struct regset sparc64obsd_gregset =
405  {
406    NULL, sparc64obsd_supply_gregset, NULL
407  };
408
409static const struct regset sparc64obsd_fpregset =
410  {
411    NULL, sparc64obsd_supply_fpregset, NULL
412  };
413
414static void
415sparc64obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
416{
417  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
418
419  tdep->gregset = &sparc64obsd_gregset;
420  tdep->sizeof_gregset = 288;
421  tdep->fpregset = &sparc64obsd_fpregset;
422  tdep->sizeof_fpregset = 272;
423
424  /* Make sure we can single-step "new" syscalls.  */
425  tdep->step_trap = sparcnbsd_step_trap;
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.  */
434  set_solib_svr4_fetch_link_map_offsets
435    (gdbarch, svr4_lp64_fetch_link_map_offsets);
436  set_gdbarch_skip_solib_resolver (gdbarch, obsd_skip_solib_resolver);
437
438  /* OpenBSD provides a user-level threads implementation.  */
439  bsd_uthread_set_supply_uthread (gdbarch, sparc64obsd_supply_uthread);
440  bsd_uthread_set_collect_uthread (gdbarch, sparc64obsd_collect_uthread);
441}
442
443void _initialize_sparc64obsd_tdep ();
444void
445_initialize_sparc64obsd_tdep ()
446{
447  gdbarch_register_osabi (bfd_arch_sparc, bfd_mach_sparc_v9,
448			  GDB_OSABI_OPENBSD, sparc64obsd_init_abi);
449}
450