Fix register fetch/store order for native AArch64 Linux
authorLuis Machado <luis.machado@arm.com>
Fri, 17 Mar 2023 21:23:59 +0000 (21:23 +0000)
committerLuis Machado <luis.machado@arm.com>
Wed, 4 Oct 2023 15:23:39 +0000 (16:23 +0100)
I noticed we don't handle register reads/writes in the best way for native
AArch64 Linux.  Some other registers are fetched/stored even if upper level
code told us to fetch a particular register number.

Fix this by being more strict about which registers we touch when
reading/writing them in the native AArch64 Linux layer.

There should be no user-visible changes due to this patch.

Regression-tested on aarch64-linux Ubuntu 22.04/20.04.

Reviewed-by: Thiago Jung Bauermann <thiago.bauermann@linaro.org>
gdb/aarch64-linux-nat.c

index eeb9761bfe5726dfa4b9a23680539452302b100e..8844fc722cf3adfbe0ea83338babf225b748d16d 100644 (file)
@@ -504,6 +504,7 @@ aarch64_fetch_registers (struct regcache *regcache, int regno)
   aarch64_gdbarch_tdep *tdep
     = gdbarch_tdep<aarch64_gdbarch_tdep> (regcache->arch ());
 
+  /* Do we need to fetch all registers?  */
   if (regno == -1)
     {
       fetch_gregs_from_thread (regcache);
@@ -521,28 +522,28 @@ aarch64_fetch_registers (struct regcache *regcache, int regno)
       if (tdep->has_tls ())
        fetch_tlsregs_from_thread (regcache);
     }
+  /* General purpose register?  */
   else if (regno < AARCH64_V0_REGNUM)
     fetch_gregs_from_thread (regcache);
-  else if (tdep->has_sve ())
+  /* SVE register?  */
+  else if (tdep->has_sve () && regno <= AARCH64_SVE_VG_REGNUM)
     fetch_sveregs_from_thread (regcache);
-  else
+  /* FPSIMD register?  */
+  else if (regno <= AARCH64_FPCR_REGNUM)
     fetch_fpregs_from_thread (regcache);
-
-  if (tdep->has_pauth ())
-    {
-      if (regno == AARCH64_PAUTH_DMASK_REGNUM (tdep->pauth_reg_base)
-         || regno == AARCH64_PAUTH_CMASK_REGNUM (tdep->pauth_reg_base))
-       fetch_pauth_masks_from_thread (regcache);
-    }
-
-  /* Fetch individual MTE registers.  */
-  if (tdep->has_mte ()
-      && (regno == tdep->mte_reg_base))
+  /* PAuth register?  */
+  else if (tdep->has_pauth ()
+          && (regno == AARCH64_PAUTH_DMASK_REGNUM (tdep->pauth_reg_base)
+              || regno == AARCH64_PAUTH_CMASK_REGNUM (tdep->pauth_reg_base)))
+    fetch_pauth_masks_from_thread (regcache);
+  /* MTE register?  */
+  else if (tdep->has_mte ()
+          && (regno == tdep->mte_reg_base))
     fetch_mteregs_from_thread (regcache);
-
-  if (tdep->has_tls ()
-      && regno >= tdep->tls_regnum_base
-      && regno < tdep->tls_regnum_base + tdep->tls_register_count)
+  /* TLS register?  */
+  else if (tdep->has_tls ()
+          && regno >= tdep->tls_regnum_base
+          && regno < tdep->tls_regnum_base + tdep->tls_register_count)
     fetch_tlsregs_from_thread (regcache);
 }
 
@@ -592,6 +593,7 @@ aarch64_store_registers (struct regcache *regcache, int regno)
   aarch64_gdbarch_tdep *tdep
     = gdbarch_tdep<aarch64_gdbarch_tdep> (regcache->arch ());
 
+  /* Do we need to store all registers?  */
   if (regno == -1)
     {
       store_gregs_to_thread (regcache);
@@ -606,22 +608,26 @@ aarch64_store_registers (struct regcache *regcache, int regno)
       if (tdep->has_tls ())
        store_tlsregs_to_thread (regcache);
     }
+  /* General purpose register?  */
   else if (regno < AARCH64_V0_REGNUM)
     store_gregs_to_thread (regcache);
-  else if (tdep->has_sve ())
+  /* SVE register?  */
+  else if (tdep->has_sve () && regno <= AARCH64_SVE_VG_REGNUM)
     store_sveregs_to_thread (regcache);
-  else
+  /* FPSIMD register?  */
+  else if (regno <= AARCH64_FPCR_REGNUM)
     store_fpregs_to_thread (regcache);
-
-  /* Store MTE registers.  */
-  if (tdep->has_mte ()
-      && (regno == tdep->mte_reg_base))
+  /* MTE register?  */
+  else if (tdep->has_mte ()
+          && (regno == tdep->mte_reg_base))
     store_mteregs_to_thread (regcache);
-
-  if (tdep->has_tls ()
-      && regno >= tdep->tls_regnum_base
-      && regno < tdep->tls_regnum_base + tdep->tls_register_count)
+  /* TLS register?  */
+  else if (tdep->has_tls ()
+          && regno >= tdep->tls_regnum_base
+          && regno < tdep->tls_regnum_base + tdep->tls_register_count)
     store_tlsregs_to_thread (regcache);
+
+  /* PAuth registers are read-only.  */
 }
 
 /* A version of the "store_registers" target_ops method used when running