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