* [patch/rfa-mips] MIPS GNU/Linux sigtramp unwinders
@ 2004-03-24 19:20 Daniel Jacobowitz
2004-03-25 0:20 ` Andrew Cagney
0 siblings, 1 reply; 3+ messages in thread
From: Daniel Jacobowitz @ 2004-03-24 19:20 UTC (permalink / raw)
To: gdb-patches; +Cc: cagney
I ported my local sigtramp unwinders over to the tramp_frame interface.
Results look pretty good so far. The only change I needed to make in
mips-tdep.c was to append the catch-all unwinder after initializing the OS
ABI; otherwise this code is never reached. OK?
This will need the obvious revision for Andrew's patch to add a sentinel
value for the instruction sequence in tramp-frame. Ignore ORIG_ZERO_REGNUM
for the moment; it's a reminder to myself for a followup patch (it serves
the same role as ORIG_EAX).
--
Daniel Jacobowitz
MontaVista Software Debian GNU/Linux Developer
2004-03-24 Daniel Jacobowitz <drow@mvista.com>
* 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 <asm/elf.h>. */
#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, 0 },
+ mips_linux_o32_sigframe_init
+};
+
+struct tramp_frame mips_linux_o32_rt_sigframe = {
+ 4,
+ { MIPS_INST_LI_V0_RT_SIGRETURN, MIPS_INST_SYSCALL, 0 },
+ mips_linux_o32_sigframe_init
+};
+
+struct tramp_frame mips_linux_n32_rt_sigframe = {
+ 4,
+ { MIPS_INST_LI_V0_N32_RT_SIGRETURN, MIPS_INST_SYSCALL, 0 },
+ mips_linux_n32n64_sigframe_init
+};
+
+struct tramp_frame mips_linux_n64_rt_sigframe = {
+ 4,
+ { MIPS_INST_LI_V0_N64_RT_SIGRETURN, MIPS_INST_SYSCALL, 0 },
+ 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;
}
^ permalink raw reply [flat|nested] 3+ messages in thread* Re: [patch/rfa-mips] MIPS GNU/Linux sigtramp unwinders 2004-03-24 19:20 [patch/rfa-mips] MIPS GNU/Linux sigtramp unwinders Daniel Jacobowitz @ 2004-03-25 0:20 ` Andrew Cagney 2004-03-25 1:28 ` Daniel Jacobowitz 0 siblings, 1 reply; 3+ messages in thread From: Andrew Cagney @ 2004-03-25 0:20 UTC (permalink / raw) To: Daniel Jacobowitz; +Cc: gdb-patches > /* 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. Andrew ^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [patch/rfa-mips] MIPS GNU/Linux sigtramp unwinders 2004-03-25 0:20 ` Andrew Cagney @ 2004-03-25 1:28 ` Daniel Jacobowitz 0 siblings, 0 replies; 3+ messages in thread From: Daniel Jacobowitz @ 2004-03-25 1:28 UTC (permalink / raw) To: gdb-patches 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 <drow@mvista.com> * 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 <asm/elf.h>. */ #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; } ^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2004-03-25 1:28 UTC | newest] Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2004-03-24 19:20 [patch/rfa-mips] MIPS GNU/Linux sigtramp unwinders Daniel Jacobowitz 2004-03-25 0:20 ` Andrew Cagney 2004-03-25 1:28 ` Daniel Jacobowitz
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox