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