diff options
-rw-r--r-- | gdb/ChangeLog | 21 | ||||
-rw-r--r-- | gdb/mips-linux-tdep.c | 113 | ||||
-rw-r--r-- | gdb/tramp-frame.c | 4 | ||||
-rw-r--r-- | gdb/tramp-frame.h | 7 |
4 files changed, 139 insertions, 6 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index ebb36b7..80eb8c9 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,24 @@ +2014-12-03 Maciej W. Rozycki <macro@codesourcery.com> + + * tramp-frame.h (tramp_frame): Add `validate' member. + * tramp-frame.c (tramp_frame_start): Validate trampoline before + scanning. + * mips-linux-tdep.c (MICROMIPS_INST_LI_V0): New macro. + (MICROMIPS_INST_POOL32A, MICROMIPS_INST_SYSCALL): Likewise. + (mips_linux_o32_sigframe): Initialize `validate' member. + (mips_linux_o32_rt_sigframe): Likewise. + (mips_linux_n32_rt_sigframe): Likewise. + (mips_linux_n64_rt_sigframe): Likewise. + (micromips_linux_o32_sigframe): New variable. + (micromips_linux_o32_rt_sigframe): Likewise. + (micromips_linux_n32_rt_sigframe): Likewise. + (micromips_linux_n64_rt_sigframe): Likewise. + (mips_linux_o32_sigframe_init): Handle microMIPS trampolines. + (mips_linux_n32n64_sigframe_init): Likewise. + (mips_linux_sigframe_validate): New function. + (micromips_linux_sigframe_validate): Likewise. + (mips_linux_init_abi): Install microMIPS trampoline unwinders. + 2014-12-03 Ulrich Weigand <uweigand@de.ibm.com> * config/sparc/sol2.mh (NATDEPFILES): Remove core-regset.o. diff --git a/gdb/mips-linux-tdep.c b/gdb/mips-linux-tdep.c index bc42921..41602ba 100644 --- a/gdb/mips-linux-tdep.c +++ b/gdb/mips-linux-tdep.c @@ -827,6 +827,14 @@ static void mips_linux_n32n64_sigframe_init (const struct tramp_frame *self, struct trad_frame_cache *this_cache, CORE_ADDR func); +static int mips_linux_sigframe_validate (const struct tramp_frame *self, + struct frame_info *this_frame, + CORE_ADDR *pc); + +static int micromips_linux_sigframe_validate (const struct tramp_frame *self, + struct frame_info *this_frame, + CORE_ADDR *pc); + #define MIPS_NR_LINUX 4000 #define MIPS_NR_N64_LINUX 5000 #define MIPS_NR_N32_LINUX 6000 @@ -842,6 +850,10 @@ static void mips_linux_n32n64_sigframe_init (const struct tramp_frame *self, #define MIPS_INST_LI_V0_N32_RT_SIGRETURN 0x24020000 + MIPS_NR_N32_rt_sigreturn #define MIPS_INST_SYSCALL 0x0000000c +#define MICROMIPS_INST_LI_V0 0x3040 +#define MICROMIPS_INST_POOL32A 0x0000 +#define MICROMIPS_INST_SYSCALL 0x8b7c + static const struct tramp_frame mips_linux_o32_sigframe = { SIGTRAMP_FRAME, 4, @@ -850,7 +862,8 @@ static const struct tramp_frame mips_linux_o32_sigframe = { { MIPS_INST_SYSCALL, -1 }, { TRAMP_SENTINEL_INSN, -1 } }, - mips_linux_o32_sigframe_init + mips_linux_o32_sigframe_init, + mips_linux_sigframe_validate }; static const struct tramp_frame mips_linux_o32_rt_sigframe = { @@ -860,7 +873,8 @@ static const struct tramp_frame mips_linux_o32_rt_sigframe = { { MIPS_INST_LI_V0_RT_SIGRETURN, -1 }, { MIPS_INST_SYSCALL, -1 }, { TRAMP_SENTINEL_INSN, -1 } }, - mips_linux_o32_sigframe_init + mips_linux_o32_sigframe_init, + mips_linux_sigframe_validate }; static const struct tramp_frame mips_linux_n32_rt_sigframe = { @@ -871,7 +885,8 @@ static const struct tramp_frame mips_linux_n32_rt_sigframe = { { MIPS_INST_SYSCALL, -1 }, { TRAMP_SENTINEL_INSN, -1 } }, - mips_linux_n32n64_sigframe_init + mips_linux_n32n64_sigframe_init, + mips_linux_sigframe_validate }; static const struct tramp_frame mips_linux_n64_rt_sigframe = { @@ -882,7 +897,64 @@ static const struct tramp_frame mips_linux_n64_rt_sigframe = { { MIPS_INST_SYSCALL, -1 }, { TRAMP_SENTINEL_INSN, -1 } }, - mips_linux_n32n64_sigframe_init + mips_linux_n32n64_sigframe_init, + mips_linux_sigframe_validate +}; + +static const struct tramp_frame micromips_linux_o32_sigframe = { + SIGTRAMP_FRAME, + 2, + { + { MICROMIPS_INST_LI_V0, -1 }, + { MIPS_NR_sigreturn, -1 }, + { MICROMIPS_INST_POOL32A, -1 }, + { MICROMIPS_INST_SYSCALL, -1 }, + { TRAMP_SENTINEL_INSN, -1 } + }, + mips_linux_o32_sigframe_init, + micromips_linux_sigframe_validate +}; + +static const struct tramp_frame micromips_linux_o32_rt_sigframe = { + SIGTRAMP_FRAME, + 2, + { + { MICROMIPS_INST_LI_V0, -1 }, + { MIPS_NR_rt_sigreturn, -1 }, + { MICROMIPS_INST_POOL32A, -1 }, + { MICROMIPS_INST_SYSCALL, -1 }, + { TRAMP_SENTINEL_INSN, -1 } + }, + mips_linux_o32_sigframe_init, + micromips_linux_sigframe_validate +}; + +static const struct tramp_frame micromips_linux_n32_rt_sigframe = { + SIGTRAMP_FRAME, + 2, + { + { MICROMIPS_INST_LI_V0, -1 }, + { MIPS_NR_N32_rt_sigreturn, -1 }, + { MICROMIPS_INST_POOL32A, -1 }, + { MICROMIPS_INST_SYSCALL, -1 }, + { TRAMP_SENTINEL_INSN, -1 } + }, + mips_linux_n32n64_sigframe_init, + micromips_linux_sigframe_validate +}; + +static const struct tramp_frame micromips_linux_n64_rt_sigframe = { + SIGTRAMP_FRAME, + 2, + { + { MICROMIPS_INST_LI_V0, -1 }, + { MIPS_NR_N64_rt_sigreturn, -1 }, + { MICROMIPS_INST_POOL32A, -1 }, + { MICROMIPS_INST_SYSCALL, -1 }, + { TRAMP_SENTINEL_INSN, -1 } + }, + mips_linux_n32n64_sigframe_init, + micromips_linux_sigframe_validate }; /* *INDENT-OFF* */ @@ -1002,7 +1074,8 @@ mips_linux_o32_sigframe_init (const struct tramp_frame *self, const struct mips_regnum *regs = mips_regnum (gdbarch); CORE_ADDR regs_base; - if (self == &mips_linux_o32_sigframe) + if (self == &mips_linux_o32_sigframe + || self == µmips_linux_o32_sigframe) sigcontext_base = frame_sp + SIGFRAME_SIGCONTEXT_OFFSET; else sigcontext_base = frame_sp + RTSIGFRAME_SIGCONTEXT_OFFSET; @@ -1203,7 +1276,8 @@ mips_linux_n32n64_sigframe_init (const struct tramp_frame *self, CORE_ADDR sigcontext_base; const struct mips_regnum *regs = mips_regnum (gdbarch); - if (self == &mips_linux_n32_rt_sigframe) + if (self == &mips_linux_n32_rt_sigframe + || self == µmips_linux_n32_rt_sigframe) sigcontext_base = frame_sp + N32_SIGFRAME_SIGCONTEXT_OFFSET; else sigcontext_base = frame_sp + N64_SIGFRAME_SIGCONTEXT_OFFSET; @@ -1273,6 +1347,26 @@ mips_linux_n32n64_sigframe_init (const struct tramp_frame *self, trad_frame_set_id (this_cache, frame_id_build (frame_sp, func)); } +/* Implement struct tramp_frame's "validate" method for standard MIPS code. */ + +static int +mips_linux_sigframe_validate (const struct tramp_frame *self, + struct frame_info *this_frame, + CORE_ADDR *pc) +{ + return mips_pc_is_mips (*pc); +} + +/* Implement struct tramp_frame's "validate" method for microMIPS code. */ + +static int +micromips_linux_sigframe_validate (const struct tramp_frame *self, + struct frame_info *this_frame, + CORE_ADDR *pc) +{ + return mips_pc_is_micromips (get_frame_arch (this_frame), *pc); +} + /* Implement the "write_pc" gdbarch method. */ static void @@ -1556,6 +1650,9 @@ mips_linux_init_abi (struct gdbarch_info info, mips_linux_get_longjmp_target); set_solib_svr4_fetch_link_map_offsets (gdbarch, svr4_ilp32_fetch_link_map_offsets); + tramp_frame_prepend_unwinder (gdbarch, µmips_linux_o32_sigframe); + tramp_frame_prepend_unwinder (gdbarch, + µmips_linux_o32_rt_sigframe); tramp_frame_prepend_unwinder (gdbarch, &mips_linux_o32_sigframe); tramp_frame_prepend_unwinder (gdbarch, &mips_linux_o32_rt_sigframe); set_xml_syscall_file_name (gdbarch, "syscalls/mips-o32-linux.xml"); @@ -1571,6 +1668,8 @@ mips_linux_init_abi (struct gdbarch_info info, except that the quiet/signalling NaN bit is reversed (GDB does not distinguish between quiet and signalling NaNs). */ set_gdbarch_long_double_format (gdbarch, floatformats_ia64_quad); + tramp_frame_prepend_unwinder (gdbarch, + µmips_linux_n32_rt_sigframe); tramp_frame_prepend_unwinder (gdbarch, &mips_linux_n32_rt_sigframe); set_xml_syscall_file_name (gdbarch, "syscalls/mips-n32-linux.xml"); break; @@ -1585,6 +1684,8 @@ mips_linux_init_abi (struct gdbarch_info info, except that the quiet/signalling NaN bit is reversed (GDB does not distinguish between quiet and signalling NaNs). */ set_gdbarch_long_double_format (gdbarch, floatformats_ia64_quad); + tramp_frame_prepend_unwinder (gdbarch, + µmips_linux_n64_rt_sigframe); tramp_frame_prepend_unwinder (gdbarch, &mips_linux_n64_rt_sigframe); set_xml_syscall_file_name (gdbarch, "syscalls/mips-n64-linux.xml"); break; diff --git a/gdb/tramp-frame.c b/gdb/tramp-frame.c index 0fd6ddc..a0e3eb5 100644 --- a/gdb/tramp-frame.c +++ b/gdb/tramp-frame.c @@ -86,6 +86,10 @@ tramp_frame_start (const struct tramp_frame *tramp, enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); int ti; + /* Check if we can use this trampoline. */ + if (tramp->validate && !tramp->validate (tramp, this_frame, &pc)) + return 0; + /* Search through the trampoline for one that matches the instruction sequence around PC. */ for (ti = 0; tramp->insn[ti].bytes != TRAMP_SENTINEL_INSN; ti++) diff --git a/gdb/tramp-frame.h b/gdb/tramp-frame.h index eeaf7b5..d659c0b 100644 --- a/gdb/tramp-frame.h +++ b/gdb/tramp-frame.h @@ -69,6 +69,13 @@ struct tramp_frame struct frame_info *this_frame, struct trad_frame_cache *this_cache, CORE_ADDR func); + /* Return non-zero if the tramp-frame is valid for the PC requested. + Adjust the PC to point to the address to check the instruction + sequence against if required. If this is NULL, then the tramp-frame + is valid for any PC. */ + int (*validate) (const struct tramp_frame *self, + struct frame_info *this_frame, + CORE_ADDR *pc); }; void tramp_frame_prepend_unwinder (struct gdbarch *gdbarch, |