X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fsparcobsd-tdep.c;h=809b53a90fb0000d10089b74fef0683cd9b92b91;hb=efcbbd1428e455c9ca59a590a91e4db200b3813c;hp=5e9d99d5616a5e7e22c44c510ac35fb1acf9bf70;hpb=1f67027d6b7ab06657d74f1810e9facc427a934d;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/sparcobsd-tdep.c b/gdb/sparcobsd-tdep.c index 5e9d99d561..809b53a90f 100644 --- a/gdb/sparcobsd-tdep.c +++ b/gdb/sparcobsd-tdep.c @@ -1,12 +1,13 @@ /* Target-dependent code for OpenBSD/sparc. - Copyright 2004 Free Software Foundation, Inc. + Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 + 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 + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, @@ -15,23 +16,24 @@ 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. */ + along with this program. If not, see . */ #include "defs.h" #include "floatformat.h" #include "frame.h" #include "frame-unwind.h" +#include "gdbcore.h" #include "osabi.h" -#include "solib-svr4.h" +#include "regcache.h" #include "symtab.h" #include "trad-frame.h" #include "gdb_assert.h" +#include "obsd-tdep.h" #include "sparc-tdep.h" -#include "nbsd-tdep.h" +#include "solib-svr4.h" +#include "bsd-uthread.h" /* Signal trampolines. */ @@ -40,7 +42,7 @@ 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 + aligned. We recognize the signal trampoline by looking for the sigreturn system call. */ static const int sparc32obsd_page_size = 4096; @@ -68,7 +70,8 @@ sparc32obsd_pc_in_sigtramp (CORE_ADDR pc, char *name) } static struct sparc_frame_cache * -sparc32obsd_frame_cache (struct frame_info *next_frame, void **this_cache) +sparc32obsd_sigtramp_frame_cache (struct frame_info *this_frame, + void **this_cache) { struct sparc_frame_cache *cache; CORE_ADDR addr; @@ -76,70 +79,157 @@ sparc32obsd_frame_cache (struct frame_info *next_frame, void **this_cache) if (*this_cache) return *this_cache; - cache = sparc_frame_cache (next_frame, this_cache); + cache = sparc_frame_cache (this_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 = get_frame_pc (this_frame); cache->pc &= ~(sparc32obsd_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); + addr = get_frame_register_unsigned (this_frame, SPARC_FP_REGNUM); cache->base = addr; } - cache->saved_regs = sparc32nbsd_sigcontext_saved_regs (next_frame); + cache->saved_regs = sparc32nbsd_sigcontext_saved_regs (this_frame); return cache; } static void -sparc32obsd_frame_this_id (struct frame_info *next_frame, void **this_cache, - struct frame_id *this_id) +sparc32obsd_sigtramp_frame_this_id (struct frame_info *this_frame, + void **this_cache, + struct frame_id *this_id) { struct sparc_frame_cache *cache = - sparc32obsd_frame_cache (next_frame, this_cache); + sparc32obsd_sigtramp_frame_cache (this_frame, this_cache); (*this_id) = frame_id_build (cache->base, cache->pc); } -static void -sparc32obsd_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) +static struct value * +sparc32obsd_sigtramp_frame_prev_register (struct frame_info *this_frame, + void **this_cache, int regnum) { struct sparc_frame_cache *cache = - sparc32obsd_frame_cache (next_frame, this_cache); + sparc32obsd_sigtramp_frame_cache (this_frame, this_cache); - trad_frame_get_prev_register (next_frame, cache->saved_regs, regnum, - optimizedp, lvalp, addrp, realnump, valuep); + return trad_frame_get_prev_register (this_frame, cache->saved_regs, regnum); } -static const struct frame_unwind sparc32obsd_frame_unwind = +static int +sparc32obsd_sigtramp_frame_sniffer (const struct frame_unwind *self, + struct frame_info *this_frame, + void **this_cache) +{ + CORE_ADDR pc = get_frame_pc (this_frame); + char *name; + + find_pc_partial_function (pc, &name, NULL, NULL); + if (sparc32obsd_pc_in_sigtramp (pc, name)) + return 1; + + return 0; +} +static const struct frame_unwind sparc32obsd_sigtramp_frame_unwind = { SIGTRAMP_FRAME, - sparc32obsd_frame_this_id, - sparc32obsd_frame_prev_register + sparc32obsd_sigtramp_frame_this_id, + sparc32obsd_sigtramp_frame_prev_register, + NULL, + sparc32obsd_sigtramp_frame_sniffer }; -static const struct frame_unwind * -sparc32obsd_sigtramp_frame_sniffer (struct frame_info *next_frame) + + +/* Offset wthin the thread structure where we can find %fp and %i7. */ +#define SPARC32OBSD_UTHREAD_FP_OFFSET 128 +#define SPARC32OBSD_UTHREAD_PC_OFFSET 132 + +static void +sparc32obsd_supply_uthread (struct regcache *regcache, + int regnum, CORE_ADDR addr) { - CORE_ADDR pc = frame_pc_unwind (next_frame); - char *name; + struct gdbarch *gdbarch = get_regcache_arch (regcache); + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + CORE_ADDR fp, fp_addr = addr + SPARC32OBSD_UTHREAD_FP_OFFSET; + gdb_byte buf[4]; - find_pc_partial_function (pc, &name, NULL, NULL); - if (sparc32obsd_pc_in_sigtramp (pc, name)) - return &sparc32obsd_frame_unwind; + gdb_assert (regnum >= -1); - return NULL; + fp = read_memory_unsigned_integer (fp_addr, 4, byte_order); + if (regnum == SPARC_SP_REGNUM || regnum == -1) + { + store_unsigned_integer (buf, 4, byte_order, fp); + regcache_raw_supply (regcache, SPARC_SP_REGNUM, buf); + + if (regnum == SPARC_SP_REGNUM) + return; + } + + if (regnum == SPARC32_PC_REGNUM || regnum == SPARC32_NPC_REGNUM + || regnum == -1) + { + CORE_ADDR i7, i7_addr = addr + SPARC32OBSD_UTHREAD_PC_OFFSET; + + i7 = read_memory_unsigned_integer (i7_addr, 4, byte_order); + if (regnum == SPARC32_PC_REGNUM || regnum == -1) + { + store_unsigned_integer (buf, 4, byte_order, i7 + 8); + regcache_raw_supply (regcache, SPARC32_PC_REGNUM, buf); + } + if (regnum == SPARC32_NPC_REGNUM || regnum == -1) + { + store_unsigned_integer (buf, 4, byte_order, i7 + 12); + regcache_raw_supply (regcache, SPARC32_NPC_REGNUM, buf); + } + + if (regnum == SPARC32_PC_REGNUM || regnum == SPARC32_NPC_REGNUM) + return; + } + + sparc_supply_rwindow (regcache, fp, regnum); +} + +static void +sparc32obsd_collect_uthread(const struct regcache *regcache, + int regnum, CORE_ADDR addr) +{ + struct gdbarch *gdbarch = get_regcache_arch (regcache); + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + CORE_ADDR sp; + gdb_byte buf[4]; + + gdb_assert (regnum >= -1); + + if (regnum == SPARC_SP_REGNUM || regnum == -1) + { + CORE_ADDR fp_addr = addr + SPARC32OBSD_UTHREAD_FP_OFFSET; + + regcache_raw_collect (regcache, SPARC_SP_REGNUM, buf); + write_memory (fp_addr,buf, 4); + } + + if (regnum == SPARC32_PC_REGNUM || regnum == -1) + { + CORE_ADDR i7, i7_addr = addr + SPARC32OBSD_UTHREAD_PC_OFFSET; + + regcache_raw_collect (regcache, SPARC32_PC_REGNUM, buf); + i7 = extract_unsigned_integer (buf, 4, byte_order) - 8; + write_memory_unsigned_integer (i7_addr, 4, byte_order, i7); + + if (regnum == SPARC32_PC_REGNUM) + return; + } + + regcache_raw_collect (regcache, SPARC_SP_REGNUM, buf); + sp = extract_unsigned_integer (buf, 4, byte_order); + sparc_collect_rwindow (regcache, sp, regnum); } @@ -148,14 +238,16 @@ sparc32obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) { struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - /* OpenBSD doesn't support the 128-bit `long double' from the psABI. */ - set_gdbarch_long_double_bit (gdbarch, 64); - set_gdbarch_long_double_format (gdbarch, &floatformat_ieee_double_big); + /* OpenBSD/sparc is very similar to NetBSD/sparc ELF. */ + sparc32nbsd_elf_init_abi (info, gdbarch); + + set_gdbarch_skip_solib_resolver (gdbarch, obsd_skip_solib_resolver); - frame_unwind_append_sniffer (gdbarch, sparc32obsd_sigtramp_frame_sniffer); + frame_unwind_append_unwinder (gdbarch, &sparc32obsd_sigtramp_frame_unwind); - set_solib_svr4_fetch_link_map_offsets - (gdbarch, nbsd_ilp32_solib_svr4_fetch_link_map_offsets); + /* OpenBSD provides a user-level threads implementation. */ + bsd_uthread_set_supply_uthread (gdbarch, sparc32obsd_supply_uthread); + bsd_uthread_set_collect_uthread (gdbarch, sparc32obsd_collect_uthread); }