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