From 81f726abf0aa11a89163ad39b7a0a5575d96b023 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 21 Apr 2005 22:04:04 +0000 Subject: * sparc-linux-tdep.c (sparc32_linux_sigframe_init): New function. (sparc32_linux_sigframe, sparc32_linux_rt_sigframe): New tramp_frames. (sparc_linux_sigtramp_start, sparc32_linux_sigtramp_start, sparc32_linux_rt_sigtramp_start, sparc32_linux_sigtramp_p, sparc32_linux_sigtramp_frame_cache, sparc32_linux_sigtramp_frame_this_id, sparc32_linux_sigtramp_frame_prev_register, sparc32_linux_sigtramp_frame_unwind, sparc32_linux_sigtramp_frame_sniffer): Delete. (sparc32_linux_init_abi): Register new tramp unwinders. Kill register of old sigtramp sniffer. * sparc64-linux-tdep.c (sparc64_linux_sigframe_init): New function. (sparc64_linux_rt_sigframe): New tramp frame. (sparc64_linux_sigtramp_start, sparc64_linux_sigtramp_p, sparc64_linux_sigtramp_frame_cache, sparc64_linux_sigtramp_frame_this_id, sparc64_linux_sigtramp_frame_prev_register, sparc64_linux_sigtramp_frame_unwind, sparc64_linux_sigtramp_frame_sniffer): Delete. (sparc64_linux_init_abi): Register new tramp unwinders. Kill register of old sigtramp sniffer. Makefile.in (sparc64-linux-tdep.o): Update dependencies. (sparc-linux-tdep.o): Likewise. --- gdb/sparc64-linux-tdep.c | 192 +++++++++++------------------------------------ 1 file changed, 45 insertions(+), 147 deletions(-) (limited to 'gdb/sparc64-linux-tdep.c') diff --git a/gdb/sparc64-linux-tdep.c b/gdb/sparc64-linux-tdep.c index 0047625b1c9..3401d2b4fcc 100644 --- a/gdb/sparc64-linux-tdep.c +++ b/gdb/sparc64-linux-tdep.c @@ -22,15 +22,13 @@ #include "defs.h" #include "frame.h" #include "frame-unwind.h" +#include "tramp-frame.h" #include "gdbarch.h" #include "osabi.h" #include "solib-svr4.h" #include "symtab.h" #include "trad-frame.h" -#include "gdb_assert.h" -#include "gdb_string.h" - #include "sparc64-tdep.h" /* The instruction sequence for RT signals is @@ -43,162 +41,62 @@ #define LINUX64_RT_SIGTRAMP_INSN0 0x82102065 #define LINUX64_RT_SIGTRAMP_INSN1 0x91d0206d -/* If PC is in a sigtramp routine consisting of the instructions - LINUX64_RT_SIGTRAMP_INSN0 and LINUX64_RT_SIGTRAMP_INSN1, return - the address of the start of the routine. Otherwise, return 0. */ - -static CORE_ADDR -sparc64_linux_sigtramp_start (struct frame_info *next_frame) -{ - CORE_ADDR pc = frame_pc_unwind (next_frame); - ULONGEST word0, word1; - unsigned char buf[8]; /* Two instructions. */ - - /* We only recognize a signal trampoline if PC is at the start of - one of the instructions. We optimize for finding the PC at the - start of the instruction sequence, as will be the case when the - trampoline is not the first frame on the stack. We assume that - in the case where the PC is not at the start of the instruction - sequence, there will be a few trailing readable bytes on the - stack. */ - - if (!safe_frame_unwind_memory (next_frame, pc, buf, sizeof buf)) - return 0; - - word0 = extract_unsigned_integer (buf, 4); - if (word0 != LINUX64_RT_SIGTRAMP_INSN0) - { - if (word0 != LINUX64_RT_SIGTRAMP_INSN1) - return 0; - - pc -= 4; - if (!safe_frame_unwind_memory (next_frame, pc, buf, sizeof buf)) - return 0; - - word0 = extract_unsigned_integer (buf, 4); - } - - word1 = extract_unsigned_integer (buf + 4, 4); - if (word0 != LINUX64_RT_SIGTRAMP_INSN0 - || word1 != LINUX64_RT_SIGTRAMP_INSN1) - return 0; - - return pc; -} - -static int -sparc64_linux_sigtramp_p (struct frame_info *next_frame) -{ - CORE_ADDR pc = frame_pc_unwind (next_frame); - char *name; - find_pc_partial_function (pc, &name, NULL, NULL); +static void sparc64_linux_sigframe_init (const struct tramp_frame *self, + struct frame_info *next_frame, + struct trad_frame_cache *this_cache, + CORE_ADDR func); - /* If we have NAME, we can optimize the search. The trampolines is - named __rt_sigreturn_stub. However, is isn't dynamically exported - from the shared C library, so the trampoline may appear to be part - of the preceding function. This should always be sigaction, - __sigaction, or __libc_sigaction (all aliases to the same function). */ - if (name == NULL || strstr (name, "sigaction") != NULL) - return (sparc64_linux_sigtramp_start (next_frame) != 0); - - return (strcmp ("__rt_sigreturn_stub", name) == 0); -} +static const struct tramp_frame sparc64_linux_rt_sigframe = { + SIGTRAMP_FRAME, + 4, + { + { LINUX64_RT_SIGTRAMP_INSN0, -1 }, + { LINUX64_RT_SIGTRAMP_INSN1, -1 }, + { TRAMP_SENTINEL_INSN, -1 } + }, + sparc64_linux_sigframe_init +}; -static struct sparc_frame_cache * -sparc64_linux_sigtramp_frame_cache (struct frame_info *next_frame, - void **this_cache) +static void +sparc64_linux_sigframe_init (const struct tramp_frame *self, + struct frame_info *next_frame, + struct trad_frame_cache *this_cache, + CORE_ADDR func) { - struct sparc_frame_cache *cache; - CORE_ADDR sigcontext_addr, addr; + CORE_ADDR base, addr; int regnum; - if (*this_cache) - return *this_cache; - - cache = sparc_frame_cache (next_frame, this_cache); - gdb_assert (cache == *this_cache); - - regnum = SPARC_SP_REGNUM; - cache->base = frame_unwind_register_unsigned (next_frame, regnum); - if (cache->base & 1) - cache->base += BIAS; - - regnum = SPARC_O1_REGNUM; - sigcontext_addr = frame_unwind_register_unsigned (next_frame, regnum); - - /* If this is a RT signal trampoline, adjust SIGCONTEXT_ADDR - accordingly. */ - addr = sparc64_linux_sigtramp_start (next_frame); - if (addr) - sigcontext_addr += 128; - else - addr = frame_func_unwind (next_frame); - - cache->pc = addr; - - cache->saved_regs = trad_frame_alloc_saved_regs (next_frame); + base = frame_unwind_register_unsigned (next_frame, SPARC_O1_REGNUM); + base += 128; /* Offsets from */ /* Since %g0 is always zero, keep the identity encoding. */ - for (addr = sigcontext_addr + 8, regnum = SPARC_G1_REGNUM; - regnum <= SPARC_O7_REGNUM; regnum++, addr += 8) - cache->saved_regs[regnum].addr = addr; - - cache->saved_regs[SPARC64_STATE_REGNUM].addr = addr + 0; - cache->saved_regs[SPARC64_PC_REGNUM].addr = addr + 8; - cache->saved_regs[SPARC64_NPC_REGNUM].addr = addr + 16; - cache->saved_regs[SPARC64_Y_REGNUM].addr = addr + 24; - cache->saved_regs[SPARC64_FPRS_REGNUM].addr = addr + 28; - - for (regnum = SPARC_L0_REGNUM, addr = cache->base; - regnum <= SPARC_I7_REGNUM; regnum++, addr += 8) - cache->saved_regs[regnum].addr = addr; - - return cache; -} - -static void -sparc64_linux_sigtramp_frame_this_id (struct frame_info *next_frame, - void **this_cache, - struct frame_id *this_id) -{ - struct sparc_frame_cache *cache = - sparc64_linux_sigtramp_frame_cache (next_frame, this_cache); - - (*this_id) = frame_id_build (cache->base, cache->pc); -} - -static void -sparc64_linux_sigtramp_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 = - sparc64_linux_sigtramp_frame_cache (next_frame, this_cache); + addr = base + 0x08; + for (regnum = SPARC_G1_REGNUM; regnum <= SPARC_O7_REGNUM; regnum++) + { + trad_frame_set_reg_addr (this_cache, regnum, addr); + addr += 8; + } - trad_frame_get_prev_register (next_frame, cache->saved_regs, regnum, - optimizedp, lvalp, addrp, realnump, valuep); -} + trad_frame_set_reg_addr (this_cache, SPARC64_STATE_REGNUM, addr + 0x00); + trad_frame_set_reg_addr (this_cache, SPARC64_PC_REGNUM, addr + 0x08); + trad_frame_set_reg_addr (this_cache, SPARC64_NPC_REGNUM, addr + 0x10); + trad_frame_set_reg_addr (this_cache, SPARC64_Y_REGNUM, addr + 0x18); + trad_frame_set_reg_addr (this_cache, SPARC64_FPRS_REGNUM, addr + 0x1c); -static const struct frame_unwind sparc64_linux_sigtramp_frame_unwind = -{ - SIGTRAMP_FRAME, - sparc64_linux_sigtramp_frame_this_id, - sparc64_linux_sigtramp_frame_prev_register -}; - -static const struct frame_unwind * -sparc64_linux_sigtramp_frame_sniffer (struct frame_info *next_frame) -{ - if (sparc64_linux_sigtramp_p (next_frame)) - return &sparc64_linux_sigtramp_frame_unwind; + addr = frame_unwind_register_unsigned (next_frame, SPARC_SP_REGNUM); + if (addr & 1) + addr += BIAS; - return NULL; + base = addr; + for (regnum = SPARC_L0_REGNUM; regnum <= SPARC_I7_REGNUM; regnum++) + { + trad_frame_set_reg_addr (this_cache, regnum, addr); + addr += 8; + } + trad_frame_set_id (this_cache, frame_id_build (base, func)); } static void @@ -206,7 +104,7 @@ sparc64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) { struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - frame_unwind_append_sniffer (gdbarch, sparc64_linux_sigtramp_frame_sniffer); + tramp_frame_prepend_unwinder (gdbarch, &sparc64_linux_rt_sigframe); /* GNU/Linux is very similar to Solaris ... */ sparc64_sol2_init_abi (info, gdbarch); -- cgit v1.2.1