gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / gdb / sparc-obsd-tdep.c
CommitLineData
566626fa
MK
1/* Target-dependent code for OpenBSD/sparc.
2
b811d2c2 3 Copyright (C) 2004-2020 Free Software Foundation, Inc.
566626fa
MK
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
a9762ec7 9 the Free Software Foundation; either version 3 of the License, or
566626fa
MK
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
a9762ec7 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
566626fa
MK
19
20#include "defs.h"
566626fa
MK
21#include "frame.h"
22#include "frame-unwind.h"
92c2d36a 23#include "gdbcore.h"
566626fa 24#include "osabi.h"
92c2d36a 25#include "regcache.h"
566626fa
MK
26#include "symtab.h"
27#include "trad-frame.h"
28
dfe1ff2e 29#include "obsd-tdep.h"
566626fa 30#include "sparc-tdep.h"
92c2d36a
MK
31#include "solib-svr4.h"
32#include "bsd-uthread.h"
0d12e84c 33#include "gdbarch.h"
566626fa
MK
34
35/* Signal trampolines. */
36
37/* The OpenBSD kernel maps the signal trampoline at some random
38 location in user space, which means that the traditional BSD way of
39 detecting it won't work.
40
41 The signal trampoline will be mapped at an address that is page
37e28b92 42 aligned. We recognize the signal trampoline by looking for the
566626fa
MK
43 sigreturn system call. */
44
45static const int sparc32obsd_page_size = 4096;
46
47static int
2c02bd72 48sparc32obsd_pc_in_sigtramp (CORE_ADDR pc, const char *name)
566626fa
MK
49{
50 CORE_ADDR start_pc = (pc & ~(sparc32obsd_page_size - 1));
51 unsigned long insn;
52
53 if (name)
54 return 0;
55
56 /* Check for "restore %g0, SYS_sigreturn, %g1". */
57 insn = sparc_fetch_instruction (start_pc + 0xec);
58 if (insn != 0x83e82067)
59 return 0;
60
61 /* Check for "t ST_SYSCALL". */
62 insn = sparc_fetch_instruction (start_pc + 0xf4);
63 if (insn != 0x91d02000)
64 return 0;
65
66 return 1;
67}
68
69static struct sparc_frame_cache *
7ea566be
MK
70sparc32obsd_sigtramp_frame_cache (struct frame_info *this_frame,
71 void **this_cache)
566626fa
MK
72{
73 struct sparc_frame_cache *cache;
74 CORE_ADDR addr;
75
76 if (*this_cache)
19ba03f4 77 return (struct sparc_frame_cache *) *this_cache;
566626fa 78
7ea566be 79 cache = sparc_frame_cache (this_frame, this_cache);
566626fa
MK
80 gdb_assert (cache == *this_cache);
81
82 /* If we couldn't find the frame's function, we're probably dealing
83 with an on-stack signal trampoline. */
84 if (cache->pc == 0)
85 {
7ea566be 86 cache->pc = get_frame_pc (this_frame);
566626fa
MK
87 cache->pc &= ~(sparc32obsd_page_size - 1);
88
89 /* Since we couldn't find the frame's function, the cache was
90 initialized under the assumption that we're frameless. */
369c397b 91 sparc_record_save_insn (cache);
7ea566be 92 addr = get_frame_register_unsigned (this_frame, SPARC_FP_REGNUM);
566626fa
MK
93 cache->base = addr;
94 }
95
7ea566be 96 cache->saved_regs = sparc32nbsd_sigcontext_saved_regs (this_frame);
566626fa
MK
97
98 return cache;
99}
100
101static void
7ea566be
MK
102sparc32obsd_sigtramp_frame_this_id (struct frame_info *this_frame,
103 void **this_cache,
104 struct frame_id *this_id)
566626fa
MK
105{
106 struct sparc_frame_cache *cache =
7ea566be 107 sparc32obsd_sigtramp_frame_cache (this_frame, this_cache);
566626fa
MK
108
109 (*this_id) = frame_id_build (cache->base, cache->pc);
110}
111
7ea566be
MK
112static struct value *
113sparc32obsd_sigtramp_frame_prev_register (struct frame_info *this_frame,
114 void **this_cache, int regnum)
566626fa
MK
115{
116 struct sparc_frame_cache *cache =
7ea566be 117 sparc32obsd_sigtramp_frame_cache (this_frame, this_cache);
566626fa 118
7ea566be 119 return trad_frame_get_prev_register (this_frame, cache->saved_regs, regnum);
566626fa
MK
120}
121
7ea566be
MK
122static int
123sparc32obsd_sigtramp_frame_sniffer (const struct frame_unwind *self,
124 struct frame_info *this_frame,
125 void **this_cache)
566626fa 126{
7ea566be 127 CORE_ADDR pc = get_frame_pc (this_frame);
2c02bd72 128 const char *name;
566626fa
MK
129
130 find_pc_partial_function (pc, &name, NULL, NULL);
131 if (sparc32obsd_pc_in_sigtramp (pc, name))
7ea566be 132 return 1;
566626fa 133
7ea566be 134 return 0;
566626fa 135}
7ea566be
MK
136static const struct frame_unwind sparc32obsd_sigtramp_frame_unwind =
137{
138 SIGTRAMP_FRAME,
8fbca658 139 default_frame_unwind_stop_reason,
7ea566be
MK
140 sparc32obsd_sigtramp_frame_this_id,
141 sparc32obsd_sigtramp_frame_prev_register,
142 NULL,
143 sparc32obsd_sigtramp_frame_sniffer
144};
145
566626fa
MK
146\f
147
92c2d36a
MK
148/* Offset wthin the thread structure where we can find %fp and %i7. */
149#define SPARC32OBSD_UTHREAD_FP_OFFSET 128
150#define SPARC32OBSD_UTHREAD_PC_OFFSET 132
151
152static void
153sparc32obsd_supply_uthread (struct regcache *regcache,
154 int regnum, CORE_ADDR addr)
155{
ac7936df 156 struct gdbarch *gdbarch = regcache->arch ();
e17a4113 157 enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
92c2d36a
MK
158 CORE_ADDR fp, fp_addr = addr + SPARC32OBSD_UTHREAD_FP_OFFSET;
159 gdb_byte buf[4];
160
161 gdb_assert (regnum >= -1);
162
e17a4113 163 fp = read_memory_unsigned_integer (fp_addr, 4, byte_order);
92c2d36a
MK
164 if (regnum == SPARC_SP_REGNUM || regnum == -1)
165 {
e17a4113 166 store_unsigned_integer (buf, 4, byte_order, fp);
73e1c03f 167 regcache->raw_supply (SPARC_SP_REGNUM, buf);
92c2d36a
MK
168
169 if (regnum == SPARC_SP_REGNUM)
170 return;
171 }
172
173 if (regnum == SPARC32_PC_REGNUM || regnum == SPARC32_NPC_REGNUM
174 || regnum == -1)
175 {
176 CORE_ADDR i7, i7_addr = addr + SPARC32OBSD_UTHREAD_PC_OFFSET;
177
e17a4113 178 i7 = read_memory_unsigned_integer (i7_addr, 4, byte_order);
92c2d36a
MK
179 if (regnum == SPARC32_PC_REGNUM || regnum == -1)
180 {
e17a4113 181 store_unsigned_integer (buf, 4, byte_order, i7 + 8);
73e1c03f 182 regcache->raw_supply (SPARC32_PC_REGNUM, buf);
92c2d36a
MK
183 }
184 if (regnum == SPARC32_NPC_REGNUM || regnum == -1)
185 {
e17a4113 186 store_unsigned_integer (buf, 4, byte_order, i7 + 12);
73e1c03f 187 regcache->raw_supply (SPARC32_NPC_REGNUM, buf);
92c2d36a
MK
188 }
189
190 if (regnum == SPARC32_PC_REGNUM || regnum == SPARC32_NPC_REGNUM)
191 return;
192 }
193
194 sparc_supply_rwindow (regcache, fp, regnum);
195}
196
197static void
198sparc32obsd_collect_uthread(const struct regcache *regcache,
199 int regnum, CORE_ADDR addr)
200{
ac7936df 201 struct gdbarch *gdbarch = regcache->arch ();
e17a4113 202 enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
92c2d36a
MK
203 CORE_ADDR sp;
204 gdb_byte buf[4];
205
206 gdb_assert (regnum >= -1);
207
208 if (regnum == SPARC_SP_REGNUM || regnum == -1)
209 {
210 CORE_ADDR fp_addr = addr + SPARC32OBSD_UTHREAD_FP_OFFSET;
211
34a79281 212 regcache->raw_collect (SPARC_SP_REGNUM, buf);
92c2d36a
MK
213 write_memory (fp_addr,buf, 4);
214 }
215
216 if (regnum == SPARC32_PC_REGNUM || regnum == -1)
217 {
218 CORE_ADDR i7, i7_addr = addr + SPARC32OBSD_UTHREAD_PC_OFFSET;
219
34a79281 220 regcache->raw_collect (SPARC32_PC_REGNUM, buf);
e17a4113
UW
221 i7 = extract_unsigned_integer (buf, 4, byte_order) - 8;
222 write_memory_unsigned_integer (i7_addr, 4, byte_order, i7);
92c2d36a
MK
223
224 if (regnum == SPARC32_PC_REGNUM)
225 return;
226 }
227
34a79281 228 regcache->raw_collect (SPARC_SP_REGNUM, buf);
e17a4113 229 sp = extract_unsigned_integer (buf, 4, byte_order);
92c2d36a
MK
230 sparc_collect_rwindow (regcache, sp, regnum);
231}
232\f
233
566626fa
MK
234static void
235sparc32obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
236{
19671c2b 237 /* OpenBSD/sparc is very similar to NetBSD/sparc ELF. */
1736a7bd 238 sparc32nbsd_init_abi (info, gdbarch);
566626fa 239
dfe1ff2e
MK
240 set_gdbarch_skip_solib_resolver (gdbarch, obsd_skip_solib_resolver);
241
7ea566be 242 frame_unwind_append_unwinder (gdbarch, &sparc32obsd_sigtramp_frame_unwind);
92c2d36a
MK
243
244 /* OpenBSD provides a user-level threads implementation. */
245 bsd_uthread_set_supply_uthread (gdbarch, sparc32obsd_supply_uthread);
246 bsd_uthread_set_collect_uthread (gdbarch, sparc32obsd_collect_uthread);
566626fa
MK
247}
248
6c265988 249void _initialize_sparc32obsd_tdep ();
566626fa 250void
6c265988 251_initialize_sparc32obsd_tdep ()
566626fa 252{
1736a7bd 253 gdbarch_register_osabi (bfd_arch_sparc, 0, GDB_OSABI_OPENBSD,
566626fa
MK
254 sparc32obsd_init_abi);
255}
This page took 1.711898 seconds and 4 git commands to generate.