diff options
Diffstat (limited to 'gdb/riscv-tdep.c')
-rw-r--r-- | gdb/riscv-tdep.c | 92 |
1 files changed, 71 insertions, 21 deletions
diff --git a/gdb/riscv-tdep.c b/gdb/riscv-tdep.c index a735c09..680176b 100644 --- a/gdb/riscv-tdep.c +++ b/gdb/riscv-tdep.c @@ -4163,6 +4163,20 @@ riscv_gnu_triplet_regexp (struct gdbarch *gdbarch) return "riscv(32|64)?"; } +/* Implement the "print_insn" gdbarch method. */ + +static int +riscv_print_insn (bfd_vma addr, struct disassemble_info *info) +{ + /* Initialize the BFD section to enable ISA string detection depending on the + object in scope. */ + struct obj_section *s = find_pc_section (addr); + if (s != nullptr) + info->section = s->the_bfd_section; + + return default_print_insn (addr, info); +} + /* Implementation of `gdbarch_stap_is_single_operand', as defined in gdbarch.h. */ @@ -4429,6 +4443,9 @@ riscv_gdbarch_init (struct gdbarch_info info, disassembler_options_riscv ()); set_gdbarch_disassembler_options (gdbarch, &riscv_disassembler_options); + /* Disassembler print_insn. */ + set_gdbarch_print_insn (gdbarch, riscv_print_insn); + /* SystemTap Support. */ set_gdbarch_stap_is_single_operand (gdbarch, riscv_stap_is_single_operand); set_gdbarch_stap_register_indirection_prefixes @@ -4778,9 +4795,7 @@ riscv_supply_regset (const struct regset *regset, } } -void _initialize_riscv_tdep (); -void -_initialize_riscv_tdep () +INIT_GDB_FILE (riscv_tdep) { riscv_init_reggroups (); @@ -4884,7 +4899,7 @@ try_read (struct regcache *regcache, int regnum, ULONGEST &addr) if (regcache->raw_read (regnum, &addr) != register_status::REG_VALID) { - warning (_("Can not read at address %lx"), addr); + warning (_("Can not read at address %s"), hex_string (addr)); return false; } return true; @@ -4909,6 +4924,8 @@ public: /* Corner cases. */ ECALL, EBREAK, + SRET, + MRET, }; private: @@ -4993,6 +5010,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 @@ -5051,7 +5076,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. */ @@ -5158,7 +5184,7 @@ private: { return (is_csrrw_insn (ival) || is_csrrs_insn (ival) || is_csrrc_insn (ival) || is_csrrwi_insn (ival) || is_csrrsi_insn (ival) - || is_csrrc_insn (ival)); + || is_csrrci_insn (ival)); } /* Returns true if instruction is classified. This function can set @@ -5255,14 +5281,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) @@ -5270,8 +5308,8 @@ private: || try_save_pc_rd_mem (ival, regcache)) return !has_error (); - warning (_("Currently this instruction with len 4(%lx) is unsupported"), - ival); + warning (_("Currently this instruction with len 4(%s) is unsupported"), + hex_string (ival)); return false; } @@ -5356,8 +5394,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)) @@ -5380,8 +5417,8 @@ private: || !save_mem (addr + offset, 4) || set_ordinary_record_type ()); } - warning (_("Currently this instruction with len 2(%lx) is unsupported"), - ival); + warning (_("Currently this instruction with len 2(%s) is unsupported"), + hex_string (ival)); return false; } @@ -5399,8 +5436,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; @@ -5415,7 +5464,8 @@ public: are not defined yet, so just ignore it. */ gdb_assert (m_length > 0 && m_length % 2 == 0); - warning (_("Can not record unknown instruction (opcode = %lx)"), ival); + warning (_("Can not record unknown instruction (opcode = %s)"), + hex_string (ival)); return false; } @@ -5493,6 +5543,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: @@ -5508,9 +5561,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; } |