* 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:
parent
f516dd4c10
commit
5792a79bd1
4 changed files with 330 additions and 3 deletions
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue