1130803Smarcel/* Target-dependent code for Solaris SPARC.
2130803Smarcel
3130803Smarcel   Copyright 2003 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 "frame.h"
24130803Smarcel#include "frame-unwind.h"
25130803Smarcel#include "gdbcore.h"
26130803Smarcel#include "symtab.h"
27130803Smarcel#include "objfiles.h"
28130803Smarcel#include "osabi.h"
29130803Smarcel#include "regcache.h"
30130803Smarcel#include "target.h"
31130803Smarcel#include "trad-frame.h"
32130803Smarcel
33130803Smarcel#include "gdb_assert.h"
34130803Smarcel#include "gdb_string.h"
35130803Smarcel
36130803Smarcel#include "sparc-tdep.h"
37130803Smarcel
38130803Smarcel/* From <sys/regset.h>.  */
39130803Smarcelconst struct sparc_gregset sparc32_sol2_gregset =
40130803Smarcel{
41130803Smarcel  32 * 4,			/* %psr */
42130803Smarcel  33 * 4,			/* %pc */
43130803Smarcel  34 * 4,			/* %npc */
44130803Smarcel  35 * 4,			/* %y */
45130803Smarcel  36 * 4,			/* %wim */
46130803Smarcel  37 * 4,			/* %tbr */
47130803Smarcel  1 * 4,			/* %g1 */
48130803Smarcel  16 * 4,			/* %l0 */
49130803Smarcel};
50130803Smarcel
51130803Smarcel
52130803Smarcel/* The Solaris signal trampolines reside in libc.  For normal signals,
53130803Smarcel   the function `sigacthandler' is used.  This signal trampoline will
54130803Smarcel   call the signal handler using the System V calling convention,
55130803Smarcel   where the third argument is a pointer to an instance of
56130803Smarcel   `ucontext_t', which has a member `uc_mcontext' that contains the
57130803Smarcel   saved registers.  Incidentally, the kernel passes the `ucontext_t'
58130803Smarcel   pointer as the third argument of the signal trampoline too, and
59130803Smarcel   `sigacthandler' simply passes it on. However, if you link your
60130803Smarcel   program with "-L/usr/ucblib -R/usr/ucblib -lucb", the function
61130803Smarcel   `ucbsigvechandler' will be used, which invokes the using the BSD
62130803Smarcel   convention, where the third argument is a pointer to an instance of
63130803Smarcel   `struct sigcontext'.  It is the `ucbsigvechandler' function that
64130803Smarcel   converts the `ucontext_t' to a `sigcontext', and back.  Unless the
65130803Smarcel   signal handler modifies the `struct sigcontext' we can safely
66130803Smarcel   ignore this.  */
67130803Smarcel
68130803Smarcelint
69130803Smarcelsparc_sol2_pc_in_sigtramp (CORE_ADDR pc, char *name)
70130803Smarcel{
71130803Smarcel  return (name && (strcmp (name, "sigacthandler") == 0
72130803Smarcel		   || strcmp (name, "ucbsigvechandler") == 0));
73130803Smarcel}
74130803Smarcel
75130803Smarcelstatic struct sparc_frame_cache *
76130803Smarcelsparc32_sol2_sigtramp_frame_cache (struct frame_info *next_frame,
77130803Smarcel				   void **this_cache)
78130803Smarcel{
79130803Smarcel  struct sparc_frame_cache *cache;
80130803Smarcel  CORE_ADDR mcontext_addr, addr;
81130803Smarcel  int regnum;
82130803Smarcel
83130803Smarcel  if (*this_cache)
84130803Smarcel    return *this_cache;
85130803Smarcel
86130803Smarcel  cache = sparc_frame_cache (next_frame, this_cache);
87130803Smarcel  gdb_assert (cache == *this_cache);
88130803Smarcel
89130803Smarcel  cache->saved_regs = trad_frame_alloc_saved_regs (next_frame);
90130803Smarcel
91130803Smarcel  /* The third argument is a pointer to an instance of `ucontext_t',
92130803Smarcel     which has a member `uc_mcontext' that contains the saved
93130803Smarcel     registers.  */
94130803Smarcel  regnum = (cache->frameless_p ? SPARC_O2_REGNUM : SPARC_I2_REGNUM);
95130803Smarcel  mcontext_addr = frame_unwind_register_unsigned (next_frame, regnum) + 40;
96130803Smarcel
97130803Smarcel  cache->saved_regs[SPARC32_PSR_REGNUM].addr = mcontext_addr + 0 * 4;
98130803Smarcel  cache->saved_regs[SPARC32_PC_REGNUM].addr = mcontext_addr + 1 * 4;
99130803Smarcel  cache->saved_regs[SPARC32_NPC_REGNUM].addr = mcontext_addr + 2 * 4;
100130803Smarcel  cache->saved_regs[SPARC32_Y_REGNUM].addr = mcontext_addr + 3 * 4;
101130803Smarcel
102130803Smarcel  /* Since %g0 is always zero, keep the identity encoding.  */
103130803Smarcel  for (regnum = SPARC_G1_REGNUM, addr = mcontext_addr + 4 * 4;
104130803Smarcel       regnum <= SPARC_O7_REGNUM; regnum++, addr += 4)
105130803Smarcel    cache->saved_regs[regnum].addr = addr;
106130803Smarcel
107130803Smarcel  if (get_frame_memory_unsigned (next_frame, mcontext_addr + 19 * 4, 4))
108130803Smarcel    {
109130803Smarcel      /* The register windows haven't been flushed.  */
110130803Smarcel      for (regnum = SPARC_L0_REGNUM; regnum <= SPARC_I7_REGNUM; regnum++)
111130803Smarcel	trad_frame_set_unknown (cache->saved_regs, regnum);
112130803Smarcel    }
113130803Smarcel  else
114130803Smarcel    {
115130803Smarcel      addr = cache->saved_regs[SPARC_SP_REGNUM].addr;
116130803Smarcel      addr = get_frame_memory_unsigned (next_frame, addr, 4);
117130803Smarcel      for (regnum = SPARC_L0_REGNUM;
118130803Smarcel	   regnum <= SPARC_I7_REGNUM; regnum++, addr += 4)
119130803Smarcel	cache->saved_regs[regnum].addr = addr;
120130803Smarcel    }
121130803Smarcel
122130803Smarcel  return cache;
123130803Smarcel}
124130803Smarcel
125130803Smarcelstatic void
126130803Smarcelsparc32_sol2_sigtramp_frame_this_id (struct frame_info *next_frame,
127130803Smarcel				     void **this_cache,
128130803Smarcel				     struct frame_id *this_id)
129130803Smarcel{
130130803Smarcel  struct sparc_frame_cache *cache =
131130803Smarcel    sparc32_sol2_sigtramp_frame_cache (next_frame, this_cache);
132130803Smarcel
133130803Smarcel  (*this_id) = frame_id_build (cache->base, cache->pc);
134130803Smarcel}
135130803Smarcel
136130803Smarcelstatic void
137130803Smarcelsparc32_sol2_sigtramp_frame_prev_register (struct frame_info *next_frame,
138130803Smarcel					   void **this_cache,
139130803Smarcel					   int regnum, int *optimizedp,
140130803Smarcel					   enum lval_type *lvalp,
141130803Smarcel					   CORE_ADDR *addrp,
142130803Smarcel					   int *realnump, void *valuep)
143130803Smarcel{
144130803Smarcel  struct sparc_frame_cache *cache =
145130803Smarcel    sparc32_sol2_sigtramp_frame_cache (next_frame, this_cache);
146130803Smarcel
147130803Smarcel  trad_frame_prev_register (next_frame, cache->saved_regs, regnum,
148130803Smarcel			    optimizedp, lvalp, addrp, realnump, valuep);
149130803Smarcel}
150130803Smarcel
151130803Smarcelstatic const struct frame_unwind sparc32_sol2_sigtramp_frame_unwind =
152130803Smarcel{
153130803Smarcel  SIGTRAMP_FRAME,
154130803Smarcel  sparc32_sol2_sigtramp_frame_this_id,
155130803Smarcel  sparc32_sol2_sigtramp_frame_prev_register
156130803Smarcel};
157130803Smarcel
158130803Smarcelstatic const struct frame_unwind *
159130803Smarcelsparc32_sol2_sigtramp_frame_sniffer (struct frame_info *next_frame)
160130803Smarcel{
161130803Smarcel  CORE_ADDR pc = frame_pc_unwind (next_frame);
162130803Smarcel  char *name;
163130803Smarcel
164130803Smarcel  find_pc_partial_function (pc, &name, NULL, NULL);
165130803Smarcel  if (sparc_sol2_pc_in_sigtramp (pc, name))
166130803Smarcel    return &sparc32_sol2_sigtramp_frame_unwind;
167130803Smarcel
168130803Smarcel  return NULL;
169130803Smarcel}
170130803Smarcel
171130803Smarcel
172130803Smarcelvoid
173130803Smarcelsparc32_sol2_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
174130803Smarcel{
175130803Smarcel  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
176130803Smarcel
177130803Smarcel  /* Solaris has SVR4-style shared libraries...  */
178130803Smarcel  set_gdbarch_in_solib_call_trampoline (gdbarch, in_plt_section);
179130803Smarcel  set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
180130803Smarcel
181130803Smarcel  /* ...which means that we need some special handling when doing
182130803Smarcel     prologue analysis.  */
183130803Smarcel  tdep->plt_entry_size = 12;
184130803Smarcel
185130803Smarcel  /* Solaris has kernel-assisted single-stepping support.  */
186130803Smarcel  set_gdbarch_software_single_step (gdbarch, NULL);
187130803Smarcel
188130803Smarcel  set_gdbarch_pc_in_sigtramp (gdbarch, sparc_sol2_pc_in_sigtramp);
189130803Smarcel  frame_unwind_append_sniffer (gdbarch, sparc32_sol2_sigtramp_frame_sniffer);
190130803Smarcel}
191130803Smarcel
192130803Smarcel
193130803Smarcel/* Provide a prototype to silence -Wmissing-prototypes.  */
194130803Smarcelvoid _initialize_sparc_sol2_tdep (void);
195130803Smarcel
196130803Smarcelvoid
197130803Smarcel_initialize_sparc_sol2_tdep (void)
198130803Smarcel{
199130803Smarcel  gdbarch_register_osabi (bfd_arch_sparc, 0,
200130803Smarcel			  GDB_OSABI_SOLARIS, sparc32_sol2_init_abi);
201130803Smarcel}
202