AArch64: Add MTE register set support for GDB and gdbserver
AArch64 MTE support in the Linux kernel exposes a new register through ptrace. This patch adds the required code to support it. include/ChangeLog: 2021-03-24 Luis Machado <luis.machado@linaro.org> * elf/common.h (NT_ARM_TAGGED_ADDR_CTRL): Define. gdb/ChangeLog: 2021-03-24 Luis Machado <luis.machado@linaro.org> * aarch64-linux-nat.c (fetch_mteregs_from_thread): New function. (store_mteregs_to_thread): New function. (aarch64_linux_nat_target::fetch_registers): Update to call fetch_mteregs_from_thread. (aarch64_linux_nat_target::store_registers): Update to call store_mteregs_to_thread. * aarch64-tdep.c (aarch64_mte_register_names): New struct. (aarch64_cannot_store_register): Handle MTE registers. (aarch64_gdbarch_init): Initialize and setup MTE registers. * aarch64-tdep.h (gdbarch_tdep) <mte_reg_base>: New field. <has_mte>: New method. * arch/aarch64-linux.h (AARCH64_LINUX_SIZEOF_MTE): Define. gdbserver/ChangeLog: 2021-03-24 Luis Machado <luis.machado@linaro.org> * linux-aarch64-low.cc (aarch64_fill_mteregset): New function. (aarch64_store_mteregset): New function. (aarch64_regsets): Add MTE register set entry. (aarch64_sve_regsets): Add MTE register set entry.
This commit is contained in:
parent
c1bd443b4d
commit
5e984dbf35
@ -1,3 +1,18 @@
|
||||
2021-03-24 Luis Machado <luis.machado@linaro.org>
|
||||
|
||||
* aarch64-linux-nat.c (fetch_mteregs_from_thread): New function.
|
||||
(store_mteregs_to_thread): New function.
|
||||
(aarch64_linux_nat_target::fetch_registers): Update to call
|
||||
fetch_mteregs_from_thread.
|
||||
(aarch64_linux_nat_target::store_registers): Update to call
|
||||
store_mteregs_to_thread.
|
||||
* aarch64-tdep.c (aarch64_mte_register_names): New struct.
|
||||
(aarch64_cannot_store_register): Handle MTE registers.
|
||||
(aarch64_gdbarch_init): Initialize and setup MTE registers.
|
||||
* aarch64-tdep.h (gdbarch_tdep) <mte_reg_base>: New field.
|
||||
<has_mte>: New method.
|
||||
* arch/aarch64-linux.h (AARCH64_LINUX_SIZEOF_MTE): Define.
|
||||
|
||||
2021-03-24 Luis Machado <luis.machado@linaro.org>
|
||||
|
||||
* aarch64-linux-nat.c
|
||||
|
@ -461,6 +461,58 @@ fetch_pauth_masks_from_thread (struct regcache *regcache)
|
||||
&pauth_regset[1]);
|
||||
}
|
||||
|
||||
/* Fill GDB's register array with the MTE register values from
|
||||
the current thread. */
|
||||
|
||||
static void
|
||||
fetch_mteregs_from_thread (struct regcache *regcache)
|
||||
{
|
||||
struct gdbarch_tdep *tdep = gdbarch_tdep (regcache->arch ());
|
||||
int regno = tdep->mte_reg_base;
|
||||
|
||||
gdb_assert (regno != -1);
|
||||
|
||||
uint64_t tag_ctl = 0;
|
||||
struct iovec iovec;
|
||||
|
||||
iovec.iov_base = &tag_ctl;
|
||||
iovec.iov_len = sizeof (tag_ctl);
|
||||
|
||||
int tid = get_ptrace_pid (regcache->ptid ());
|
||||
if (ptrace (PTRACE_GETREGSET, tid, NT_ARM_TAGGED_ADDR_CTRL, &iovec) != 0)
|
||||
perror_with_name (_("unable to fetch MTE registers."));
|
||||
|
||||
regcache->raw_supply (regno, &tag_ctl);
|
||||
}
|
||||
|
||||
/* Store to the current thread the valid MTE register set in the GDB's
|
||||
register array. */
|
||||
|
||||
static void
|
||||
store_mteregs_to_thread (struct regcache *regcache)
|
||||
{
|
||||
struct gdbarch_tdep *tdep = gdbarch_tdep (regcache->arch ());
|
||||
int regno = tdep->mte_reg_base;
|
||||
|
||||
gdb_assert (regno != -1);
|
||||
|
||||
uint64_t tag_ctl = 0;
|
||||
|
||||
if (REG_VALID != regcache->get_register_status (regno))
|
||||
return;
|
||||
|
||||
regcache->raw_collect (regno, (char *) &tag_ctl);
|
||||
|
||||
struct iovec iovec;
|
||||
|
||||
iovec.iov_base = &tag_ctl;
|
||||
iovec.iov_len = sizeof (tag_ctl);
|
||||
|
||||
int tid = get_ptrace_pid (regcache->ptid ());
|
||||
if (ptrace (PTRACE_SETREGSET, tid, NT_ARM_TAGGED_ADDR_CTRL, &iovec) != 0)
|
||||
perror_with_name (_("unable to store MTE registers."));
|
||||
}
|
||||
|
||||
/* Implement the "fetch_registers" target_ops method. */
|
||||
|
||||
void
|
||||
@ -479,6 +531,9 @@ aarch64_linux_nat_target::fetch_registers (struct regcache *regcache,
|
||||
|
||||
if (tdep->has_pauth ())
|
||||
fetch_pauth_masks_from_thread (regcache);
|
||||
|
||||
if (tdep->has_mte ())
|
||||
fetch_mteregs_from_thread (regcache);
|
||||
}
|
||||
else if (regno < AARCH64_V0_REGNUM)
|
||||
fetch_gregs_from_thread (regcache);
|
||||
@ -493,6 +548,11 @@ aarch64_linux_nat_target::fetch_registers (struct regcache *regcache,
|
||||
|| regno == AARCH64_PAUTH_CMASK_REGNUM (tdep->pauth_reg_base))
|
||||
fetch_pauth_masks_from_thread (regcache);
|
||||
}
|
||||
|
||||
/* Fetch individual MTE registers. */
|
||||
if (tdep->has_mte ()
|
||||
&& (regno == tdep->mte_reg_base))
|
||||
fetch_mteregs_from_thread (regcache);
|
||||
}
|
||||
|
||||
/* Implement the "store_registers" target_ops method. */
|
||||
@ -510,6 +570,9 @@ aarch64_linux_nat_target::store_registers (struct regcache *regcache,
|
||||
store_sveregs_to_thread (regcache);
|
||||
else
|
||||
store_fpregs_to_thread (regcache);
|
||||
|
||||
if (tdep->has_mte ())
|
||||
store_mteregs_to_thread (regcache);
|
||||
}
|
||||
else if (regno < AARCH64_V0_REGNUM)
|
||||
store_gregs_to_thread (regcache);
|
||||
@ -517,6 +580,11 @@ aarch64_linux_nat_target::store_registers (struct regcache *regcache,
|
||||
store_sveregs_to_thread (regcache);
|
||||
else
|
||||
store_fpregs_to_thread (regcache);
|
||||
|
||||
/* Store MTE registers. */
|
||||
if (tdep->has_mte ()
|
||||
&& (regno == tdep->mte_reg_base))
|
||||
store_mteregs_to_thread (regcache);
|
||||
}
|
||||
|
||||
/* Fill register REGNO (if it is a general-purpose register) in
|
||||
|
@ -172,6 +172,12 @@ static const char *const aarch64_pauth_register_names[] =
|
||||
"pauth_cmask"
|
||||
};
|
||||
|
||||
static const char *const aarch64_mte_register_names[] =
|
||||
{
|
||||
/* Tag Control Register. */
|
||||
"tag_ctl"
|
||||
};
|
||||
|
||||
/* AArch64 prologue cache structure. */
|
||||
struct aarch64_prologue_cache
|
||||
{
|
||||
@ -3346,6 +3352,7 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
|
||||
bool valid_p = true;
|
||||
int i, num_regs = 0, num_pseudo_regs = 0;
|
||||
int first_pauth_regnum = -1, pauth_ra_state_offset = -1;
|
||||
int first_mte_regnum = -1;
|
||||
|
||||
/* Use the vector length passed via the target info. Here -1 is used for no
|
||||
SVE, and 0 is unset. If unset then use the vector length from the existing
|
||||
@ -3383,6 +3390,8 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
|
||||
feature_fpu = tdesc_find_feature (tdesc, "org.gnu.gdb.aarch64.fpu");
|
||||
feature_sve = tdesc_find_feature (tdesc, "org.gnu.gdb.aarch64.sve");
|
||||
feature_pauth = tdesc_find_feature (tdesc, "org.gnu.gdb.aarch64.pauth");
|
||||
const struct tdesc_feature *feature_mte
|
||||
= tdesc_find_feature (tdesc, "org.gnu.gdb.aarch64.mte");
|
||||
|
||||
if (feature_core == nullptr)
|
||||
return nullptr;
|
||||
@ -3453,6 +3462,20 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
|
||||
num_pseudo_regs += 1; /* Count RA_STATE pseudo register. */
|
||||
}
|
||||
|
||||
/* Add the MTE registers. */
|
||||
if (feature_mte != NULL)
|
||||
{
|
||||
first_mte_regnum = num_regs;
|
||||
/* Validate the descriptor provides the mandatory MTE registers and
|
||||
allocate their numbers. */
|
||||
for (i = 0; i < ARRAY_SIZE (aarch64_mte_register_names); i++)
|
||||
valid_p &= tdesc_numbered_register (feature_mte, tdesc_data.get (),
|
||||
first_mte_regnum + i,
|
||||
aarch64_mte_register_names[i]);
|
||||
|
||||
num_regs += i;
|
||||
}
|
||||
|
||||
if (!valid_p)
|
||||
return nullptr;
|
||||
|
||||
@ -3470,6 +3493,7 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
|
||||
tdep->pauth_reg_base = first_pauth_regnum;
|
||||
tdep->pauth_ra_state_regnum = (feature_pauth == NULL) ? -1
|
||||
: pauth_ra_state_offset + num_regs;
|
||||
tdep->mte_reg_base = first_mte_regnum;
|
||||
|
||||
set_gdbarch_push_dummy_call (gdbarch, aarch64_push_dummy_call);
|
||||
set_gdbarch_frame_align (gdbarch, aarch64_frame_align);
|
||||
|
@ -100,6 +100,15 @@ struct gdbarch_tdep
|
||||
{
|
||||
return pauth_reg_base != -1;
|
||||
}
|
||||
|
||||
/* First MTE register. This is -1 if no MTE registers are available. */
|
||||
int mte_reg_base;
|
||||
|
||||
/* Returns true if the target supports MTE. */
|
||||
bool has_mte () const
|
||||
{
|
||||
return mte_reg_base != -1;
|
||||
}
|
||||
};
|
||||
|
||||
const target_desc *aarch64_read_description (uint64_t vq, bool pauth_p,
|
||||
|
@ -25,4 +25,7 @@
|
||||
#define HWCAP2_MTE (1 << 18)
|
||||
#endif
|
||||
|
||||
/* The MTE regset consists of a single 64-bit register. */
|
||||
#define AARCH64_LINUX_SIZEOF_MTE 8
|
||||
|
||||
#endif /* ARCH_AARCH64_LINUX_H */
|
||||
|
@ -1,3 +1,10 @@
|
||||
2021-03-24 Luis Machado <luis.machado@linaro.org>
|
||||
|
||||
* linux-aarch64-low.cc (aarch64_fill_mteregset): New function.
|
||||
(aarch64_store_mteregset): New function.
|
||||
(aarch64_regsets): Add MTE register set entry.
|
||||
(aarch64_sve_regsets): Add MTE register set entry.
|
||||
|
||||
2021-03-24 Luis Machado <luis.machado@linaro.org>
|
||||
|
||||
* linux-aarch64-ipa.cc (get_ipa_tdesc): Update call to
|
||||
|
@ -261,6 +261,29 @@ aarch64_store_pauthregset (struct regcache *regcache, const void *buf)
|
||||
&pauth_regset[1]);
|
||||
}
|
||||
|
||||
/* Fill BUF with the MTE registers from the regcache. */
|
||||
|
||||
static void
|
||||
aarch64_fill_mteregset (struct regcache *regcache, void *buf)
|
||||
{
|
||||
uint64_t *mte_regset = (uint64_t *) buf;
|
||||
int mte_base = find_regno (regcache->tdesc, "tag_ctl");
|
||||
|
||||
collect_register (regcache, mte_base, mte_regset);
|
||||
}
|
||||
|
||||
/* Store the MTE registers to regcache. */
|
||||
|
||||
static void
|
||||
aarch64_store_mteregset (struct regcache *regcache, const void *buf)
|
||||
{
|
||||
uint64_t *mte_regset = (uint64_t *) buf;
|
||||
int mte_base = find_regno (regcache->tdesc, "tag_ctl");
|
||||
|
||||
/* Tag Control register */
|
||||
supply_register (regcache, mte_base, mte_regset);
|
||||
}
|
||||
|
||||
bool
|
||||
aarch64_target::low_supports_breakpoints ()
|
||||
{
|
||||
@ -706,6 +729,9 @@ static struct regset_info aarch64_regsets[] =
|
||||
{ PTRACE_GETREGSET, PTRACE_SETREGSET, NT_ARM_PAC_MASK,
|
||||
AARCH64_PAUTH_REGS_SIZE, OPTIONAL_REGS,
|
||||
NULL, aarch64_store_pauthregset },
|
||||
{ PTRACE_GETREGSET, PTRACE_SETREGSET, NT_ARM_TAGGED_ADDR_CTRL,
|
||||
AARCH64_LINUX_SIZEOF_MTE, OPTIONAL_REGS, aarch64_fill_mteregset,
|
||||
aarch64_store_mteregset },
|
||||
NULL_REGSET
|
||||
};
|
||||
|
||||
@ -735,6 +761,9 @@ static struct regset_info aarch64_sve_regsets[] =
|
||||
{ PTRACE_GETREGSET, PTRACE_SETREGSET, NT_ARM_PAC_MASK,
|
||||
AARCH64_PAUTH_REGS_SIZE, OPTIONAL_REGS,
|
||||
NULL, aarch64_store_pauthregset },
|
||||
{ PTRACE_GETREGSET, PTRACE_SETREGSET, NT_ARM_TAGGED_ADDR_CTRL,
|
||||
AARCH64_LINUX_SIZEOF_MTE, OPTIONAL_REGS, aarch64_fill_mteregset,
|
||||
aarch64_store_mteregset },
|
||||
NULL_REGSET
|
||||
};
|
||||
|
||||
|
@ -672,6 +672,9 @@
|
||||
/* note name must be "LINUX". */
|
||||
#define NT_ARM_PAC_MASK 0x406 /* AArch pointer authentication code masks */
|
||||
/* note name must be "LINUX". */
|
||||
#define NT_ARM_TAGGED_ADDR_CTRL 0x409 /* AArch64 tagged address control
|
||||
(prctl()) */
|
||||
/* note name must be "LINUX". */
|
||||
#define NT_ARC_V2 0x600 /* ARC HS accumulator/extra registers. */
|
||||
/* note name must be "LINUX". */
|
||||
#define NT_RISCV_CSR 0x900 /* RISC-V Control and Status Registers */
|
||||
|
Loading…
x
Reference in New Issue
Block a user