Skip to content

Commit 76bed0f

Browse files
committed
AArch64: Read pauth registers
Initialise the pauth registers when creating a target description, and store the regnum of the first pauth register. Use ptrace to read the registers in the pauth feature. Do not allow the registers to be written. gdb/ChangeLog: * aarch64-linux-nat.c (fetch_pauth_masks_from_thread): New function. (aarch64_linux_nat_target::fetch_registers): Read pauth registers. * aarch64-tdep.c (aarch64_cannot_store_register): New function. (aarch64_gdbarch_init): Add puth registers. * aarch64-tdep.h (struct gdbarch_tdep): Add pauth features. * arch/aarch64.h (AARCH64_PAUTH_DMASK_REGNUM): New define. (AARCH64_PAUTH_CMASK_REGNUM): Likewise.
1 parent ee4fbcf commit 76bed0f

File tree

5 files changed

+101
-0
lines changed

5 files changed

+101
-0
lines changed

gdb/ChangeLog

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,15 @@
1+
2019-03-22 Alan Hayward <alan.hayward@arm.com>
2+
Jiong Wang <jiong.wang@arm.com>
3+
4+
* aarch64-linux-nat.c (fetch_pauth_masks_from_thread): New
5+
function.
6+
(aarch64_linux_nat_target::fetch_registers): Read pauth registers.
7+
* aarch64-tdep.c (aarch64_cannot_store_register): New function.
8+
(aarch64_gdbarch_init): Add puth registers.
9+
* aarch64-tdep.h (struct gdbarch_tdep): Add pauth features.
10+
* arch/aarch64.h (AARCH64_PAUTH_DMASK_REGNUM): New define.
11+
(AARCH64_PAUTH_CMASK_REGNUM): Likewise.
12+
113
2019-03-22 Alan Hayward <alan.hayward@arm.com>
214
Jiong Wang <jiong.wang@arm.com>
315

gdb/aarch64-linux-nat.c

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,31 @@ store_sveregs_to_thread (struct regcache *regcache)
423423
perror_with_name (_("Unable to store sve registers"));
424424
}
425425

426+
/* Fill GDB's register array with the pointer authentication mask values from
427+
the current thread. */
428+
429+
static void
430+
fetch_pauth_masks_from_thread (struct regcache *regcache)
431+
{
432+
struct gdbarch_tdep *tdep = gdbarch_tdep (regcache->arch ());
433+
int ret;
434+
struct iovec iovec;
435+
uint64_t pauth_regset[2] = {0, 0};
436+
int tid = regcache->ptid ().lwp ();
437+
438+
iovec.iov_base = &pauth_regset;
439+
iovec.iov_len = sizeof (pauth_regset);
440+
441+
ret = ptrace (PTRACE_GETREGSET, tid, NT_ARM_PAC_MASK, &iovec);
442+
if (ret != 0)
443+
perror_with_name (_("unable to fetch pauth registers."));
444+
445+
regcache->raw_supply (AARCH64_PAUTH_DMASK_REGNUM (tdep->pauth_reg_base),
446+
&pauth_regset[0]);
447+
regcache->raw_supply (AARCH64_PAUTH_CMASK_REGNUM (tdep->pauth_reg_base),
448+
&pauth_regset[1]);
449+
}
450+
426451
/* Implement the "fetch_registers" target_ops method. */
427452

428453
void
@@ -438,13 +463,23 @@ aarch64_linux_nat_target::fetch_registers (struct regcache *regcache,
438463
fetch_sveregs_from_thread (regcache);
439464
else
440465
fetch_fpregs_from_thread (regcache);
466+
467+
if (tdep->has_pauth ())
468+
fetch_pauth_masks_from_thread (regcache);
441469
}
442470
else if (regno < AARCH64_V0_REGNUM)
443471
fetch_gregs_from_thread (regcache);
444472
else if (tdep->has_sve ())
445473
fetch_sveregs_from_thread (regcache);
446474
else
447475
fetch_fpregs_from_thread (regcache);
476+
477+
if (tdep->has_pauth ())
478+
{
479+
if (regno == AARCH64_PAUTH_DMASK_REGNUM (tdep->pauth_reg_base)
480+
|| regno == AARCH64_PAUTH_CMASK_REGNUM (tdep->pauth_reg_base))
481+
fetch_pauth_masks_from_thread (regcache);
482+
}
448483
}
449484

450485
/* Implement the "store_registers" target_ops method. */

gdb/aarch64-tdep.c

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,14 @@ static const char *const aarch64_sve_register_names[] =
175175
"ffr", "vg"
176176
};
177177

178+
static const char *const aarch64_pauth_register_names[] =
179+
{
180+
/* Authentication mask for data pointer. */
181+
"pauth_dmask",
182+
/* Authentication mask for code pointer. */
183+
"pauth_cmask"
184+
};
185+
178186
/* AArch64 prologue cache structure. */
179187
struct aarch64_prologue_cache
180188
{
@@ -2936,6 +2944,21 @@ aarch64_add_reggroups (struct gdbarch *gdbarch)
29362944
reggroup_add (gdbarch, restore_reggroup);
29372945
}
29382946

2947+
/* Implement the "cannot_store_register" gdbarch method. */
2948+
2949+
static int
2950+
aarch64_cannot_store_register (struct gdbarch *gdbarch, int regnum)
2951+
{
2952+
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
2953+
2954+
if (!tdep->has_pauth ())
2955+
return 0;
2956+
2957+
/* Pointer authentication registers are read-only. */
2958+
return (regnum == AARCH64_PAUTH_DMASK_REGNUM (tdep->pauth_reg_base)
2959+
|| regnum == AARCH64_PAUTH_CMASK_REGNUM (tdep->pauth_reg_base));
2960+
}
2961+
29392962
/* Initialize the current architecture based on INFO. If possible,
29402963
re-use an architecture from ARCHES, which is a list of
29412964
architectures already created during this debugging session.
@@ -2956,8 +2979,10 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
29562979
const struct tdesc_feature *feature_core;
29572980
const struct tdesc_feature *feature_fpu;
29582981
const struct tdesc_feature *feature_sve;
2982+
const struct tdesc_feature *feature_pauth;
29592983
int num_regs = 0;
29602984
int num_pseudo_regs = 0;
2985+
int first_pauth_regnum = -1;
29612986

29622987
/* Ensure we always have a target description. */
29632988
if (!tdesc_has_registers (tdesc))
@@ -2967,6 +2992,7 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
29672992
feature_core = tdesc_find_feature (tdesc, "org.gnu.gdb.aarch64.core");
29682993
feature_fpu = tdesc_find_feature (tdesc, "org.gnu.gdb.aarch64.fpu");
29692994
feature_sve = tdesc_find_feature (tdesc, "org.gnu.gdb.aarch64.sve");
2995+
feature_pauth = tdesc_find_feature (tdesc, "org.gnu.gdb.aarch64.pauth");
29702996

29712997
if (feature_core == NULL)
29722998
return NULL;
@@ -3021,6 +3047,21 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
30213047
num_pseudo_regs += 32; /* add the Bn scalar register pseudos */
30223048
}
30233049

3050+
/* Add the pauth registers. */
3051+
if (feature_pauth != NULL)
3052+
{
3053+
first_pauth_regnum = num_regs;
3054+
3055+
/* Validate the descriptor provides the mandatory PAUTH registers and
3056+
allocate their numbers. */
3057+
for (i = 0; i < ARRAY_SIZE (aarch64_pauth_register_names); i++)
3058+
valid_p &= tdesc_numbered_register (feature_pauth, tdesc_data,
3059+
first_pauth_regnum + i,
3060+
aarch64_pauth_register_names[i]);
3061+
3062+
num_regs += i;
3063+
}
3064+
30243065
if (!valid_p)
30253066
{
30263067
tdesc_data_cleanup (tdesc_data);
@@ -3054,6 +3095,7 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
30543095
tdep->jb_pc = -1; /* Longjump support not enabled by default. */
30553096
tdep->jb_elt_size = 8;
30563097
tdep->vq = aarch64_get_tdesc_vq (tdesc);
3098+
tdep->pauth_reg_base = first_pauth_regnum;
30573099

30583100
set_gdbarch_push_dummy_call (gdbarch, aarch64_push_dummy_call);
30593101
set_gdbarch_frame_align (gdbarch, aarch64_frame_align);
@@ -3084,6 +3126,7 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
30843126
set_tdesc_pseudo_register_type (gdbarch, aarch64_pseudo_register_type);
30853127
set_tdesc_pseudo_register_reggroup_p (gdbarch,
30863128
aarch64_pseudo_register_reggroup_p);
3129+
set_gdbarch_cannot_store_register (gdbarch, aarch64_cannot_store_register);
30873130

30883131
/* ABI */
30893132
set_gdbarch_short_bit (gdbarch, 16);

gdb/aarch64-tdep.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,14 @@ struct gdbarch_tdep
8787
{
8888
return vq != 0;
8989
}
90+
91+
int pauth_reg_base;
92+
93+
/* Returns true if the target supports pauth. */
94+
bool has_pauth () const
95+
{
96+
return pauth_reg_base != -1;
97+
}
9098
};
9199

92100
const target_desc *aarch64_read_description (uint64_t vq, bool pauth_p);

gdb/arch/aarch64.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,9 @@ enum aarch64_regnum
6666
#define AARCH64_B0_REGNUM (AARCH64_H0_REGNUM + 32)
6767
#define AARCH64_SVE_V0_REGNUM (AARCH64_B0_REGNUM + 32)
6868

69+
#define AARCH64_PAUTH_DMASK_REGNUM(pauth_reg_base) (pauth_reg_base)
70+
#define AARCH64_PAUTH_CMASK_REGNUM(pauth_reg_base) (pauth_reg_base + 1)
71+
6972
#define AARCH64_X_REGS_NUM 31
7073
#define AARCH64_V_REGS_NUM 32
7174
#define AARCH64_SVE_Z_REGS_NUM AARCH64_V_REGS_NUM

0 commit comments

Comments
 (0)