]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Invert CSP/PCC and simplify access to C register numbers
authorLuis Machado <luis.machado@arm.com>
Wed, 28 Oct 2020 18:56:36 +0000 (15:56 -0300)
committerJohn Baldwin <jhb@FreeBSD.org>
Thu, 1 Sep 2022 22:53:22 +0000 (15:53 -0700)
This change makes the code more straightforward, since we can expect the order
of the X registers to match that of the C registers.  That way we don't have to
deal with ordering issues.

It also simplifies the access to the dynamic C register numbers through the
gdbarch tdep data structure.

gdb/ChangeLog:

2020-11-11  Luis Machado  <luis.machado@arm.com>

* aarch64-linux-nat.c (fetch_cregs_from_thread): Invert pcc/csp
order.
* aarch64-linux-tdep.c (aarch64_linux_sigframe_init): Likewise.
* aarch64-tdep.c (aarch64_c_register_names): Likewise.
(aarch64_analyze_prologue): Remove code to handle csp/pcc ordering
issues.
(aarch64_prologue_prev_register): Use new tdep fields.
(aarch64_dwarf2_prev_register): Use new tdep fields and handle lr/clr.
(aarch64_dwarf2_frame_init_reg): Use new tdep fields.
(aarch64_gdbarch_init): Initialize the new tdep fields.
* aarch64-tdep.h (gdbarch_tdep) <cap_reg_clr, cap_reg_csp>
<cap_reg_pcc, cap_reg_rcsp>: New fields
* features/aarch64-capability.c: Regenerate.
* features/aarch64-capability.xml: Invert pcc/csp.

gdbserver/ChangeLog:

2020-11-11  Luis Machado  <luis.machado@arm.com>

* linux-aarch64-low.cc (aarch64_store_cregset): Invert pcc/csp.

gdb/aarch64-linux-nat.c
gdb/aarch64-linux-tdep.c
gdb/aarch64-tdep.c
gdb/aarch64-tdep.h
gdb/features/aarch64-capability.c
gdb/features/aarch64-capability.xml
gdbserver/linux-aarch64-low.cc

index cdf101bad39ad59f78031b02aac6ca99ba45b5c6..5a79dd444938feb771a31845c4f20d04efd3b92b 100644 (file)
@@ -515,8 +515,8 @@ fetch_cregs_from_thread (struct regcache *regcache)
     regcache->raw_supply (regno, &cregset.cregs[i]);
 
   /* Fetch the other registers.  */
-  regcache->raw_supply (regno++, &cregset.pcc);
   regcache->raw_supply (regno++, &cregset.csp);
+  regcache->raw_supply (regno++, &cregset.pcc);
   regcache->raw_supply (regno++, &cregset.ddc);
   regcache->raw_supply (regno++, &cregset.ctpidr);
   regcache->raw_supply (regno++, &cregset.rcsp);
index 61753a2d7ea2bb6555cabc7467adc2e3e422052f..98d17b2deb97b6fc397f92ceebcab7f0a1491f92 100644 (file)
@@ -410,10 +410,6 @@ aarch64_linux_sigframe_init (const struct tramp_frame *self,
                                         offset + i * reg_size);
              }
 
-           int pcc_regnum = tdep->cap_reg_base + 31;
-           int csp_regnum = tdep->cap_reg_base + 32;
-           int rcsp_regnum = tdep->cap_reg_base + 35;
-
            if (aarch64_debug)
              {
                debug_printf ("aarch64: Reading PCC, CSP and RCSP registers "
@@ -421,11 +417,11 @@ aarch64_linux_sigframe_init (const struct tramp_frame *self,
                              paddress (gdbarch, offset + 31 * reg_size));
              }
 
-           trad_frame_set_reg_addr (this_cache, csp_regnum,
+           trad_frame_set_reg_addr (this_cache, tdep->cap_reg_csp,
                                     offset + 31 * reg_size);
-           trad_frame_set_reg_addr (this_cache, rcsp_regnum,
+           trad_frame_set_reg_addr (this_cache, tdep->cap_reg_rcsp,
                                     offset + 32 * reg_size);
-           trad_frame_set_reg_addr (this_cache, pcc_regnum,
+           trad_frame_set_reg_addr (this_cache, tdep->cap_reg_pcc,
                                     offset + 33 * reg_size);
 
            section += size;
index 045483b20d1482da919ffb2d379686c0c5ce5f87..fd9120460bd20727ef661f0e958cc4f055ff2c29 100644 (file)
@@ -268,8 +268,8 @@ static const char *const aarch64_c_register_names[] =
   "c0", "c1", "c2", "c3", "c4", "c5", "c6", "c7",
   "c8", "c9", "c10", "c11", "c12", "c13", "c14", "c15",
   "c16", "c17", "c18", "c19", "c20", "c21", "c22", "c23",
-  "c24", "c25", "c26", "c27", "c28", "c29", "c30", "pcc",
-  "csp", "ddc", "ctpidr", "rcsp", "rddc", "rctpidr", "cid",
+  "c24", "c25", "c26", "c27", "c28", "c29", "c30", "csp",
+  "pcc", "ddc", "ctpidr", "rcsp", "rddc", "rctpidr", "cid",
   "tag_map", "cctlr"
 };
 
@@ -865,9 +865,6 @@ aarch64_analyze_prologue (struct gdbarch *gdbarch,
 
   if (tdep->has_capability ())
     {
-      int pcc_regnum = tdep->cap_reg_base + 31;
-      int csp_regnum = tdep->cap_reg_base + 32;
-
       /* Also save the C registers.  */
       for (i = 0; i < AARCH64_X_REGISTER_COUNT; i++)
        {
@@ -879,15 +876,7 @@ aarch64_analyze_prologue (struct gdbarch *gdbarch,
                debug_printf ("aarch64: %s Register C%d found at offset %s\n",
                              __func__, i, core_addr_to_string_nz (offset));
 
-             /* FIXME-Morello: We should really invert CSP/PCC to make them
-                match the order of the X registers.  Then we wouldn't need
-                this conditional block.  */
-             if (i == AARCH64_SP_REGNUM)
-               cache->saved_regs[csp_regnum].set_addr (offset);
-             else if (i == AARCH64_PC_REGNUM)
-               cache->saved_regs[pcc_regnum].set_addr (offset);
-             else
-               cache->saved_regs[tdep->cap_reg_base + i].set_addr (offset);
+             cache->saved_regs[tdep->cap_reg_base + i].set_addr (offset);
            }
        }
     }
@@ -1442,16 +1431,12 @@ aarch64_prologue_prev_register (struct frame_info *this_frame,
   aarch64_gdbarch_tdep *tdep
     = (aarch64_gdbarch_tdep *) gdbarch_tdep (get_frame_arch (this_frame));
 
-  int pcc_regnum = -1;
-  if (tdep->has_capability ())
-    pcc_regnum = tdep->cap_reg_base + 31;
-
   /* If we are asked to unwind the PC, then we need to return the LR
      instead.  The prologue may save PC, but it will point into this
      frame's prologue, not the next frame's resume location.
 
      We do the same for PCC and CLR.  */
-  if (prev_regnum == AARCH64_PC_REGNUM || prev_regnum == pcc_regnum)
+  if (prev_regnum == AARCH64_PC_REGNUM || prev_regnum == tdep->cap_reg_pcc)
     {
       CORE_ADDR lr;
       struct gdbarch *gdbarch = get_frame_arch (this_frame);
@@ -1462,7 +1447,7 @@ aarch64_prologue_prev_register (struct frame_info *this_frame,
       if (prev_regnum == AARCH64_PC_REGNUM)
        lr_regnum = AARCH64_LR_REGNUM;
       else
-       lr_regnum = tdep->cap_reg_base + 30;
+       lr_regnum = tdep->cap_reg_clr;
 
       struct value *lr_value = frame_unwind_register_value (this_frame,
                                                            lr_regnum);
@@ -1483,7 +1468,7 @@ aarch64_prologue_prev_register (struct frame_info *this_frame,
          = frame_unwind_got_constant (this_frame, prev_regnum, lr);
 
       /* Copy the capability tag over, if it exists.  */
-      if (prev_regnum == pcc_regnum && value_tagged (lr_value))
+      if (prev_regnum == tdep->cap_reg_pcc && value_tagged (lr_value))
        {
          set_value_tagged (lr_value_adjusted, 1);
          set_value_tag (lr_value_adjusted, value_tag (lr_value));
@@ -1507,11 +1492,8 @@ aarch64_prologue_prev_register (struct frame_info *this_frame,
         |          |
         |          |<- SP
         +----------+  */
-  int csp_regnum = -1;
-  if (tdep->has_capability ())
-    csp_regnum = tdep->cap_reg_base + 32;
 
-  if (prev_regnum == AARCH64_SP_REGNUM || prev_regnum == csp_regnum)
+  if (prev_regnum == AARCH64_SP_REGNUM || prev_regnum == tdep->cap_reg_csp)
     return frame_unwind_got_constant (this_frame, prev_regnum,
                                      cache->prev_sp);
 
@@ -1653,20 +1635,41 @@ static struct value *
 aarch64_dwarf2_prev_register (struct frame_info *this_frame,
                              void **this_cache, int regnum)
 {
-  gdbarch *arch = get_frame_arch (this_frame);
-  aarch64_gdbarch_tdep *tdep = (aarch64_gdbarch_tdep *) gdbarch_tdep (arch);
-  CORE_ADDR lr;
-
-  int pcc_regnum = -1;
-  if (tdep->has_capability ())
-    pcc_regnum = tdep->cap_reg_base + 31;
+  gdbarch *gdbarch = get_frame_arch (this_frame);
+  aarch64_gdbarch_tdep *tdep = (aarch64_gdbarch_tdep *) gdbarch_tdep (gdbarch);
 
-  if (regnum == AARCH64_PC_REGNUM || regnum == pcc_regnum)
+  if (regnum == AARCH64_PC_REGNUM || regnum == tdep->cap_reg_pcc)
     {
-      lr = frame_unwind_register_unsigned (this_frame, AARCH64_LR_REGNUM);
+      /* Fetch LR or CLR depending on the ABI.  */
+      int lr_regnum;
+      if (regnum == AARCH64_PC_REGNUM)
+       lr_regnum = AARCH64_LR_REGNUM;
+      else
+       lr_regnum = tdep->cap_reg_clr;
+
+      struct value *lr_value = frame_unwind_register_value (this_frame,
+                                                            lr_regnum);
+
+      /* Extract only the bottom 8 bytes of CLR.  This truncates the capability
+        to 8 bytes.  For LR, this gets us the whole register.  */
+      CORE_ADDR lr
+       = extract_unsigned_integer (value_contents_all (lr_value).data (), 8,
+                                   gdbarch_byte_order (gdbarch));
+
       lr = aarch64_frame_unmask_lr (tdep, this_frame, lr);
-      lr = gdbarch_addr_bits_remove (arch, lr);
-      return frame_unwind_got_constant (this_frame, regnum, lr);
+      lr = gdbarch_addr_bits_remove (gdbarch, lr);
+
+      struct value *lr_value_adjusted
+       = frame_unwind_got_constant (this_frame, regnum, lr);
+
+      /* Copy the capability tag over, if it exists.  */
+      if (regnum == tdep->cap_reg_pcc && value_tagged (lr_value))
+       {
+         set_value_tagged (lr_value_adjusted, 1);
+         set_value_tag (lr_value_adjusted, value_tag (lr_value));
+       }
+
+      return lr_value_adjusted;
     }
 
   internal_error (__FILE__, __LINE__, _("Unexpected register %d"), regnum);
@@ -1683,23 +1686,15 @@ aarch64_dwarf2_frame_init_reg (struct gdbarch *gdbarch, int regnum,
                               struct frame_info *this_frame)
 {
   aarch64_gdbarch_tdep *tdep = (aarch64_gdbarch_tdep *) gdbarch_tdep (gdbarch);
-  int pcc_regnum = -1;
-  int csp_regnum = -1;
-
-  if (tdep->has_capability ())
-    {
-      pcc_regnum = tdep->cap_reg_base + 31;
-      csp_regnum = tdep->cap_reg_base + 32;
-    }
 
-  if (regnum == AARCH64_PC_REGNUM || regnum == pcc_regnum)
+  if (regnum == AARCH64_PC_REGNUM || regnum == tdep->cap_reg_pcc)
     {
       reg->how = DWARF2_FRAME_REG_FN;
       reg->loc.fn = aarch64_dwarf2_prev_register;
       return;
     }
 
-  if (regnum == AARCH64_SP_REGNUM || regnum == csp_regnum)
+  if (regnum == AARCH64_SP_REGNUM || regnum == tdep->cap_reg_csp)
     {
       reg->how = DWARF2_FRAME_REG_CFA;
       return;
@@ -2630,7 +2625,7 @@ aarch64_dwarf_reg_to_regnum (struct gdbarch *gdbarch, int reg)
        return tdep->cap_reg_base + (reg - AARCH64_DWARF_C0);
 
       if (reg == AARCH64_DWARF_CSP)
-       return tdep->cap_reg_base + 32;
+       return tdep->cap_reg_csp;
     }
 
   return -1;
@@ -4326,8 +4321,13 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   tdep->mte_reg_base = first_mte_regnum;
   tdep->tls_regnum = tls_regnum;
 
+  /* Initialize the capability register numbers.  */
   tdep->cap_reg_base = first_cap_regnum;
   tdep->cap_reg_last = last_cap_regnum;
+  tdep->cap_reg_clr = (first_cap_regnum == -1)? -1 : first_cap_regnum + 30;
+  tdep->cap_reg_csp = (first_cap_regnum == -1)? -1 : first_cap_regnum + 31;
+  tdep->cap_reg_pcc = (first_cap_regnum == -1)? -1 : first_cap_regnum + 32;
+  tdep->cap_reg_rcsp = (first_cap_regnum == -1)? -1 : first_cap_regnum + 35;
 
   set_gdbarch_push_dummy_call (gdbarch, aarch64_push_dummy_call);
   set_gdbarch_frame_align (gdbarch, aarch64_frame_align);
index 6a77f98b93c1c95f5b706f933f8221adb767b846..f3241f8e5d47d7283a255d93aee97be6d4733229 100644 (file)
@@ -147,6 +147,14 @@ struct aarch64_gdbarch_tdep : gdbarch_tdep
   int cap_reg_base;
   /* Last register from the capability set.  */
   int cap_reg_last;
+  /* CLR register number.  */
+  int cap_reg_clr;
+  /* CSP register numbers.  */
+  int cap_reg_csp;
+  /* PCC register number.  */
+  int cap_reg_pcc;
+  /* RCSP register number.  */
+  int cap_reg_rcsp;
 
   /* Returns true if the target supports capabilities.  */
   bool has_capability () const
index dfd78615ac0cae831d48f284ed2e54629a9a2ea9..b6180e64b6d0fc9288b88fc3064be39f64e194dc 100644 (file)
@@ -41,8 +41,8 @@ create_feature_aarch64_capability (struct target_desc *result, long regnum)
   tdesc_create_reg (feature, "c28", regnum++, 1, "general", 128, "uintcap");
   tdesc_create_reg (feature, "c29", regnum++, 1, "general", 128, "uintcap");
   tdesc_create_reg (feature, "c30", regnum++, 1, "general", 128, "uintcap");
-  tdesc_create_reg (feature, "pcc", regnum++, 1, "general", 128, "uintcap");
   tdesc_create_reg (feature, "csp", regnum++, 1, "general", 128, "uintcap");
+  tdesc_create_reg (feature, "pcc", regnum++, 1, "general", 128, "uintcap");
   tdesc_create_reg (feature, "ddc", regnum++, 1, "system", 128, "uintcap");
   tdesc_create_reg (feature, "ctpidr", regnum++, 1, "system", 128, "uintcap");
   tdesc_create_reg (feature, "rcsp", regnum++, 1, "system", 128, "uintcap");
index 33110cdbd89359443c25cc20729d17859a0d769c..ebe8aea733c9935d62c9bac2c64bbf55b4dad50c 100644 (file)
@@ -38,8 +38,8 @@
   <reg name="c28" bitsize="128" type="uintcap" group="general"/>
   <reg name="c29" bitsize="128" type="uintcap" group="general"/>
   <reg name="c30" bitsize="128" type="uintcap" group="general"/>
-  <reg name="pcc" bitsize="128" type="uintcap" group="general"/>
   <reg name="csp" bitsize="128" type="uintcap" group="general"/>
+  <reg name="pcc" bitsize="128" type="uintcap" group="general"/>
   <reg name="ddc" bitsize="128" type="uintcap" group="system"/>
   <reg name="ctpidr" bitsize="128" type="uintcap" group="system"/>
   <reg name="rcsp" bitsize="128" type="uintcap" group="general"/>
index 5d5dc817b0f682c4a4b84af117fc2de578e65ee9..48e0a3726f8a8eaafcfe51b8f25195525f551a28 100644 (file)
@@ -326,8 +326,8 @@ aarch64_store_cregset (struct regcache *regcache, const void *buf)
     supply_register (regcache, regno, &cregset->cregs[i]);
 
   /* Fetch the other registers.  */
-  supply_register (regcache, regno++, &cregset->pcc);
   supply_register (regcache, regno++, &cregset->csp);
+  supply_register (regcache, regno++, &cregset->pcc);
   supply_register (regcache, regno++, &cregset->ddc);
   supply_register (regcache, regno++, &cregset->ctpidr);
   supply_register (regcache, regno++, &cregset->rcsp);