diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c index 1b2d4435088..a9cf6e3127f 100644 --- a/gdb/aarch64-linux-tdep.c +++ b/gdb/aarch64-linux-tdep.c @@ -171,6 +171,7 @@ #define AARCH64_ZT_MAGIC 0x5a544e01 #define AARCH64_GCS_MAGIC 0x47435300 #define AARCH64_FPMR_MAGIC 0x46504d52 +#define AARCH64_POE_MAGIC 0x504f4530 /* Defines for the extra_context that follows an AARCH64_EXTRA_MAGIC. */ #define AARCH64_EXTRA_DATAP_OFFSET 8 @@ -220,6 +221,9 @@ /* FPMR constants. */ #define AARCH64_FPMR_OFFSET 8 +/* POE constants. */ +#define AARCH64_POE_OFFSET 8 + /* Holds information about the signal frame. */ struct aarch64_linux_sigframe { @@ -273,6 +277,10 @@ struct aarch64_linux_sigframe /* FPMR value. */ CORE_ADDR fpmr = 0; + /* True if we have a POE entry in the signal context, false otherwise. */ + bool poe_available = false; + /* POE value. */ + CORE_ADDR poe = 0; }; /* Read an aarch64_ctx, returning the magic value, and setting *SIZE to the @@ -605,6 +613,22 @@ aarch64_linux_read_signal_frame_info (const frame_info_ptr &this_frame, section += size; break; } + case AARCH64_POE_MAGIC: + { + gdb_byte buf[8]; + if (target_read_memory (section + AARCH64_POE_OFFSET, + buf, 8) != 0) + { + warning (_("Failed to read the POE section address from the" + " signal frame context.")); + section += size; + break; + } + signal_frame.poe = extract_unsigned_integer (buf, 8, byte_order); + signal_frame.poe_available = true; + section += size; + break; + } case AARCH64_EXTRA_MAGIC: { /* Extra is always the last valid section in reserved and points to @@ -775,6 +799,10 @@ aarch64_linux_sigframe_init (const struct tramp_frame *self, signal_frame.fpmr); } + /* Handle POE register. */ + if (tdep->has_poe () && signal_frame.poe_available) + trad_frame_set_reg_value (this_cache, tdep->poe_regnum, signal_frame.poe); + /* Restore the tpidr2 register, if the target supports it and if there is an entry for it. */ if (signal_frame.tpidr2_section != 0 && tdep->has_tls () @@ -828,6 +856,7 @@ aarch64_linux_sigframe_prev_arch (const frame_info_ptr &this_frame, features.vq = sve_vq_from_vl (signal_frame.vl); features.svq = (uint8_t) sve_vq_from_vl (signal_frame.svl); features.fpmr = signal_frame.fpmr_available; + features.poe = signal_frame.poe_available; struct gdbarch_info info; info.bfd_arch_info = bfd_lookup_arch (bfd_arch_aarch64, bfd_mach_aarch64); @@ -1655,6 +1684,23 @@ aarch64_linux_iterate_over_regset_sections (struct gdbarch *gdbarch, &aarch64_linux_fpmr_regset, "FPMR", cb_data); } + if (tdep->has_poe ()) + { + const struct regcache_map_entry poe_regmap[] = + { + { 1, tdep->poe_regnum, sizeof (uint64_t) }, + { 0 } + }; + + const struct regset aarch64_linux_poe_regset = + { + poe_regmap, regcache_supply_regset, regcache_collect_regset + }; + + cb (".reg-aarch-poe", sizeof (uint64_t), sizeof (uint64_t), + &aarch64_linux_poe_regset, "POE register", cb_data); + } + if (tdep->has_pauth ()) { /* Create this on the fly in order to handle the variable location. */ @@ -1768,6 +1814,7 @@ aarch64_linux_core_read_description (struct gdbarch *gdbarch, features.gcs = features.gcs_linux = hwcap & AARCH64_HWCAP_GCS; features.mte = hwcap2 & AARCH64_HWCAP2_MTE; features.fpmr = hwcap2 & AARCH64_HWCAP2_FPMR; + features.poe = hwcap2 & AARCH64_HWCAP2_POE; /* Handle the TLS section. */ asection *tls = bfd_get_section_by_name (abfd, ".reg-aarch-tls");