From patchwork Fri Dec 16 10:57:22 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luis Machado X-Patchwork-Id: 61995 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 5B5E2382E1AA for ; Fri, 16 Dec 2022 10:58:13 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 5B5E2382E1AA DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1671188293; bh=giSqC+tTYalUY3xH/1Ax3E5r1bWFrhc4vdcy8JCyuCw=; h=To:CC:Subject:Date:List-Id:List-Unsubscribe:List-Archive: List-Post:List-Help:List-Subscribe:From:Reply-To:From; b=P1SgdEY/81L51hFNhXEkuzrCsGt6mInkJtZW9e3ObDgtlnDA6qENRic2mqvaWu0uv ttgtMEKMdC2v6NTqJa13mHZ+TEhW+xMTzr7rR21f/sK4o3e4g6HZdzEPTOONbju/pP iEl2SpY133VtBvJ5BhULoE/tD1U67IMCyf2R5TgA= X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from EUR05-VI1-obe.outbound.protection.outlook.com (mail-vi1eur05on2047.outbound.protection.outlook.com [40.107.21.47]) by sourceware.org (Postfix) with ESMTPS id 7DD84382E74C for ; Fri, 16 Dec 2022 10:57:43 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 7DD84382E74C Received: from AM5PR0601CA0072.eurprd06.prod.outlook.com (2603:10a6:206::37) by DBBPR08MB6076.eurprd08.prod.outlook.com (2603:10a6:10:1f5::5) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5944.5; Fri, 16 Dec 2022 10:57:37 +0000 Received: from AM7EUR03FT042.eop-EUR03.prod.protection.outlook.com (2603:10a6:206:0:cafe::af) by AM5PR0601CA0072.outlook.office365.com (2603:10a6:206::37) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5924.15 via Frontend Transport; Fri, 16 Dec 2022 10:57:37 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 63.35.35.123) smtp.mailfrom=arm.com; dkim=pass (signature was verified) header.d=armh.onmicrosoft.com;dmarc=pass action=none header.from=arm.com; Received-SPF: Pass (protection.outlook.com: domain of arm.com designates 63.35.35.123 as permitted sender) receiver=protection.outlook.com; client-ip=63.35.35.123; helo=64aa7808-outbound-1.mta.getcheckrecipient.com; pr=C Received: from 64aa7808-outbound-1.mta.getcheckrecipient.com (63.35.35.123) by AM7EUR03FT042.mail.protection.outlook.com (100.127.140.209) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5924.15 via Frontend Transport; Fri, 16 Dec 2022 10:57:36 +0000 Received: ("Tessian outbound 58faf9791229:v130"); Fri, 16 Dec 2022 10:57:36 +0000 X-CheckRecipientChecked: true X-CR-MTA-CID: 42dc54f0dfa86165 X-CR-MTA-TID: 64aa7808 Received: from 043076f47096.1 by 64aa7808-outbound-1.mta.getcheckrecipient.com id 22021B8C-595F-4C74-A444-8BEC872DC27B.1; Fri, 16 Dec 2022 10:57:28 +0000 Received: from EUR02-AM0-obe.outbound.protection.outlook.com by 64aa7808-outbound-1.mta.getcheckrecipient.com with ESMTPS id 043076f47096.1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384); Fri, 16 Dec 2022 10:57:28 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=YtHuu7kPKxPbjxEoHw6SmBVV6+AdiAeU0yOmPwKoToKc8osrRp7GG6fprBbLvPFFMG5dudYx6ZGN6A/hmDYOdVqmbbEP+k+OZ5W4Z/bGzq3lA5Jtxp6ky0g9p0bqcKPYDIHMzOrq8zxJcjVFiOtYOacROSQ4NRQrr3K2jSdgbVAMl6giuKrYoiq0DmZkPUyY+zT2AsiBm9vVjSYowTeyAsY57BmDrjRTwgDXPr9bY6NrHMWJKREA34KvnVDszESghI7/IN4PdtfVk32nQt6R5sdxwtMr7fkgpxrNI0MczY3Hgsw/1z7ZjpeyYlbGCnKh++6zRuF7RXpvZco7DsuuuQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=giSqC+tTYalUY3xH/1Ax3E5r1bWFrhc4vdcy8JCyuCw=; b=C14pjrTdtHcAx0pz1O3cHHq2RyyIFmbeBujW0qNHiXwjoyDtGF7v3U4mk5aIkGFeA5uh6PFeLj0J79VEu0Y1tHeIBBwikdhRxq2eqQJNWI/lJtQ/W5rD86FHT8q0t5fHP5IuKinOs72J2yxtt9rJ1XdYf4zm00mE/qkjpfXGblneICJ47PFl4WkCKSCMaT5+MQut0de2bL2XtRcAC5M9aDmgaOmUL3O/IOU5QDh6bLuGMxdnE7Akxoz/MJlV02S3ytnclp8nD0DhEfSaVhWjp2jd7Arh2Ki1NOee7Oq0rlbp+CPFeevgE+ABNB3GH/g8RFk39Rzx0souQFAe+nzTsQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 40.67.248.234) smtp.rcpttodomain=sourceware.org smtp.mailfrom=arm.com; dmarc=pass (p=none sp=none pct=100) action=none header.from=arm.com; dkim=none (message not signed); arc=none Received: from AS9PR06CA0217.eurprd06.prod.outlook.com (2603:10a6:20b:45e::17) by DB9PR08MB6636.eurprd08.prod.outlook.com (2603:10a6:10:250::8) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5944.5; Fri, 16 Dec 2022 10:57:23 +0000 Received: from AM7EUR03FT063.eop-EUR03.prod.protection.outlook.com (2603:10a6:20b:45e:cafe::34) by AS9PR06CA0217.outlook.office365.com (2603:10a6:20b:45e::17) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5924.15 via Frontend Transport; Fri, 16 Dec 2022 10:57:23 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 40.67.248.234) smtp.mailfrom=arm.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=arm.com; Received-SPF: Pass (protection.outlook.com: domain of arm.com designates 40.67.248.234 as permitted sender) receiver=protection.outlook.com; client-ip=40.67.248.234; helo=nebula.arm.com; pr=C Received: from nebula.arm.com (40.67.248.234) by AM7EUR03FT063.mail.protection.outlook.com (100.127.140.221) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.5924.11 via Frontend Transport; Fri, 16 Dec 2022 10:57:22 +0000 Received: from AZ-NEU-EX02.Emea.Arm.com (10.251.26.5) by AZ-NEU-EX03.Arm.com (10.251.24.31) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.16; Fri, 16 Dec 2022 10:57:22 +0000 Received: from AZ-NEU-EX04.Arm.com (10.251.24.32) by AZ-NEU-EX02.Emea.Arm.com (10.251.26.5) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.16; Fri, 16 Dec 2022 10:57:22 +0000 Received: from e129171.arm.com (10.57.74.38) by mail.arm.com (10.251.24.32) with Microsoft SMTP Server id 15.1.2507.16 via Frontend Transport; Fri, 16 Dec 2022 10:57:22 +0000 To: CC: , Subject: [PATCH] [AArch64] Enable pointer authentication support for aarch64 bare metal/kernel mode addresses Date: Fri, 16 Dec 2022 10:57:22 +0000 Message-ID: <20221216105722.1413765-1-luis.machado@arm.com> X-Mailer: git-send-email 2.25.1 MIME-Version: 1.0 X-EOPAttributedMessage: 1 X-MS-TrafficTypeDiagnostic: AM7EUR03FT063:EE_|DB9PR08MB6636:EE_|AM7EUR03FT042:EE_|DBBPR08MB6076:EE_ X-MS-Office365-Filtering-Correlation-Id: 6465f945-b5e5-44b4-ccc8-08dadf54576c x-checkrecipientrouted: true NoDisclaimer: true X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam-Untrusted: BCL:0; X-Microsoft-Antispam-Message-Info-Original: nrl0vESeouBae/oAkxtgvhb2YZJlqnXLDgVjemLJPuubxfophhiSllry9MYCLJoMQI/JE6WX7AALACekC6pXxX3C5ZZjdLd+LxIZl4BGRMviZiBLK5ZLr2gq5Bg2g6YMxoLKbwVx1RrORcSodyy1pb8rICE4U3wG6KCSH3VFNURhZUzgteLXwB5rZzNVhXsPb1KDhtJ5c0WxvlxY1WeVe0oJRa5IMHhiL9je+Fah84ubEotI/cV1AuqjrfcoTNMr/CMvX20bcNvi7HjQQ3rboU4ASffCjifJS7tQhU0fRSlGuuym1rC1em1VJ5sdFmEt6Y2UJzstcZigHDsRu4WTh7C0d1GQ0juxIIWlqao5gz9mc4/ervPaj+zS7+Cjax7AxiGwRdVGjyaxKE1k7oX9G6VjEcgQg0TRROvSL7mYDLQj5blmuP85dRZNxKQQSl0+oFt8MjW4Kwny8RIZSttjdzL7tm1jMK+qpPDVSvtAlOVFNJLR14OfiiNqJsLUrUpeSijECh+3vcfb0kkOnPCejcQlQVhM9lhGk0CUPn7kEvDrvlEShryf8mkkFuxGVvAlkrT2oUVpQ09zCIr7xBYPuFm6hGbfgEE/MFILXr5PlciGXk+ATMKMkHVUKMAq9GxLCgYwKqNGcOpdlescI9UVe14w2ANLMRBFxlL24Eg9M5fywy4fmdFjwN1RHHsBDfn9yM/DJHHD0oyUtHwnjT+a/qVc8iyJzyewbS3N5l2VBVg= X-Forefront-Antispam-Report-Untrusted: CIP:40.67.248.234; CTRY:IE; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:nebula.arm.com; PTR:InfoDomainNonexistent; CAT:NONE; SFS:(13230022)(4636009)(136003)(346002)(39860400002)(396003)(376002)(451199015)(46966006)(36840700001)(81166007)(40480700001)(356005)(86362001)(82740400003)(30864003)(5660300002)(44832011)(8936002)(41300700001)(336012)(426003)(1076003)(2616005)(47076005)(2906002)(6916009)(316002)(478600001)(54906003)(966005)(4326008)(70586007)(8676002)(70206006)(7696005)(186003)(26005)(36860700001)(36756003)(82310400005)(83380400001)(66899015)(36900700001); DIR:OUT; SFP:1101; X-MS-Exchange-Transport-CrossTenantHeadersStamped: DB9PR08MB6636 X-MS-Exchange-Transport-CrossTenantHeadersStripped: AM7EUR03FT042.eop-EUR03.prod.protection.outlook.com X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id-Prvs: 247caf3e-032e-433d-78bf-08dadf544f73 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: sKxlFkHjliCJd+63qjMOB7fXbZNipbJaRtkOiC5er6mOq1I+LlsJezeXrAzbPFoxgEQr1HGnwLWpUPNkHmPrhEuUwq8Wk7Rg2F4fG+IswZwHclchfHwwZgD0yXKkWWNXvWgm3Osd/uCBYOPBwjCxBH1DskDAx2H84KGCyvmnHEQTrxd59DPWkNyX/KJyX1fDxfjqYVvi9dSFNWLTUNexSZ6j9eM5IKCpcHsZSPPflhGDqkXHxmyFoNtlRNYqwgXccwlFpDa7MPN6UJZZfrThhA0vNe81OAfscR8/cXLfxjOcWDpkFDRG1uECzLO4dfRR6LHj/Fg1t1SADeFjyI7ohxGFX8PgXtNKRDzaiow6nEkwnUC5grGWzrStjYRhxdU9EGDvuVsGIzhwLAroR0i9l/MIr+b1s8QsKQL4L22hzRT+fIwpViDVA+RzEhF08cUoeJAF3gnF4yke5mGObBoDs1vVvlVh+J97WmzX53RMWkfRKfi6MaFBuKdiqPByt0mxXi6X9JxUpKJPsZTYpJURDCWqRyWbYFhXuTRm0t49KGXnslQK9euDcKEuXaIQ2oDbRdHlSc8v0Kl6/KVju8vJOlD62purFW15VJXXu8Fz+ZauIThvYsjwZR5qcXFXMsKXIIV5LHw8ZH0MmtelSj3uHHvB/iohOgb+1U1BICzIumfcBtrXVKid0QbovqvbtLMsT+fQtW2loaSZHzHALp8l+ocuSpTumMRx6mEvL+BW8O0= X-Forefront-Antispam-Report: CIP:63.35.35.123; CTRY:IE; LANG:en; SCL:1; SRV:; IPV:CAL; SFV:NSPM; H:64aa7808-outbound-1.mta.getcheckrecipient.com; PTR:ec2-63-35-35-123.eu-west-1.compute.amazonaws.com; CAT:NONE; SFS:(13230022)(4636009)(346002)(136003)(39860400002)(396003)(376002)(451199015)(46966006)(36840700001)(40470700004)(41300700001)(82310400005)(36860700001)(8676002)(83380400001)(8936002)(81166007)(44832011)(5660300002)(30864003)(70586007)(4326008)(70206006)(47076005)(426003)(336012)(2616005)(1076003)(40480700001)(40460700003)(86362001)(66899015)(82740400003)(107886003)(478600001)(966005)(6916009)(2906002)(26005)(316002)(186003)(7696005)(36756003)(54906003); DIR:OUT; SFP:1101; X-OriginatorOrg: arm.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 16 Dec 2022 10:57:36.2404 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 6465f945-b5e5-44b4-ccc8-08dadf54576c X-MS-Exchange-CrossTenant-Id: f34e5979-57d9-4aaa-ad4d-b122a662184d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=f34e5979-57d9-4aaa-ad4d-b122a662184d; Ip=[63.35.35.123]; Helo=[64aa7808-outbound-1.mta.getcheckrecipient.com] X-MS-Exchange-CrossTenant-AuthSource: AM7EUR03FT042.eop-EUR03.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: DBBPR08MB6076 X-Spam-Status: No, score=-12.2 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, FORGED_SPF_HELO, GIT_PATCH_0, KAM_DMARC_NONE, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, SPF_HELO_PASS, SPF_NONE, TXREP, UNPARSEABLE_RELAY autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Luis Machado via Gdb-patches From: Luis Machado Reply-To: Luis Machado Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org Sender: "Gdb-patches" At the moment GDB only handles pointer authentication (pauth) for userspace addresses and if we're debugging a Linux-hosted program. The Linux Kernel can be configured to use pauth instructions for some additional security hardening, but GDB doesn't handle this well. To overcome this limitation, GDB needs a couple things: 1 - The target needs to advertise pauth support. 2 - The hook to remove non-address bits from a pointer needs to be registered in aarch64-tdep.c as opposed to aarch64-linux-tdep.c. There is a patch for QEMU [1] that addresses the first point, and it makes QEMU's gdbstub expose a couple more pauth mask registers, so overall we will have up to 4 pauth masks (2 masks or 4 masks): pauth_dmask pauth_cmask pauth_dmask_high pauth_cmask_high pauth_dmask and pauth_cmask are the masks used to remove pauth signatures from userspace addresses. pauth_dmask_high and pauth_cmask_high masks are used to remove pauth signatures from kernel addresses. The second point is easily addressed by moving code around. When debugging a Linux Kernel built with pauth with an unpatched GDB, we get the following backtrace: #0 __fput (file=0xffff0000c17a6400) at /repos/linux/fs/file_table.c:296 #1 0xffff8000082bd1f0 in ____fput (work=) at /repos/linux/fs/file_table.c:348 #2 0x30008000080ade30 [PAC] in ?? () #3 0x30d48000080ade30 in ?? () Backtrace stopped: previous frame identical to this frame (corrupt stack?) With a patched GDB, we get something a lot more meaningful: #0 __fput (file=0xffff0000c1bcfa00) at /repos/linux/fs/file_table.c:296 #1 0xffff8000082bd1f0 in ____fput (work=) at /repos/linux/fs/file_table.c:348 #2 0xffff8000080ade30 [PAC] in task_work_run () at /repos/linux/kernel/task_work.c:179 #3 0xffff80000801db90 [PAC] in resume_user_mode_work (regs=0xffff80000a96beb0) at /repos/linux/include/linux/resume_user_mode.h:49 #4 do_notify_resume (regs=regs@entry=0xffff80000a96beb0, thread_flags=4) at /repos/linux/arch/arm64/kernel/signal.c:1127 #5 0xffff800008fb9974 [PAC] in prepare_exit_to_user_mode (regs=0xffff80000a96beb0) at /repos/linux/arch/arm64/kernel/entry-common.c:137 #6 exit_to_user_mode (regs=0xffff80000a96beb0) at /repos/linux/arch/arm64/kernel/entry-common.c:142 #7 el0_svc (regs=0xffff80000a96beb0) at /repos/linux/arch/arm64/kernel/entry-common.c:638 #8 0xffff800008fb9d34 [PAC] in el0t_64_sync_handler (regs=) at /repos/linux/arch/arm64/kernel/entry-common.c:655 #9 0xffff800008011548 [PAC] in el0t_64_sync () at /repos/linux/arch/arm64/kernel/entry.S:586 Backtrace stopped: Cannot access memory at address 0xffff80000a96c0c8 [1] https://gitlab.com/rth7680/qemu/-/commit/e440ce6de3e14bf19ee70935be9086c05359f07b Reviewed-by: Thiago Jung Bauermann --- gdb/aarch64-linux-tdep.c | 40 --------------- gdb/aarch64-tdep.c | 103 ++++++++++++++++++++++++++++++++++----- gdb/aarch64-tdep.h | 2 + gdb/arch/aarch64.h | 6 +++ 4 files changed, 100 insertions(+), 51 deletions(-) diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c index 7e04bd9251f..1f091fbc540 100644 --- a/gdb/aarch64-linux-tdep.c +++ b/gdb/aarch64-linux-tdep.c @@ -1980,40 +1980,6 @@ aarch64_linux_decode_memtag_section (struct gdbarch *gdbarch, return tags; } -/* AArch64 implementation of the remove_non_address_bits gdbarch hook. Remove - non address bits from a pointer value. */ - -static CORE_ADDR -aarch64_remove_non_address_bits (struct gdbarch *gdbarch, CORE_ADDR pointer) -{ - aarch64_gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - - /* By default, we assume TBI and discard the top 8 bits plus the VA range - select bit (55). */ - CORE_ADDR mask = AARCH64_TOP_BITS_MASK; - - if (tdep->has_pauth ()) - { - /* Fetch the PAC masks. These masks are per-process, so we can just - fetch data from whatever thread we have at the moment. - - Also, we have both a code mask and a data mask. For now they are the - same, but this may change in the future. */ - struct regcache *regs = get_current_regcache (); - CORE_ADDR cmask, dmask; - - if (regs->cooked_read (tdep->pauth_reg_base, &dmask) != REG_VALID) - dmask = mask; - - if (regs->cooked_read (tdep->pauth_reg_base + 1, &cmask) != REG_VALID) - cmask = mask; - - mask |= aarch64_mask_from_pac_registers (cmask, dmask); - } - - return aarch64_remove_top_bits (pointer, mask); -} - static void aarch64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) { @@ -2066,12 +2032,6 @@ aarch64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) /* Syscall record. */ tdep->aarch64_syscall_record = aarch64_linux_syscall_record; - /* The top byte of a user space address known as the "tag", - is ignored by the kernel and can be regarded as additional - data associated with the address. */ - set_gdbarch_remove_non_address_bits (gdbarch, - aarch64_remove_non_address_bits); - /* MTE-specific settings and hooks. */ if (tdep->has_mte ()) { diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c index 024385a9fd8..d99c2b3e866 100644 --- a/gdb/aarch64-tdep.c +++ b/gdb/aarch64-tdep.c @@ -133,10 +133,14 @@ static const char *const aarch64_sve_register_names[] = static const char *const aarch64_pauth_register_names[] = { - /* Authentication mask for data pointer. */ + /* Authentication mask for data pointer, low half/user pointers. */ "pauth_dmask", - /* Authentication mask for code pointer. */ - "pauth_cmask" + /* Authentication mask for code pointer, low half/user pointers. */ + "pauth_cmask", + /* Authentication mask for data pointer, high half / kernel pointers. */ + "pauth_dmask_high", + /* Authentication mask for code pointer, high half / kernel pointers. */ + "pauth_cmask_high" }; static const char *const aarch64_mte_register_names[] = @@ -222,9 +226,19 @@ aarch64_frame_unmask_lr (aarch64_gdbarch_tdep *tdep, && frame_unwind_register_unsigned (this_frame, tdep->ra_sign_state_regnum)) { - int cmask_num = AARCH64_PAUTH_CMASK_REGNUM (tdep->pauth_reg_base); - CORE_ADDR cmask = frame_unwind_register_unsigned (this_frame, cmask_num); - addr = addr & ~cmask; + /* VA range select (bit 55) tells us whether to use the low half masks + or the high half masks. */ + int cmask_num; + if (tdep->pauth_reg_count > 2 && addr & VA_RANGE_SELECT_BIT_MASK) + cmask_num = AARCH64_PAUTH_CMASK_HIGH_REGNUM (tdep->pauth_reg_base); + else + cmask_num = AARCH64_PAUTH_CMASK_REGNUM (tdep->pauth_reg_base); + + /* By default, we assume TBI and discard the top 8 bits plus the VA range + select bit (55). */ + CORE_ADDR mask = AARCH64_TOP_BITS_MASK; + mask |= frame_unwind_register_unsigned (this_frame, cmask_num); + addr = aarch64_remove_top_bits (addr, mask); /* Record in the frame that the link register required unmasking. */ set_frame_previous_pc_masked (this_frame); @@ -1317,8 +1331,8 @@ aarch64_dwarf2_frame_init_reg (struct gdbarch *gdbarch, int regnum, reg->loc.exp.len = 1; return; } - else if (regnum == AARCH64_PAUTH_DMASK_REGNUM (tdep->pauth_reg_base) - || regnum == AARCH64_PAUTH_CMASK_REGNUM (tdep->pauth_reg_base)) + else if (regnum >= tdep->pauth_reg_base + && regnum < tdep->pauth_reg_base + tdep->pauth_reg_count) { reg->how = DWARF2_FRAME_REG_SAME_VALUE; return; @@ -3492,8 +3506,8 @@ aarch64_cannot_store_register (struct gdbarch *gdbarch, int regnum) 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)); + return (regnum >= tdep->pauth_reg_base + && regnum < tdep->pauth_reg_base + tdep->pauth_reg_count); } /* Implement the stack_frame_destroyed_p gdbarch method. */ @@ -3521,6 +3535,51 @@ aarch64_stack_frame_destroyed_p (struct gdbarch *gdbarch, CORE_ADDR pc) return streq (inst.opcode->name, "ret"); } +/* AArch64 implementation of the remove_non_address_bits gdbarch hook. Remove + non address bits from a pointer value. */ + +static CORE_ADDR +aarch64_remove_non_address_bits (struct gdbarch *gdbarch, CORE_ADDR pointer) +{ + aarch64_gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + /* By default, we assume TBI and discard the top 8 bits plus the VA range + select bit (55). */ + CORE_ADDR mask = AARCH64_TOP_BITS_MASK; + + if (tdep->has_pauth ()) + { + /* Fetch the PAC masks. These masks are per-process, so we can just + fetch data from whatever thread we have at the moment. + + Also, we have both a code mask and a data mask. For now they are the + same, but this may change in the future. */ + struct regcache *regs = get_current_regcache (); + CORE_ADDR cmask, dmask; + int dmask_regnum = AARCH64_PAUTH_DMASK_REGNUM (tdep->pauth_reg_base); + int cmask_regnum = AARCH64_PAUTH_CMASK_REGNUM (tdep->pauth_reg_base); + + /* If we have a kernel address and we have kernel-mode address mask + registers, use those instead. */ + if (tdep->pauth_reg_count > 2 + && pointer & VA_RANGE_SELECT_BIT_MASK) + { + dmask_regnum = AARCH64_PAUTH_DMASK_HIGH_REGNUM (tdep->pauth_reg_base); + cmask_regnum = AARCH64_PAUTH_CMASK_HIGH_REGNUM (tdep->pauth_reg_base); + } + + if (regs->cooked_read (dmask_regnum, &dmask) != REG_VALID) + dmask = mask; + + if (regs->cooked_read (cmask_regnum, &cmask) != REG_VALID) + cmask = mask; + + mask |= aarch64_mask_from_pac_registers (cmask, dmask); + } + + return aarch64_remove_top_bits (pointer, mask); +} + /* 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. @@ -3659,19 +3718,35 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) } /* Add the pauth registers. */ + int pauth_masks = 0; if (feature_pauth != NULL) { first_pauth_regnum = num_regs; ra_sign_state_offset = num_pseudo_regs; + + /* Size of the expected register set with all 4 masks. */ + int set_size = ARRAY_SIZE (aarch64_pauth_register_names); + + /* QEMU exposes a couple additional masks for the high half of the + address. We should either have 2 registers or 4 registers. */ + if (tdesc_unnumbered_register (feature_pauth, + "pauth_dmask_high") == 0) + { + /* We did not find pauth_dmask_high, assume we only have + 2 masks. We are not dealing with QEMU/Emulators then. */ + set_size -= 2; + } + /* Validate the descriptor provides the mandatory PAUTH registers and allocate their numbers. */ - for (i = 0; i < ARRAY_SIZE (aarch64_pauth_register_names); i++) + for (i = 0; i < set_size; i++) valid_p &= tdesc_numbered_register (feature_pauth, tdesc_data.get (), first_pauth_regnum + i, aarch64_pauth_register_names[i]); num_regs += i; num_pseudo_regs += 1; /* Count RA_STATE pseudo register. */ + pauth_masks = set_size; } /* Add the MTE registers. */ @@ -3706,6 +3781,7 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) tdep->jb_elt_size = 8; tdep->vq = vq; tdep->pauth_reg_base = first_pauth_regnum; + tdep->pauth_reg_count = pauth_masks; tdep->ra_sign_state_regnum = -1; tdep->mte_reg_base = first_mte_regnum; tdep->tls_regnum_base = first_tls_regnum; @@ -3822,6 +3898,11 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) if (tdep->has_pauth ()) tdep->ra_sign_state_regnum = ra_sign_state_offset + num_regs; + /* Architecture hook to remove bits of a pointer that are not part of the + address, like memory tags (MTE) and pointer authentication signatures. */ + set_gdbarch_remove_non_address_bits (gdbarch, + aarch64_remove_non_address_bits); + /* Add standard register aliases. */ for (i = 0; i < ARRAY_SIZE (aarch64_register_aliases); i++) user_reg_add (gdbarch, aarch64_register_aliases[i].name, diff --git a/gdb/aarch64-tdep.h b/gdb/aarch64-tdep.h index ff94c0a23b0..9fbb2b510aa 100644 --- a/gdb/aarch64-tdep.h +++ b/gdb/aarch64-tdep.h @@ -94,6 +94,8 @@ struct aarch64_gdbarch_tdep : gdbarch_tdep_base } int pauth_reg_base = 0; + /* Number of pauth masks. */ + int pauth_reg_count = 0; int ra_sign_state_regnum = 0; /* Returns true if the target supports pauth. */ diff --git a/gdb/arch/aarch64.h b/gdb/arch/aarch64.h index 68048198b4d..4eeb9f8aa2c 100644 --- a/gdb/arch/aarch64.h +++ b/gdb/arch/aarch64.h @@ -132,6 +132,12 @@ 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) +/* The high versions of these masks are used for bare metal/kernel-mode pointer + authentication support. */ +#define AARCH64_PAUTH_DMASK_HIGH_REGNUM(pauth_reg_base) (pauth_reg_base + 2) +#define AARCH64_PAUTH_CMASK_HIGH_REGNUM(pauth_reg_base) (pauth_reg_base + 3) + +/* This size is only meant for Linux, not bare metal. QEMU exposes 4 masks. */ #define AARCH64_PAUTH_REGS_SIZE (16) #define AARCH64_X_REGS_NUM 31