From patchwork Wed Mar 6 13:33:35 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alan Hayward X-Patchwork-Id: 31733 Received: (qmail 35171 invoked by alias); 6 Mar 2019 13:33:48 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 35105 invoked by uid 89); 6 Mar 2019 13:33:47 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-26.9 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_NONE, SPF_HELO_PASS autolearn=ham version=3.3.2 spammy= X-HELO: EUR04-DB3-obe.outbound.protection.outlook.com Received: from mail-eopbgr60089.outbound.protection.outlook.com (HELO EUR04-DB3-obe.outbound.protection.outlook.com) (40.107.6.89) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 06 Mar 2019 13:33:44 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=armh.onmicrosoft.com; s=selector1-arm-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=Ml+PbXr6VCPcwXUFG+Qri8tIj9nsS5JYhwaHmWbW6FE=; b=rkTRP1gcSRV5MKG6XpZaF5Ow0nFW9OxrAxTMRszh7A5jsuyqlHdfReCerNxnpJ0cClpvHr4Rx5gXCvPXIfXO5jjZGBvrrKRCB7RB+sEsKVqzUCzU5OcN+r0VmiwAwYKm7oYBGBFGQ8znuEACfjETegBw28kGQs1zF6PKcq955uo= Received: from DB6PR0802MB2133.eurprd08.prod.outlook.com (10.172.227.22) by DB6PR0802MB2262.eurprd08.prod.outlook.com (10.172.227.19) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.1665.19; Wed, 6 Mar 2019 13:33:35 +0000 Received: from DB6PR0802MB2133.eurprd08.prod.outlook.com ([fe80::e974:35a7:c83c:e5b7]) by DB6PR0802MB2133.eurprd08.prod.outlook.com ([fe80::e974:35a7:c83c:e5b7%3]) with mapi id 15.20.1686.018; Wed, 6 Mar 2019 13:33:35 +0000 From: Alan Hayward To: "gdb-patches@sourceware.org" CC: nd , Alan Hayward Subject: [PATCH v2 3/8] AArch64: Read pauth registers Date: Wed, 6 Mar 2019 13:33:35 +0000 Message-ID: <20190306133325.2531-4-alan.hayward@arm.com> References: <20190306133325.2531-1-alan.hayward@arm.com> In-Reply-To: <20190306133325.2531-1-alan.hayward@arm.com> received-spf: None (protection.outlook.com: arm.com does not designate permitted sender hosts) authentication-results: spf=none (sender IP is ) smtp.mailfrom=Alan.Hayward@arm.com; x-ms-exchange-senderadcheck: 1 MIME-Version: 1.0 X-MS-Exchange-CrossTenant-mailboxtype: HOSTED X-IsSubscribed: yes 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. 2019-03-06 Alan Hayward Jiong Wang * 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. --- gdb/aarch64-linux-nat.c | 33 +++++++++++++++++++++++++++++++ gdb/aarch64-tdep.c | 43 +++++++++++++++++++++++++++++++++++++++++ gdb/aarch64-tdep.h | 8 ++++++++ gdb/arch/aarch64.h | 3 +++ 4 files changed, 87 insertions(+) diff --git a/gdb/aarch64-linux-nat.c b/gdb/aarch64-linux-nat.c index 8a7006165e..094d4e1d1c 100644 --- a/gdb/aarch64-linux-nat.c +++ b/gdb/aarch64-linux-nat.c @@ -423,6 +423,31 @@ store_sveregs_to_thread (struct regcache *regcache) perror_with_name (_("Unable to store sve registers")); } +/* Fill GDB's register array with the pointer authentication mask values from + the current thread. */ + +static void +fetch_pauth_masks_from_thread (struct regcache *regcache) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (regcache->arch ()); + int ret; + struct iovec iovec; + uint64_t pauth_regset[2] = {0, 0}; + int tid = regcache->ptid ().lwp (); + + iovec.iov_base = &pauth_regset; + iovec.iov_len = sizeof (pauth_regset); + + ret = ptrace (PTRACE_GETREGSET, tid, NT_ARM_PAC_MASK, &iovec); + if (ret != 0) + perror_with_name (_("unable to fetch pauth registers.")); + + regcache->raw_supply (AARCH64_PAUTH_DMASK_REGNUM (tdep->pauth_reg_base), + &pauth_regset[0]); + regcache->raw_supply (AARCH64_PAUTH_CMASK_REGNUM (tdep->pauth_reg_base), + &pauth_regset[1]); +} + /* Implement the "fetch_registers" target_ops method. */ void @@ -438,6 +463,9 @@ aarch64_linux_nat_target::fetch_registers (struct regcache *regcache, fetch_sveregs_from_thread (regcache); else fetch_fpregs_from_thread (regcache); + + if (tdep->has_pauth ()) + fetch_pauth_masks_from_thread (regcache); } else if (regno < AARCH64_V0_REGNUM) fetch_gregs_from_thread (regcache); @@ -445,6 +473,11 @@ aarch64_linux_nat_target::fetch_registers (struct regcache *regcache, fetch_sveregs_from_thread (regcache); else fetch_fpregs_from_thread (regcache); + + if (tdep->has_pauth ()) + if (regno == AARCH64_PAUTH_DMASK_REGNUM (tdep->pauth_reg_base) + || regno == AARCH64_PAUTH_CMASK_REGNUM (tdep->pauth_reg_base)) + fetch_pauth_masks_from_thread (regcache); } /* Implement the "store_registers" target_ops method. */ diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c index 0518837a1f..66fdd7bf05 100644 --- a/gdb/aarch64-tdep.c +++ b/gdb/aarch64-tdep.c @@ -175,6 +175,14 @@ static const char *const aarch64_sve_register_names[] = "ffr", "vg" }; +static const char *const aarch64_pauth_register_names[] = +{ + /* Authentication mask for data pointer. */ + "pauth_dmask", + /* Authentication mask for code pointer. */ + "pauth_cmask" +}; + /* AArch64 prologue cache structure. */ struct aarch64_prologue_cache { @@ -2936,6 +2944,21 @@ aarch64_add_reggroups (struct gdbarch *gdbarch) reggroup_add (gdbarch, restore_reggroup); } +/* Implement the "cannot_store_register" gdbarch method. */ + +static int +aarch64_cannot_store_register (struct gdbarch *gdbarch, int regnum) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + if (!tdep->has_pauth ()) + return 0; + + /* Pointer authentication registers are read-only. */ + return (regnum == AARCH64_PAUTH_DMASK_REGNUM (tdep->pauth_reg_base) + || regnum == AARCH64_PAUTH_CMASK_REGNUM (tdep->pauth_reg_base)); +} + /* Initialize the current architecture based on INFO. If possible, re-use an architecture from ARCHES, which is a list of architectures already created during this debugging session. @@ -2956,8 +2979,10 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) const struct tdesc_feature *feature_core; const struct tdesc_feature *feature_fpu; const struct tdesc_feature *feature_sve; + const struct tdesc_feature *feature_pauth; int num_regs = 0; int num_pseudo_regs = 0; + int first_pauth_regnum = -1; /* Ensure we always have a target description. */ if (!tdesc_has_registers (tdesc)) @@ -2967,6 +2992,7 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) feature_core = tdesc_find_feature (tdesc, "org.gnu.gdb.aarch64.core"); 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"); if (feature_core == NULL) return NULL; @@ -3021,6 +3047,21 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) num_pseudo_regs += 32; /* add the Bn scalar register pseudos */ } + /* Add the pauth registers. */ + if (feature_pauth != NULL) + { + first_pauth_regnum = num_regs; + + /* Validate the descriptor provides the mandatory PAUTH registers and + allocate their numbers. */ + for (i = 0; i < ARRAY_SIZE (aarch64_pauth_register_names); i++) + valid_p &= tdesc_numbered_register (feature_pauth, tdesc_data, + first_pauth_regnum + i, + aarch64_pauth_register_names[i]); + + num_regs += i; + } + if (!valid_p) { tdesc_data_cleanup (tdesc_data); @@ -3054,6 +3095,7 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) tdep->jb_pc = -1; /* Longjump support not enabled by default. */ tdep->jb_elt_size = 8; tdep->vq = aarch64_get_tdesc_vq (tdesc); + tdep->pauth_reg_base = first_pauth_regnum; set_gdbarch_push_dummy_call (gdbarch, aarch64_push_dummy_call); set_gdbarch_frame_align (gdbarch, aarch64_frame_align); @@ -3084,6 +3126,7 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_tdesc_pseudo_register_type (gdbarch, aarch64_pseudo_register_type); set_tdesc_pseudo_register_reggroup_p (gdbarch, aarch64_pseudo_register_reggroup_p); + set_gdbarch_cannot_store_register (gdbarch, aarch64_cannot_store_register); /* ABI */ set_gdbarch_short_bit (gdbarch, 16); diff --git a/gdb/aarch64-tdep.h b/gdb/aarch64-tdep.h index 3db6bee9f3..f9fc8965f0 100644 --- a/gdb/aarch64-tdep.h +++ b/gdb/aarch64-tdep.h @@ -87,6 +87,14 @@ struct gdbarch_tdep { return vq != 0; } + + int pauth_reg_base; + + /* Returns true if the target supports pauth. */ + bool has_pauth () const + { + return pauth_reg_base != -1; + } }; const target_desc *aarch64_read_description (uint64_t vq, bool pauth_p); diff --git a/gdb/arch/aarch64.h b/gdb/arch/aarch64.h index 4fe6d02f6e..8c80b7be62 100644 --- a/gdb/arch/aarch64.h +++ b/gdb/arch/aarch64.h @@ -66,6 +66,9 @@ enum aarch64_regnum #define AARCH64_B0_REGNUM (AARCH64_H0_REGNUM + 32) #define AARCH64_SVE_V0_REGNUM (AARCH64_B0_REGNUM + 32) +#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_X_REGS_NUM 31 #define AARCH64_V_REGS_NUM 32 #define AARCH64_SVE_Z_REGS_NUM AARCH64_V_REGS_NUM