1 /* Target-dependent code for OpenBSD/powerpc.
2 
3    Copyright (C) 2004, 2005, 2006 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 2 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, write to the Free Software
19    Foundation, Inc., 51 Franklin Street, Fifth Floor,
20    Boston, MA 02110-1301, USA.  */
21 
22 #include "defs.h"
23 #include "arch-utils.h"
24 #include "floatformat.h"
25 #include "frame.h"
26 #include "frame-unwind.h"
27 #include "osabi.h"
28 #include "regcache.h"
29 #include "regset.h"
30 #include "symtab.h"
31 #include "trad-frame.h"
32 
33 #include "gdb_assert.h"
34 #include "gdb_string.h"
35 
36 #include "ppc-tdep.h"
37 #include "ppcobsd-tdep.h"
38 #include "solib-svr4.h"
39 
40 /* Register offsets from <machine/reg.h>.  */
41 struct ppc_reg_offsets ppcobsd_reg_offsets;
42 struct ppc_reg_offsets ppcobsd_fpreg_offsets;
43 
44 
45 /* Core file support.  */
46 
47 /* Supply register REGNUM in the general-purpose register set REGSET
48    from the buffer specified by GREGS and LEN to register cache
49    REGCACHE.  If REGNUM is -1, do this for all registers in REGSET.  */
50 
51 void
ppcobsd_supply_gregset(const struct regset * regset,struct regcache * regcache,int regnum,const void * gregs,size_t len)52 ppcobsd_supply_gregset (const struct regset *regset,
53 			struct regcache *regcache, int regnum,
54 			const void *gregs, size_t len)
55 {
56   /* FIXME: jimb/2004-05-05: Some PPC variants don't have floating
57      point registers.  Traditionally, GDB's register set has still
58      listed the floating point registers for such machines, so this
59      code is harmless.  However, the new E500 port actually omits the
60      floating point registers entirely from the register set --- they
61      don't even have register numbers assigned to them.
62 
63      It's not clear to me how best to update this code, so this assert
64      will alert the first person to encounter the OpenBSD/E500
65      combination to the problem.  */
66   gdb_assert (ppc_floating_point_unit_p (current_gdbarch));
67 
68   ppc_supply_gregset (regset, regcache, regnum, gregs, len);
69   ppc_supply_fpregset (regset, regcache, regnum, gregs, len);
70 }
71 
72 /* Collect register REGNUM in the general-purpose register set
73    REGSET. from register cache REGCACHE into the buffer specified by
74    GREGS and LEN.  If REGNUM is -1, do this for all registers in
75    REGSET.  */
76 
77 void
ppcobsd_collect_gregset(const struct regset * regset,const struct regcache * regcache,int regnum,void * gregs,size_t len)78 ppcobsd_collect_gregset (const struct regset *regset,
79 			 const struct regcache *regcache, int regnum,
80 			 void *gregs, size_t len)
81 {
82   /* FIXME: jimb/2004-05-05: Some PPC variants don't have floating
83      point registers.  Traditionally, GDB's register set has still
84      listed the floating point registers for such machines, so this
85      code is harmless.  However, the new E500 port actually omits the
86      floating point registers entirely from the register set --- they
87      don't even have register numbers assigned to them.
88 
89      It's not clear to me how best to update this code, so this assert
90      will alert the first person to encounter the OpenBSD/E500
91      combination to the problem.  */
92   gdb_assert (ppc_floating_point_unit_p (current_gdbarch));
93 
94   ppc_collect_gregset (regset, regcache, regnum, gregs, len);
95   ppc_collect_fpregset (regset, regcache, regnum, gregs, len);
96 }
97 
98 /* OpenBSD/powerpc register set.  */
99 
100 struct regset ppcobsd_gregset =
101 {
102   &ppcobsd_reg_offsets,
103   ppcobsd_supply_gregset
104 };
105 
106 struct regset ppcobsd_fpregset =
107 {
108   &ppcobsd_fpreg_offsets,
109   ppc_supply_fpregset
110 };
111 
112 /* Return the appropriate register set for the core section identified
113    by SECT_NAME and SECT_SIZE.  */
114 
115 static const struct regset *
ppcobsd_regset_from_core_section(struct gdbarch * gdbarch,const char * sect_name,size_t sect_size)116 ppcobsd_regset_from_core_section (struct gdbarch *gdbarch,
117 				  const char *sect_name, size_t sect_size)
118 {
119   if (strcmp (sect_name, ".reg") == 0 && sect_size >= 412)
120     return &ppcobsd_gregset;
121 
122   if (strcmp (sect_name, ".reg2") == 0 && sect_size >= 260)
123     return &ppcobsd_fpregset;
124 
125   return NULL;
126 }
127 
128 
129 /* Signal trampolines.  */
130 
131 /* Since OpenBSD 3.2, the sigtramp routine is mapped at a random page
132    in virtual memory.  The randomness makes it somewhat tricky to
133    detect it, but fortunately we can rely on the fact that the start
134    of the sigtramp routine is page-aligned.  We recognize the
135    trampoline by looking for the code that invokes the sigreturn
136    system call.  The offset where we can find that code varies from
137    release to release.
138 
139    By the way, the mapping mentioned above is read-only, so you cannot
140    place a breakpoint in the signal trampoline.  */
141 
142 /* Default page size.  */
143 static const int ppcobsd_page_size = 4096;
144 
145 /* Offset for sigreturn(2).  */
146 static const int ppcobsd_sigreturn_offset[] = {
147   0x98,				/* OpenBSD 3.8 */
148   0x0c,				/* OpenBSD 3.2 */
149   -1
150 };
151 
152 static int
ppcobsd_sigtramp_p(struct frame_info * next_frame)153 ppcobsd_sigtramp_p (struct frame_info *next_frame)
154 {
155   CORE_ADDR pc = frame_pc_unwind (next_frame);
156   CORE_ADDR start_pc = (pc & ~(ppcobsd_page_size - 1));
157   const int *offset;
158   char *name;
159 
160   find_pc_partial_function (pc, &name, NULL, NULL);
161   if (name)
162     return 0;
163 
164   for (offset = ppcobsd_sigreturn_offset; *offset != -1; offset++)
165     {
166       char buf[2 * PPC_INSN_SIZE];
167       unsigned long insn;
168 
169       if (!safe_frame_unwind_memory (next_frame, start_pc + *offset,
170 				     buf, sizeof buf))
171 	continue;
172 
173       /* Check for "li r0,SYS_sigreturn".  */
174       insn = extract_unsigned_integer (buf, PPC_INSN_SIZE);
175       if (insn != 0x38000067)
176 	continue;
177 
178       /* Check for "sc".  */
179       insn = extract_unsigned_integer (buf + PPC_INSN_SIZE, PPC_INSN_SIZE);
180       if (insn != 0x44000002)
181 	continue;
182 
183       return 1;
184     }
185 
186   return 0;
187 }
188 
189 static struct trad_frame_cache *
ppcobsd_sigtramp_frame_cache(struct frame_info * next_frame,void ** this_cache)190 ppcobsd_sigtramp_frame_cache (struct frame_info *next_frame, void **this_cache)
191 {
192   struct gdbarch *gdbarch = get_frame_arch (next_frame);
193   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
194   struct trad_frame_cache *cache;
195   CORE_ADDR addr, base, func;
196   char buf[PPC_INSN_SIZE];
197   unsigned long insn, sigcontext_offset;
198   int i;
199 
200   if (*this_cache)
201     return *this_cache;
202 
203   cache = trad_frame_cache_zalloc (next_frame);
204   *this_cache = cache;
205 
206   func = frame_pc_unwind (next_frame);
207   func &= ~(ppcobsd_page_size - 1);
208   if (!safe_frame_unwind_memory (next_frame, func, buf, sizeof buf))
209     return cache;
210 
211   /* Calculate the offset where we can find `struct sigcontext'.  We
212      base our calculation on the amount of stack space reserved by the
213      first instruction of the signal trampoline.  */
214   insn = extract_unsigned_integer (buf, PPC_INSN_SIZE);
215   sigcontext_offset = (0x10000 - (insn & 0x0000ffff)) + 8;
216 
217   base = frame_unwind_register_unsigned (next_frame, SP_REGNUM);
218   addr = base + sigcontext_offset + 2 * tdep->wordsize;
219   for (i = 0; i < ppc_num_gprs; i++, addr += tdep->wordsize)
220     {
221       int regnum = i + tdep->ppc_gp0_regnum;
222       trad_frame_set_reg_addr (cache, regnum, addr);
223     }
224   trad_frame_set_reg_addr (cache, tdep->ppc_lr_regnum, addr);
225   addr += tdep->wordsize;
226   trad_frame_set_reg_addr (cache, tdep->ppc_cr_regnum, addr);
227   addr += tdep->wordsize;
228   trad_frame_set_reg_addr (cache, tdep->ppc_xer_regnum, addr);
229   addr += tdep->wordsize;
230   trad_frame_set_reg_addr (cache, tdep->ppc_ctr_regnum, addr);
231   addr += tdep->wordsize;
232   trad_frame_set_reg_addr (cache, PC_REGNUM, addr); /* SRR0? */
233   addr += tdep->wordsize;
234 
235   /* Construct the frame ID using the function start.  */
236   trad_frame_set_id (cache, frame_id_build (base, func));
237 
238   return cache;
239 }
240 
241 static void
ppcobsd_sigtramp_frame_this_id(struct frame_info * next_frame,void ** this_cache,struct frame_id * this_id)242 ppcobsd_sigtramp_frame_this_id (struct frame_info *next_frame,
243 				void **this_cache, struct frame_id *this_id)
244 {
245   struct trad_frame_cache *cache =
246     ppcobsd_sigtramp_frame_cache (next_frame, this_cache);
247 
248   trad_frame_get_id (cache, this_id);
249 }
250 
251 static void
ppcobsd_sigtramp_frame_prev_register(struct frame_info * next_frame,void ** this_cache,int regnum,int * optimizedp,enum lval_type * lvalp,CORE_ADDR * addrp,int * realnump,char * valuep)252 ppcobsd_sigtramp_frame_prev_register (struct frame_info *next_frame,
253 				      void **this_cache, int regnum,
254 				      int *optimizedp, enum lval_type *lvalp,
255 				      CORE_ADDR *addrp, int *realnump,
256 				      char *valuep)
257 {
258   struct trad_frame_cache *cache =
259     ppcobsd_sigtramp_frame_cache (next_frame, this_cache);
260 
261   trad_frame_get_register (cache, next_frame, regnum,
262 			   optimizedp, lvalp, addrp, realnump, valuep);
263 }
264 
265 static const struct frame_unwind ppcobsd_sigtramp_frame_unwind = {
266   SIGTRAMP_FRAME,
267   ppcobsd_sigtramp_frame_this_id,
268   ppcobsd_sigtramp_frame_prev_register
269 };
270 
271 static const struct frame_unwind *
ppcobsd_sigtramp_frame_sniffer(struct frame_info * next_frame)272 ppcobsd_sigtramp_frame_sniffer (struct frame_info *next_frame)
273 {
274   if (ppcobsd_sigtramp_p (next_frame))
275     return &ppcobsd_sigtramp_frame_unwind;
276 
277   return NULL;
278 }
279 
280 
281 static void
ppcobsd_init_abi(struct gdbarch_info info,struct gdbarch * gdbarch)282 ppcobsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
283 {
284   /* OpenBSD doesn't support the 128-bit `long double' from the psABI.  */
285   set_gdbarch_long_double_bit (gdbarch, 64);
286   set_gdbarch_long_double_format (gdbarch, &floatformat_ieee_double_big);
287 
288   /* OpenBSD currently uses a broken GCC.  */
289   set_gdbarch_return_value (gdbarch, ppc_sysv_abi_broken_return_value);
290 
291   /* OpenBSD uses SVR4-style shared libraries.  */
292   set_solib_svr4_fetch_link_map_offsets
293     (gdbarch, svr4_ilp32_fetch_link_map_offsets);
294 
295   set_gdbarch_regset_from_core_section
296     (gdbarch, ppcobsd_regset_from_core_section);
297 
298   frame_unwind_append_sniffer (gdbarch, ppcobsd_sigtramp_frame_sniffer);
299 }
300 
301 
302 /* OpenBSD uses uses the traditional NetBSD core file format, even for
303    ports that use ELF.  */
304 #define GDB_OSABI_NETBSD_CORE GDB_OSABI_OPENBSD_ELF
305 
306 static enum gdb_osabi
ppcobsd_core_osabi_sniffer(bfd * abfd)307 ppcobsd_core_osabi_sniffer (bfd *abfd)
308 {
309   if (strcmp (bfd_get_target (abfd), "netbsd-core") == 0)
310     return GDB_OSABI_NETBSD_CORE;
311 
312   return GDB_OSABI_UNKNOWN;
313 }
314 
315 
316 /* Provide a prototype to silence -Wmissing-prototypes.  */
317 void _initialize_ppcobsd_tdep (void);
318 
319 void
_initialize_ppcobsd_tdep(void)320 _initialize_ppcobsd_tdep (void)
321 {
322   /* BFD doesn't set a flavour for NetBSD style a.out core files.  */
323   gdbarch_register_osabi_sniffer (bfd_arch_powerpc, bfd_target_unknown_flavour,
324                                   ppcobsd_core_osabi_sniffer);
325 
326   gdbarch_register_osabi (bfd_arch_rs6000, 0, GDB_OSABI_OPENBSD_ELF,
327 			  ppcobsd_init_abi);
328   gdbarch_register_osabi (bfd_arch_powerpc, 0, GDB_OSABI_OPENBSD_ELF,
329 			  ppcobsd_init_abi);
330 
331   /* Avoid initializing the register offsets again if they were
332      already initailized by ppcobsd-nat.c.  */
333   if (ppcobsd_reg_offsets.pc_offset == 0)
334     {
335       /* General-purpose registers.  */
336       ppcobsd_reg_offsets.r0_offset = 0;
337       ppcobsd_reg_offsets.pc_offset = 384;
338       ppcobsd_reg_offsets.ps_offset = 388;
339       ppcobsd_reg_offsets.cr_offset = 392;
340       ppcobsd_reg_offsets.lr_offset = 396;
341       ppcobsd_reg_offsets.ctr_offset = 400;
342       ppcobsd_reg_offsets.xer_offset = 404;
343       ppcobsd_reg_offsets.mq_offset = 408;
344 
345       /* Floating-point registers.  */
346       ppcobsd_reg_offsets.f0_offset = 128;
347       ppcobsd_reg_offsets.fpscr_offset = -1;
348 
349       /* AltiVec registers.  */
350       ppcobsd_reg_offsets.vr0_offset = 0;
351       ppcobsd_reg_offsets.vscr_offset = 512;
352       ppcobsd_reg_offsets.vrsave_offset = 520;
353     }
354 
355   if (ppcobsd_fpreg_offsets.fpscr_offset == 0)
356     {
357       /* Floating-point registers.  */
358       ppcobsd_reg_offsets.f0_offset = 0;
359       ppcobsd_reg_offsets.fpscr_offset = 256;
360     }
361 }
362