From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 19382 invoked by alias); 25 Mar 2004 01:28:04 -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 19240 invoked from network); 25 Mar 2004 01:28:00 -0000 Received: from unknown (HELO nevyn.them.org) (66.93.172.17) by sources.redhat.com with SMTP; 25 Mar 2004 01:28:00 -0000 Received: from drow by nevyn.them.org with local (Exim 4.30 #1 (Debian)) id 1B6Jf4-00024l-Ew for ; Wed, 24 Mar 2004 20:27:58 -0500 Date: Thu, 25 Mar 2004 01:28:00 -0000 From: Daniel Jacobowitz To: gdb-patches@sources.redhat.com Subject: Re: [patch/rfa-mips] MIPS GNU/Linux sigtramp unwinders Message-ID: <20040325012758.GA7940@nevyn.them.org> Mail-Followup-To: gdb-patches@sources.redhat.com References: <20040324192041.GA21977@nevyn.them.org> <406225B7.8030403@gnu.org> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <406225B7.8030403@gnu.org> User-Agent: Mutt/1.5.1i X-SW-Source: 2004-03/txt/msg00585.txt.bz2 On Wed, Mar 24, 2004 at 07:20:07PM -0500, Andrew Cagney wrote: > > /* Unwind the frame. */ > > set_gdbarch_unwind_pc (gdbarch, mips_unwind_pc); > >- frame_unwind_append_sniffer (gdbarch, mips_mdebug_frame_sniffer); > > set_gdbarch_unwind_dummy_id (gdbarch, mips_unwind_dummy_id); > >- frame_base_append_sniffer (gdbarch, mips_mdebug_frame_base_sniffer); > > > > /* Map debug register numbers onto internal register numbers. */ > > set_gdbarch_stab_reg_to_regnum (gdbarch, mips_stab_reg_to_regnum); > >@@ -5807,6 +5805,10 @@ mips_gdbarch_init (struct gdbarch_info i > > > > /* Hook in OS ABI-specific overrides, if they have been registered. */ > > gdbarch_init_osabi (info, gdbarch); > >+ > >+ /* Unwind the frame. */ > >+ frame_unwind_append_sniffer (gdbarch, mips_mdebug_frame_sniffer); > >+ frame_base_append_sniffer (gdbarch, mips_mdebug_frame_base_sniffer); > > Yes, ok. I did the same move for PPC. OK, here's what I checked in (with the TRAMP_SENTINEL_INSN change). -- Daniel Jacobowitz MontaVista Software Debian GNU/Linux Developer 2004-03-24 Daniel Jacobowitz * Makefile.in (mips-linux-tdep.o): Update dependencies. * mips-tdep.c (mips_gdbarch_init): Move frame predicates to after osabi initialization. * mips-linux-tdep.c: Include "trad-frame.h" and "tramp-frame.h". (mips_linux_o32_sigframe_init, mips_linux_n32n64_sigframe_init): New functions. (mips_linux_o32_sigframe, mips_linux_o32_rt_sigframe) (mips_linux_n32_rt_sigframe, mips_linux_n64_rt_sigframe): New variables. (mips_linux_init_abi): Append signal trampoline unwinders. Index: Makefile.in =================================================================== RCS file: /big/fsf/rsync/src-cvs/src/gdb/Makefile.in,v retrieving revision 1.529 diff -u -p -r1.529 Makefile.in --- Makefile.in 23 Mar 2004 14:12:30 -0000 1.529 +++ Makefile.in 24 Mar 2004 01:12:01 -0000 @@ -2052,7 +2052,7 @@ mips-irix-tdep.o: mips-irix-tdep.c $(def mips-linux-nat.o: mips-linux-nat.c $(defs_h) $(mips_tdep_h) mips-linux-tdep.o: mips-linux-tdep.c $(defs_h) $(gdbcore_h) $(target_h) \ $(solib_svr4_h) $(osabi_h) $(mips_tdep_h) $(gdb_string_h) \ - $(gdb_assert_h) $(frame_h) + $(gdb_assert_h) $(frame_h) $(trad_frame_h) $(tramp_frame_h) mips-nat.o: mips-nat.c $(defs_h) $(inferior_h) $(gdbcore_h) $(regcache_h) mipsnbsd-nat.o: mipsnbsd-nat.c $(defs_h) $(inferior_h) $(regcache_h) \ $(mipsnbsd_tdep_h) Index: mips-linux-tdep.c =================================================================== RCS file: /big/fsf/rsync/src-cvs/src/gdb/mips-linux-tdep.c,v retrieving revision 1.20 diff -u -p -r1.20 mips-linux-tdep.c --- mips-linux-tdep.c 15 Mar 2004 20:38:08 -0000 1.20 +++ mips-linux-tdep.c 24 Mar 2004 19:13:13 -0000 @@ -28,6 +28,8 @@ #include "gdb_string.h" #include "gdb_assert.h" #include "frame.h" +#include "trad-frame.h" +#include "tramp-frame.h" /* Copied from . */ #define ELF_NGREG 45 @@ -797,6 +799,312 @@ mips_linux_skip_resolver (struct gdbarch return 0; } +/* Signal trampoline support. There are four supported layouts for a + signal frame: o32 sigframe, o32 rt_sigframe, n32 rt_sigframe, and + n64 rt_sigframe. We handle them all independently; not the most + efficient way, but simplest. First, declare all the unwinders. */ + +static void mips_linux_o32_sigframe_init (const struct tramp_frame *self, + struct frame_info *next_frame, + struct trad_frame_cache *this_cache, + CORE_ADDR func); + +static void mips_linux_n32n64_sigframe_init (const struct tramp_frame *self, + struct frame_info *next_frame, + struct trad_frame_cache *this_cache, + CORE_ADDR func); + +#define MIPS_NR_LINUX 4000 +#define MIPS_NR_N64_LINUX 5000 +#define MIPS_NR_N32_LINUX 6000 + +#define MIPS_NR_sigreturn MIPS_NR_LINUX + 119 +#define MIPS_NR_rt_sigreturn MIPS_NR_LINUX + 193 +#define MIPS_NR_N64_rt_sigreturn MIPS_NR_N64_LINUX + 211 +#define MIPS_NR_N32_rt_sigreturn MIPS_NR_N32_LINUX + 211 + +#define MIPS_INST_LI_V0_SIGRETURN 0x24020000 + MIPS_NR_sigreturn +#define MIPS_INST_LI_V0_RT_SIGRETURN 0x24020000 + MIPS_NR_rt_sigreturn +#define MIPS_INST_LI_V0_N64_RT_SIGRETURN 0x24020000 + MIPS_NR_N64_rt_sigreturn +#define MIPS_INST_LI_V0_N32_RT_SIGRETURN 0x24020000 + MIPS_NR_N32_rt_sigreturn +#define MIPS_INST_SYSCALL 0x0000000c + +struct tramp_frame mips_linux_o32_sigframe = { + 4, + { MIPS_INST_LI_V0_SIGRETURN, MIPS_INST_SYSCALL, TRAMP_SENTINEL_INSN }, + mips_linux_o32_sigframe_init +}; + +struct tramp_frame mips_linux_o32_rt_sigframe = { + 4, + { MIPS_INST_LI_V0_RT_SIGRETURN, MIPS_INST_SYSCALL, TRAMP_SENTINEL_INSN }, + mips_linux_o32_sigframe_init +}; + +struct tramp_frame mips_linux_n32_rt_sigframe = { + 4, + { MIPS_INST_LI_V0_N32_RT_SIGRETURN, MIPS_INST_SYSCALL, TRAMP_SENTINEL_INSN }, + mips_linux_n32n64_sigframe_init +}; + +struct tramp_frame mips_linux_n64_rt_sigframe = { + 4, + { MIPS_INST_LI_V0_N64_RT_SIGRETURN, MIPS_INST_SYSCALL, TRAMP_SENTINEL_INSN }, + mips_linux_n32n64_sigframe_init +}; + +/* *INDENT-OFF* */ +/* The unwinder for o32 signal frames. The legacy structures look + like this: + + struct sigframe { + u32 sf_ass[4]; [argument save space for o32] + u32 sf_code[2]; [signal trampoline] + struct sigcontext sf_sc; + sigset_t sf_mask; + }; + + struct sigcontext { + unsigned int sc_regmask; [Unused] + unsigned int sc_status; + unsigned long long sc_pc; + unsigned long long sc_regs[32]; + unsigned long long sc_fpregs[32]; + unsigned int sc_ownedfp; + unsigned int sc_fpc_csr; + unsigned int sc_fpc_eir; [Unused] + unsigned int sc_used_math; + unsigned int sc_ssflags; [Unused] + [Alignment hole of four bytes] + unsigned long long sc_mdhi; + unsigned long long sc_mdlo; + + unsigned int sc_cause; [Unused] + unsigned int sc_badvaddr; [Unused] + + unsigned long sc_sigset[4]; [kernel's sigset_t] + }; + + The RT signal frames look like this: + + struct rt_sigframe { + u32 rs_ass[4]; [argument save space for o32] + u32 rs_code[2] [signal trampoline] + struct siginfo rs_info; + struct ucontext rs_uc; + }; + + struct ucontext { + unsigned long uc_flags; + struct ucontext *uc_link; + stack_t uc_stack; + [Alignment hole of four bytes] + struct sigcontext uc_mcontext; + sigset_t uc_sigmask; + }; */ +/* *INDENT-ON* */ + +#define SIGFRAME_CODE_OFFSET (4 * 4) +#define SIGFRAME_SIGCONTEXT_OFFSET (6 * 4) + +#define RTSIGFRAME_SIGINFO_SIZE 128 +#define STACK_T_SIZE (3 * 4) +#define UCONTEXT_SIGCONTEXT_OFFSET (2 * 4 + STACK_T_SIZE + 4) +#define RTSIGFRAME_SIGCONTEXT_OFFSET (SIGFRAME_SIGCONTEXT_OFFSET \ + + RTSIGFRAME_SIGINFO_SIZE \ + + UCONTEXT_SIGCONTEXT_OFFSET) + +#define SIGCONTEXT_PC (1 * 8) +#define SIGCONTEXT_REGS (2 * 8) +#define SIGCONTEXT_FPREGS (34 * 8) +#define SIGCONTEXT_FPCSR (66 * 8 + 4) +#define SIGCONTEXT_HI (69 * 8) +#define SIGCONTEXT_LO (70 * 8) +#define SIGCONTEXT_CAUSE (71 * 8 + 0) +#define SIGCONTEXT_BADVADDR (71 * 8 + 4) + +#define SIGCONTEXT_REG_SIZE 8 + +static void +mips_linux_o32_sigframe_init (const struct tramp_frame *self, + struct frame_info *next_frame, + struct trad_frame_cache *this_cache, + CORE_ADDR func) +{ + int ireg, reg_position; + CORE_ADDR sigcontext_base = func - SIGFRAME_CODE_OFFSET; + const struct mips_regnum *regs = mips_regnum (current_gdbarch); + + if (self == &mips_linux_o32_sigframe) + sigcontext_base += SIGFRAME_SIGCONTEXT_OFFSET; + else + sigcontext_base += RTSIGFRAME_SIGCONTEXT_OFFSET; + + /* I'm not proud of this hack. Eventually we will have the infrastructure + to indicate the size of saved registers on a per-frame basis, but + right now we don't; the kernel saves eight bytes but we only want + four. */ + if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG) + sigcontext_base += 4; + +#if 0 + trad_frame_set_reg_addr (this_cache, ORIG_ZERO_REGNUM + NUM_REGS, + sigcontext_base + SIGCONTEXT_REGS); +#endif + + for (ireg = 1; ireg < 32; ireg++) + trad_frame_set_reg_addr (this_cache, ireg + ZERO_REGNUM + NUM_REGS, + sigcontext_base + SIGCONTEXT_REGS + + ireg * SIGCONTEXT_REG_SIZE); + + for (ireg = 0; ireg < 32; ireg++) + trad_frame_set_reg_addr (this_cache, ireg + regs->fp0 + NUM_REGS, + sigcontext_base + SIGCONTEXT_FPREGS + + ireg * SIGCONTEXT_REG_SIZE); + + trad_frame_set_reg_addr (this_cache, regs->pc + NUM_REGS, + sigcontext_base + SIGCONTEXT_PC); + + trad_frame_set_reg_addr (this_cache, regs->fp_control_status + NUM_REGS, + sigcontext_base + SIGCONTEXT_FPCSR); + trad_frame_set_reg_addr (this_cache, regs->hi + NUM_REGS, + sigcontext_base + SIGCONTEXT_HI); + trad_frame_set_reg_addr (this_cache, regs->lo + NUM_REGS, + sigcontext_base + SIGCONTEXT_LO); + trad_frame_set_reg_addr (this_cache, regs->cause + NUM_REGS, + sigcontext_base + SIGCONTEXT_CAUSE); + trad_frame_set_reg_addr (this_cache, regs->badvaddr + NUM_REGS, + sigcontext_base + SIGCONTEXT_BADVADDR); + + /* Choice of the bottom of the sigframe is somewhat arbitrary. */ + trad_frame_set_id (this_cache, + frame_id_build (func - SIGFRAME_CODE_OFFSET, func)); +} + +/* *INDENT-OFF* */ +/* For N32/N64 things look different. There is no non-rt signal frame. + + struct rt_sigframe_n32 { + u32 rs_ass[4]; [ argument save space for o32 ] + u32 rs_code[2]; [ signal trampoline ] + struct siginfo rs_info; + struct ucontextn32 rs_uc; + }; + + struct ucontextn32 { + u32 uc_flags; + s32 uc_link; + stack32_t uc_stack; + struct sigcontext uc_mcontext; + sigset_t uc_sigmask; [ mask last for extensibility ] + }; + + struct rt_sigframe_n32 { + u32 rs_ass[4]; [ argument save space for o32 ] + u32 rs_code[2]; [ signal trampoline ] + struct siginfo rs_info; + struct ucontext rs_uc; + }; + + struct ucontext { + unsigned long uc_flags; + struct ucontext *uc_link; + stack_t uc_stack; + struct sigcontext uc_mcontext; + sigset_t uc_sigmask; [ mask last for extensibility ] + }; + + And the sigcontext is different (this is for both n32 and n64): + + struct sigcontext { + unsigned long long sc_regs[32]; + unsigned long long sc_fpregs[32]; + unsigned long long sc_mdhi; + unsigned long long sc_mdlo; + unsigned long long sc_pc; + unsigned int sc_status; + unsigned int sc_fpc_csr; + unsigned int sc_fpc_eir; + unsigned int sc_used_math; + unsigned int sc_cause; + unsigned int sc_badvaddr; + }; */ +/* *INDENT-ON* */ + +#define N32_STACK_T_SIZE STACK_T_SIZE +#define N64_STACK_T_SIZE (2 * 8 + 4) +#define N32_UCONTEXT_SIGCONTEXT_OFFSET (2 * 4 + N32_STACK_T_SIZE + 4) +#define N64_UCONTEXT_SIGCONTEXT_OFFSET (2 * 8 + N64_STACK_T_SIZE + 4) +#define N32_SIGFRAME_SIGCONTEXT_OFFSET (SIGFRAME_SIGCONTEXT_OFFSET \ + + RTSIGFRAME_SIGINFO_SIZE \ + + N32_UCONTEXT_SIGCONTEXT_OFFSET) +#define N64_SIGFRAME_SIGCONTEXT_OFFSET (SIGFRAME_SIGCONTEXT_OFFSET \ + + RTSIGFRAME_SIGINFO_SIZE \ + + N64_UCONTEXT_SIGCONTEXT_OFFSET) + +#define N64_SIGCONTEXT_REGS (0 * 8) +#define N64_SIGCONTEXT_FPREGS (32 * 8) +#define N64_SIGCONTEXT_HI (64 * 8) +#define N64_SIGCONTEXT_LO (65 * 8) +#define N64_SIGCONTEXT_PC (66 * 8) +#define N64_SIGCONTEXT_FPCSR (67 * 8 + 1 * 4) +#define N64_SIGCONTEXT_FIR (67 * 8 + 2 * 4) +#define N64_SIGCONTEXT_CAUSE (67 * 8 + 4 * 4) +#define N64_SIGCONTEXT_BADVADDR (67 * 8 + 5 * 4) + +#define N64_SIGCONTEXT_REG_SIZE 8 + +static void +mips_linux_n32n64_sigframe_init (const struct tramp_frame *self, + struct frame_info *next_frame, + struct trad_frame_cache *this_cache, + CORE_ADDR func) +{ + int ireg, reg_position; + CORE_ADDR sigcontext_base = func - SIGFRAME_CODE_OFFSET; + const struct mips_regnum *regs = mips_regnum (current_gdbarch); + + if (self == &mips_linux_n32_rt_sigframe) + sigcontext_base += N32_SIGFRAME_SIGCONTEXT_OFFSET; + else + sigcontext_base += N64_SIGFRAME_SIGCONTEXT_OFFSET; + +#if 0 + trad_frame_set_reg_addr (this_cache, ORIG_ZERO_REGNUM + NUM_REGS, + sigcontext_base + N64_SIGCONTEXT_REGS); +#endif + + for (ireg = 1; ireg < 32; ireg++) + trad_frame_set_reg_addr (this_cache, ireg + ZERO_REGNUM + NUM_REGS, + sigcontext_base + N64_SIGCONTEXT_REGS + + ireg * N64_SIGCONTEXT_REG_SIZE); + + for (ireg = 0; ireg < 32; ireg++) + trad_frame_set_reg_addr (this_cache, ireg + regs->fp0 + NUM_REGS, + sigcontext_base + N64_SIGCONTEXT_FPREGS + + ireg * N64_SIGCONTEXT_REG_SIZE); + + trad_frame_set_reg_addr (this_cache, regs->pc + NUM_REGS, + sigcontext_base + N64_SIGCONTEXT_PC); + + trad_frame_set_reg_addr (this_cache, regs->fp_control_status + NUM_REGS, + sigcontext_base + N64_SIGCONTEXT_FPCSR); + trad_frame_set_reg_addr (this_cache, regs->hi + NUM_REGS, + sigcontext_base + N64_SIGCONTEXT_HI); + trad_frame_set_reg_addr (this_cache, regs->lo + NUM_REGS, + sigcontext_base + N64_SIGCONTEXT_LO); + trad_frame_set_reg_addr (this_cache, regs->cause + NUM_REGS, + sigcontext_base + N64_SIGCONTEXT_CAUSE); + trad_frame_set_reg_addr (this_cache, regs->badvaddr + NUM_REGS, + sigcontext_base + N64_SIGCONTEXT_BADVADDR); + + /* Choice of the bottom of the sigframe is somewhat arbitrary. */ + trad_frame_set_id (this_cache, + frame_id_build (func - SIGFRAME_CODE_OFFSET, func)); +} + +/* Initialize one of the GNU/Linux OS ABIs. */ + static void mips_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) { @@ -811,6 +1119,8 @@ mips_linux_init_abi (struct gdbarch_info set_solib_svr4_fetch_link_map_offsets (gdbarch, mips_linux_svr4_fetch_link_map_offsets); set_mips_linux_register_addr (gdbarch, mips_linux_register_addr); + tramp_frame_append (gdbarch, &mips_linux_o32_sigframe); + tramp_frame_append (gdbarch, &mips_linux_o32_rt_sigframe); break; case MIPS_ABI_N32: set_gdbarch_get_longjmp_target (gdbarch, @@ -818,6 +1128,7 @@ mips_linux_init_abi (struct gdbarch_info set_solib_svr4_fetch_link_map_offsets (gdbarch, mips_linux_svr4_fetch_link_map_offsets); set_mips_linux_register_addr (gdbarch, mips64_linux_register_addr); + tramp_frame_append (gdbarch, &mips_linux_n32_rt_sigframe); break; case MIPS_ABI_N64: set_gdbarch_get_longjmp_target (gdbarch, @@ -825,6 +1136,7 @@ mips_linux_init_abi (struct gdbarch_info set_solib_svr4_fetch_link_map_offsets (gdbarch, mips64_linux_svr4_fetch_link_map_offsets); set_mips_linux_register_addr (gdbarch, mips64_linux_register_addr); + tramp_frame_append (gdbarch, &mips_linux_n64_rt_sigframe); break; default: internal_error (__FILE__, __LINE__, "can't handle ABI"); Index: mips-tdep.c =================================================================== RCS file: /big/fsf/rsync/src-cvs/src/gdb/mips-tdep.c,v retrieving revision 1.285 diff -u -p -r1.285 mips-tdep.c --- mips-tdep.c 23 Mar 2004 14:47:56 -0000 1.285 +++ mips-tdep.c 24 Mar 2004 19:04:30 -0000 @@ -5741,9 +5741,7 @@ mips_gdbarch_init (struct gdbarch_info i /* Unwind the frame. */ set_gdbarch_unwind_pc (gdbarch, mips_unwind_pc); - frame_unwind_append_sniffer (gdbarch, mips_mdebug_frame_sniffer); set_gdbarch_unwind_dummy_id (gdbarch, mips_unwind_dummy_id); - frame_base_append_sniffer (gdbarch, mips_mdebug_frame_base_sniffer); /* Map debug register numbers onto internal register numbers. */ set_gdbarch_stab_reg_to_regnum (gdbarch, mips_stab_reg_to_regnum); @@ -5807,6 +5805,10 @@ mips_gdbarch_init (struct gdbarch_info i /* Hook in OS ABI-specific overrides, if they have been registered. */ gdbarch_init_osabi (info, gdbarch); + + /* Unwind the frame. */ + frame_unwind_append_sniffer (gdbarch, mips_mdebug_frame_sniffer); + frame_base_append_sniffer (gdbarch, mips_mdebug_frame_base_sniffer); return gdbarch; }