From ed96a7a577fb917004bf319bf4ee8a677306b9d3 Mon Sep 17 00:00:00 2001 From: Luis Machado Date: Wed, 28 Oct 2020 15:56:36 -0300 Subject: [PATCH] Invert CSP/PCC and simplify access to C register numbers 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 * 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) : New fields * features/aarch64-capability.c: Regenerate. * features/aarch64-capability.xml: Invert pcc/csp. gdbserver/ChangeLog: 2020-11-11 Luis Machado * linux-aarch64-low.cc (aarch64_store_cregset): Invert pcc/csp. --- gdb/aarch64-linux-nat.c | 2 +- gdb/aarch64-linux-tdep.c | 10 +-- gdb/aarch64-tdep.c | 94 ++++++++++++++--------------- gdb/aarch64-tdep.h | 8 +++ gdb/features/aarch64-capability.c | 2 +- gdb/features/aarch64-capability.xml | 2 +- gdbserver/linux-aarch64-low.cc | 2 +- 7 files changed, 62 insertions(+), 58 deletions(-) diff --git a/gdb/aarch64-linux-nat.c b/gdb/aarch64-linux-nat.c index cdf101bad39..5a79dd44493 100644 --- a/gdb/aarch64-linux-nat.c +++ b/gdb/aarch64-linux-nat.c @@ -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); diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c index 61753a2d7ea..98d17b2deb9 100644 --- a/gdb/aarch64-linux-tdep.c +++ b/gdb/aarch64-linux-tdep.c @@ -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; diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c index 045483b20d1..fd9120460bd 100644 --- a/gdb/aarch64-tdep.c +++ b/gdb/aarch64-tdep.c @@ -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); diff --git a/gdb/aarch64-tdep.h b/gdb/aarch64-tdep.h index 6a77f98b93c..f3241f8e5d4 100644 --- a/gdb/aarch64-tdep.h +++ b/gdb/aarch64-tdep.h @@ -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 diff --git a/gdb/features/aarch64-capability.c b/gdb/features/aarch64-capability.c index dfd78615ac0..b6180e64b6d 100644 --- a/gdb/features/aarch64-capability.c +++ b/gdb/features/aarch64-capability.c @@ -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"); diff --git a/gdb/features/aarch64-capability.xml b/gdb/features/aarch64-capability.xml index 33110cdbd89..ebe8aea733c 100644 --- a/gdb/features/aarch64-capability.xml +++ b/gdb/features/aarch64-capability.xml @@ -38,8 +38,8 @@ - + diff --git a/gdbserver/linux-aarch64-low.cc b/gdbserver/linux-aarch64-low.cc index 5d5dc817b0f..48e0a3726f8 100644 --- a/gdbserver/linux-aarch64-low.cc +++ b/gdbserver/linux-aarch64-low.cc @@ -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); -- 2.47.2