From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 14143 invoked by alias); 21 Apr 2005 21:41:24 -0000 Mailing-List: contact gdb-patches-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sources.redhat.com Received: (qmail 14091 invoked from network); 21 Apr 2005 21:41:12 -0000 Received: from unknown (HELO cheetah.davemloft.net) (216.27.180.174) by sourceware.org with SMTP; 21 Apr 2005 21:41:12 -0000 Received: from localhost ([127.0.0.1] helo=cheetah.davemloft.net ident=davem) by cheetah.davemloft.net with smtp (Exim 3.36 #1 (Debian)) id 1DOjJS-0002dO-00; Thu, 21 Apr 2005 14:34:18 -0700 Date: Thu, 21 Apr 2005 21:41:00 -0000 From: "David S. Miller" To: Mark Kettenis Cc: gdb-patches@sources.redhat.com Subject: Re: [PATCH] Add sparc64-linux sigtramp support Message-Id: <20050421143418.26d8a104.davem@davemloft.net> In-Reply-To: <200504212120.j3LLKB42010991@elgar.sibelius.xs4all.nl> References: <20050420204427.20d670e6.davem@davemloft.net> <200504211923.j3LJNHo6010891@elgar.sibelius.xs4all.nl> <20050421122250.6108168c.davem@davemloft.net> <200504212120.j3LLKB42010991@elgar.sibelius.xs4all.nl> Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable X-SW-Source: 2005-04/txt/msg00266.txt.bz2 On Thu, 21 Apr 2005 23:20:11 +0200 (CEST) Mark Kettenis wrote: > It'd be great if you could convert things to use the tramp_frame > stuff. Should be doable for SPARC/UltraSPARC Linux without too much > effort, and simplify the code a bit. Done. How does this look? 2005-04-21 David S. Miller * 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. --- Makefile.in 21 Apr 2005 19:38:19 -0000 1.717 +++ Makefile.in 21 Apr 2005 21:36:53 -0000 @@ -2567,7 +2567,7 @@ sparc64-linux-nat.o: sparc64-linux-nat.c $(sparc_nat_h) sparc64-linux-tdep.o: sparc64-linux-tdep.c $(defs_h) $(frame_h) \ $(frame_unwind_h) $(gdbarch_h) $(osabi_h) $(solib_svr4_h) \ - $(symtab_h) $(trad_frame_h) $(gdb_assert_h) $(gdb_string_h) \ + $(symtab_h) $(trad_frame_h) \ $(sparc64_tdep_h) sparc64-nat.o: sparc64-nat.c $(defs_h) $(gdbarch_h) $(sparc64_tdep_h) \ $(sparc_nat_h) @@ -2590,8 +2590,8 @@ sparc64-tdep.o: sparc64-tdep.c $(defs_h) $(sparc64_tdep_h) sparc-linux-tdep.o: sparc-linux-tdep.c $(defs_h) $(floatformat_h) $(frame_= h) \ $(frame_unwind_h) $(gdbarch_h) $(gdbcore_h) $(osabi_h) $(regcache_h) \ - $(solib_svr4_h) $(symtab_h) $(trad_frame_h) $(gdb_assert_h) \ - $(gdb_string_h) $(sparc_tdep_h) + $(solib_svr4_h) $(symtab_h) $(trad_frame_h) \ + $(sparc_tdep_h) sparc-nat.o: sparc-nat.c $(defs_h) $(inferior_h) $(regcache_h) $(target_h)= \ $(gdb_assert_h) $(gdb_string_h) $(gdb_wait_h) $(sparc_tdep_h) \ $(sparc_nat_h) $(inf_ptrace_h) --- sparc-linux-tdep.c 21 Apr 2005 19:38:20 -0000 1.10 +++ sparc-linux-tdep.c 21 Apr 2005 21:36:53 -0000 @@ -23,6 +23,7 @@ #include "floatformat.h" #include "frame.h" #include "frame-unwind.h" +#include "tramp-frame.h" #include "gdbarch.h" #include "gdbcore.h" #include "osabi.h" @@ -31,12 +32,9 @@ #include "symtab.h" #include "trad-frame.h" =20 -#include "gdb_assert.h" -#include "gdb_string.h" - #include "sparc-tdep.h" =20 -/* Recognizing signal handler frames. */ +/* Signal trampoline support. */ =20 /* GNU/Linux has two flavors of signals. Normal signal handlers, and "realtime" (RT) signals. The RT signals can provide additional @@ -69,195 +67,86 @@ =20 /* The instruction sequence for RT signals is mov __NR_rt_sigreturn, %g1 ! hex: 0x82102065 - ta {0x10,0x6d} ! hex: 0x91d02010 or 0x91d0206d + ta {0x10,0x6d} ! hex: 0x91d02010 =20 - The effect is to call the system call rt_sigreturn. The trap number - is variable based upon whether this is a 32-bit or 64-bit sparc binary. + The effect is to call the system call rt_sigreturn. Note that 64-bit binaries only use this RT signal return method. */ =20 #define LINUX32_RT_SIGTRAMP_INSN0 0x82102065 #define LINUX32_RT_SIGTRAMP_INSN1 0x91d02010 =20 -/* If PC is in a sigtramp routine consisting of the instructions INSN0 - and INSN1, return the address of the start of the routine. - Otherwise, return 0. */ - -CORE_ADDR -sparc_linux_sigtramp_start (struct frame_info *next_frame, - ULONGEST insn0, ULONGEST insn1) -{ - CORE_ADDR pc =3D 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 =3D extract_unsigned_integer (buf, 4); - if (word0 !=3D insn0) - { - if (word0 !=3D insn1) - return 0; - - pc -=3D 4; - if (!safe_frame_unwind_memory (next_frame, pc, buf, sizeof buf)) - return 0; - - word0 =3D extract_unsigned_integer (buf, 4); - } - - word1 =3D extract_unsigned_integer (buf + 4, 4); - if (word0 !=3D insn0 || word1 !=3D insn1) - return 0; - - return pc; -} - -static CORE_ADDR -sparc32_linux_sigtramp_start (struct frame_info *next_frame) -{ - return sparc_linux_sigtramp_start (next_frame, LINUX32_SIGTRAMP_INSN0, - LINUX32_SIGTRAMP_INSN1); -} - -static CORE_ADDR -sparc32_linux_rt_sigtramp_start (struct frame_info *next_frame) -{ - return sparc_linux_sigtramp_start (next_frame, LINUX32_RT_SIGTRAMP_INSN0, - LINUX32_RT_SIGTRAMP_INSN1); -} +static void sparc32_linux_sigframe_init (const struct tramp_frame *self, + struct frame_info *next_frame, + struct trad_frame_cache *this_cache, + CORE_ADDR func); =20 -static int -sparc32_linux_sigtramp_p (struct frame_info *next_frame) -{ - CORE_ADDR pc =3D frame_pc_unwind (next_frame); - char *name; - - find_pc_partial_function (pc, &name, NULL, NULL); - - /* If we have NAME, we can optimize the search. The trampolines are - named __sigreturn_stub and __rt_sigreturn_stub. However, they - aren'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 =3D=3D NULL || strstr (name, "sigaction") !=3D NULL) - return (sparc32_linux_sigtramp_start (next_frame) !=3D 0 - || sparc32_linux_rt_sigtramp_start (next_frame) !=3D 0); +static const struct tramp_frame sparc32_linux_sigframe =3D { + SIGTRAMP_FRAME, + 4, + { + { LINUX32_SIGTRAMP_INSN0, -1 }, + { LINUX32_SIGTRAMP_INSN1, -1 }, + { TRAMP_SENTINEL_INSN, -1 } + }, + sparc32_linux_sigframe_init +}; =20 - return (strcmp ("__sigreturn_stub", name) =3D=3D 0 - || strcmp ("__rt_sigreturn_stub", name) =3D=3D 0); -} +static const struct tramp_frame sparc32_linux_rt_sigframe =3D { + SIGTRAMP_FRAME, + 4, + { + { LINUX32_RT_SIGTRAMP_INSN0, -1 }, + { LINUX32_RT_SIGTRAMP_INSN1, -1 }, + { TRAMP_SENTINEL_INSN, -1 } + }, + sparc32_linux_sigframe_init +}; =20 -static struct sparc_frame_cache * -sparc32_linux_sigtramp_frame_cache (struct frame_info *next_frame, - void **this_cache) +static void +sparc32_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; =20 - if (*this_cache) - return *this_cache; - - cache =3D sparc32_frame_cache (next_frame, this_cache); - gdb_assert (cache =3D=3D *this_cache); - - /* ??? What about signal trampolines that aren't frameless? */ - regnum =3D SPARC_SP_REGNUM; - cache->base =3D frame_unwind_register_unsigned (next_frame, regnum); - - regnum =3D SPARC_O1_REGNUM; - sigcontext_addr =3D frame_unwind_register_unsigned (next_frame, regnum); - - addr =3D sparc32_linux_sigtramp_start (next_frame); - if (addr =3D=3D 0) - { - /* If this is a RT signal trampoline, adjust SIGCONTEXT_ADDR - accordingly. */ - addr =3D sparc32_linux_rt_sigtramp_start (next_frame); - if (addr) - sigcontext_addr +=3D 128; - else - addr =3D frame_func_unwind (next_frame); - } - cache->pc =3D addr; - - cache->saved_regs =3D trad_frame_alloc_saved_regs (next_frame); + base =3D frame_unwind_register_unsigned (next_frame, SPARC_O1_REGNUM); + if (self =3D=3D &sparc32_linux_rt_sigframe) + base +=3D 128; =20 /* Offsets from */ =20 - cache->saved_regs[SPARC32_PSR_REGNUM].addr =3D sigcontext_addr + 0; - cache->saved_regs[SPARC32_PC_REGNUM].addr =3D sigcontext_addr + 4; - cache->saved_regs[SPARC32_NPC_REGNUM].addr =3D sigcontext_addr + 8; - cache->saved_regs[SPARC32_Y_REGNUM].addr =3D sigcontext_addr + 12; + trad_frame_set_reg_addr (this_cache, SPARC32_PSR_REGNUM, base + 0x00); + trad_frame_set_reg_addr (this_cache, SPARC32_PC_REGNUM, base + 0x04); + trad_frame_set_reg_addr (this_cache, SPARC32_NPC_REGNUM, base + 0x08); + trad_frame_set_reg_addr (this_cache, SPARC32_Y_REGNUM, base + 0x0c); =20 /* Since %g0 is always zero, keep the identity encoding. */ - for (regnum =3D SPARC_G1_REGNUM, addr =3D sigcontext_addr + 20; - regnum <=3D SPARC_O7_REGNUM; regnum++, addr +=3D 4) - cache->saved_regs[regnum].addr =3D addr; - - for (regnum =3D SPARC_L0_REGNUM, addr =3D cache->base; - regnum <=3D SPARC_I7_REGNUM; regnum++, addr +=3D 4) - cache->saved_regs[regnum].addr =3D addr; - - return cache; -} - -static void -sparc32_linux_sigtramp_frame_this_id (struct frame_info *next_frame, - void **this_cache, - struct frame_id *this_id) -{ - struct sparc_frame_cache *cache =3D - sparc32_linux_sigtramp_frame_cache (next_frame, this_cache); - - (*this_id) =3D frame_id_build (cache->base, cache->pc); -} - -static void -sparc32_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 =3D - sparc32_linux_sigtramp_frame_cache (next_frame, this_cache); + addr =3D base + 0x14; + for (regnum =3D SPARC_G1_REGNUM; regnum <=3D SPARC_O7_REGNUM; regnum++) + { + trad_frame_set_reg_addr (this_cache, regnum, addr); + addr +=3D 4; + } =20 - trad_frame_get_prev_register (next_frame, cache->saved_regs, regnum, - optimizedp, lvalp, addrp, realnump, valuep); + base =3D addr =3D frame_unwind_register_unsigned (next_frame, SPARC_SP_R= EGNUM); + for (regnum =3D SPARC_L0_REGNUM; regnum <=3D SPARC_I7_REGNUM; regnum++) + { + trad_frame_set_reg_addr (this_cache, regnum, addr); + addr +=3D 4; + } + trad_frame_set_id (this_cache, frame_id_build (base, func)); } =20 -static const struct frame_unwind sparc32_linux_sigtramp_frame_unwind =3D -{ - SIGTRAMP_FRAME, - sparc32_linux_sigtramp_frame_this_id, - sparc32_linux_sigtramp_frame_prev_register -}; - -static const struct frame_unwind * -sparc32_linux_sigtramp_frame_sniffer (struct frame_info *next_frame) -{ - if (sparc32_linux_sigtramp_p (next_frame)) - return &sparc32_linux_sigtramp_frame_unwind; - - return NULL; -} =0C =20 static void sparc32_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) { + tramp_frame_prepend_unwinder (gdbarch, &sparc32_linux_sigframe); + tramp_frame_prepend_unwinder (gdbarch, &sparc32_linux_rt_sigframe); + /* GNU/Linux is very similar to Solaris ... */ sparc32_sol2_init_abi (info, gdbarch); =20 @@ -268,8 +157,6 @@ sparc32_linux_init_abi (struct gdbarch_i set_gdbarch_long_double_bit (gdbarch, 64); set_gdbarch_long_double_format (gdbarch, &floatformat_ieee_double_big); =20 - frame_unwind_append_sniffer (gdbarch, sparc32_linux_sigtramp_frame_sniff= er); - /* Enable TLS support. */ set_gdbarch_fetch_tls_load_module_address (gdbarch, svr4_fetch_objfile_link_map); --- sparc64-linux-tdep.c 21 Apr 2005 19:38:20 -0000 1.5 +++ sparc64-linux-tdep.c 21 Apr 2005 21:36:53 -0000 @@ -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" =20 -#include "gdb_assert.h" -#include "gdb_string.h" - #include "sparc64-tdep.h" =20 /* The instruction sequence for RT signals is @@ -43,162 +41,62 @@ #define LINUX64_RT_SIGTRAMP_INSN0 0x82102065 #define LINUX64_RT_SIGTRAMP_INSN1 0x91d0206d =20 -/* 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 =3D 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 =3D extract_unsigned_integer (buf, 4); - if (word0 !=3D LINUX64_RT_SIGTRAMP_INSN0) - { - if (word0 !=3D LINUX64_RT_SIGTRAMP_INSN1) - return 0; - - pc -=3D 4; - if (!safe_frame_unwind_memory (next_frame, pc, buf, sizeof buf)) - return 0; - - word0 =3D extract_unsigned_integer (buf, 4); - } - - word1 =3D extract_unsigned_integer (buf + 4, 4); - if (word0 !=3D LINUX64_RT_SIGTRAMP_INSN0 - || word1 !=3D LINUX64_RT_SIGTRAMP_INSN1) - return 0; - - return pc; -} - -static int -sparc64_linux_sigtramp_p (struct frame_info *next_frame) -{ - CORE_ADDR pc =3D frame_pc_unwind (next_frame); - char *name; =20 - 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); =20 - /* 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 =3D=3D NULL || strstr (name, "sigaction") !=3D NULL) - return (sparc64_linux_sigtramp_start (next_frame) !=3D 0); - - return (strcmp ("__rt_sigreturn_stub", name) =3D=3D 0); -} +static const struct tramp_frame sparc64_linux_rt_sigframe =3D { + SIGTRAMP_FRAME, + 4, + { + { LINUX64_RT_SIGTRAMP_INSN0, -1 }, + { LINUX64_RT_SIGTRAMP_INSN1, -1 }, + { TRAMP_SENTINEL_INSN, -1 } + }, + sparc64_linux_sigframe_init +}; =20 -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; =20 - if (*this_cache) - return *this_cache; - - cache =3D sparc_frame_cache (next_frame, this_cache); - gdb_assert (cache =3D=3D *this_cache); - - regnum =3D SPARC_SP_REGNUM; - cache->base =3D frame_unwind_register_unsigned (next_frame, regnum); - if (cache->base & 1) - cache->base +=3D BIAS; - - regnum =3D SPARC_O1_REGNUM; - sigcontext_addr =3D frame_unwind_register_unsigned (next_frame, regnum); - - /* If this is a RT signal trampoline, adjust SIGCONTEXT_ADDR - accordingly. */ - addr =3D sparc64_linux_sigtramp_start (next_frame); - if (addr) - sigcontext_addr +=3D 128; - else - addr =3D frame_func_unwind (next_frame); - - cache->pc =3D addr; - - cache->saved_regs =3D trad_frame_alloc_saved_regs (next_frame); + base =3D frame_unwind_register_unsigned (next_frame, SPARC_O1_REGNUM); + base +=3D 128; =20 /* Offsets from */ =20 /* Since %g0 is always zero, keep the identity encoding. */ - for (addr =3D sigcontext_addr + 8, regnum =3D SPARC_G1_REGNUM; - regnum <=3D SPARC_O7_REGNUM; regnum++, addr +=3D 8) - cache->saved_regs[regnum].addr =3D addr; - - cache->saved_regs[SPARC64_STATE_REGNUM].addr =3D addr + 0; - cache->saved_regs[SPARC64_PC_REGNUM].addr =3D addr + 8; - cache->saved_regs[SPARC64_NPC_REGNUM].addr =3D addr + 16; - cache->saved_regs[SPARC64_Y_REGNUM].addr =3D addr + 24; - cache->saved_regs[SPARC64_FPRS_REGNUM].addr =3D addr + 28; - - for (regnum =3D SPARC_L0_REGNUM, addr =3D cache->base; - regnum <=3D SPARC_I7_REGNUM; regnum++, addr +=3D 8) - cache->saved_regs[regnum].addr =3D 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 =3D - sparc64_linux_sigtramp_frame_cache (next_frame, this_cache); - - (*this_id) =3D 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 =3D - sparc64_linux_sigtramp_frame_cache (next_frame, this_cache); - - trad_frame_get_prev_register (next_frame, cache->saved_regs, regnum, - optimizedp, lvalp, addrp, realnump, valuep); -} - -static const struct frame_unwind sparc64_linux_sigtramp_frame_unwind =3D -{ - SIGTRAMP_FRAME, - sparc64_linux_sigtramp_frame_this_id, - sparc64_linux_sigtramp_frame_prev_register -}; + addr =3D base + 0x08; + for (regnum =3D SPARC_G1_REGNUM; regnum <=3D SPARC_O7_REGNUM; regnum++) + { + trad_frame_set_reg_addr (this_cache, regnum, addr); + addr +=3D 8; + } =20 -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; + 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); + + addr =3D frame_unwind_register_unsigned (next_frame, SPARC_SP_REGNUM); + if (addr & 1) + addr +=3D BIAS; =20 - return NULL; + base =3D addr; + for (regnum =3D SPARC_L0_REGNUM; regnum <=3D SPARC_I7_REGNUM; regnum++) + { + trad_frame_set_reg_addr (this_cache, regnum, addr); + addr +=3D 8; + } + trad_frame_set_id (this_cache, frame_id_build (base, func)); } =0C static void @@ -206,7 +104,7 @@ sparc64_linux_init_abi (struct gdbarch_i { struct gdbarch_tdep *tdep =3D gdbarch_tdep (gdbarch); =20 - frame_unwind_append_sniffer (gdbarch, sparc64_linux_sigtramp_frame_sniff= er); + tramp_frame_prepend_unwinder (gdbarch, &sparc64_linux_rt_sigframe); =20 /* GNU/Linux is very similar to Solaris ... */ sparc64_sol2_init_abi (info, gdbarch);