diff options
Diffstat (limited to 'gdb/riscv-tdep.c')
-rw-r--r-- | gdb/riscv-tdep.c | 66 |
1 files changed, 48 insertions, 18 deletions
diff --git a/gdb/riscv-tdep.c b/gdb/riscv-tdep.c index f5b8523..697071b 100644 --- a/gdb/riscv-tdep.c +++ b/gdb/riscv-tdep.c @@ -56,7 +56,6 @@ #include "arch/riscv.h" #include "record-full.h" #include "riscv-ravenscar-thread.h" -#include "gdbsupport/gdb-safe-ctype.h" #include <vector> @@ -4183,9 +4182,9 @@ riscv_print_insn (bfd_vma addr, struct disassemble_info *info) static int riscv_stap_is_single_operand (struct gdbarch *gdbarch, const char *s) { - return (ISDIGIT (*s) /* Literal number. */ + return (c_isdigit (*s) /* Literal number. */ || *s == '(' /* Register indirection. */ - || ISALPHA (*s)); /* Register value. */ + || c_isalpha (*s)); /* Register value. */ } /* String that appears before a register name in a SystemTap register @@ -4924,6 +4923,8 @@ public: /* Corner cases. */ ECALL, EBREAK, + SRET, + MRET, }; private: @@ -5008,6 +5009,14 @@ private: return (ival >> OP_SH_CSR) & OP_MASK_CSR; } + /* Set any record type. Always returns true. */ + bool + set_record_type (record_type type) noexcept + { + m_record_type = type; + return true; + } + /* Set ordinary record type. Always returns true. */ bool set_ordinary_record_type () noexcept @@ -5066,7 +5075,8 @@ private: return (is_beq_insn (ival) || is_bne_insn (ival) || is_blt_insn (ival) || is_bge_insn (ival) || is_bltu_insn (ival) || is_bgeu_insn (ival) || is_fence_insn (ival) || is_pause_insn (ival) - || is_fence_i_insn (ival)); + || is_fence_i_insn (ival) || is_wfi_insn (ival) + || is_sfence_vma_insn (ival)); } /* Returns true if instruction is classified. */ @@ -5270,14 +5280,26 @@ private: if (is_ecall_insn (ival)) { - m_record_type = record_type::ECALL; - return true; + return set_record_type (record_type::ECALL); } if (is_ebreak_insn (ival)) { - m_record_type = record_type::EBREAK; - return true; + return set_record_type (record_type::EBREAK); + } + + if (is_sret_insn (ival)) + { + return (!save_reg (RISCV_CSR_SSTATUS_REGNUM) + || !save_reg (RISCV_CSR_MEPC_REGNUM) + || set_record_type (record_type::SRET)); + } + + if (is_mret_insn (ival)) + { + return (!save_reg (RISCV_CSR_MSTATUS_REGNUM) + || !save_reg (RISCV_CSR_MEPC_REGNUM) + || set_record_type (record_type::MRET)); } if (try_save_pc (ival) || try_save_pc_rd (ival) || try_save_pc_fprd (ival) @@ -5371,8 +5393,7 @@ private: if (is_c_ebreak_insn (ival)) { - m_record_type = record_type::EBREAK; - return true; + return set_record_type (record_type::EBREAK); } if (is_c_jalr_insn (ival)) @@ -5414,8 +5435,20 @@ public: gdb_assert (regcache != nullptr); int m_length = 0; + ULONGEST ival = 0; m_xlen = riscv_isa_xlen (gdbarch); - ULONGEST ival = riscv_insn::fetch_instruction (gdbarch, addr, &m_length); + + /* Since fetch_instruction can throw an exception, + it must be wrapped in a try-catch block. */ + try + { + ival = riscv_insn::fetch_instruction (gdbarch, addr, &m_length); + } + catch (const gdb_exception_error &ex) + { + warning ("%s", ex.what ()); + return false; + } if (!save_reg (RISCV_PC_REGNUM)) return false; @@ -5509,6 +5542,9 @@ riscv_record_insn_details (struct gdbarch *gdbarch, struct regcache *regcache, switch (insn.get_record_type ()) { case riscv_recorded_insn::record_type::ORDINARY: + case riscv_recorded_insn::record_type::EBREAK: + case riscv_recorded_insn::record_type::SRET: + case riscv_recorded_insn::record_type::MRET: break; case riscv_recorded_insn::record_type::ECALL: @@ -5524,9 +5560,6 @@ riscv_record_insn_details (struct gdbarch *gdbarch, struct regcache *regcache, return tdep->riscv_syscall_record (regcache, reg_val); } - case riscv_recorded_insn::record_type::EBREAK: - break; - default: return -1; } @@ -5546,10 +5579,7 @@ riscv_process_record (struct gdbarch *gdbarch, struct regcache *regcache, riscv_recorded_insn insn; if (!insn.record (gdbarch, regcache, addr)) - { - record_full_arch_list_add_end (); - return -1; - } + return -1; int ret_val = riscv_record_insn_details (gdbarch, regcache, insn); |