]> 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>
Thu, 23 Oct 2025 04:17:04 +0000 (01:17 -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 30af583476c7453535d029914f1e4999c172580c..10077d902bf4c771eeced2592a33b9ee3777f394 100644 (file)
@@ -4431,6 +4431,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.  */
 
@@ -5023,6 +5039,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 46603487ebfa2d4c571218db85458de4f680738b..f77174c108319769d9f5c45dfb52b8cd2d246b03 100644 (file)
@@ -1139,6 +1139,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 aa322c8cf6b77e40fa72c0f393261312a52d706d..038c8c220483ab5b660feb494e5f398ba4fcf102 100644 (file)
@@ -264,6 +264,7 @@ struct gdbarch
   gdbarch_get_shadow_stack_pointer_ftype *get_shadow_stack_pointer = default_get_shadow_stack_pointer;
   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 get_shadow_stack_pointer, 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 ());
@@ -1419,6 +1421,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);
 }
@@ -5605,3 +5610,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 ad76d167d1fb8ba7c291e8df1a4272884bb7f7f8..e93fa9576e54f848204014d6e464487f4947ad0d 100644 (file)
@@ -1825,3 +1825,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 28d31e60df3fdb0958a38f5a443f70a4fbcc572c..ea4bd0ace135fed8b15fbcbbb78042e78e04a6e2 100644 (file)
@@ -2898,3 +2898,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 41f8fedf8b64f7cb2054ba2792e1260abd2f0614..1d86287125facfa1aea69f83ca76355b63501318 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 a8ee90f12ab08e3d1b0443b5233c1500421bdd98..a25c6432dac366cc27e4ecf967621776d8f2c35c 100644 (file)
@@ -292,6 +292,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;