* 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.
This commit is contained in:
Daniel Jacobowitz 2004-03-25 01:27:26 +00:00
parent f516dd4c10
commit 5792a79bd1
4 changed files with 330 additions and 3 deletions

View file

@ -1,3 +1,16 @@
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.
2004-03-24 Andrew Cagney <cagney@redhat.com>
* tramp-frame.h (TRAMP_SENTINEL_INSN): Define, document.

View file

@ -2052,7 +2052,7 @@ mips-irix-tdep.o: mips-irix-tdep.c $(defs_h) $(osabi_h) $(elf_bfd_h)
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)

View file

@ -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 *gdbarch, CORE_ADDR pc)
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 info, struct gdbarch *gdbarch)
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 info, struct gdbarch *gdbarch)
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 info, struct gdbarch *gdbarch)
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");

View file

@ -5741,9 +5741,7 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
/* 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);
@ -5808,6 +5806,10 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
/* 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;
}