1 /* Target-dependent code for OpenBSD/sparc64.
3 Copyright 2004, 2005 Free Software Foundation, Inc.
5 This file is part of GDB.
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.
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.
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., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
24 #include "frame-unwind.h"
29 #include "solib-svr4.h"
30 #include "trad-frame.h"
32 #include "gdb_assert.h"
34 #include "sparc64-tdep.h"
36 /* OpenBSD uses the traditional NetBSD core file format, even for
37 ports that use ELF. The core files don't use multiple register
38 sets. Instead, the general-purpose and floating-point registers
39 are lumped together in a single section. Unlike on NetBSD, OpenBSD
40 uses a different layout for its general-purpose registers than the
41 layout used for ptrace(2). */
43 /* From <machine/reg.h>. */
44 const struct sparc_gregset sparc64obsd_core_gregset
=
58 sparc64obsd_supply_gregset (const struct regset
*regset
,
59 struct regcache
*regcache
,
60 int regnum
, const void *gregs
, size_t len
)
62 const char *regs
= gregs
;
64 sparc64_supply_gregset (&sparc64obsd_core_gregset
, regcache
, regnum
, regs
);
65 sparc64_supply_fpregset (regcache
, regnum
, regs
+ 288);
69 /* Signal trampolines. */
71 /* Since OpenBSD 3.2, the sigtramp routine is mapped at a random page
72 in virtual memory. The randomness makes it somewhat tricky to
73 detect it, but fortunately we can rely on the fact that the start
74 of the sigtramp routine is page-aligned. We recognize the
75 trampoline by looking for the code that invokes the sigreturn
76 system call. The offset where we can find that code varies from
79 By the way, the mapping mentioned above is read-only, so you cannot
80 place a breakpoint in the signal trampoline. */
82 /* Default page size. */
83 static const int sparc64obsd_page_size
= 8192;
85 /* Offset for sigreturn(2). */
86 static const int sparc64obsd_sigreturn_offset
[] = {
87 0xf0, /* OpenBSD 3.8 */
88 0xec, /* OpenBSD 3.6 */
89 0xe8, /* OpenBSD 3.2 */
94 sparc64obsd_pc_in_sigtramp (CORE_ADDR pc
, char *name
)
96 CORE_ADDR start_pc
= (pc
& ~(sparc64obsd_page_size
- 1));
103 for (offset
= sparc64obsd_sigreturn_offset
; *offset
!= -1; offset
++)
105 /* Check for "restore %g0, SYS_sigreturn, %g1". */
106 insn
= sparc_fetch_instruction (start_pc
+ *offset
);
107 if (insn
!= 0x83e82067)
110 /* Check for "t ST_SYSCALL". */
111 insn
= sparc_fetch_instruction (start_pc
+ *offset
+ 8);
112 if (insn
!= 0x91d02000)
121 static struct sparc_frame_cache
*
122 sparc64obsd_frame_cache (struct frame_info
*next_frame
, void **this_cache
)
124 struct sparc_frame_cache
*cache
;
130 cache
= sparc_frame_cache (next_frame
, this_cache
);
131 gdb_assert (cache
== *this_cache
);
133 /* If we couldn't find the frame's function, we're probably dealing
134 with an on-stack signal trampoline. */
137 cache
->pc
= frame_pc_unwind (next_frame
);
138 cache
->pc
&= ~(sparc64obsd_page_size
- 1);
140 /* Since we couldn't find the frame's function, the cache was
141 initialized under the assumption that we're frameless. */
142 cache
->frameless_p
= 0;
143 addr
= frame_unwind_register_unsigned (next_frame
, SPARC_FP_REGNUM
);
149 /* We find the appropriate instance of `struct sigcontext' at a
150 fixed offset in the signal frame. */
151 addr
= cache
->base
+ 128 + 16;
152 cache
->saved_regs
= sparc64nbsd_sigcontext_saved_regs (addr
, next_frame
);
158 sparc64obsd_frame_this_id (struct frame_info
*next_frame
, void **this_cache
,
159 struct frame_id
*this_id
)
161 struct sparc_frame_cache
*cache
=
162 sparc64obsd_frame_cache (next_frame
, this_cache
);
164 (*this_id
) = frame_id_build (cache
->base
, cache
->pc
);
168 sparc64obsd_frame_prev_register (struct frame_info
*next_frame
,
170 int regnum
, int *optimizedp
,
171 enum lval_type
*lvalp
, CORE_ADDR
*addrp
,
172 int *realnump
, gdb_byte
*valuep
)
174 struct sparc_frame_cache
*cache
=
175 sparc64obsd_frame_cache (next_frame
, this_cache
);
177 trad_frame_get_prev_register (next_frame
, cache
->saved_regs
, regnum
,
178 optimizedp
, lvalp
, addrp
, realnump
, valuep
);
181 static const struct frame_unwind sparc64obsd_frame_unwind
=
184 sparc64obsd_frame_this_id
,
185 sparc64obsd_frame_prev_register
188 static const struct frame_unwind
*
189 sparc64obsd_sigtramp_frame_sniffer (struct frame_info
*next_frame
)
191 CORE_ADDR pc
= frame_pc_unwind (next_frame
);
194 find_pc_partial_function (pc
, &name
, NULL
, NULL
);
195 if (sparc64obsd_pc_in_sigtramp (pc
, name
))
196 return &sparc64obsd_frame_unwind
;
203 sparc64obsd_init_abi (struct gdbarch_info info
, struct gdbarch
*gdbarch
)
205 struct gdbarch_tdep
*tdep
= gdbarch_tdep (gdbarch
);
207 tdep
->gregset
= regset_alloc (gdbarch
, sparc64obsd_supply_gregset
, NULL
);
208 tdep
->sizeof_gregset
= 832;
210 frame_unwind_append_sniffer (gdbarch
, sparc64obsd_sigtramp_frame_sniffer
);
212 sparc64_init_abi (info
, gdbarch
);
214 /* OpenBSD/sparc64 has SVR4-style shared libraries. */
215 set_gdbarch_skip_trampoline_code (gdbarch
, find_solib_trampoline_target
);
216 set_solib_svr4_fetch_link_map_offsets
217 (gdbarch
, svr4_lp64_fetch_link_map_offsets
);
221 /* Provide a prototype to silence -Wmissing-prototypes. */
222 void _initialize_sparc64obsd_tdep (void);
225 _initialize_sparc64obsd_tdep (void)
227 gdbarch_register_osabi (bfd_arch_sparc
, bfd_mach_sparc_v9
,
228 GDB_OSABI_OPENBSD_ELF
, sparc64obsd_init_abi
);