1130803Smarcel/* Target-dependent code for OpenBSD/sparc.
2130803Smarcel
3130803Smarcel   Copyright 2004 Free Software Foundation, Inc.
4130803Smarcel
5130803Smarcel   This file is part of GDB.
6130803Smarcel
7130803Smarcel   This program is free software; you can redistribute it and/or modify
8130803Smarcel   it under the terms of the GNU General Public License as published by
9130803Smarcel   the Free Software Foundation; either version 2 of the License, or
10130803Smarcel   (at your option) any later version.
11130803Smarcel
12130803Smarcel   This program is distributed in the hope that it will be useful,
13130803Smarcel   but WITHOUT ANY WARRANTY; without even the implied warranty of
14130803Smarcel   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15130803Smarcel   GNU General Public License for more details.
16130803Smarcel
17130803Smarcel   You should have received a copy of the GNU General Public License
18130803Smarcel   along with this program; if not, write to the Free Software
19130803Smarcel   Foundation, Inc., 59 Temple Place - Suite 330,
20130803Smarcel   Boston, MA 02111-1307, USA.  */
21130803Smarcel
22130803Smarcel#include "defs.h"
23130803Smarcel#include "floatformat.h"
24130803Smarcel#include "frame.h"
25130803Smarcel#include "frame-unwind.h"
26130803Smarcel#include "osabi.h"
27130803Smarcel#include "solib-svr4.h"
28130803Smarcel#include "symtab.h"
29130803Smarcel#include "trad-frame.h"
30130803Smarcel
31130803Smarcel#include "gdb_assert.h"
32130803Smarcel
33130803Smarcel#include "sparc-tdep.h"
34130803Smarcel#include "nbsd-tdep.h"
35130803Smarcel
36130803Smarcel/* Signal trampolines.  */
37130803Smarcel
38130803Smarcel/* The OpenBSD kernel maps the signal trampoline at some random
39130803Smarcel   location in user space, which means that the traditional BSD way of
40130803Smarcel   detecting it won't work.
41130803Smarcel
42130803Smarcel   The signal trampoline will be mapped at an address that is page
43130803Smarcel   aligned.  We recognize the signal trampoline by the looking for the
44130803Smarcel   sigreturn system call.  */
45130803Smarcel
46130803Smarcelstatic const int sparc32obsd_page_size = 4096;
47130803Smarcel
48130803Smarcelstatic int
49130803Smarcelsparc32obsd_pc_in_sigtramp (CORE_ADDR pc, char *name)
50130803Smarcel{
51130803Smarcel  CORE_ADDR start_pc = (pc & ~(sparc32obsd_page_size - 1));
52130803Smarcel  unsigned long insn;
53130803Smarcel
54130803Smarcel  if (name)
55130803Smarcel    return 0;
56130803Smarcel
57130803Smarcel  /* Check for "restore %g0, SYS_sigreturn, %g1".  */
58130803Smarcel  insn = sparc_fetch_instruction (start_pc + 0xec);
59130803Smarcel  if (insn != 0x83e82067)
60130803Smarcel    return 0;
61130803Smarcel
62130803Smarcel  /* Check for "t ST_SYSCALL".  */
63130803Smarcel  insn = sparc_fetch_instruction (start_pc + 0xf4);
64130803Smarcel  if (insn != 0x91d02000)
65130803Smarcel    return 0;
66130803Smarcel
67130803Smarcel  return 1;
68130803Smarcel}
69130803Smarcel
70130803Smarcelstatic struct sparc_frame_cache *
71130803Smarcelsparc32obsd_frame_cache (struct frame_info *next_frame, void **this_cache)
72130803Smarcel{
73130803Smarcel  struct sparc_frame_cache *cache;
74130803Smarcel  CORE_ADDR addr;
75130803Smarcel
76130803Smarcel  if (*this_cache)
77130803Smarcel    return *this_cache;
78130803Smarcel
79130803Smarcel  cache = sparc_frame_cache (next_frame, this_cache);
80130803Smarcel  gdb_assert (cache == *this_cache);
81130803Smarcel
82130803Smarcel  /* If we couldn't find the frame's function, we're probably dealing
83130803Smarcel     with an on-stack signal trampoline.  */
84130803Smarcel  if (cache->pc == 0)
85130803Smarcel    {
86130803Smarcel      cache->pc = frame_pc_unwind (next_frame);
87130803Smarcel      cache->pc &= ~(sparc32obsd_page_size - 1);
88130803Smarcel
89130803Smarcel      /* Since we couldn't find the frame's function, the cache was
90130803Smarcel         initialized under the assumption that we're frameless.  */
91130803Smarcel      cache->frameless_p = 0;
92130803Smarcel      addr = frame_unwind_register_unsigned (next_frame, SPARC_FP_REGNUM);
93130803Smarcel      cache->base = addr;
94130803Smarcel    }
95130803Smarcel
96130803Smarcel  cache->saved_regs = sparc32nbsd_sigcontext_saved_regs (next_frame);
97130803Smarcel
98130803Smarcel  return cache;
99130803Smarcel}
100130803Smarcel
101130803Smarcelstatic void
102130803Smarcelsparc32obsd_frame_this_id (struct frame_info *next_frame, void **this_cache,
103130803Smarcel			   struct frame_id *this_id)
104130803Smarcel{
105130803Smarcel  struct sparc_frame_cache *cache =
106130803Smarcel    sparc32obsd_frame_cache (next_frame, this_cache);
107130803Smarcel
108130803Smarcel  (*this_id) = frame_id_build (cache->base, cache->pc);
109130803Smarcel}
110130803Smarcel
111130803Smarcelstatic void
112130803Smarcelsparc32obsd_frame_prev_register (struct frame_info *next_frame,
113130803Smarcel				 void **this_cache,
114130803Smarcel				 int regnum, int *optimizedp,
115130803Smarcel				 enum lval_type *lvalp, CORE_ADDR *addrp,
116130803Smarcel				 int *realnump, void *valuep)
117130803Smarcel{
118130803Smarcel  struct sparc_frame_cache *cache =
119130803Smarcel    sparc32obsd_frame_cache (next_frame, this_cache);
120130803Smarcel
121130803Smarcel  trad_frame_prev_register (next_frame, cache->saved_regs, regnum,
122130803Smarcel			    optimizedp, lvalp, addrp, realnump, valuep);
123130803Smarcel}
124130803Smarcel
125130803Smarcelstatic const struct frame_unwind sparc32obsd_frame_unwind =
126130803Smarcel{
127130803Smarcel  SIGTRAMP_FRAME,
128130803Smarcel  sparc32obsd_frame_this_id,
129130803Smarcel  sparc32obsd_frame_prev_register
130130803Smarcel};
131130803Smarcel
132130803Smarcelstatic const struct frame_unwind *
133130803Smarcelsparc32obsd_sigtramp_frame_sniffer (struct frame_info *next_frame)
134130803Smarcel{
135130803Smarcel  CORE_ADDR pc = frame_pc_unwind (next_frame);
136130803Smarcel  char *name;
137130803Smarcel
138130803Smarcel  find_pc_partial_function (pc, &name, NULL, NULL);
139130803Smarcel  if (sparc32obsd_pc_in_sigtramp (pc, name))
140130803Smarcel    return &sparc32obsd_frame_unwind;
141130803Smarcel
142130803Smarcel  return NULL;
143130803Smarcel}
144130803Smarcel
145130803Smarcel
146130803Smarcelstatic void
147130803Smarcelsparc32obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
148130803Smarcel{
149130803Smarcel  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
150130803Smarcel
151130803Smarcel  /* OpenBSD doesn't support the 128-bit `long double' from the psABI.  */
152130803Smarcel  set_gdbarch_long_double_bit (gdbarch, 64);
153130803Smarcel  set_gdbarch_long_double_format (gdbarch, &floatformat_ieee_double_big);
154130803Smarcel
155130803Smarcel  set_gdbarch_pc_in_sigtramp (gdbarch, sparc32obsd_pc_in_sigtramp);
156130803Smarcel  frame_unwind_append_sniffer (gdbarch, sparc32obsd_sigtramp_frame_sniffer);
157130803Smarcel
158130803Smarcel  set_solib_svr4_fetch_link_map_offsets
159130803Smarcel    (gdbarch, nbsd_ilp32_solib_svr4_fetch_link_map_offsets);
160130803Smarcel}
161130803Smarcel
162130803Smarcel
163130803Smarcel/* Provide a prototype to silence -Wmissing-prototypes.  */
164130803Smarcelvoid _initialize_sparc32obsd_tdep (void);
165130803Smarcel
166130803Smarcelvoid
167130803Smarcel_initialize_sparc32obsd_tdep (void)
168130803Smarcel{
169130803Smarcel  gdbarch_register_osabi (bfd_arch_sparc, 0, GDB_OSABI_OPENBSD_ELF,
170130803Smarcel			  sparc32obsd_init_abi);
171130803Smarcel}
172