]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/sparc-obsd-tdep.c
Document the effect of --as-needed on --rpath on Linux based systems.
[thirdparty/binutils-gdb.git] / gdb / sparc-obsd-tdep.c
CommitLineData
566626fa
MK
1/* Target-dependent code for OpenBSD/sparc.
2
3666a048 3 Copyright (C) 2004-2021 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{
139 SIGTRAMP_FRAME,
8fbca658 140 default_frame_unwind_stop_reason,
7ea566be
MK
141 sparc32obsd_sigtramp_frame_this_id,
142 sparc32obsd_sigtramp_frame_prev_register,
143 NULL,
144 sparc32obsd_sigtramp_frame_sniffer
145};
146
566626fa
MK
147\f
148
92c2d36a
MK
149/* Offset wthin the thread structure where we can find %fp and %i7. */
150#define SPARC32OBSD_UTHREAD_FP_OFFSET 128
151#define SPARC32OBSD_UTHREAD_PC_OFFSET 132
152
153static void
154sparc32obsd_supply_uthread (struct regcache *regcache,
155 int regnum, CORE_ADDR addr)
156{
ac7936df 157 struct gdbarch *gdbarch = regcache->arch ();
e17a4113 158 enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
92c2d36a
MK
159 CORE_ADDR fp, fp_addr = addr + SPARC32OBSD_UTHREAD_FP_OFFSET;
160 gdb_byte buf[4];
161
d1e93af6
SM
162 /* This function calls functions that depend on the global current thread. */
163 gdb_assert (regcache->ptid () == inferior_ptid);
164
92c2d36a
MK
165 gdb_assert (regnum >= -1);
166
e17a4113 167 fp = read_memory_unsigned_integer (fp_addr, 4, byte_order);
92c2d36a
MK
168 if (regnum == SPARC_SP_REGNUM || regnum == -1)
169 {
e17a4113 170 store_unsigned_integer (buf, 4, byte_order, fp);
73e1c03f 171 regcache->raw_supply (SPARC_SP_REGNUM, buf);
92c2d36a
MK
172
173 if (regnum == SPARC_SP_REGNUM)
174 return;
175 }
176
177 if (regnum == SPARC32_PC_REGNUM || regnum == SPARC32_NPC_REGNUM
178 || regnum == -1)
179 {
180 CORE_ADDR i7, i7_addr = addr + SPARC32OBSD_UTHREAD_PC_OFFSET;
181
e17a4113 182 i7 = read_memory_unsigned_integer (i7_addr, 4, byte_order);
92c2d36a
MK
183 if (regnum == SPARC32_PC_REGNUM || regnum == -1)
184 {
e17a4113 185 store_unsigned_integer (buf, 4, byte_order, i7 + 8);
73e1c03f 186 regcache->raw_supply (SPARC32_PC_REGNUM, buf);
92c2d36a
MK
187 }
188 if (regnum == SPARC32_NPC_REGNUM || regnum == -1)
189 {
e17a4113 190 store_unsigned_integer (buf, 4, byte_order, i7 + 12);
73e1c03f 191 regcache->raw_supply (SPARC32_NPC_REGNUM, buf);
92c2d36a
MK
192 }
193
194 if (regnum == SPARC32_PC_REGNUM || regnum == SPARC32_NPC_REGNUM)
195 return;
196 }
197
198 sparc_supply_rwindow (regcache, fp, regnum);
199}
200
201static void
202sparc32obsd_collect_uthread(const struct regcache *regcache,
203 int regnum, CORE_ADDR addr)
204{
ac7936df 205 struct gdbarch *gdbarch = regcache->arch ();
e17a4113 206 enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
92c2d36a
MK
207 CORE_ADDR sp;
208 gdb_byte buf[4];
209
d1e93af6
SM
210 /* This function calls functions that depend on the global current thread. */
211 gdb_assert (regcache->ptid () == inferior_ptid);
212
92c2d36a
MK
213 gdb_assert (regnum >= -1);
214
215 if (regnum == SPARC_SP_REGNUM || regnum == -1)
216 {
217 CORE_ADDR fp_addr = addr + SPARC32OBSD_UTHREAD_FP_OFFSET;
218
34a79281 219 regcache->raw_collect (SPARC_SP_REGNUM, buf);
92c2d36a
MK
220 write_memory (fp_addr,buf, 4);
221 }
222
223 if (regnum == SPARC32_PC_REGNUM || regnum == -1)
224 {
225 CORE_ADDR i7, i7_addr = addr + SPARC32OBSD_UTHREAD_PC_OFFSET;
226
34a79281 227 regcache->raw_collect (SPARC32_PC_REGNUM, buf);
e17a4113
UW
228 i7 = extract_unsigned_integer (buf, 4, byte_order) - 8;
229 write_memory_unsigned_integer (i7_addr, 4, byte_order, i7);
92c2d36a
MK
230
231 if (regnum == SPARC32_PC_REGNUM)
232 return;
233 }
234
34a79281 235 regcache->raw_collect (SPARC_SP_REGNUM, buf);
e17a4113 236 sp = extract_unsigned_integer (buf, 4, byte_order);
92c2d36a
MK
237 sparc_collect_rwindow (regcache, sp, regnum);
238}
239\f
240
566626fa
MK
241static void
242sparc32obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
243{
19671c2b 244 /* OpenBSD/sparc is very similar to NetBSD/sparc ELF. */
1736a7bd 245 sparc32nbsd_init_abi (info, gdbarch);
566626fa 246
dfe1ff2e
MK
247 set_gdbarch_skip_solib_resolver (gdbarch, obsd_skip_solib_resolver);
248
7ea566be 249 frame_unwind_append_unwinder (gdbarch, &sparc32obsd_sigtramp_frame_unwind);
92c2d36a
MK
250
251 /* OpenBSD provides a user-level threads implementation. */
252 bsd_uthread_set_supply_uthread (gdbarch, sparc32obsd_supply_uthread);
253 bsd_uthread_set_collect_uthread (gdbarch, sparc32obsd_collect_uthread);
566626fa
MK
254}
255
6c265988 256void _initialize_sparc32obsd_tdep ();
566626fa 257void
6c265988 258_initialize_sparc32obsd_tdep ()
566626fa 259{
1736a7bd 260 gdbarch_register_osabi (bfd_arch_sparc, 0, GDB_OSABI_OPENBSD,
566626fa
MK
261 sparc32obsd_init_abi);
262}