From: Luis Machado Date: Fri, 9 Oct 2020 16:50:17 +0000 (-0300) Subject: [Morello] Unwinding: Restore CLR and PCC properly X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0b9434536880ef252d12cb129b47ee3d4e64c570;p=thirdparty%2Fbinutils-gdb.git [Morello] Unwinding: Restore CLR and PCC properly This patch teaches GDB how to handle restoring CLR and PCC values properly. gdb/ChangeLog: 2020-10-20 Luis Machado * aarch64-tdep.c (aarch64_prologue_prev_register): Use LR or CLR depending on the request. (aarch64_dwarf_reg_to_regnum): Redirect CLR to LR temporarily. * aarch64-tdep.h (AARCH64_DWARF_CLR): New constant. --- diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c index 7b395dafdb8..8900ac816ff 100644 --- a/gdb/aarch64-tdep.c +++ b/gdb/aarch64-tdep.c @@ -1280,20 +1280,48 @@ aarch64_prologue_prev_register (struct frame_info *this_frame, /* 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. */ + 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) { CORE_ADDR lr; struct gdbarch *gdbarch = get_frame_arch (this_frame); + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - lr = frame_unwind_register_unsigned (this_frame, AARCH64_LR_REGNUM); + /* Fetch LR or CLR depending on the ABI. */ + int lr_regnum; + if (prev_regnum == AARCH64_PC_REGNUM) + lr_regnum = AARCH64_LR_REGNUM; + else + lr_regnum = tdep->cap_reg_base + 30; + + 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. */ + lr = extract_unsigned_integer (value_contents_all (lr_value).data (), 8, + byte_order); if (tdep->has_pauth () && cache->saved_regs[tdep->pauth_ra_state_regnum].is_value ()) lr = aarch64_frame_unmask_lr (tdep, this_frame, lr); + /* Remove any potential LSB's in the address. */ lr = gdbarch_addr_bits_remove (gdbarch, lr); - return frame_unwind_got_constant (this_frame, prev_regnum, lr); + + struct value *lr_value_adjusted + = 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)) + { + set_value_tagged (lr_value_adjusted, 1); + set_value_tag (lr_value_adjusted, value_tag (lr_value)); + } + + return lr_value_adjusted; } /* SP is generally not saved to the stack, but this frame is @@ -2416,6 +2444,10 @@ aarch64_dwarf_reg_to_regnum (struct gdbarch *gdbarch, int reg) if (tdep->has_capability ()) { + /* FIXME-Morello: Redirect CLR to LR for now. */ + if (reg == AARCH64_DWARF_CLR) + return AARCH64_LR_REGNUM; + if (reg >= AARCH64_DWARF_C0 && reg <= AARCH64_DWARF_C0 + 30) return tdep->cap_reg_base + (reg - AARCH64_DWARF_C0); diff --git a/gdb/aarch64-tdep.h b/gdb/aarch64-tdep.h index 7598df1471e..6a77f98b93c 100644 --- a/gdb/aarch64-tdep.h +++ b/gdb/aarch64-tdep.h @@ -43,6 +43,7 @@ struct regset; #define AARCH64_DWARF_SVE_P0 48 #define AARCH64_DWARF_SVE_Z0 96 #define AARCH64_DWARF_C0 198 +#define AARCH64_DWARF_CLR 228 #define AARCH64_DWARF_CSP 229 #define AARCH64_DWARF_PCC 230 #define AARCH64_DWARF_DDC 231