1 /* Target-dependent code for Solaris SPARC.
2 
3    Copyright (C) 2003-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 "symtab.h"
25 #include "objfiles.h"
26 #include "osabi.h"
27 #include "regcache.h"
28 #include "regset.h"
29 #include "target.h"
30 #include "trad-frame.h"
31 
32 #include "sol2-tdep.h"
33 #include "sparc-tdep.h"
34 #include "solib-svr4.h"
35 
36 /* From <sys/regset.h>.  */
37 const struct sparc_gregmap sparc32_sol2_gregmap =
38 {
39   32 * 4,			/* %psr */
40   33 * 4,			/* %pc */
41   34 * 4,			/* %npc */
42   35 * 4,			/* %y */
43   36 * 4,			/* %wim */
44   37 * 4,			/* %tbr */
45   1 * 4,			/* %g1 */
46   16 * 4,			/* %l0 */
47 };
48 
49 const struct sparc_fpregmap sparc32_sol2_fpregmap =
50 {
51   0 * 4,			/* %f0 */
52   33 * 4,			/* %fsr */
53 };
54 
55 static void
sparc32_sol2_supply_core_gregset(const struct regset * regset,struct regcache * regcache,int regnum,const void * gregs,size_t len)56 sparc32_sol2_supply_core_gregset (const struct regset *regset,
57 				  struct regcache *regcache,
58 				  int regnum, const void *gregs, size_t len)
59 {
60   sparc32_supply_gregset (&sparc32_sol2_gregmap, regcache, regnum, gregs);
61 }
62 
63 static void
sparc32_sol2_collect_core_gregset(const struct regset * regset,const struct regcache * regcache,int regnum,void * gregs,size_t len)64 sparc32_sol2_collect_core_gregset (const struct regset *regset,
65 				   const struct regcache *regcache,
66 				   int regnum, void *gregs, size_t len)
67 {
68   sparc32_collect_gregset (&sparc32_sol2_gregmap, regcache, regnum, gregs);
69 }
70 
71 static void
sparc32_sol2_supply_core_fpregset(const struct regset * regset,struct regcache * regcache,int regnum,const void * fpregs,size_t len)72 sparc32_sol2_supply_core_fpregset (const struct regset *regset,
73 				   struct regcache *regcache,
74 				   int regnum, const void *fpregs, size_t len)
75 {
76   sparc32_supply_fpregset (&sparc32_sol2_fpregmap, regcache, regnum, fpregs);
77 }
78 
79 static void
sparc32_sol2_collect_core_fpregset(const struct regset * regset,const struct regcache * regcache,int regnum,void * fpregs,size_t len)80 sparc32_sol2_collect_core_fpregset (const struct regset *regset,
81 				    const struct regcache *regcache,
82 				    int regnum, void *fpregs, size_t len)
83 {
84   sparc32_collect_fpregset (&sparc32_sol2_fpregmap, regcache, regnum, fpregs);
85 }
86 
87 static const struct regset sparc32_sol2_gregset =
88   {
89     NULL,
90     sparc32_sol2_supply_core_gregset,
91     sparc32_sol2_collect_core_gregset
92   };
93 
94 static const struct regset sparc32_sol2_fpregset =
95   {
96     NULL,
97     sparc32_sol2_supply_core_fpregset,
98     sparc32_sol2_collect_core_fpregset
99   };
100 
101 
102 static struct sparc_frame_cache *
sparc32_sol2_sigtramp_frame_cache(struct frame_info * this_frame,void ** this_cache)103 sparc32_sol2_sigtramp_frame_cache (struct frame_info *this_frame,
104 				   void **this_cache)
105 {
106   struct sparc_frame_cache *cache;
107   CORE_ADDR mcontext_addr, addr;
108   int regnum;
109 
110   if (*this_cache)
111     return (struct sparc_frame_cache *) *this_cache;
112 
113   cache = sparc_frame_cache (this_frame, this_cache);
114   gdb_assert (cache == *this_cache);
115 
116   cache->saved_regs = trad_frame_alloc_saved_regs (this_frame);
117 
118   /* The third argument is a pointer to an instance of `ucontext_t',
119      which has a member `uc_mcontext' that contains the saved
120      registers.  */
121   regnum =
122     (cache->copied_regs_mask & 0x04) ? SPARC_I2_REGNUM : SPARC_O2_REGNUM;
123   mcontext_addr = get_frame_register_unsigned (this_frame, regnum) + 40;
124 
125   cache->saved_regs[SPARC32_PSR_REGNUM].addr = mcontext_addr + 0 * 4;
126   cache->saved_regs[SPARC32_PC_REGNUM].addr = mcontext_addr + 1 * 4;
127   cache->saved_regs[SPARC32_NPC_REGNUM].addr = mcontext_addr + 2 * 4;
128   cache->saved_regs[SPARC32_Y_REGNUM].addr = mcontext_addr + 3 * 4;
129 
130   /* Since %g0 is always zero, keep the identity encoding.  */
131   for (regnum = SPARC_G1_REGNUM, addr = mcontext_addr + 4 * 4;
132        regnum <= SPARC_O7_REGNUM; regnum++, addr += 4)
133     cache->saved_regs[regnum].addr = addr;
134 
135   if (get_frame_memory_unsigned (this_frame, mcontext_addr + 19 * 4, 4))
136     {
137       /* The register windows haven't been flushed.  */
138       for (regnum = SPARC_L0_REGNUM; regnum <= SPARC_I7_REGNUM; regnum++)
139 	trad_frame_set_unknown (cache->saved_regs, regnum);
140     }
141   else
142     {
143       addr = cache->saved_regs[SPARC_SP_REGNUM].addr;
144       addr = get_frame_memory_unsigned (this_frame, addr, 4);
145       for (regnum = SPARC_L0_REGNUM;
146 	   regnum <= SPARC_I7_REGNUM; regnum++, addr += 4)
147 	cache->saved_regs[regnum].addr = addr;
148     }
149 
150   return cache;
151 }
152 
153 static void
sparc32_sol2_sigtramp_frame_this_id(struct frame_info * this_frame,void ** this_cache,struct frame_id * this_id)154 sparc32_sol2_sigtramp_frame_this_id (struct frame_info *this_frame,
155 				     void **this_cache,
156 				     struct frame_id *this_id)
157 {
158   struct sparc_frame_cache *cache =
159     sparc32_sol2_sigtramp_frame_cache (this_frame, this_cache);
160 
161   (*this_id) = frame_id_build (cache->base, cache->pc);
162 }
163 
164 static struct value *
sparc32_sol2_sigtramp_frame_prev_register(struct frame_info * this_frame,void ** this_cache,int regnum)165 sparc32_sol2_sigtramp_frame_prev_register (struct frame_info *this_frame,
166 					   void **this_cache,
167 					   int regnum)
168 {
169   struct sparc_frame_cache *cache =
170     sparc32_sol2_sigtramp_frame_cache (this_frame, this_cache);
171 
172   return trad_frame_get_prev_register (this_frame, cache->saved_regs, regnum);
173 }
174 
175 static int
sparc32_sol2_sigtramp_frame_sniffer(const struct frame_unwind * self,struct frame_info * this_frame,void ** this_cache)176 sparc32_sol2_sigtramp_frame_sniffer (const struct frame_unwind *self,
177 				     struct frame_info *this_frame,
178 				     void **this_cache)
179 {
180   return sol2_sigtramp_p (this_frame);
181 }
182 
183 static const struct frame_unwind sparc32_sol2_sigtramp_frame_unwind =
184 {
185   SIGTRAMP_FRAME,
186   default_frame_unwind_stop_reason,
187   sparc32_sol2_sigtramp_frame_this_id,
188   sparc32_sol2_sigtramp_frame_prev_register,
189   NULL,
190   sparc32_sol2_sigtramp_frame_sniffer
191 };
192 
193 
194 
195 static void
sparc32_sol2_init_abi(struct gdbarch_info info,struct gdbarch * gdbarch)196 sparc32_sol2_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
197 {
198   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
199 
200   tdep->gregset = &sparc32_sol2_gregset;
201   tdep->sizeof_gregset = 152;
202 
203   tdep->fpregset = &sparc32_sol2_fpregset;
204   tdep->sizeof_fpregset = 400;
205 
206   sol2_init_abi (info, gdbarch);
207 
208   /* Solaris has SVR4-style shared libraries...  */
209   set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
210   set_solib_svr4_fetch_link_map_offsets
211     (gdbarch, svr4_ilp32_fetch_link_map_offsets);
212 
213   /* ...which means that we need some special handling when doing
214      prologue analysis.  */
215   tdep->plt_entry_size = 12;
216 
217   /* Solaris has kernel-assisted single-stepping support.  */
218   set_gdbarch_software_single_step (gdbarch, NULL);
219 
220   frame_unwind_append_unwinder (gdbarch, &sparc32_sol2_sigtramp_frame_unwind);
221 }
222 
223 void _initialize_sparc_sol2_tdep ();
224 void
_initialize_sparc_sol2_tdep()225 _initialize_sparc_sol2_tdep ()
226 {
227   gdbarch_register_osabi (bfd_arch_sparc, 0,
228 			  GDB_OSABI_SOLARIS, sparc32_sol2_init_abi);
229 }
230