]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
GDB: regcache: Invalidate variable-size registers ...
authorThiago Jung Bauermann <thiago.bauermann@linaro.org>
Sun, 27 Apr 2025 02:28:10 +0000 (23:28 -0300)
committerThiago Jung Bauermann <thiago.bauermann@linaro.org>
Mon, 28 Apr 2025 04:52:53 +0000 (01:52 -0300)
... if register-based parameter changes.

gdb/aarch64-tdep.c
gdb/arch-utils.c
gdb/gdbarch-gen.c
gdb/gdbarch-gen.h
gdb/gdbarch_components.py
gdb/regcache.c
gdb/regcache.h

index c119554bb06bb2bfbebf8ebe851f86cfc40cfbb5..b719c8547a29d9a382fd388e28bc3990ede8361e 100644 (file)
@@ -4337,6 +4337,22 @@ aarch64_fetch_tdesc_parameter (gdbarch *gdbarch, readable_regcache *regcache,
     }
 }
 
+static bool
+aarch64_invalidate_tdesc_parameters (struct gdbarch *gdbarch, int regno,
+                                    reg_buffer *regcache)
+{
+  /* All current AArch64 parameters depend on VG.  */
+  if (tdesc_num_parameters (gdbarch) == 0 || regno != AARCH64_SVE_VG_REGNUM)
+    return false;
+
+  aarch64_gdbarch_tdep *tdep = gdbarch_tdep<aarch64_gdbarch_tdep> (gdbarch);
+
+  regcache->invalidate_tdesc_parameter (tdep->param_sve_vector_length);
+  regcache->invalidate_tdesc_parameter (tdep->param_sve_predicate_length);
+
+  return true;
+}
+
 /* Given NAMES, a vector of strings, initialize it with all the SME
    pseudo-register names for the current streaming vector length.  */
 
@@ -4882,6 +4898,8 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
     tdep->param_sve_predicate_length = *param_id;
 
   set_gdbarch_fetch_tdesc_parameter (gdbarch, aarch64_fetch_tdesc_parameter);
+  set_gdbarch_invalidate_tdesc_parameters (gdbarch,
+                                          aarch64_invalidate_tdesc_parameters);
 
   return gdbarch;
 }
index 6fe727fa021fc148424d6ac4e84349e2f1703b8d..2b934acb5fdb727f3ad4c72a2e12abce0c4662c2 100644 (file)
@@ -1145,6 +1145,13 @@ default_register_is_variable_size (struct gdbarch *gdbarch, int regno)
   return false;
 }
 
+static bool
+default_invalidate_tdesc_parameters (struct gdbarch *gdbarch, int regno,
+                                    reg_buffer *regcache)
+{
+  return false;
+}
+
 /* Non-zero if we want to trace architecture code.  */
 
 #ifndef GDBARCH_DEBUG
index 275145d69a0e12303bea02b0ce8b0fdaf459f905..ea6371c1cf3baf06d90a7ffc52aaf52acd9749a7 100644 (file)
@@ -264,6 +264,7 @@ struct gdbarch
   gdbarch_core_parse_exec_context_ftype *core_parse_exec_context = default_core_parse_exec_context;
   gdbarch_fetch_tdesc_parameter_ftype *fetch_tdesc_parameter = default_fetch_tdesc_parameter;
   gdbarch_register_is_variable_size_ftype *register_is_variable_size = default_register_is_variable_size;
+  gdbarch_invalidate_tdesc_parameters_ftype *invalidate_tdesc_parameters = default_invalidate_tdesc_parameters;
 };
 
 /* Create a new ``struct gdbarch'' based on information provided by
@@ -539,6 +540,7 @@ verify_gdbarch (struct gdbarch *gdbarch)
   /* Skip verify of core_parse_exec_context, invalid_p == 0.  */
   /* Skip verify of fetch_tdesc_parameter, invalid_p == 0.  */
   /* Skip verify of register_is_variable_size, invalid_p == 0.  */
+  /* Skip verify of invalidate_tdesc_parameters, invalid_p == 0.  */
   if (!log.empty ())
     internal_error (_("verify_gdbarch: the following are invalid ...%s"),
                    log.c_str ());
@@ -1416,6 +1418,9 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
   gdb_printf (file,
              "gdbarch_dump: register_is_variable_size = <%s>\n",
              host_address_to_string (gdbarch->register_is_variable_size));
+  gdb_printf (file,
+             "gdbarch_dump: invalidate_tdesc_parameters = <%s>\n",
+             host_address_to_string (gdbarch->invalidate_tdesc_parameters));
   if (gdbarch->dump_tdep != NULL)
     gdbarch->dump_tdep (gdbarch, file);
 }
@@ -5595,3 +5600,20 @@ set_gdbarch_register_is_variable_size (struct gdbarch *gdbarch,
 {
   gdbarch->register_is_variable_size = register_is_variable_size;
 }
+
+bool
+gdbarch_invalidate_tdesc_parameters (struct gdbarch *gdbarch, int regno, reg_buffer *regcache)
+{
+  gdb_assert (gdbarch != NULL);
+  gdb_assert (gdbarch->invalidate_tdesc_parameters != NULL);
+  if (gdbarch_debug >= 2)
+    gdb_printf (gdb_stdlog, "gdbarch_invalidate_tdesc_parameters called\n");
+  return gdbarch->invalidate_tdesc_parameters (gdbarch, regno, regcache);
+}
+
+void
+set_gdbarch_invalidate_tdesc_parameters (struct gdbarch *gdbarch,
+                                        gdbarch_invalidate_tdesc_parameters_ftype invalidate_tdesc_parameters)
+{
+  gdbarch->invalidate_tdesc_parameters = invalidate_tdesc_parameters;
+}
index d6058da93be9763c8284c3082f13960939385a85..8cc807c32d3fc96f43788b9b35457de597d7b7e1 100644 (file)
@@ -1813,3 +1813,11 @@ extern void set_gdbarch_fetch_tdesc_parameter (struct gdbarch *gdbarch, gdbarch_
 typedef bool (gdbarch_register_is_variable_size_ftype) (struct gdbarch *gdbarch, int regno);
 extern bool gdbarch_register_is_variable_size (struct gdbarch *gdbarch, int regno);
 extern void set_gdbarch_register_is_variable_size (struct gdbarch *gdbarch, gdbarch_register_is_variable_size_ftype *register_is_variable_size);
+
+/* Invalidate all target description parameters in REGCACHE which depend on the
+   value of REGNO.  Returns true if any parameter was invalidated, false
+   otherwise. */
+
+typedef bool (gdbarch_invalidate_tdesc_parameters_ftype) (struct gdbarch *gdbarch, int regno, reg_buffer *regcache);
+extern bool gdbarch_invalidate_tdesc_parameters (struct gdbarch *gdbarch, int regno, reg_buffer *regcache);
+extern void set_gdbarch_invalidate_tdesc_parameters (struct gdbarch *gdbarch, gdbarch_invalidate_tdesc_parameters_ftype *invalidate_tdesc_parameters);
index c893d5c941a6339475d29899eb9327ddf91ddf63..a158d85956bededd11fdb53ac852e5d8fac9ebf3 100644 (file)
@@ -2873,3 +2873,16 @@ Can the size of this register change during runtime?
     predefault="default_register_is_variable_size",
     invalid=False,
 )
+
+Method(
+    comment="""
+Invalidate all target description parameters in REGCACHE which depend on the
+value of REGNO.  Returns true if any parameter was invalidated, false
+otherwise.
+""",
+    type="bool",
+    name="invalidate_tdesc_parameters",
+    params=[("int", "regno"), ("reg_buffer *", "regcache")],
+    predefault="default_invalidate_tdesc_parameters",
+    invalid=False,
+)
index ce99d4f59795c118e93e3888365a1ee28a8d4946..eff4267fda8b63a124e59dbd3e1bb41b0e49ff2f 100644 (file)
@@ -394,6 +394,26 @@ reg_buffer::initialize_variable_size_registers ()
 
 /* See regcache.h.  */
 
+void
+reg_buffer::invalidate_variable_size_registers ()
+{
+  /* There's nothing to do if there are already no variable-size register
+     contents.  */
+  if (m_variable_size_registers == nullptr)
+    return;
+
+  for (unsigned int i = 0; i < m_descr->nr_cooked_registers; i++)
+    if (m_descr->register_is_variable_size[i])
+      invalidate (i);
+
+  m_variable_size_registers = nullptr;
+  m_variable_size_register_type.clear ();
+  m_variable_size_register_sizeof.clear ();
+  m_variable_size_register_offset.clear ();
+}
+
+/* See regcache.h.  */
+
 bool
 reg_buffer::has_variable_size_registers ()
 {
@@ -1439,6 +1459,12 @@ reg_buffer::raw_supply (int regnum, gdb::array_view<const gdb_byte> src)
 
   if (src.data () != nullptr)
     {
+      if (memcmp (src.data (), dst.data (), dst.size ())
+         && gdbarch_invalidate_tdesc_parameters (m_descr->gdbarch, regnum,
+                                                 this))
+       /* Invalidate variable-size registers.  */
+       this->invalidate_variable_size_registers ();
+
       copy (src, dst);
       m_register_status[regnum] = REG_VALID;
     }
@@ -1472,6 +1498,11 @@ reg_buffer::raw_supply_integer (int regnum, const gdb_byte *addr, int addr_len,
   gdb::array_view<gdb_byte> dst = register_buffer (regnum);
   bfd_endian byte_order = gdbarch_byte_order (m_descr->gdbarch);
 
+  if (memcmp (addr, dst.data (), dst.size ())
+      && gdbarch_invalidate_tdesc_parameters (m_descr->gdbarch, regnum, this))
+    /* Invalidate variable-size registers.  */
+    this->invalidate_variable_size_registers ();
+
   copy_integer_to_size (dst.data (), dst.size (), addr, addr_len, is_signed,
                        byte_order);
   m_register_status[regnum] = REG_VALID;
index f62d67c4f8410eb9673afefe28181c34fe691e1b..7fa40e06e3c906966d53735b7e3c4cb00ee86069 100644 (file)
@@ -293,6 +293,9 @@ protected:
      reg_buffer.  */
   void initialize_variable_size_registers ();
 
+  /* Reset information about variable-size registers in this reg_buffer.  */
+  void invalidate_variable_size_registers ();
+
   /* Return a view on register REGNUM's buffer cache.  */
   template <typename ElemType>
   gdb::array_view<ElemType> register_buffer (int regnum) const;