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