* gdbtypes.c (check_typedef): Document that this function can
[platform/upstream/binutils.git] / gdb / sparc64obsd-tdep.c
1 /* Target-dependent code for OpenBSD/sparc64.
2
3    Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
4    Free Software Foundation, Inc.
5
6    This file is part of GDB.
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
20
21 #include "defs.h"
22 #include "frame.h"
23 #include "frame-unwind.h"
24 #include "gdbcore.h"
25 #include "osabi.h"
26 #include "regcache.h"
27 #include "regset.h"
28 #include "symtab.h"
29 #include "objfiles.h"
30 #include "trad-frame.h"
31
32 #include "gdb_assert.h"
33
34 #include "obsd-tdep.h"
35 #include "sparc64-tdep.h"
36 #include "solib-svr4.h"
37 #include "bsd-uthread.h"
38
39 /* OpenBSD uses the traditional NetBSD core file format, even for
40    ports that use ELF.  The core files don't use multiple register
41    sets.  Instead, the general-purpose and floating-point registers
42    are lumped together in a single section.  Unlike on NetBSD, OpenBSD
43    uses a different layout for its general-purpose registers than the
44    layout used for ptrace(2).  */
45
46 /* From <machine/reg.h>.  */
47 const struct sparc_gregset sparc64obsd_core_gregset =
48 {
49   0 * 8,                        /* "tstate" */
50   1 * 8,                        /* %pc */
51   2 * 8,                        /* %npc */
52   3 * 8,                        /* %y */
53   -1,                           /* %fprs */
54   -1,
55   7 * 8,                        /* %g1 */
56   22 * 8,                       /* %l0 */
57   4                             /* sizeof (%y) */
58 };
59
60 static void
61 sparc64obsd_supply_gregset (const struct regset *regset,
62                             struct regcache *regcache,
63                             int regnum, const void *gregs, size_t len)
64 {
65   const char *regs = gregs;
66
67   sparc64_supply_gregset (&sparc64obsd_core_gregset, regcache, regnum, regs);
68   sparc64_supply_fpregset (regcache, regnum, regs + 288);
69 }
70 \f
71
72 /* Signal trampolines.  */
73
74 /* Since OpenBSD 3.2, the sigtramp routine is mapped at a random page
75    in virtual memory.  The randomness makes it somewhat tricky to
76    detect it, but fortunately we can rely on the fact that the start
77    of the sigtramp routine is page-aligned.  We recognize the
78    trampoline by looking for the code that invokes the sigreturn
79    system call.  The offset where we can find that code varies from
80    release to release.
81
82    By the way, the mapping mentioned above is read-only, so you cannot
83    place a breakpoint in the signal trampoline.  */
84
85 /* Default page size.  */
86 static const int sparc64obsd_page_size = 8192;
87
88 /* Offset for sigreturn(2).  */
89 static const int sparc64obsd_sigreturn_offset[] = {
90   0xf0,                         /* OpenBSD 3.8 */
91   0xec,                         /* OpenBSD 3.6 */
92   0xe8,                         /* OpenBSD 3.2 */
93   -1
94 };
95
96 static int
97 sparc64obsd_pc_in_sigtramp (CORE_ADDR pc, char *name)
98 {
99   CORE_ADDR start_pc = (pc & ~(sparc64obsd_page_size - 1));
100   unsigned long insn;
101   const int *offset;
102
103   if (name)
104     return 0;
105
106   for (offset = sparc64obsd_sigreturn_offset; *offset != -1; offset++)
107     {
108       /* Check for "restore %g0, SYS_sigreturn, %g1".  */
109       insn = sparc_fetch_instruction (start_pc + *offset);
110       if (insn != 0x83e82067)
111         continue;
112
113       /* Check for "t ST_SYSCALL".  */
114       insn = sparc_fetch_instruction (start_pc + *offset + 8);
115       if (insn != 0x91d02000)
116         continue;
117
118       return 1;
119     }
120
121   return 0;
122 }
123
124 static struct sparc_frame_cache *
125 sparc64obsd_frame_cache (struct frame_info *this_frame, void **this_cache)
126 {
127   struct sparc_frame_cache *cache;
128   CORE_ADDR addr;
129
130   if (*this_cache)
131     return *this_cache;
132
133   cache = sparc_frame_cache (this_frame, this_cache);
134   gdb_assert (cache == *this_cache);
135
136   /* If we couldn't find the frame's function, we're probably dealing
137      with an on-stack signal trampoline.  */
138   if (cache->pc == 0)
139     {
140       cache->pc = get_frame_pc (this_frame);
141       cache->pc &= ~(sparc64obsd_page_size - 1);
142
143       /* Since we couldn't find the frame's function, the cache was
144          initialized under the assumption that we're frameless.  */
145       sparc_record_save_insn (cache);
146       addr = get_frame_register_unsigned (this_frame, SPARC_FP_REGNUM);
147       if (addr & 1)
148         addr += BIAS;
149       cache->base = addr;
150     }
151
152   /* We find the appropriate instance of `struct sigcontext' at a
153      fixed offset in the signal frame.  */
154   addr = cache->base + 128 + 16;
155   cache->saved_regs = sparc64nbsd_sigcontext_saved_regs (addr, this_frame);
156
157   return cache;
158 }
159
160 static void
161 sparc64obsd_frame_this_id (struct frame_info *this_frame, void **this_cache,
162                            struct frame_id *this_id)
163 {
164   struct sparc_frame_cache *cache =
165     sparc64obsd_frame_cache (this_frame, this_cache);
166
167   (*this_id) = frame_id_build (cache->base, cache->pc);
168 }
169
170 static struct value *
171 sparc64obsd_frame_prev_register (struct frame_info *this_frame,
172                                  void **this_cache, int regnum)
173 {
174   struct sparc_frame_cache *cache =
175     sparc64obsd_frame_cache (this_frame, this_cache);
176
177   return trad_frame_get_prev_register (this_frame, cache->saved_regs, regnum);
178 }
179
180 static int
181 sparc64obsd_sigtramp_frame_sniffer (const struct frame_unwind *self,
182                                     struct frame_info *this_frame,
183                                     void **this_cache)
184 {
185   CORE_ADDR pc = get_frame_pc (this_frame);
186   char *name;
187
188   find_pc_partial_function (pc, &name, NULL, NULL);
189   if (sparc64obsd_pc_in_sigtramp (pc, name))
190     return 1;
191
192   return 0;
193 }
194
195 static const struct frame_unwind sparc64obsd_frame_unwind =
196 {
197   SIGTRAMP_FRAME,
198   default_frame_unwind_stop_reason,
199   sparc64obsd_frame_this_id,
200   sparc64obsd_frame_prev_register,
201   NULL,
202   sparc64obsd_sigtramp_frame_sniffer
203 };
204 \f
205 /* Kernel debugging support.  */
206
207 static struct sparc_frame_cache *
208 sparc64obsd_trapframe_cache (struct frame_info *this_frame, void **this_cache)
209 {
210   struct sparc_frame_cache *cache;
211   CORE_ADDR sp, trapframe_addr;
212   int regnum;
213
214   if (*this_cache)
215     return *this_cache;
216
217   cache = sparc_frame_cache (this_frame, this_cache);
218   gdb_assert (cache == *this_cache);
219
220   sp = get_frame_register_unsigned (this_frame, SPARC_SP_REGNUM);
221   trapframe_addr = sp + BIAS + 176;
222
223   cache->saved_regs = trad_frame_alloc_saved_regs (this_frame);
224
225   cache->saved_regs[SPARC64_STATE_REGNUM].addr = trapframe_addr;
226   cache->saved_regs[SPARC64_PC_REGNUM].addr = trapframe_addr + 8;
227   cache->saved_regs[SPARC64_NPC_REGNUM].addr = trapframe_addr + 16;
228
229   for (regnum = SPARC_G0_REGNUM; regnum <= SPARC_I7_REGNUM; regnum++)
230     cache->saved_regs[regnum].addr =
231       trapframe_addr + 48 + (regnum - SPARC_G0_REGNUM) * 8;
232
233   return cache;
234 }
235
236 static void
237 sparc64obsd_trapframe_this_id (struct frame_info *this_frame,
238                                void **this_cache, struct frame_id *this_id)
239 {
240   struct sparc_frame_cache *cache =
241     sparc64obsd_trapframe_cache (this_frame, this_cache);
242
243   (*this_id) = frame_id_build (cache->base, cache->pc);
244 }
245
246 static struct value *
247 sparc64obsd_trapframe_prev_register (struct frame_info *this_frame,
248                                      void **this_cache, int regnum)
249 {
250   struct sparc_frame_cache *cache =
251     sparc64obsd_trapframe_cache (this_frame, this_cache);
252
253   return trad_frame_get_prev_register (this_frame, cache->saved_regs, regnum);
254 }
255
256 static int
257 sparc64obsd_trapframe_sniffer (const struct frame_unwind *self,
258                                struct frame_info *this_frame,
259                                void **this_cache)
260 {
261   CORE_ADDR pc;
262   ULONGEST pstate;
263   char *name;
264
265   /* Check whether we are in privileged mode, and bail out if we're not.  */
266   pstate = get_frame_register_unsigned (this_frame, SPARC64_PSTATE_REGNUM);
267   if ((pstate & SPARC64_PSTATE_PRIV) == 0)
268     return 0;
269
270   pc = get_frame_address_in_block (this_frame);
271   find_pc_partial_function (pc, &name, NULL, NULL);
272   if (name && strcmp (name, "Lslowtrap_reenter") == 0)
273     return 1;
274
275   return 0;
276 }
277
278 static const struct frame_unwind sparc64obsd_trapframe_unwind =
279 {
280   NORMAL_FRAME,
281   default_frame_unwind_stop_reason,
282   sparc64obsd_trapframe_this_id,
283   sparc64obsd_trapframe_prev_register,
284   NULL,
285   sparc64obsd_trapframe_sniffer
286 };
287 \f
288
289 /* Threads support.  */
290
291 /* Offset wthin the thread structure where we can find %fp and %i7.  */
292 #define SPARC64OBSD_UTHREAD_FP_OFFSET   232
293 #define SPARC64OBSD_UTHREAD_PC_OFFSET   240
294
295 static void
296 sparc64obsd_supply_uthread (struct regcache *regcache,
297                             int regnum, CORE_ADDR addr)
298 {
299   struct gdbarch *gdbarch = get_regcache_arch (regcache);
300   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
301   CORE_ADDR fp, fp_addr = addr + SPARC64OBSD_UTHREAD_FP_OFFSET;
302   gdb_byte buf[8];
303
304   gdb_assert (regnum >= -1);
305
306   fp = read_memory_unsigned_integer (fp_addr, 8, byte_order);
307   if (regnum == SPARC_SP_REGNUM || regnum == -1)
308     {
309       store_unsigned_integer (buf, 8, byte_order, fp);
310       regcache_raw_supply (regcache, SPARC_SP_REGNUM, buf);
311
312       if (regnum == SPARC_SP_REGNUM)
313         return;
314     }
315
316   if (regnum == SPARC64_PC_REGNUM || regnum == SPARC64_NPC_REGNUM
317       || regnum == -1)
318     {
319       CORE_ADDR i7, i7_addr = addr + SPARC64OBSD_UTHREAD_PC_OFFSET;
320
321       i7 = read_memory_unsigned_integer (i7_addr, 8, byte_order);
322       if (regnum == SPARC64_PC_REGNUM || regnum == -1)
323         {
324           store_unsigned_integer (buf, 8, byte_order, i7 + 8);
325           regcache_raw_supply (regcache, SPARC64_PC_REGNUM, buf);
326         }
327       if (regnum == SPARC64_NPC_REGNUM || regnum == -1)
328         {
329           store_unsigned_integer (buf, 8, byte_order, i7 + 12);
330           regcache_raw_supply (regcache, SPARC64_NPC_REGNUM, buf);
331         }
332
333       if (regnum == SPARC64_PC_REGNUM || regnum == SPARC64_NPC_REGNUM)
334         return;
335     }
336
337   sparc_supply_rwindow (regcache, fp, regnum);
338 }
339
340 static void
341 sparc64obsd_collect_uthread(const struct regcache *regcache,
342                             int regnum, CORE_ADDR addr)
343 {
344   struct gdbarch *gdbarch = get_regcache_arch (regcache);
345   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
346   CORE_ADDR sp;
347   gdb_byte buf[8];
348
349   gdb_assert (regnum >= -1);
350
351   if (regnum == SPARC_SP_REGNUM || regnum == -1)
352     {
353       CORE_ADDR fp_addr = addr + SPARC64OBSD_UTHREAD_FP_OFFSET;
354
355       regcache_raw_collect (regcache, SPARC_SP_REGNUM, buf);
356       write_memory (fp_addr,buf, 8);
357     }
358
359   if (regnum == SPARC64_PC_REGNUM || regnum == -1)
360     {
361       CORE_ADDR i7, i7_addr = addr + SPARC64OBSD_UTHREAD_PC_OFFSET;
362
363       regcache_raw_collect (regcache, SPARC64_PC_REGNUM, buf);
364       i7 = extract_unsigned_integer (buf, 8, byte_order) - 8;
365       write_memory_unsigned_integer (i7_addr, 8, byte_order, i7);
366
367       if (regnum == SPARC64_PC_REGNUM)
368         return;
369     }
370
371   regcache_raw_collect (regcache, SPARC_SP_REGNUM, buf);
372   sp = extract_unsigned_integer (buf, 8, byte_order);
373   sparc_collect_rwindow (regcache, sp, regnum);
374 }
375 \f
376
377 static void
378 sparc64obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
379 {
380   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
381
382   tdep->gregset = regset_alloc (gdbarch, sparc64obsd_supply_gregset, NULL);
383   tdep->sizeof_gregset = 832;
384
385   /* Make sure we can single-step "new" syscalls.  */
386   tdep->step_trap = sparcnbsd_step_trap;
387
388   frame_unwind_append_unwinder (gdbarch, &sparc64obsd_frame_unwind);
389   frame_unwind_append_unwinder (gdbarch, &sparc64obsd_trapframe_unwind);
390
391   sparc64_init_abi (info, gdbarch);
392
393   /* OpenBSD/sparc64 has SVR4-style shared libraries.  */
394   set_solib_svr4_fetch_link_map_offsets
395     (gdbarch, svr4_lp64_fetch_link_map_offsets);
396   set_gdbarch_skip_solib_resolver (gdbarch, obsd_skip_solib_resolver);
397
398   /* OpenBSD provides a user-level threads implementation.  */
399   bsd_uthread_set_supply_uthread (gdbarch, sparc64obsd_supply_uthread);
400   bsd_uthread_set_collect_uthread (gdbarch, sparc64obsd_collect_uthread);
401 }
402 \f
403
404 /* Provide a prototype to silence -Wmissing-prototypes.  */
405 void _initialize_sparc64obsd_tdep (void);
406
407 void
408 _initialize_sparc64obsd_tdep (void)
409 {
410   gdbarch_register_osabi (bfd_arch_sparc, bfd_mach_sparc_v9,
411                           GDB_OSABI_OPENBSD_ELF, sparc64obsd_init_abi);
412 }