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