[binutils-gdb] [gdb/record] Fix syscall exit recording for riscv
Tom de Vries via Gdb-cvs <[email protected]>
| Newsgroups | gmane.comp.gdb.cvs |
|---|---|
| Message-ID | <[email protected]> |
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=a570ac19e30c17211f414c13af031b0e093b4cc1 commit a570ac19e30c17211f414c13af031b0e093b4cc1 Author: Tom de Vries <[email protected]> Date: Wed Mar 25 14:12:11 2026 +0100 [gdb/record] Fix syscall exit recording for riscv [ Submitted earlier [1] with $subject: "[gdb/record] Fix syscall recording for riscv". ] On riscv64-linux, I run into: ... (gdb) continue^M Continuing.^M The next instruction is syscall exit_group. It will make the program exit. \ Do you want to stop the program?([y] or n) yes^M Process record: failed to record execution log.^M ^M Program stopped.^M __GI__exit (status=status@entry=0) at _exit.c:30^M warning: 30 _exit.c: No such file or directory^M (gdb) FAIL: gdb.reverse/sigall-reverse.exp: continue to signal exit ... The problem is here in record_insn_len4: ... /* We are in linux mode. */ return (read_reg (RISCV_A7_REGNUM, reg_val) && m_gdbarch->riscv_syscall_record (m_regcache, reg_val) == 0); ... where return values 1 and -1 are handled the same. Fix this in the usual way, by passing through the 1 value all the way to riscv_process_record. That requires changing a few functions from type bool to int. That's also the case for record_insn_len4, where I factored out record_insn_len4_1 to keep changes to a minimum. Also introduce a common enum record_result, and use it instead of hardcoded 1/0/-1. Tested on riscv64-linux. Approved-By: Guinevere Larsen <[email protected]> [1] https://sourceware.org/pipermail/gdb-patches/2026-February/225384.html Diff: --- gdb/record-full.h | 15 +++++++++++++ gdb/riscv-tdep.c | 64 ++++++++++++++++++++++++++++++++++--------------------- 2 files changed, 55 insertions(+), 24 deletions(-) diff --git a/gdb/record-full.h b/gdb/record-full.h index ea78f6e886c..51effe74560 100644 --- a/gdb/record-full.h +++ b/gdb/record-full.h @@ -24,6 +24,21 @@ extern bool record_full_memory_query; +/* Type to be used to return values in the gdbarch_process_record hook. */ + +enum record_result +{ + /* Process record does not support instruction $hex at address $hex. + Process record: failed to record execution log. */ + RECORD_UNSUPPORTED = -2, + /* Process record: failed to record execution log. */ + RECORD_FAILURE = -1, + /* No failure. */ + RECORD_SUCCESS = 0, + /* Process record: inferior program stopped. */ + RECORD_UNKNOWN = 1 +}; + extern int record_full_arch_list_add_reg (struct regcache *regcache, int num); extern int record_full_arch_list_add_mem (CORE_ADDR addr, int len); extern int record_full_arch_list_add_end (void); diff --git a/gdb/riscv-tdep.c b/gdb/riscv-tdep.c index ebecd1e79d5..6b5c9c02d46 100644 --- a/gdb/riscv-tdep.c +++ b/gdb/riscv-tdep.c @@ -5199,26 +5199,14 @@ class riscv_recorded_insn final } /* Returns true if instruction is successfully recorded. The length of - the instruction must be equal to 4 bytes. */ + the instruction must be equal to 4 bytes. Helper function for + record_insn_len4. */ bool - record_insn_len4 (ULONGEST ival) noexcept + record_insn_len4_1 (ULONGEST ival) noexcept { mem_len len = 0; - ULONGEST reg_val = 0; - - if (is_ecall_insn (ival)) - { - /* We are in baremetal mode. */ - if (m_in_baremetal_mode) - { - warning (_("Syscall record is not supported")); - return false; - } - /* We are in linux mode. */ - return (read_reg (RISCV_A7_REGNUM, reg_val) - && m_gdbarch->riscv_syscall_record (m_regcache, reg_val) == 0); - } + gdb_assert (!is_ecall_insn (ival)); if (is_ebreak_insn (ival)) return true; @@ -5256,6 +5244,32 @@ class riscv_recorded_insn final return false; } + /* Returns RECORD_SUCCESS if instruction is successfully recorded. The + length of the instruction must be equal to 4 bytes. */ + int + record_insn_len4 (ULONGEST ival) noexcept + { + ULONGEST reg_val = 0; + + if (is_ecall_insn (ival)) + { + /* We are in baremetal mode. */ + if (m_in_baremetal_mode) + { + warning (_("Syscall record is not supported")); + return RECORD_FAILURE; + } + + /* We are in linux mode. */ + if (!read_reg (RISCV_A7_REGNUM, reg_val)) + return RECORD_FAILURE; + + return m_gdbarch->riscv_syscall_record (m_regcache, reg_val); + } + + return record_insn_len4_1 (ival) ? RECORD_SUCCESS : RECORD_FAILURE; + } + /* Returns true if instruction is successfully recorded. The length of the instruction must be equal to 2 bytes. */ bool @@ -5388,8 +5402,9 @@ class riscv_recorded_insn final } public: - /* Record instruction at address addr. Returns false if error happened. */ - bool + /* Record instruction at address addr. Return RECORD_FAILURE if error + happened. */ + int record (gdbarch *gdbarch, struct regcache *regcache, CORE_ADDR addr) noexcept { gdb_assert (gdbarch != nullptr); @@ -5412,14 +5427,14 @@ public: catch (const gdb_exception_error &ex) { warning ("%s", ex.what ()); - return false; + return RECORD_FAILURE; } if (!save_reg (RISCV_PC_REGNUM)) - return false; + return RECORD_FAILURE; if (insn_length == 2) - return record_insn_len2 (ival); + return record_insn_len2 (ival) ? RECORD_SUCCESS : RECORD_FAILURE; if (insn_length == 4) return record_insn_len4 (ival); @@ -5431,7 +5446,7 @@ public: warning (_("Can not record unknown instruction (opcode = %s)"), hex_string (ival)); - return false; + return RECORD_FAILURE; } }; @@ -5447,8 +5462,9 @@ riscv_process_record (struct gdbarch *gdbarch, struct regcache *regcache, gdb_assert (regcache != nullptr); riscv_recorded_insn insn; - if (!insn.record (gdbarch, regcache, addr)) - return -1; + int res = insn.record (gdbarch, regcache, addr); + if (res != RECORD_SUCCESS) + return res; if (record_full_arch_list_add_end ()) return -1;