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