From 1ef53e6b8328acd5b7d54ee2fe288836ce12992e Mon Sep 17 00:00:00 2001 From: Alan Hayward Date: Fri, 22 Mar 2019 10:34:09 +0000 Subject: [PATCH] AArch64: gdbserver: read pauth registers Add the pauth registers to the regset lists. Add a new regset type OPTIONAL_REGS which allows for the regset read to fail. Once the read fails, it will not be checked again. This allows targets with optional features to keep a single static regset_info structure. gdb/ChangeLog: * arch/aarch64.h (AARCH64_PAUTH_REGS_SIZE): New define. gdb/gdbserver/ChangeLog: * linux-aarch64-low.c (aarch64_store_pauthregset): New function. * linux-low.c (regsets_store_inferior_registers): Allow optional reads to fail. * linux-low.h (enum regset_type): Add OPTIONAL_REGS. --- gdb/ChangeLog | 5 +++++ gdb/arch/aarch64.h | 1 + gdb/gdbserver/ChangeLog | 8 ++++++++ gdb/gdbserver/linux-aarch64-low.c | 23 +++++++++++++++++++++++ gdb/gdbserver/linux-low.c | 14 ++++++++------ gdb/gdbserver/linux-low.h | 1 + 6 files changed, 46 insertions(+), 6 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 78ec7045d3..8622c9bfa8 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,8 @@ +2019-03-22 Alan Hayward + Jiong Wang + + * arch/aarch64.h (AARCH64_PAUTH_REGS_SIZE): New define. + 2019-03-22 Alan Hayward Jiong Wang diff --git a/gdb/arch/aarch64.h b/gdb/arch/aarch64.h index 8c80b7be62..309fe75273 100644 --- a/gdb/arch/aarch64.h +++ b/gdb/arch/aarch64.h @@ -68,6 +68,7 @@ enum aarch64_regnum #define AARCH64_PAUTH_DMASK_REGNUM(pauth_reg_base) (pauth_reg_base) #define AARCH64_PAUTH_CMASK_REGNUM(pauth_reg_base) (pauth_reg_base + 1) +#define AARCH64_PAUTH_REGS_SIZE (16) #define AARCH64_X_REGS_NUM 31 #define AARCH64_V_REGS_NUM 32 diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog index 3b585ca992..21c286d5ef 100644 --- a/gdb/gdbserver/ChangeLog +++ b/gdb/gdbserver/ChangeLog @@ -1,3 +1,11 @@ +2019-03-22 Alan Hayward + Jiong Wang + + * linux-aarch64-low.c (aarch64_store_pauthregset): New function. + * linux-low.c (regsets_store_inferior_registers): Allow optional reads + to fail. + * linux-low.h (enum regset_type): Add OPTIONAL_REGS. + 2019-03-22 Alan Hayward Jiong Wang diff --git a/gdb/gdbserver/linux-aarch64-low.c b/gdb/gdbserver/linux-aarch64-low.c index e2e25f0e27..20c75493b0 100644 --- a/gdb/gdbserver/linux-aarch64-low.c +++ b/gdb/gdbserver/linux-aarch64-low.c @@ -135,6 +135,23 @@ aarch64_store_fpregset (struct regcache *regcache, const void *buf) supply_register (regcache, AARCH64_FPCR_REGNUM, ®set->fpcr); } +/* Store the pauth registers to regcache. */ + +static void +aarch64_store_pauthregset (struct regcache *regcache, const void *buf) +{ + uint64_t *pauth_regset = (uint64_t *) buf; + int pauth_base = find_regno (regcache->tdesc, "pauth_dmask"); + + if (pauth_base == 0) + return; + + supply_register (regcache, AARCH64_PAUTH_DMASK_REGNUM (pauth_base), + &pauth_regset[0]); + supply_register (regcache, AARCH64_PAUTH_CMASK_REGNUM (pauth_base), + &pauth_regset[1]); +} + /* Enable miscellaneous debugging output. The name is historical - it was originally used to debug LinuxThreads support. */ extern int debug_threads; @@ -564,6 +581,9 @@ static struct regset_info aarch64_regsets[] = sizeof (struct user_fpsimd_state), FP_REGS, aarch64_fill_fpregset, aarch64_store_fpregset }, + { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_ARM_PAC_MASK, + AARCH64_PAUTH_REGS_SIZE, OPTIONAL_REGS, + NULL, aarch64_store_pauthregset }, NULL_REGSET }; @@ -590,6 +610,9 @@ static struct regset_info aarch64_sve_regsets[] = SVE_PT_SIZE (AARCH64_MAX_SVE_VQ, SVE_PT_REGS_SVE), EXTENDED_REGS, aarch64_sve_regs_copy_from_regcache, aarch64_sve_regs_copy_to_regcache }, + { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_ARM_PAC_MASK, + AARCH64_PAUTH_REGS_SIZE, OPTIONAL_REGS, + NULL, aarch64_store_pauthregset }, NULL_REGSET }; diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c index b1a9d12899..6f703f589f 100644 --- a/gdb/gdbserver/linux-low.c +++ b/gdb/gdbserver/linux-low.c @@ -5358,10 +5358,11 @@ regsets_fetch_inferior_registers (struct regsets_info *regsets_info, #endif if (res < 0) { - if (errno == EIO) + if (errno == EIO + || (errno == EINVAL && regset->type == OPTIONAL_REGS)) { - /* If we get EIO on a regset, do not try it again for - this process mode. */ + /* If we get EIO on a regset, or an EINVAL and the regset is + optional, do not try it again for this process mode. */ disable_regset (regsets_info, regset); } else if (errno == ENODATA) @@ -5456,10 +5457,11 @@ regsets_store_inferior_registers (struct regsets_info *regsets_info, if (res < 0) { - if (errno == EIO) + if (errno == EIO + || (errno == EINVAL && regset->type == OPTIONAL_REGS)) { - /* If we get EIO on a regset, do not try it again for - this process mode. */ + /* If we get EIO on a regset, or an EINVAL and the regset is + optional, do not try it again for this process mode. */ disable_regset (regsets_info, regset); } else if (errno == ESRCH) diff --git a/gdb/gdbserver/linux-low.h b/gdb/gdbserver/linux-low.h index d09390dd99..1ade35d648 100644 --- a/gdb/gdbserver/linux-low.h +++ b/gdb/gdbserver/linux-low.h @@ -40,6 +40,7 @@ enum regset_type { GENERAL_REGS, FP_REGS, EXTENDED_REGS, + OPTIONAL_REGS, /* Do not error if the regset cannot be accessed. */ }; /* The arch's regsets array initializer must be terminated with a NULL -- 2.34.1