From 1e067c66c867575bae58872ec9822ce2812250b1 Mon Sep 17 00:00:00 2001 From: Mark Kettenis Date: Sat, 24 Jan 2004 22:18:22 +0000 Subject: [PATCH] * sparc64-tdep.h (stryct_frame_info, struct trad_frame_saved_reg): Add opaque declarations. (sparc64nbsd_sigcontext_saved_regs): New prototype. * sparc64nbsd-tdep.c (sparc64nbsd_sigcontext_saved_regs): New function with code split out from sparc64nbsd_sigcontext_frame_cache. (sparc64nbsd_sigcontext_frame_cache): Use sparc64nbsd_sigcontext_saved_regs. (_initialize_sparc64nbsd_tdep): Don't register OS ABI handler for OpenBSD. * sparc64obsd-tdep.c: New file. * Makefile.in (ALLDEPFILES): Add sparc64obsd-tdep.c. (sparc64obsd-tdep.o): New dependency. * configure.tgt (sparc64-*-openbsd*): Set gdb_target to obsd64 and gdb_osabi to GDB_OSABI_OPENBSD_ELF. * config/sparc/obsd64.mt: New file. --- gdb/ChangeLog | 17 +++ gdb/Makefile.in | 8 +- gdb/config/sparc/obsd64.mt | 5 + gdb/configure.tgt | 4 +- gdb/sparc64-tdep.h | 10 +- gdb/sparc64nbsd-tdep.c | 96 +++++++++-------- gdb/sparc64obsd-tdep.c | 210 +++++++++++++++++++++++++++++++++++++ 7 files changed, 301 insertions(+), 49 deletions(-) create mode 100644 gdb/config/sparc/obsd64.mt create mode 100644 gdb/sparc64obsd-tdep.c diff --git a/gdb/ChangeLog b/gdb/ChangeLog index a77b6b29733..1bba3686cf0 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,22 @@ 2004-01-24 Mark Kettenis + * sparc64-tdep.h (stryct_frame_info, struct trad_frame_saved_reg): + Add opaque declarations. + (sparc64nbsd_sigcontext_saved_regs): New prototype. + * sparc64nbsd-tdep.c (sparc64nbsd_sigcontext_saved_regs): New + function with code split out from + sparc64nbsd_sigcontext_frame_cache. + (sparc64nbsd_sigcontext_frame_cache): Use + sparc64nbsd_sigcontext_saved_regs. + (_initialize_sparc64nbsd_tdep): Don't register OS ABI handler for + OpenBSD. + * sparc64obsd-tdep.c: New file. + * Makefile.in (ALLDEPFILES): Add sparc64obsd-tdep.c. + (sparc64obsd-tdep.o): New dependency. + * configure.tgt (sparc64-*-openbsd*): Set gdb_target to obsd64 and + gdb_osabi to GDB_OSABI_OPENBSD_ELF. + * config/sparc/obsd64.mt: New file. + * sparc-tdep.c (sparc_fetch_instruction): Return zero if we can't read the instruction at PC. diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 0affd3585a4..5883f80bf6d 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -1327,8 +1327,8 @@ ALLDEPFILES = \ sparc-tdep.c sparc-sol2-nat.c sparc-sol2-tdep.c sparc64-linux-nat.c \ sparc64-linux-tdep.c sparc64-nat.c sparc64-sol2-tdep.c \ sparc64-tdep.c sparc64fbsd-nat.c sparc64fbsd-tdep.c \ - sparc64nbsd-nat.c sparc64nbsd-tdep.c sparcnbsd-nat.c \ - sparcnbsd-tdep.c \ + sparc64nbsd-nat.c sparc64nbsd-tdep.c sparc64obsd-tdep.c \ + sparcnbsd-nat.c sparcnbsd-tdep.c \ sun3-nat.c \ symm-tdep.c symm-nat.c \ vax-tdep.c \ @@ -2363,6 +2363,10 @@ sparc64nbsd-tdep.o: sparc64nbsd-tdep.c $(defs_h) $(frame_h) \ $(frame_unwind_h) $(gdbcore_h) $(osabi_h) $(regcache_h) $(regset_h) \ $(symtab_h) $(solib_svr4_h) $(trad_frame_h) $(gdb_assert_h) \ $(gdb_string_h) $(sparc64_tdep_h) $(nbsd_tdep_h) +sparc64obsd-tdep.o: sparc64obsd-tdep.c $(defs_h) $(frame_h) \ + $(frame_unwind_h) $(osabi_h) $(regset_h) $(symtab_h) \ + $(solib_svr4_h) $(trad_frame_h) $(gdb_assert_h) \ + $(sparc64_tdep_h) $(nbsd_tdep_h) sparc64-sol2-tdep.o: sparc64-sol2-tdep.c $(defs_h) $(frame_h) \ $(frame_unwind_h) $(gdbarch_h) $(symtab_h) $(objfiles_h) $(osabi_h) \ $(trad_frame_h) $(gdb_assert_h) $(sparc64_tdep_h) diff --git a/gdb/config/sparc/obsd64.mt b/gdb/config/sparc/obsd64.mt new file mode 100644 index 00000000000..a69281754c4 --- /dev/null +++ b/gdb/config/sparc/obsd64.mt @@ -0,0 +1,5 @@ +# Target: OpenBSD/sparc64 +TDEPFILES= sparc64-tdep.o sparc64nbsd-tdep.o sparc64obsd-tdep.o \ + sparc-tdep.o sparcnbsd-tdep.o nbsd-tdep.o \ + corelow.o solib.o solib-svr4.o +TM_FILE= tm-nbsd.h diff --git a/gdb/configure.tgt b/gdb/configure.tgt index d57018b57fc..23863e5a9c4 100644 --- a/gdb/configure.tgt +++ b/gdb/configure.tgt @@ -191,7 +191,9 @@ sparc64-*-linux*) gdb_target=linux64 ;; sparc-*-netbsd*) gdb_target=nbsd ;; sparc64-*-netbsd*) gdb_target=nbsd64 ;; sparc-*-openbsd*) gdb_target=nbsd ;; -sparc64-*-openbsd*) gdb_target=nbsd64 ;; +sparc64-*-openbsd*) gdb_target=obsd64 + gdb_osabi=GDB_OSABI_OPENBSD_ELF + ;; sparc-*-solaris2.[0-6] | sparc-*-solaris2.[0-6].*) gdb_target=sol2 ;; diff --git a/gdb/sparc64-tdep.h b/gdb/sparc64-tdep.h index f5ab60d87e5..c3073b90b3a 100644 --- a/gdb/sparc64-tdep.h +++ b/gdb/sparc64-tdep.h @@ -22,9 +22,11 @@ #ifndef SPARC64_TDEP_H #define SPARC64_TDEP_H 1 +struct frame_info; struct gdbarch; -struct sparc_gregset; struct regcache; +struct sparc_gregset; +struct trad_frame_saved_reg; #include "sparc-tdep.h" @@ -109,9 +111,13 @@ extern void sparc64_sol2_init_abi (struct gdbarch_info info, /* Register offsets for FreeBSD/sparc64. */ extern const struct sparc_gregset sparc64fbsd_gregset; -/* Variables exported from sparc64nbsd-tdep.c. */ +/* Functions and variables exported from sparc64nbsd-tdep.c. */ /* Register offsets for NetBSD/sparc64. */ extern const struct sparc_gregset sparc64nbsd_gregset; +extern struct trad_frame_saved_reg * + sparc64nbsd_sigcontext_saved_regs (CORE_ADDR sigcontext_addr, + struct frame_info *next_frame); + #endif /* sparc64-tdep.h */ diff --git a/gdb/sparc64nbsd-tdep.c b/gdb/sparc64nbsd-tdep.c index dccb3a1810d..8e7987008e7 100644 --- a/gdb/sparc64nbsd-tdep.c +++ b/gdb/sparc64nbsd-tdep.c @@ -88,14 +88,61 @@ sparc64nbsd_pc_in_sigtramp (CORE_ADDR pc, char *name) return nbsd_pc_in_sigtramp (pc, name); } +struct trad_frame_saved_reg * +sparc64nbsd_sigcontext_saved_regs (CORE_ADDR sigcontext_addr, + struct frame_info *next_frame) +{ + struct trad_frame_saved_reg *saved_regs; + CORE_ADDR addr, sp; + int regnum, delta; + + saved_regs = trad_frame_alloc_saved_regs (next_frame); + + /* The registers are saved in bits and pieces scattered all over the + place. The code below records their location on the assumption + that the part of the signal trampoline that saves the state has + been executed. */ + + saved_regs[SPARC_SP_REGNUM].addr = sigcontext_addr + 8; + saved_regs[SPARC64_PC_REGNUM].addr = sigcontext_addr + 16; + saved_regs[SPARC64_NPC_REGNUM].addr = sigcontext_addr + 24; + saved_regs[SPARC64_STATE_REGNUM].addr = sigcontext_addr + 32; + saved_regs[SPARC_G1_REGNUM].addr = sigcontext_addr + 40; + saved_regs[SPARC_O0_REGNUM].addr = sigcontext_addr + 48; + + /* The remaining `global' registers and %y are saved in the `local' + registers. */ + delta = SPARC_L0_REGNUM - SPARC_G0_REGNUM; + for (regnum = SPARC_G2_REGNUM; regnum <= SPARC_G7_REGNUM; regnum++) + saved_regs[regnum].realreg = regnum + delta; + saved_regs[SPARC64_Y_REGNUM].realreg = SPARC_L1_REGNUM; + + /* The remaining `out' registers can be found in the current frame's + `in' registers. */ + delta = SPARC_I0_REGNUM - SPARC_O0_REGNUM; + for (regnum = SPARC_O1_REGNUM; regnum <= SPARC_O5_REGNUM; regnum++) + saved_regs[regnum].realreg = regnum + delta; + saved_regs[SPARC_O7_REGNUM].realreg = SPARC_I7_REGNUM; + + /* The `local' and `in' registers have been saved in the register + save area. */ + addr = saved_regs[SPARC_SP_REGNUM].addr; + sp = get_frame_memory_unsigned (next_frame, addr, 8); + for (regnum = SPARC_L0_REGNUM, addr = sp + BIAS; + regnum <= SPARC_I7_REGNUM; regnum++, addr += 8) + saved_regs[regnum].addr = addr; + + /* TODO: Handle the floating-point registers. */ + + return saved_regs; +} + static struct sparc_frame_cache * sparc64nbsd_sigcontext_frame_cache (struct frame_info *next_frame, void **this_cache) { struct sparc_frame_cache *cache; - CORE_ADDR addr, sigcontext_addr, sp; - LONGEST fprs; - int regnum, delta; + CORE_ADDR addr; if (*this_cache) return *this_cache; @@ -103,11 +150,6 @@ sparc64nbsd_sigcontext_frame_cache (struct frame_info *next_frame, cache = sparc_frame_cache (next_frame, this_cache); gdb_assert (cache == *this_cache); - /* The registers are saved in bits and pieces scattered all over the - place. The code below records their location on the assumption - that the part of the signal trampoline that saves the state has - been executed. */ - /* If we couldn't find the frame's function, we're probably dealing with an on-stack signal trampoline. */ if (cache->pc == 0) @@ -121,42 +163,10 @@ sparc64nbsd_sigcontext_frame_cache (struct frame_info *next_frame, cache->base = addr; } - cache->saved_regs = trad_frame_alloc_saved_regs (next_frame); - /* We find the appropriate instance of `struct sigcontext' at a fixed offset in the signal frame. */ - sigcontext_addr = cache->base + BIAS + 128 + 8; - - cache->saved_regs[SPARC_SP_REGNUM].addr = sigcontext_addr + 8; - cache->saved_regs[SPARC64_PC_REGNUM].addr = sigcontext_addr + 16; - cache->saved_regs[SPARC64_NPC_REGNUM].addr = sigcontext_addr + 24; - cache->saved_regs[SPARC64_STATE_REGNUM].addr = sigcontext_addr + 32; - cache->saved_regs[SPARC_G1_REGNUM].addr = sigcontext_addr + 40; - cache->saved_regs[SPARC_O0_REGNUM].addr = sigcontext_addr + 48; - - /* The remaining `global' registers and %y are saved in the `local' - registers. */ - delta = SPARC_L0_REGNUM - SPARC_G0_REGNUM; - for (regnum = SPARC_G2_REGNUM; regnum <= SPARC_G7_REGNUM; regnum++) - cache->saved_regs[regnum].realreg = regnum + delta; - cache->saved_regs[SPARC64_Y_REGNUM].realreg = SPARC_L1_REGNUM; - - /* The remaining `out' registers can be found in the current frame's - `in' registers. */ - delta = SPARC_I0_REGNUM - SPARC_O0_REGNUM; - for (regnum = SPARC_O1_REGNUM; regnum <= SPARC_O5_REGNUM; regnum++) - cache->saved_regs[regnum].realreg = regnum + delta; - cache->saved_regs[SPARC_O7_REGNUM].realreg = SPARC_I7_REGNUM; - - /* The `local' and `in' registers have been saved in the register - save area. */ - addr = cache->saved_regs[SPARC_SP_REGNUM].addr; - sp = get_frame_memory_unsigned (next_frame, addr, 8); - for (regnum = SPARC_L0_REGNUM, addr = sp + BIAS; - regnum <= SPARC_I7_REGNUM; regnum++, addr += 8) - cache->saved_regs[regnum].addr = addr; - - /* TODO: Handle the floating-point registers. */ + addr = cache->base + BIAS + 128 + 8; + cache->saved_regs = sparc64nbsd_sigcontext_saved_regs (addr, next_frame); return cache; } @@ -243,6 +253,4 @@ _initialize_sparc64nbsd_tdep (void) { gdbarch_register_osabi (bfd_arch_sparc, bfd_mach_sparc_v9, GDB_OSABI_NETBSD_ELF, sparc64nbsd_init_abi); - gdbarch_register_osabi (bfd_arch_sparc, bfd_mach_sparc_v9, - GDB_OSABI_OPENBSD_ELF, sparc64nbsd_init_abi); } diff --git a/gdb/sparc64obsd-tdep.c b/gdb/sparc64obsd-tdep.c new file mode 100644 index 00000000000..190a46be1fa --- /dev/null +++ b/gdb/sparc64obsd-tdep.c @@ -0,0 +1,210 @@ +/* Target-dependent code for OpenBSD/sparc64. + + Copyright 2004 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "defs.h" +#include "frame.h" +#include "frame-unwind.h" +#include "osabi.h" +#include "regset.h" +#include "symtab.h" +#include "solib-svr4.h" +#include "trad-frame.h" + +#include "gdb_assert.h" + +#include "sparc64-tdep.h" +#include "nbsd-tdep.h" + +/* OpenBSD uses the traditional NetBSD core file format, even for + ports that use ELF. The core files don't use multiple register + sets. Instead, the general-purpose and floating-point registers + are lumped together in a single section. Unlike on NetBSD, OpenBSD + uses a different layout for its general-purpose registers than the + layout used for ptrace(2). */ + +/* From . */ +const struct sparc_gregset sparc64obsd_core_gregset = +{ + 0 * 8, /* "tstate" */ + 1 * 8, /* %pc */ + 2 * 8, /* %npc */ + 3 * 8, /* %y */ + -1, /* %fprs */ + -1, + 7 * 8, /* %g1 */ + 22 * 8, /* %l0 */ + 4 /* sizeof (%y) */ +}; + +static void +sparc64obsd_supply_gregset (const struct regset *regset, + struct regcache *regcache, + int regnum, const void *gregs, size_t len) +{ + const char *regs = gregs; + + sparc64_supply_gregset (regset->descr, regcache, regnum, regs); + sparc64_supply_fpregset (regcache, regnum, regs + 288); +} + + +/* Signal trampolines. */ + +/* The OpenBSD kernel maps the signal trampoline at some random + location in user space, which means that the traditional BSD way of + detecting it won't work. + + The signal trampoline will be mapped at an address that is page + aligned. We recognize the signal trampoline by the looking for the + sigreturn system call. */ + +static const int sparc64obsd_page_size = 8192; + +static int +sparc64obsd_pc_in_sigtramp (CORE_ADDR pc, char *name) +{ + CORE_ADDR start_pc = (pc & ~(sparc64obsd_page_size - 1)); + unsigned long insn; + + if (name) + return 0; + + /* Check for "restore %g0, SYS_sigreturn, %g1". */ + insn = sparc_fetch_instruction (start_pc + 0xe8); + if (insn != 0x83e82067) + return 0; + + /* Check for "t ST_SYSCALL". */ + insn = sparc_fetch_instruction (start_pc + 0xf0); + if (insn != 0x91d02000) + return 0; + + return 1; +} + +static struct sparc_frame_cache * +sparc64obsd_frame_cache (struct frame_info *next_frame, void **this_cache) +{ + struct sparc_frame_cache *cache; + CORE_ADDR addr; + + if (*this_cache) + return *this_cache; + + cache = sparc_frame_cache (next_frame, this_cache); + gdb_assert (cache == *this_cache); + + /* If we couldn't find the frame's function, we're probably dealing + with an on-stack signal trampoline. */ + if (cache->pc == 0) + { + cache->pc = frame_pc_unwind (next_frame); + cache->pc &= ~(sparc64obsd_page_size - 1); + + /* Since we couldn't find the frame's function, the cache was + initialized under the assumption that we're frameless. */ + cache->frameless_p = 0; + addr = frame_unwind_register_unsigned (next_frame, SPARC_FP_REGNUM); + cache->base = addr; + } + + /* We find the appropriate instance of `struct sigcontext' at a + fixed offset in the signal frame. */ + addr = cache->base + BIAS + 128 + 16; + cache->saved_regs = sparc64nbsd_sigcontext_saved_regs (addr, next_frame); + + return cache; +} + +static void +sparc64obsd_frame_this_id (struct frame_info *next_frame, void **this_cache, + struct frame_id *this_id) +{ + struct sparc_frame_cache *cache = + sparc64obsd_frame_cache (next_frame, this_cache); + + (*this_id) = frame_id_build (cache->base, cache->pc); +} + +static void +sparc64obsd_frame_prev_register (struct frame_info *next_frame, + void **this_cache, + int regnum, int *optimizedp, + enum lval_type *lvalp, CORE_ADDR *addrp, + int *realnump, void *valuep) +{ + struct sparc_frame_cache *cache = + sparc64obsd_frame_cache (next_frame, this_cache); + + trad_frame_prev_register (next_frame, cache->saved_regs, regnum, + optimizedp, lvalp, addrp, realnump, valuep); +} + +static const struct frame_unwind sparc64obsd_frame_unwind = +{ + SIGTRAMP_FRAME, + sparc64obsd_frame_this_id, + sparc64obsd_frame_prev_register +}; + +static const struct frame_unwind * +sparc64obsd_sigtramp_frame_sniffer (struct frame_info *next_frame) +{ + CORE_ADDR pc = frame_pc_unwind (next_frame); + char *name; + + find_pc_partial_function (pc, &name, NULL, NULL); + if (sparc64obsd_pc_in_sigtramp (pc, name)) + return &sparc64obsd_frame_unwind; + + return NULL; +} + + +static void +sparc64obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + tdep->gregset = XMALLOC (struct regset); + tdep->gregset->descr = &sparc64obsd_core_gregset; + tdep->gregset->supply_regset = sparc64obsd_supply_gregset; + tdep->sizeof_gregset = 832; + + set_gdbarch_pc_in_sigtramp (gdbarch, sparc64obsd_pc_in_sigtramp); + frame_unwind_append_sniffer (gdbarch, sparc64obsd_sigtramp_frame_sniffer); + + sparc64_init_abi (info, gdbarch); + + set_solib_svr4_fetch_link_map_offsets + (gdbarch, nbsd_lp64_solib_svr4_fetch_link_map_offsets); +} + + +/* Provide a prototype to silence -Wmissing-prototypes. */ +void _initialize_sparc64obsd_tdep (void); + +void +_initialize_sparc64obsd_tdep (void) +{ + gdbarch_register_osabi (bfd_arch_sparc, bfd_mach_sparc_v9, + GDB_OSABI_OPENBSD_ELF, sparc64obsd_init_abi); +}