From patchwork Tue Jul 30 14:41:27 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alan Hayward X-Patchwork-Id: 33859 Received: (qmail 55124 invoked by alias); 30 Jul 2019 14:41: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 55103 invoked by uid 89); 30 Jul 2019 14:41:47 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-23.9 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_NONE, SPF_HELO_PASS, SPF_PASS autolearn=ham version=3.3.1 spammy=felt X-HELO: EUR01-HE1-obe.outbound.protection.outlook.com Received: from mail-eopbgr130057.outbound.protection.outlook.com (HELO EUR01-HE1-obe.outbound.protection.outlook.com) (40.107.13.57) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 30 Jul 2019 14:41:43 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=armh.onmicrosoft.com; s=selector2-armh-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=wp/ONhQnl9p3/eyOmtfhDw4YU4U653hTIZSbbsjZfRs=; b=TXIRkJlHykgZ5bCt/Zz8ie67+8OzJ4W6ihIeZmt6sbInHBKBxOeQD1c7IPuhoSEiBIMaSVRu46bYF4lw+Tq8JXb9Va/fT5BO+vteQW/svWbJ3893hLC0oo9HAOF6pzow2C4KzlwOal8sUiYot2fuE6oYVHtJABM/aYaGxpTZrZo= Received: from AM6PR08CA0004.eurprd08.prod.outlook.com (2603:10a6:20b:b2::16) by DB6PR0801MB1845.eurprd08.prod.outlook.com (2603:10a6:4:39::18) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.2115.14; Tue, 30 Jul 2019 14:41:38 +0000 Received: from AM5EUR03FT028.eop-EUR03.prod.protection.outlook.com (2a01:111:f400:7e08::204) by AM6PR08CA0004.outlook.office365.com (2603:10a6:20b:b2::16) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) id 15.20.2136.12 via Frontend Transport; Tue, 30 Jul 2019 14:41:38 +0000 Authentication-Results: spf=temperror (sender IP is 63.35.35.123) smtp.mailfrom=arm.com; sourceware.org; dkim=pass (signature was verified) header.d=armh.onmicrosoft.com; sourceware.org; dmarc=temperror action=none header.from=arm.com; Received-SPF: TempError (protection.outlook.com: error in processing during lookup of arm.com: DNS Timeout) Received: from 64aa7808-outbound-1.mta.getcheckrecipient.com (63.35.35.123) by AM5EUR03FT028.mail.protection.outlook.com (10.152.16.118) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) id 15.20.2052.18 via Frontend Transport; Tue, 30 Jul 2019 14:41:34 +0000 Received: ("Tessian outbound cc8a947d4660:v26"); Tue, 30 Jul 2019 14:41:34 +0000 X-CheckRecipientChecked: true X-CR-MTA-CID: 936f838ed910ea3a X-CR-MTA-TID: 64aa7808 Received: from 6c5ee6486dd8.2 (ip-172-16-0-2.eu-west-1.compute.internal [104.47.0.50]) by 64aa7808-outbound-1.mta.getcheckrecipient.com id 06E1FBB2-AFFD-43EB-8CA5-E5A7752C092F.1; Tue, 30 Jul 2019 14:41:29 +0000 Received: from EUR01-HE1-obe.outbound.protection.outlook.com (mail-he1eur01lp2050.outbound.protection.outlook.com [104.47.0.50]) by 64aa7808-outbound-1.mta.getcheckrecipient.com with ESMTPS id 6c5ee6486dd8.2 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384); Tue, 30 Jul 2019 14:41:29 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=cIqeiqK9AzSzJhKuqWmcKkmYUle9L0O7mlmsjXhCUCltDOUuvo6n76Ab3zjboBSQsfNBhfGYuL+zZL+aQz8J8w2AGWhbJgqWEk7eBoDzjnE+aYGfhjLvHIfyj8Iyja14HKsbN0v+6CvW9T2g7aQe14K+gxCSjoHG1WkNoC9qWAlMIuvSPFpciJs4XWwDiVLka4h1tU7ZhOvqdvNpZG4mJbvEa58m5KGX3ML0DX0EZ++koOIqrHkids3gwWOFO67UnOxRGi1yfuVe/veDB85ZMCu8aSTKhCllROq3TcxRd/ic3k0wAPY9nzeGzI9R1jcpbYHsiWAAv9Le/IIzc2wZVA== 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-SenderADCheck; bh=wp/ONhQnl9p3/eyOmtfhDw4YU4U653hTIZSbbsjZfRs=; b=O+OVIKoVq5oOAjerWQrRqCmMug2sywmF8XnzJqwDY2HlMp9N5GJJ1BJsPY8kHRiyeRXEpfIxqqtmNomsF4/DvPa9tL3mBVNAnNpvY87fC5fdkDhVOs4LXv2YCzppAZclY97lRFjSwwcCn4THwLPvA01UaIVxfnY8YI78PMeq0DQJZEkc5q+sJhtD2firTe2ptsJLJimsREjefNZRN/dfNngEgNhv+ZeuasZbfIWy0No/LooIMuXjmrG24CRhV/Opi9kX8yXM12QYKn2gz6GbT/tXjY0tdoYE7qq31Q+iz2JRV9Wx0xexzI6orzEm8miaCtIYniiH6qkMqcq/Liy/Jw== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=arm.com; dmarc=pass action=none header.from=arm.com; dkim=pass header.d=arm.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=armh.onmicrosoft.com; s=selector2-armh-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=wp/ONhQnl9p3/eyOmtfhDw4YU4U653hTIZSbbsjZfRs=; b=TXIRkJlHykgZ5bCt/Zz8ie67+8OzJ4W6ihIeZmt6sbInHBKBxOeQD1c7IPuhoSEiBIMaSVRu46bYF4lw+Tq8JXb9Va/fT5BO+vteQW/svWbJ3893hLC0oo9HAOF6pzow2C4KzlwOal8sUiYot2fuE6oYVHtJABM/aYaGxpTZrZo= Received: from DB6PR0802MB2133.eurprd08.prod.outlook.com (10.172.227.22) by DB6PR0802MB2150.eurprd08.prod.outlook.com (10.172.227.142) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.2115.10; Tue, 30 Jul 2019 14:41:27 +0000 Received: from DB6PR0802MB2133.eurprd08.prod.outlook.com ([fe80::5ce5:cf42:42dd:eda1]) by DB6PR0802MB2133.eurprd08.prod.outlook.com ([fe80::5ce5:cf42:42dd:eda1%6]) with mapi id 15.20.2115.005; Tue, 30 Jul 2019 14:41:27 +0000 From: Alan Hayward To: "gdb-patches@sourceware.org" CC: nd , Alan Hayward Subject: [PATCH V2] AArch64 pauth: Indicate unmasked addresses in backtrace Date: Tue, 30 Jul 2019 14:41:27 +0000 Message-ID: <20190730144123.11135-1-alan.hayward@arm.com> Authentication-Results-Original: spf=none (sender IP is ) smtp.mailfrom=Alan.Hayward@arm.com; X-Microsoft-Antispam-Untrusted: BCL:0; PCL:0; RULEID:(2390118)(7020095)(4652040)(8989299)(4534185)(4627221)(201703031133081)(201702281549075)(8990200)(5600148)(711020)(4605104)(1401327)(4618075)(2017052603328)(7193020); SRVR:DB6PR0802MB2150; x-checkrecipientrouted: true x-ms-oob-tlc-oobclassifiers: OLM:1284;OLM:1284; X-Forefront-Antispam-Report-Untrusted: SFV:NSPM; SFS:(10009020)(4636009)(396003)(376002)(366004)(39860400002)(136003)(346002)(189003)(199004)(54534003)(68736007)(25786009)(6506007)(386003)(4326008)(6436002)(66476007)(44832011)(66556008)(66946007)(66446008)(2501003)(256004)(14444005)(14454004)(86362001)(7736002)(6116002)(64756008)(2906002)(305945005)(3846002)(1076003)(36756003)(6486002)(66066001)(5660300002)(5640700003)(71190400001)(2351001)(50226002)(6916009)(186003)(8936002)(53936002)(54906003)(71200400001)(316002)(26005)(52116002)(6512007)(99286004)(102836004)(81166006)(476003)(2616005)(8676002)(478600001)(81156014)(486006); DIR:OUT; SFP:1101; SCL:1; SRVR:DB6PR0802MB2150; H:DB6PR0802MB2133.eurprd08.prod.outlook.com; FPR:; SPF:None; LANG:en; PTR:InfoNoRecords; MX:1; A:1; received-spf: None (protection.outlook.com: arm.com does not designate permitted sender hosts) X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam-Message-Info-Original: sY9F51vFisoc3QX/oR+Z/qagakgmvm+ZDhOAD3aGTwOimUW7+vOT+jpl0+INxPgaLIYg4tgVEQ7rmjOv9GZi2npVGEV5tcF3Rjw58sftF8LnJJLe954FphfSTEOPDfw8LrlTlHU7dZx0X6aW1jAN6wHN/zecfQudQ4LXZYXlXpSpdFh4MRmkyXYLW6FbrvRVGr/Wcfy6sQ00n3IAg8G2Y1hv8ilt2dNmvJFeRzNXhFeaiOtDP8M/mBrYiwbH5nkvuTrvUKX2EEKNItgfe3+5uPbVofyji/0UKh8AUcJ5Po0a1OVdm5QAA17AI7kWVXHotQPaWV0IYzEsN0gaIjtM1Vm8Xjp3PY8+R6RCmtdIj465P12O+4endaxWZ3AVovwLzQEynI6PNHBQH0KuFhuAPk3AgOYJBGAq4qZGKMlmTak= MIME-Version: 1.0 Original-Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=Alan.Hayward@arm.com; Return-Path: Alan.Hayward@arm.com X-MS-Exchange-Transport-CrossTenantHeadersStripped: AM5EUR03FT028.eop-EUR03.prod.protection.outlook.com X-MS-Office365-Filtering-Correlation-Id-Prvs: 3f59283f-dc6f-4e2e-3287-08d714fc008d X-IsSubscribed: yes [Updated after reviews: *Marker changed to [PAC]. *Did not change address column width, as didn't want to have to pre-parse all the frames that can fit on the screen in order to determine if extra spaces are needed, as that seemed too heavyweight. Considered setting a bool so that once a single address requires PAC, then all backtraces would have the extra spaces, but felt this would cause too many spaces when not required. *Added to python backtrace, but did expose it in python. *Added documentation ] Armv8.3-a Pointer Authentication causes the function return address to be obfuscated on entry to some functions. GDB must unmask the link register in order to produce a backtrace. The following patch adds markers of [PAC] to the bracktrace, to indicate which addresses needed unmasking. This includes the backtrace when using MI. For example, consider the following backtrace: (gdb) bt 0 0x0000000000400490 in puts@plt () 1 0x00000000004005dc in foo ("hello") at cbreak-lib.c:6 2 0x0000000000400604 [PAC] in bar () at cbreak-lib.c:12 3 0x0000000000400620 [PAC] in main2 () at cbreak.c:17 4 0x00000000004005b4 in main () at cbreak-3.c:10 The functions in cbreak-lib use pointer auth, which masks the return address to the previous function, causing the addresses of bar (in the library) and main2 (in the main binary) to require unmasking in order to unwind the backtrace. An extra bool is added alongside the prev_pc in the frame structure. At the point at which the link register is unmasked, the AArch64 port calls into frame to sets the bool. This is the most efficient way of doing it. The marker is also added to the python frame printer, which is always printed if set. The marker is not explicitly exposed to the python code. I expect this will potentially cause issues with some tests in the testsuite when Armv8.3 pointer authentication is used. This should be fixed up in the the future once real hardware is available for full testsuite testing. gdb/ChangeLog: 2019-07-30 Alan Hayward * NEWS: Expand the Pointer Authentication entry. * aarch64-tdep.c (aarch64_frame_unmask_address): Rename from this. (aarch64_frame_unmask_lr): ... to this. (aarch64_prologue_prev_register, aarch64_dwarf2_prev_register): Call aarch64_frame_unmask_lr. * frame.c (struct frame_info): Add "masked" variable. (frame_set_previous_pc_masked) (frame_get_pc_masked): New functions. (fprint_frame): Check for masked pc. * frame.h (frame_set_previous_pc_masked) (frame_get_pc_masked): New declarations. * python/py-framefilter.c (py_print_frame): Check for masked pc. * stack.c (print_frame): Check for masked pc. gdb/doc/ChangeLog: 2019-07-30 Alan Hayward * gdb.texinfo (AArch64 Pointer Authentication): New subsection. --- gdb/NEWS | 4 +++- gdb/aarch64-tdep.c | 17 ++++++++++------- gdb/doc/gdb.texinfo | 8 ++++++++ gdb/frame.c | 28 ++++++++++++++++++++++++++-- gdb/frame.h | 9 +++++++++ gdb/python/py-framefilter.c | 2 ++ gdb/stack.c | 6 +++++- 7 files changed, 63 insertions(+), 11 deletions(-) diff --git a/gdb/NEWS b/gdb/NEWS index 4e821eab4c..fc644817e7 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -16,7 +16,9 @@ architectures require kernel changes. TLS is not yet supported for amd64 and i386 process core dumps. -* Support for Pointer Authentication on AArch64 Linux. +* Support for Pointer Authentication (PAC) on AArch64 Linux. Return + addresses that required unmasking are shown in the backtrace with the + postfix [PAC]. * Two new convenience functions $_cimag and $_creal that extract the imaginary and real parts respectively from complex numbers. diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c index e23cc3f956..9b6324f0fc 100644 --- a/gdb/aarch64-tdep.c +++ b/gdb/aarch64-tdep.c @@ -250,13 +250,13 @@ class instruction_reader : public abstract_instruction_reader } // namespace -/* If address signing is enabled, mask off the signature bits from ADDR, using - the register values in THIS_FRAME. */ +/* If address signing is enabled, mask off the signature bits from the link + register, which is passed by value in ADDR, using the register values in + THIS_FRAME. */ static CORE_ADDR -aarch64_frame_unmask_address (struct gdbarch_tdep *tdep, - struct frame_info *this_frame, - CORE_ADDR addr) +aarch64_frame_unmask_lr (struct gdbarch_tdep *tdep, + struct frame_info *this_frame, CORE_ADDR addr) { if (tdep->has_pauth () && frame_unwind_register_unsigned (this_frame, @@ -265,6 +265,9 @@ aarch64_frame_unmask_address (struct gdbarch_tdep *tdep, 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; + + /* Record in the frame that the link register required unmasking. */ + set_frame_previous_pc_masked (this_frame); } return addr; @@ -952,7 +955,7 @@ aarch64_prologue_prev_register (struct frame_info *this_frame, if (tdep->has_pauth () && trad_frame_value_p (cache->saved_regs, tdep->pauth_ra_state_regnum)) - lr = aarch64_frame_unmask_address (tdep, this_frame, lr); + lr = aarch64_frame_unmask_lr (tdep, this_frame, lr); return frame_unwind_got_constant (this_frame, prev_regnum, lr); } @@ -1119,7 +1122,7 @@ aarch64_dwarf2_prev_register (struct frame_info *this_frame, { case AARCH64_PC_REGNUM: lr = frame_unwind_register_unsigned (this_frame, AARCH64_LR_REGNUM); - lr = aarch64_frame_unmask_address (tdep, this_frame, lr); + lr = aarch64_frame_unmask_lr (tdep, this_frame, lr); return frame_unwind_got_constant (this_frame, regnum, lr); default: diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 0fcd131f71..b7dba2f918 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -24380,6 +24380,14 @@ but the lengths of the @code{z} and @code{p} registers will not change. This is a known limitation of @value{GDBN} and does not affect the execution of the target process. +@subsubsection AArch64 Pointer Authentication. +@cindex AArch64 Pointer Authentication. + +When @value{GDBN} is debugging the AArch64 architecture, and the program is +using the v8.3-A feature Pointer Authentication (PAC), then whenever the link +register @code{$lr} is pointing to an PAC function it's value will be masked. +When GDB prints a backtrace, any addresses that required unmasking will be +postfixed with the marker [PAC]. @node i386 @subsection x86 Architecture-specific Issues diff --git a/gdb/frame.c b/gdb/frame.c index 84e0397db9..6046b3ba8d 100644 --- a/gdb/frame.c +++ b/gdb/frame.c @@ -124,6 +124,8 @@ struct frame_info struct { enum cached_copy_status status; CORE_ADDR value; + /* Did VALUE require unmasking when being read. */ + bool masked; } prev_pc; /* Cached copy of the previous frame's function address. */ @@ -161,6 +163,25 @@ struct frame_info const char *stop_string; }; +/* See frame.h. */ + +void +set_frame_previous_pc_masked (struct frame_info *frame) +{ + frame->prev_pc.masked = true; +} + +/* See frame.h. */ + +bool +get_frame_pc_masked (struct frame_info *frame) +{ + gdb_assert (frame->next != nullptr); + gdb_assert (frame->next->prev_pc.status == CC_VALUE); + + return frame->next->prev_pc.masked; +} + /* A frame stash used to speed up frame lookups. Create a hash table to stash frames previously accessed from the frame cache for quicker subsequent retrieval. The hash table is emptied whenever @@ -429,8 +450,11 @@ fprint_frame (struct ui_file *file, struct frame_info *fi) if (fi->next == NULL || fi->next->prev_pc.status == CC_UNKNOWN) fprintf_unfiltered (file, ""); else if (fi->next->prev_pc.status == CC_VALUE) - fprintf_unfiltered (file, "%s", - hex_string (fi->next->prev_pc.value)); + { + fprintf_unfiltered (file, "%s", hex_string (fi->next->prev_pc.value)); + if (fi->next->prev_pc.masked) + fprintf_unfiltered (file, "[PAC]"); + } else if (fi->next->prev_pc.status == CC_NOT_SAVED) val_print_not_saved (file); else if (fi->next->prev_pc.status == CC_UNAVAILABLE) diff --git a/gdb/frame.h b/gdb/frame.h index ccc285005a..501708ef4c 100644 --- a/gdb/frame.h +++ b/gdb/frame.h @@ -949,4 +949,13 @@ extern const gdb::option::option_def set_backtrace_option_defs[2]; /* The values behind the global "set backtrace ..." settings. */ extern set_backtrace_options user_set_backtrace_options; +/* Mark that the PC value is masked for the previous frame. */ + +extern void set_frame_previous_pc_masked (struct frame_info *frame); + +/* Get whether the PC value is masked for the given frame. */ + +extern bool get_frame_pc_masked (struct frame_info *frame); + + #endif /* !defined (FRAME_H) */ diff --git a/gdb/python/py-framefilter.c b/gdb/python/py-framefilter.c index a2a96ac0d3..d805ec68f2 100644 --- a/gdb/python/py-framefilter.c +++ b/gdb/python/py-framefilter.c @@ -901,6 +901,8 @@ py_print_frame (PyObject *filter, frame_filter_flags flags, { annotate_frame_address (); out->field_core_addr ("addr", gdbarch, address); + if (get_frame_pc_masked (frame)) + out->field_string ("pac", " [PAC]"); annotate_frame_address_end (); out->text (" in "); } diff --git a/gdb/stack.c b/gdb/stack.c index 7833ca4aeb..9d49809895 100644 --- a/gdb/stack.c +++ b/gdb/stack.c @@ -1298,7 +1298,11 @@ print_frame (const frame_print_options &fp_opts, { annotate_frame_address (); if (pc_p) - uiout->field_core_addr ("addr", gdbarch, pc); + { + uiout->field_core_addr ("addr", gdbarch, pc); + if (get_frame_pc_masked (frame)) + uiout->field_string ("pac", " [PAC]"); + } else uiout->field_string ("addr", "", ui_out_style_kind::ADDRESS);