]> 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)
committerLuis Machado <luis.machado@linaro.org>
Tue, 8 Dec 2020 18:02:58 +0000 (15:02 -0300)
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/ChangeLog
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/ChangeLog
gdbserver/linux-aarch64-low.cc

index 98004350a358d64d8bc4a239adc9788064ac6323..b596c7571d36b29e555b1104c3382a78d12389ed 100644 (file)
@@ -1,3 +1,20 @@
+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.
+
 2020-11-11  Luis Machado  <luis.machado@arm.com>
 
        * aarch64-tdep.c (aarch64_prologue_prev_register): Guard use of
index dc006de7f0d38cc775adb808a7a0e9909aea9222..d1859c89da40338675cd2abc40d72b97200681ce 100644 (file)
@@ -489,8 +489,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 398b429341d8c17c48551e11a63ff5faade566b5..9c4d27610c0fd58f4ccb74186f2540b8f81788cb 100644 (file)
@@ -313,10 +313,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 "
@@ -324,11 +320,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 16c85e394665a7f51dd2df0cd12817bdf9bf9804..c8ca8ac73685b733467dff742ef51c2847f334ea 100644 (file)
@@ -272,8 +272,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,8 +865,6 @@ aarch64_analyze_prologue (struct gdbarch *gdbarch,
   if (gdbarch_tdep (gdbarch)->has_capability ())
     {
       struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
-      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 +877,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].addr = offset;
-             else if (i == AARCH64_PC_REGNUM)
-               cache->saved_regs[pcc_regnum].addr = offset;
-             else
-               cache->saved_regs[tdep->cap_reg_base + i].addr = offset;
+             cache->saved_regs[tdep->cap_reg_base + i].addr = offset;
            }
        }
     }
@@ -1402,16 +1392,12 @@ aarch64_prologue_prev_register (struct frame_info *this_frame,
 
   struct gdbarch_tdep *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);
@@ -1422,7 +1408,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);
@@ -1444,7 +1430,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));
@@ -1468,11 +1454,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);
 
@@ -1614,18 +1597,38 @@ aarch64_dwarf2_prev_register (struct frame_info *this_frame,
 {
   struct gdbarch *gdbarch = get_frame_arch (this_frame);
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
-  CORE_ADDR lr;
 
-  int pcc_regnum = -1;
-  if (tdep->has_capability ())
-    pcc_regnum = tdep->cap_reg_base + 31;
-
-  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), 8,
+                                               gdbarch_byte_order (gdbarch));
+
       lr = aarch64_frame_unmask_lr (tdep, this_frame, lr);
       lr = gdbarch_addr_bits_remove (gdbarch, lr);
-      return frame_unwind_got_constant (this_frame, regnum, 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);
@@ -1642,23 +1645,15 @@ aarch64_dwarf2_frame_init_reg (struct gdbarch *gdbarch, int regnum,
                               struct frame_info *this_frame)
 {
   struct gdbarch_tdep *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;
@@ -2593,7 +2588,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;
@@ -4220,8 +4215,13 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   tdep->pauth_ra_state_regnum = (feature_pauth == NULL) ? -1
                                : pauth_ra_state_offset + num_regs;
 
+  /* 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 a9d89c0d8b7f6f0254c2b63b3d64e8f2b4fe3d46..f87322dffb6a24e3bb4d8b35dfe836bae8ad5b00 100644 (file)
@@ -128,6 +128,14 @@ struct 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 7a4aa4eed2747d60424a167d00e89dbfbd126965..a0b901b23dde624b2f7a9243e08fcded57c836e0 100644 (file)
@@ -1,3 +1,7 @@
+2020-11-11  Luis Machado  <luis.machado@arm.com>
+
+       * linux-aarch64-low.cc (aarch64_store_cregset): Invert pcc/csp.
+
 2020-10-20  Luis Machado  <luis.machado@arm.com>
 
        * linux-aarch64-low.c: arch/aarch64-cap-linux.h.
index 940399d381b391b1faa86ce9fe90fc3c0ec85a2a..d034e783cb23a0dbd44e746c990916e2d7990117 100644 (file)
@@ -279,8 +279,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);