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/?a=commitdiff_plain;h=9e9a064bf40f7e1ecbafd9fd0ad3edef3d11c4d5;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/ChangeLog b/gdb/ChangeLog index 1db787a233a..6df56cc91e7 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,10 @@ +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. + 2020-10-20 Luis Machado * aarch64-tdep.c (aarch64_prologue_prev_register): Handle the PCC and diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c index 20b84c37649..b28ed42a9d0 100644 --- a/gdb/aarch64-tdep.c +++ b/gdb/aarch64-tdep.c @@ -1238,21 +1238,49 @@ 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), 8, + byte_order); if (tdep->has_pauth () && trad_frame_value_p (cache->saved_regs, tdep->pauth_ra_state_regnum)) 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 @@ -2377,6 +2405,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 c7238207c0e..a9d89c0d8b7 100644 --- a/gdb/aarch64-tdep.h +++ b/gdb/aarch64-tdep.h @@ -41,6 +41,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