[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;
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.