windows-nat: Don't change current_event.dwThreadId in handle_output_debug_string()
[deliverable/binutils-gdb.git] / gdb / sparcobsd-tdep.c
CommitLineData
566626fa
MK
1/* Target-dependent code for OpenBSD/sparc.
2
32d0add0 3 Copyright (C) 2004-2015 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"
21#include "floatformat.h"
22#include "frame.h"
23#include "frame-unwind.h"
92c2d36a 24#include "gdbcore.h"
566626fa 25#include "osabi.h"
92c2d36a 26#include "regcache.h"
566626fa
MK
27#include "symtab.h"
28#include "trad-frame.h"
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"
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)
77 return *this_cache;
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{
e17a4113
UW
156 struct gdbarch *gdbarch = get_regcache_arch (regcache);
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);
92c2d36a
MK
167 regcache_raw_supply (regcache, SPARC_SP_REGNUM, buf);
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);
92c2d36a
MK
182 regcache_raw_supply (regcache, SPARC32_PC_REGNUM, buf);
183 }
184 if (regnum == SPARC32_NPC_REGNUM || regnum == -1)
185 {
e17a4113 186 store_unsigned_integer (buf, 4, byte_order, i7 + 12);
92c2d36a
MK
187 regcache_raw_supply (regcache, SPARC32_NPC_REGNUM, buf);
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{
e17a4113
UW
201 struct gdbarch *gdbarch = get_regcache_arch (regcache);
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
212 regcache_raw_collect (regcache, SPARC_SP_REGNUM, buf);
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
220 regcache_raw_collect (regcache, 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
228 regcache_raw_collect (regcache, 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{
237 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
238
19671c2b
MK
239 /* OpenBSD/sparc is very similar to NetBSD/sparc ELF. */
240 sparc32nbsd_elf_init_abi (info, gdbarch);
566626fa 241
dfe1ff2e
MK
242 set_gdbarch_skip_solib_resolver (gdbarch, obsd_skip_solib_resolver);
243
7ea566be 244 frame_unwind_append_unwinder (gdbarch, &sparc32obsd_sigtramp_frame_unwind);
92c2d36a
MK
245
246 /* OpenBSD provides a user-level threads implementation. */
247 bsd_uthread_set_supply_uthread (gdbarch, sparc32obsd_supply_uthread);
248 bsd_uthread_set_collect_uthread (gdbarch, sparc32obsd_collect_uthread);
566626fa
MK
249}
250
251\f
252/* Provide a prototype to silence -Wmissing-prototypes. */
253void _initialize_sparc32obsd_tdep (void);
254
255void
256_initialize_sparc32obsd_tdep (void)
257{
258 gdbarch_register_osabi (bfd_arch_sparc, 0, GDB_OSABI_OPENBSD_ELF,
259 sparc32obsd_init_abi);
260}
This page took 1.287148 seconds and 4 git commands to generate.