xref: /openbsd-src/gnu/usr.bin/binutils/gdb/ppc64obsd-tdep.c (revision f3d8f83828e3913cb1e2df05876f5de04b6ab89b)
1*f3d8f838Skettenis /* Target-dependent code for OpenBSD/powerpc64.
2*f3d8f838Skettenis 
3*f3d8f838Skettenis    Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
4*f3d8f838Skettenis 
5*f3d8f838Skettenis    This file is part of GDB.
6*f3d8f838Skettenis 
7*f3d8f838Skettenis    This program is free software; you can redistribute it and/or modify
8*f3d8f838Skettenis    it under the terms of the GNU General Public License as published by
9*f3d8f838Skettenis    the Free Software Foundation; either version 2 of the License, or
10*f3d8f838Skettenis    (at your option) any later version.
11*f3d8f838Skettenis 
12*f3d8f838Skettenis    This program is distributed in the hope that it will be useful,
13*f3d8f838Skettenis    but WITHOUT ANY WARRANTY; without even the implied warranty of
14*f3d8f838Skettenis    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15*f3d8f838Skettenis    GNU General Public License for more details.
16*f3d8f838Skettenis 
17*f3d8f838Skettenis    You should have received a copy of the GNU General Public License
18*f3d8f838Skettenis    along with this program; if not, write to the Free Software
19*f3d8f838Skettenis    Foundation, Inc., 51 Franklin Street, Fifth Floor,
20*f3d8f838Skettenis    Boston, MA 02110-1301, USA.  */
21*f3d8f838Skettenis 
22*f3d8f838Skettenis #include "defs.h"
23*f3d8f838Skettenis #include "arch-utils.h"
24*f3d8f838Skettenis #include "floatformat.h"
25*f3d8f838Skettenis #include "frame.h"
26*f3d8f838Skettenis #include "frame-unwind.h"
27*f3d8f838Skettenis #include "osabi.h"
28*f3d8f838Skettenis #include "regcache.h"
29*f3d8f838Skettenis #include "regset.h"
30*f3d8f838Skettenis #include "symtab.h"
31*f3d8f838Skettenis #include "trad-frame.h"
32*f3d8f838Skettenis 
33*f3d8f838Skettenis #include "gdb_assert.h"
34*f3d8f838Skettenis #include "gdb_string.h"
35*f3d8f838Skettenis 
36*f3d8f838Skettenis #include "ppc-tdep.h"
37*f3d8f838Skettenis #include "ppc64obsd-tdep.h"
38*f3d8f838Skettenis #include "solib-svr4.h"
39*f3d8f838Skettenis 
40*f3d8f838Skettenis /* Register offsets from <machine/reg.h>.  */
41*f3d8f838Skettenis struct ppc_reg_offsets ppc64obsd_reg_offsets;
42*f3d8f838Skettenis struct ppc_reg_offsets ppc64obsd_fpreg_offsets;
43*f3d8f838Skettenis 
44*f3d8f838Skettenis 
45*f3d8f838Skettenis /* Register set support functions.  */
46*f3d8f838Skettenis 
47*f3d8f838Skettenis static void
ppc64_supply_reg(struct regcache * regcache,int regnum,const char * regs,size_t offset)48*f3d8f838Skettenis ppc64_supply_reg (struct regcache *regcache, int regnum,
49*f3d8f838Skettenis 		  const char *regs, size_t offset)
50*f3d8f838Skettenis {
51*f3d8f838Skettenis   if (regnum != -1 && offset != -1)
52*f3d8f838Skettenis     regcache_raw_supply (regcache, regnum, regs + offset);
53*f3d8f838Skettenis }
54*f3d8f838Skettenis 
55*f3d8f838Skettenis static void
ppc64_collect_reg(const struct regcache * regcache,int regnum,char * regs,size_t offset)56*f3d8f838Skettenis ppc64_collect_reg (const struct regcache *regcache, int regnum,
57*f3d8f838Skettenis 		   char *regs, size_t offset)
58*f3d8f838Skettenis {
59*f3d8f838Skettenis   if (regnum != -1 && offset != -1)
60*f3d8f838Skettenis     regcache_raw_collect (regcache, regnum, regs + offset);
61*f3d8f838Skettenis }
62*f3d8f838Skettenis 
63*f3d8f838Skettenis /* Supply register REGNUM in the general-purpose register set REGSET
64*f3d8f838Skettenis    from the buffer specified by GREGS and LEN to register cache
65*f3d8f838Skettenis    REGCACHE.  If REGNUM is -1, do this for all registers in REGSET.  */
66*f3d8f838Skettenis 
67*f3d8f838Skettenis void
ppc64_supply_gregset(const struct regset * regset,struct regcache * regcache,int regnum,const void * gregs,size_t len)68*f3d8f838Skettenis ppc64_supply_gregset (const struct regset *regset, struct regcache *regcache,
69*f3d8f838Skettenis 		      int regnum, const void *gregs, size_t len)
70*f3d8f838Skettenis {
71*f3d8f838Skettenis   struct gdbarch *gdbarch = get_regcache_arch (regcache);
72*f3d8f838Skettenis   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
73*f3d8f838Skettenis   const struct ppc_reg_offsets *offsets = regset->descr;
74*f3d8f838Skettenis   size_t offset;
75*f3d8f838Skettenis   int i;
76*f3d8f838Skettenis 
77*f3d8f838Skettenis   for (i = tdep->ppc_gp0_regnum, offset = offsets->r0_offset;
78*f3d8f838Skettenis        i < tdep->ppc_gp0_regnum + ppc_num_gprs;
79*f3d8f838Skettenis        i++, offset += 8)
80*f3d8f838Skettenis     {
81*f3d8f838Skettenis       if (regnum == -1 || regnum == i)
82*f3d8f838Skettenis 	ppc64_supply_reg (regcache, i, gregs, offset);
83*f3d8f838Skettenis     }
84*f3d8f838Skettenis 
85*f3d8f838Skettenis   if (regnum == -1 || regnum == PC_REGNUM)
86*f3d8f838Skettenis     ppc64_supply_reg (regcache, PC_REGNUM, gregs, offsets->pc_offset);
87*f3d8f838Skettenis   if (regnum == -1 || regnum == tdep->ppc_ps_regnum)
88*f3d8f838Skettenis     ppc64_supply_reg (regcache, tdep->ppc_ps_regnum,
89*f3d8f838Skettenis 		      gregs, offsets->ps_offset);
90*f3d8f838Skettenis   if (regnum == -1 || regnum == tdep->ppc_cr_regnum)
91*f3d8f838Skettenis     ppc64_supply_reg (regcache, tdep->ppc_cr_regnum,
92*f3d8f838Skettenis 		      gregs, offsets->cr_offset);
93*f3d8f838Skettenis   if (regnum == -1 || regnum == tdep->ppc_lr_regnum)
94*f3d8f838Skettenis     ppc64_supply_reg (regcache, tdep->ppc_lr_regnum,
95*f3d8f838Skettenis 		      gregs, offsets->lr_offset);
96*f3d8f838Skettenis   if (regnum == -1 || regnum == tdep->ppc_ctr_regnum)
97*f3d8f838Skettenis     ppc64_supply_reg (regcache, tdep->ppc_ctr_regnum,
98*f3d8f838Skettenis 		      gregs, offsets->ctr_offset);
99*f3d8f838Skettenis   if (regnum == -1 || regnum == tdep->ppc_xer_regnum)
100*f3d8f838Skettenis     ppc64_supply_reg (regcache, tdep->ppc_xer_regnum,
101*f3d8f838Skettenis 		      gregs, offsets->cr_offset);
102*f3d8f838Skettenis }
103*f3d8f838Skettenis 
104*f3d8f838Skettenis /* Collect register REGNUM in the general-purpose register set
105*f3d8f838Skettenis    REGSET. from register cache REGCACHE into the buffer specified by
106*f3d8f838Skettenis    GREGS and LEN.  If REGNUM is -1, do this for all registers in
107*f3d8f838Skettenis    REGSET.  */
108*f3d8f838Skettenis 
109*f3d8f838Skettenis void
ppc64_collect_gregset(const struct regset * regset,const struct regcache * regcache,int regnum,void * gregs,size_t len)110*f3d8f838Skettenis ppc64_collect_gregset (const struct regset *regset,
111*f3d8f838Skettenis 		       const struct regcache *regcache,
112*f3d8f838Skettenis 		       int regnum, void *gregs, size_t len)
113*f3d8f838Skettenis {
114*f3d8f838Skettenis   struct gdbarch *gdbarch = get_regcache_arch (regcache);
115*f3d8f838Skettenis   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
116*f3d8f838Skettenis   const struct ppc_reg_offsets *offsets = regset->descr;
117*f3d8f838Skettenis   size_t offset;
118*f3d8f838Skettenis   int i;
119*f3d8f838Skettenis 
120*f3d8f838Skettenis   offset = offsets->r0_offset;
121*f3d8f838Skettenis   for (i = tdep->ppc_gp0_regnum;
122*f3d8f838Skettenis        i < tdep->ppc_gp0_regnum + ppc_num_gprs;
123*f3d8f838Skettenis        i++, offset += 8)
124*f3d8f838Skettenis     {
125*f3d8f838Skettenis       if (regnum == -1 || regnum == i)
126*f3d8f838Skettenis 	ppc64_collect_reg (regcache, i, gregs, offset);
127*f3d8f838Skettenis     }
128*f3d8f838Skettenis 
129*f3d8f838Skettenis   if (regnum == -1 || regnum == PC_REGNUM)
130*f3d8f838Skettenis     ppc64_collect_reg (regcache, PC_REGNUM, gregs, offsets->pc_offset);
131*f3d8f838Skettenis   if (regnum == -1 || regnum == tdep->ppc_ps_regnum)
132*f3d8f838Skettenis     ppc64_collect_reg (regcache, tdep->ppc_ps_regnum,
133*f3d8f838Skettenis 		       gregs, offsets->ps_offset);
134*f3d8f838Skettenis   if (regnum == -1 || regnum == tdep->ppc_cr_regnum)
135*f3d8f838Skettenis     ppc64_collect_reg (regcache, tdep->ppc_cr_regnum,
136*f3d8f838Skettenis 		       gregs, offsets->cr_offset);
137*f3d8f838Skettenis   if (regnum == -1 || regnum == tdep->ppc_lr_regnum)
138*f3d8f838Skettenis     ppc64_collect_reg (regcache, tdep->ppc_lr_regnum,
139*f3d8f838Skettenis 		       gregs, offsets->lr_offset);
140*f3d8f838Skettenis   if (regnum == -1 || regnum == tdep->ppc_ctr_regnum)
141*f3d8f838Skettenis     ppc64_collect_reg (regcache, tdep->ppc_ctr_regnum,
142*f3d8f838Skettenis 		       gregs, offsets->ctr_offset);
143*f3d8f838Skettenis   if (regnum == -1 || regnum == tdep->ppc_xer_regnum)
144*f3d8f838Skettenis     ppc64_collect_reg (regcache, tdep->ppc_xer_regnum,
145*f3d8f838Skettenis 		       gregs, offsets->xer_offset);
146*f3d8f838Skettenis }
147*f3d8f838Skettenis 
148*f3d8f838Skettenis /* Core file support.  */
149*f3d8f838Skettenis 
150*f3d8f838Skettenis /* Supply register REGNUM in the general-purpose register set REGSET
151*f3d8f838Skettenis    from the buffer specified by GREGS and LEN to register cache
152*f3d8f838Skettenis    REGCACHE.  If REGNUM is -1, do this for all registers in REGSET.  */
153*f3d8f838Skettenis 
154*f3d8f838Skettenis void
ppc64obsd_supply_gregset(const struct regset * regset,struct regcache * regcache,int regnum,const void * gregs,size_t len)155*f3d8f838Skettenis ppc64obsd_supply_gregset (const struct regset *regset,
156*f3d8f838Skettenis 			  struct regcache *regcache, int regnum,
157*f3d8f838Skettenis 			  const void *gregs, size_t len)
158*f3d8f838Skettenis {
159*f3d8f838Skettenis   ppc64_supply_gregset (regset, regcache, regnum, gregs, len);
160*f3d8f838Skettenis }
161*f3d8f838Skettenis 
162*f3d8f838Skettenis /* Collect register REGNUM in the general-purpose register set
163*f3d8f838Skettenis    REGSET. from register cache REGCACHE into the buffer specified by
164*f3d8f838Skettenis    GREGS and LEN.  If REGNUM is -1, do this for all registers in
165*f3d8f838Skettenis    REGSET.  */
166*f3d8f838Skettenis 
167*f3d8f838Skettenis void
ppc64obsd_collect_gregset(const struct regset * regset,const struct regcache * regcache,int regnum,void * gregs,size_t len)168*f3d8f838Skettenis ppc64obsd_collect_gregset (const struct regset *regset,
169*f3d8f838Skettenis 			   const struct regcache *regcache, int regnum,
170*f3d8f838Skettenis 			   void *gregs, size_t len)
171*f3d8f838Skettenis {
172*f3d8f838Skettenis   ppc64_collect_gregset (regset, regcache, regnum, gregs, len);
173*f3d8f838Skettenis }
174*f3d8f838Skettenis 
175*f3d8f838Skettenis /* OpenBSD/powerpc register set.  */
176*f3d8f838Skettenis 
177*f3d8f838Skettenis struct regset ppc64obsd_gregset =
178*f3d8f838Skettenis {
179*f3d8f838Skettenis   &ppc64obsd_reg_offsets,
180*f3d8f838Skettenis   ppc64obsd_supply_gregset
181*f3d8f838Skettenis };
182*f3d8f838Skettenis 
183*f3d8f838Skettenis struct regset ppc64obsd_fpregset =
184*f3d8f838Skettenis {
185*f3d8f838Skettenis   &ppc64obsd_fpreg_offsets,
186*f3d8f838Skettenis   ppc_supply_fpregset
187*f3d8f838Skettenis };
188*f3d8f838Skettenis 
189*f3d8f838Skettenis /* Return the appropriate register set for the core section identified
190*f3d8f838Skettenis    by SECT_NAME and SECT_SIZE.  */
191*f3d8f838Skettenis 
192*f3d8f838Skettenis static const struct regset *
ppc64obsd_regset_from_core_section(struct gdbarch * gdbarch,const char * sect_name,size_t sect_size)193*f3d8f838Skettenis ppc64obsd_regset_from_core_section (struct gdbarch *gdbarch,
194*f3d8f838Skettenis 				  const char *sect_name, size_t sect_size)
195*f3d8f838Skettenis {
196*f3d8f838Skettenis   if (strcmp (sect_name, ".reg") == 0 && sect_size >= 304)
197*f3d8f838Skettenis     return &ppc64obsd_gregset;
198*f3d8f838Skettenis 
199*f3d8f838Skettenis   if (strcmp (sect_name, ".reg2") == 0 && sect_size >= 1048)
200*f3d8f838Skettenis     return &ppc64obsd_fpregset;
201*f3d8f838Skettenis 
202*f3d8f838Skettenis   return NULL;
203*f3d8f838Skettenis }
204*f3d8f838Skettenis 
205*f3d8f838Skettenis 
206*f3d8f838Skettenis /* Signal trampolines.  */
207*f3d8f838Skettenis 
208*f3d8f838Skettenis /* Since OpenBSD 3.2, the sigtramp routine is mapped at a random page
209*f3d8f838Skettenis    in virtual memory.  The randomness makes it somewhat tricky to
210*f3d8f838Skettenis    detect it, but fortunately we can rely on the fact that the start
211*f3d8f838Skettenis    of the sigtramp routine is page-aligned.  We recognize the
212*f3d8f838Skettenis    trampoline by looking for the code that invokes the sigreturn
213*f3d8f838Skettenis    system call.  The offset where we can find that code varies from
214*f3d8f838Skettenis    release to release.
215*f3d8f838Skettenis 
216*f3d8f838Skettenis    By the way, the mapping mentioned above is read-only, so you cannot
217*f3d8f838Skettenis    place a breakpoint in the signal trampoline.  */
218*f3d8f838Skettenis 
219*f3d8f838Skettenis /* Default page size.  */
220*f3d8f838Skettenis static const int ppc64obsd_page_size = 4096;
221*f3d8f838Skettenis 
222*f3d8f838Skettenis /* Offset for sigreturn(2).  */
223*f3d8f838Skettenis static const int ppc64obsd_sigreturn_offset[] = {
224*f3d8f838Skettenis   0x98,				/* OpenBSD 3.8 */
225*f3d8f838Skettenis   0x0c,				/* OpenBSD 3.2 */
226*f3d8f838Skettenis   -1
227*f3d8f838Skettenis };
228*f3d8f838Skettenis 
229*f3d8f838Skettenis static int
ppc64obsd_sigtramp_p(struct frame_info * next_frame)230*f3d8f838Skettenis ppc64obsd_sigtramp_p (struct frame_info *next_frame)
231*f3d8f838Skettenis {
232*f3d8f838Skettenis   CORE_ADDR pc = frame_pc_unwind (next_frame);
233*f3d8f838Skettenis   CORE_ADDR start_pc = (pc & ~(ppc64obsd_page_size - 1));
234*f3d8f838Skettenis   const int *offset;
235*f3d8f838Skettenis   char *name;
236*f3d8f838Skettenis 
237*f3d8f838Skettenis   find_pc_partial_function (pc, &name, NULL, NULL);
238*f3d8f838Skettenis   if (name)
239*f3d8f838Skettenis     return 0;
240*f3d8f838Skettenis 
241*f3d8f838Skettenis   for (offset = ppc64obsd_sigreturn_offset; *offset != -1; offset++)
242*f3d8f838Skettenis     {
243*f3d8f838Skettenis       char buf[2 * PPC_INSN_SIZE];
244*f3d8f838Skettenis       unsigned long insn;
245*f3d8f838Skettenis 
246*f3d8f838Skettenis       if (!safe_frame_unwind_memory (next_frame, start_pc + *offset,
247*f3d8f838Skettenis 				     buf, sizeof buf))
248*f3d8f838Skettenis 	continue;
249*f3d8f838Skettenis 
250*f3d8f838Skettenis       /* Check for "li r0,SYS_sigreturn".  */
251*f3d8f838Skettenis       insn = extract_unsigned_integer (buf, PPC_INSN_SIZE);
252*f3d8f838Skettenis       if (insn != 0x38000067)
253*f3d8f838Skettenis 	continue;
254*f3d8f838Skettenis 
255*f3d8f838Skettenis       /* Check for "sc".  */
256*f3d8f838Skettenis       insn = extract_unsigned_integer (buf + PPC_INSN_SIZE, PPC_INSN_SIZE);
257*f3d8f838Skettenis       if (insn != 0x44000002)
258*f3d8f838Skettenis 	continue;
259*f3d8f838Skettenis 
260*f3d8f838Skettenis       return 1;
261*f3d8f838Skettenis     }
262*f3d8f838Skettenis 
263*f3d8f838Skettenis   return 0;
264*f3d8f838Skettenis }
265*f3d8f838Skettenis 
266*f3d8f838Skettenis static struct trad_frame_cache *
ppc64obsd_sigtramp_frame_cache(struct frame_info * next_frame,void ** this_cache)267*f3d8f838Skettenis ppc64obsd_sigtramp_frame_cache (struct frame_info *next_frame, void **this_cache)
268*f3d8f838Skettenis {
269*f3d8f838Skettenis   struct gdbarch *gdbarch = get_frame_arch (next_frame);
270*f3d8f838Skettenis   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
271*f3d8f838Skettenis   struct trad_frame_cache *cache;
272*f3d8f838Skettenis   CORE_ADDR addr, base, func;
273*f3d8f838Skettenis   char buf[PPC_INSN_SIZE];
274*f3d8f838Skettenis   unsigned long insn, sigcontext_offset;
275*f3d8f838Skettenis   int i;
276*f3d8f838Skettenis 
277*f3d8f838Skettenis   if (*this_cache)
278*f3d8f838Skettenis     return *this_cache;
279*f3d8f838Skettenis 
280*f3d8f838Skettenis   cache = trad_frame_cache_zalloc (next_frame);
281*f3d8f838Skettenis   *this_cache = cache;
282*f3d8f838Skettenis 
283*f3d8f838Skettenis   func = frame_pc_unwind (next_frame);
284*f3d8f838Skettenis   func &= ~(ppc64obsd_page_size - 1);
285*f3d8f838Skettenis   if (!safe_frame_unwind_memory (next_frame, func, buf, sizeof buf))
286*f3d8f838Skettenis     return cache;
287*f3d8f838Skettenis 
288*f3d8f838Skettenis   /* Calculate the offset where we can find `struct sigcontext'.  We
289*f3d8f838Skettenis      base our calculation on the amount of stack space reserved by the
290*f3d8f838Skettenis      first instruction of the signal trampoline.  */
291*f3d8f838Skettenis   insn = extract_unsigned_integer (buf, PPC_INSN_SIZE);
292*f3d8f838Skettenis   sigcontext_offset = (0x10000 - (insn & 0x0000ffff)) + 8;
293*f3d8f838Skettenis 
294*f3d8f838Skettenis   base = frame_unwind_register_unsigned (next_frame, SP_REGNUM);
295*f3d8f838Skettenis   addr = base + sigcontext_offset + 2 * tdep->wordsize;
296*f3d8f838Skettenis   for (i = 0; i < ppc_num_gprs; i++, addr += tdep->wordsize)
297*f3d8f838Skettenis     {
298*f3d8f838Skettenis       int regnum = i + tdep->ppc_gp0_regnum;
299*f3d8f838Skettenis       trad_frame_set_reg_addr (cache, regnum, addr);
300*f3d8f838Skettenis     }
301*f3d8f838Skettenis   trad_frame_set_reg_addr (cache, tdep->ppc_lr_regnum, addr);
302*f3d8f838Skettenis   addr += tdep->wordsize;
303*f3d8f838Skettenis   trad_frame_set_reg_addr (cache, tdep->ppc_cr_regnum, addr);
304*f3d8f838Skettenis   addr += tdep->wordsize;
305*f3d8f838Skettenis   trad_frame_set_reg_addr (cache, tdep->ppc_xer_regnum, addr);
306*f3d8f838Skettenis   addr += tdep->wordsize;
307*f3d8f838Skettenis   trad_frame_set_reg_addr (cache, tdep->ppc_ctr_regnum, addr);
308*f3d8f838Skettenis   addr += tdep->wordsize;
309*f3d8f838Skettenis   trad_frame_set_reg_addr (cache, PC_REGNUM, addr); /* SRR0? */
310*f3d8f838Skettenis   addr += tdep->wordsize;
311*f3d8f838Skettenis 
312*f3d8f838Skettenis   /* Construct the frame ID using the function start.  */
313*f3d8f838Skettenis   trad_frame_set_id (cache, frame_id_build (base, func));
314*f3d8f838Skettenis 
315*f3d8f838Skettenis   return cache;
316*f3d8f838Skettenis }
317*f3d8f838Skettenis 
318*f3d8f838Skettenis static void
ppc64obsd_sigtramp_frame_this_id(struct frame_info * next_frame,void ** this_cache,struct frame_id * this_id)319*f3d8f838Skettenis ppc64obsd_sigtramp_frame_this_id (struct frame_info *next_frame,
320*f3d8f838Skettenis 				void **this_cache, struct frame_id *this_id)
321*f3d8f838Skettenis {
322*f3d8f838Skettenis   struct trad_frame_cache *cache =
323*f3d8f838Skettenis     ppc64obsd_sigtramp_frame_cache (next_frame, this_cache);
324*f3d8f838Skettenis 
325*f3d8f838Skettenis   trad_frame_get_id (cache, this_id);
326*f3d8f838Skettenis }
327*f3d8f838Skettenis 
328*f3d8f838Skettenis static void
ppc64obsd_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)329*f3d8f838Skettenis ppc64obsd_sigtramp_frame_prev_register (struct frame_info *next_frame,
330*f3d8f838Skettenis 				      void **this_cache, int regnum,
331*f3d8f838Skettenis 				      int *optimizedp, enum lval_type *lvalp,
332*f3d8f838Skettenis 				      CORE_ADDR *addrp, int *realnump,
333*f3d8f838Skettenis 				      char *valuep)
334*f3d8f838Skettenis {
335*f3d8f838Skettenis   struct trad_frame_cache *cache =
336*f3d8f838Skettenis     ppc64obsd_sigtramp_frame_cache (next_frame, this_cache);
337*f3d8f838Skettenis 
338*f3d8f838Skettenis   trad_frame_get_register (cache, next_frame, regnum,
339*f3d8f838Skettenis 			   optimizedp, lvalp, addrp, realnump, valuep);
340*f3d8f838Skettenis }
341*f3d8f838Skettenis 
342*f3d8f838Skettenis static const struct frame_unwind ppc64obsd_sigtramp_frame_unwind = {
343*f3d8f838Skettenis   SIGTRAMP_FRAME,
344*f3d8f838Skettenis   ppc64obsd_sigtramp_frame_this_id,
345*f3d8f838Skettenis   ppc64obsd_sigtramp_frame_prev_register
346*f3d8f838Skettenis };
347*f3d8f838Skettenis 
348*f3d8f838Skettenis static const struct frame_unwind *
ppc64obsd_sigtramp_frame_sniffer(struct frame_info * next_frame)349*f3d8f838Skettenis ppc64obsd_sigtramp_frame_sniffer (struct frame_info *next_frame)
350*f3d8f838Skettenis {
351*f3d8f838Skettenis   if (ppc64obsd_sigtramp_p (next_frame))
352*f3d8f838Skettenis     return &ppc64obsd_sigtramp_frame_unwind;
353*f3d8f838Skettenis 
354*f3d8f838Skettenis   return NULL;
355*f3d8f838Skettenis }
356*f3d8f838Skettenis 
357*f3d8f838Skettenis 
358*f3d8f838Skettenis static void
ppc64obsd_init_abi(struct gdbarch_info info,struct gdbarch * gdbarch)359*f3d8f838Skettenis ppc64obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
360*f3d8f838Skettenis {
361*f3d8f838Skettenis   /* OpenBSD doesn't support the 128-bit `long double' from the psABI.  */
362*f3d8f838Skettenis   set_gdbarch_long_double_bit (gdbarch, 64);
363*f3d8f838Skettenis   set_gdbarch_long_double_format (gdbarch, &floatformat_ieee_double_big);
364*f3d8f838Skettenis 
365*f3d8f838Skettenis   /* OpenBSD currently uses a broken GCC.  */
366*f3d8f838Skettenis   set_gdbarch_return_value (gdbarch, ppc_sysv_abi_broken_return_value);
367*f3d8f838Skettenis 
368*f3d8f838Skettenis   /* OpenBSD uses SVR4-style shared libraries.  */
369*f3d8f838Skettenis   set_solib_svr4_fetch_link_map_offsets
370*f3d8f838Skettenis     (gdbarch, svr4_lp64_fetch_link_map_offsets);
371*f3d8f838Skettenis 
372*f3d8f838Skettenis   set_gdbarch_regset_from_core_section
373*f3d8f838Skettenis     (gdbarch, ppc64obsd_regset_from_core_section);
374*f3d8f838Skettenis 
375*f3d8f838Skettenis   frame_unwind_append_sniffer (gdbarch, ppc64obsd_sigtramp_frame_sniffer);
376*f3d8f838Skettenis }
377*f3d8f838Skettenis 
378*f3d8f838Skettenis 
379*f3d8f838Skettenis /* OpenBSD uses uses the traditional NetBSD core file format, even for
380*f3d8f838Skettenis    ports that use ELF.  */
381*f3d8f838Skettenis #define GDB_OSABI_NETBSD_CORE GDB_OSABI_OPENBSD_ELF
382*f3d8f838Skettenis 
383*f3d8f838Skettenis static enum gdb_osabi
ppc64obsd_core_osabi_sniffer(bfd * abfd)384*f3d8f838Skettenis ppc64obsd_core_osabi_sniffer (bfd *abfd)
385*f3d8f838Skettenis {
386*f3d8f838Skettenis   if (strcmp (bfd_get_target (abfd), "netbsd-core") == 0)
387*f3d8f838Skettenis     return GDB_OSABI_NETBSD_CORE;
388*f3d8f838Skettenis 
389*f3d8f838Skettenis   return GDB_OSABI_UNKNOWN;
390*f3d8f838Skettenis }
391*f3d8f838Skettenis 
392*f3d8f838Skettenis 
393*f3d8f838Skettenis /* Provide a prototype to silence -Wmissing-prototypes.  */
394*f3d8f838Skettenis void _initialize_ppc64obsd_tdep (void);
395*f3d8f838Skettenis 
396*f3d8f838Skettenis void
_initialize_ppc64obsd_tdep(void)397*f3d8f838Skettenis _initialize_ppc64obsd_tdep (void)
398*f3d8f838Skettenis {
399*f3d8f838Skettenis   /* BFD doesn't set a flavour for NetBSD style a.out core files.  */
400*f3d8f838Skettenis   gdbarch_register_osabi_sniffer (bfd_arch_powerpc, bfd_target_unknown_flavour,
401*f3d8f838Skettenis                                   ppc64obsd_core_osabi_sniffer);
402*f3d8f838Skettenis 
403*f3d8f838Skettenis #if 0
404*f3d8f838Skettenis   gdbarch_register_osabi (bfd_arch_rs6000, 0, GDB_OSABI_OPENBSD_ELF,
405*f3d8f838Skettenis 			  ppc64obsd_init_abi);
406*f3d8f838Skettenis #endif
407*f3d8f838Skettenis   gdbarch_register_osabi (bfd_arch_powerpc, bfd_mach_ppc64,
408*f3d8f838Skettenis 			  GDB_OSABI_OPENBSD_ELF, ppc64obsd_init_abi);
409*f3d8f838Skettenis 
410*f3d8f838Skettenis   /* Avoid initializing the register offsets again if they were
411*f3d8f838Skettenis      already initailized by ppc64obsd-nat.c.  */
412*f3d8f838Skettenis   if (ppc64obsd_reg_offsets.pc_offset == 0)
413*f3d8f838Skettenis     {
414*f3d8f838Skettenis       /* General-purpose registers.  */
415*f3d8f838Skettenis       ppc64obsd_reg_offsets.r0_offset = 0;
416*f3d8f838Skettenis       ppc64obsd_reg_offsets.pc_offset = 288;
417*f3d8f838Skettenis       ppc64obsd_reg_offsets.ps_offset = 296;
418*f3d8f838Skettenis       ppc64obsd_reg_offsets.cr_offset = 264;
419*f3d8f838Skettenis       ppc64obsd_reg_offsets.lr_offset = 256;
420*f3d8f838Skettenis       ppc64obsd_reg_offsets.ctr_offset = 280;
421*f3d8f838Skettenis       ppc64obsd_reg_offsets.xer_offset = 272;
422*f3d8f838Skettenis       ppc64obsd_reg_offsets.mq_offset = -1;
423*f3d8f838Skettenis 
424*f3d8f838Skettenis       /* Floating-point registers.  */
425*f3d8f838Skettenis       ppc64obsd_reg_offsets.f0_offset = -1;
426*f3d8f838Skettenis       ppc64obsd_reg_offsets.fpscr_offset = -1;
427*f3d8f838Skettenis 
428*f3d8f838Skettenis       /* AltiVec registers.  */
429*f3d8f838Skettenis       ppc64obsd_reg_offsets.vr0_offset = -1;
430*f3d8f838Skettenis       ppc64obsd_reg_offsets.vscr_offset = -1;
431*f3d8f838Skettenis       ppc64obsd_reg_offsets.vrsave_offset = -1;
432*f3d8f838Skettenis     }
433*f3d8f838Skettenis 
434*f3d8f838Skettenis   if (ppc64obsd_fpreg_offsets.fpscr_offset == 0)
435*f3d8f838Skettenis     {
436*f3d8f838Skettenis       /* Floating-point registers.  */
437*f3d8f838Skettenis       ppc64obsd_reg_offsets.f0_offset = -1;
438*f3d8f838Skettenis       ppc64obsd_reg_offsets.fpscr_offset = -1;
439*f3d8f838Skettenis     }
440*f3d8f838Skettenis }
441