From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from EUR04-HE1-obe.outbound.protection.outlook.com (mail-eopbgr70083.outbound.protection.outlook.com [40.107.7.83]) by sourceware.org (Postfix) with ESMTPS id 8B434384B82D for ; Mon, 6 Jun 2022 09:47:31 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 8B434384B82D ARC-Seal: i=2; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=pass; b=UpVvb4WwSi+2jrwxH1eceAnqImRNEoIpYbFC5vKb8tPwY9Xdp+cYRavgFKp/Qoz2UNw6aY/wHqpr+bVN0Ro30NqKK1mPk6Rz+Y3ziZ9wftRMiJjL9Qsok2IXZe4YM5EgGlyjIix6uo4ChBnXJ3Z+1Hk5ZiDpgIFLntbFJRJlIkTsv8wUE98OCd4lLcpkfpXTGQq6IJXsu89MMH1bYO4a7dT7f4JDcqCGcqZYrWOJoHNCO98C2kUvI23iAJ7XstSvwgi9guM0Aen0lC0kwqw+s81HIybOe4Gkg7c5wGflYWjxByutv6hP8Xi+RyD4ZzhsTReSoTrEsF69Aj8PEfocIw== ARC-Message-Signature: i=2; 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=UYAS9UlDk7CqvhJ+vWJzReB9UeewcihxgbmFWcp1++g=; b=DnTjO/d5prLOV1uqwxUK04/nN80r2Ce0FGo+J8FEQd+5TW3zyL0E7YECJGA1immx6d/CMEd1BgO8j2jdTTYVfDnoauTtr5/WaFMm8/lXMQZ93ooC/+gvilLkmAl43cObqvuCCRZBLbtjBsMcm8UHrsvNhbeyjbYWc0n9AHh2Fg8kBmVgCSsSN7FdfZz0AFtIsqR7wLNp/58LZ7rkKMrvDViV0OvCnIrn4GvABE1UQoNkCti9wrv8kk63sj9u++2emJle+Js2S4JNjFfMe4i2r2GViBrEqR9R+owewMMxDhNQDordmVqAMlQhFEoujCTrD+l7no4lRhQ7I/NUqXgyhg== ARC-Authentication-Results: i=2; mx.microsoft.com 1; spf=pass (sender ip is 63.35.35.123) smtp.rcpttodomain=sourceware.org smtp.mailfrom=arm.com; dmarc=pass (p=none sp=none pct=100) action=none header.from=arm.com; dkim=pass (signature was verified) header.d=armh.onmicrosoft.com; arc=pass (0 oda=1 ltdi=1 spf=[1,1,smtp.mailfrom=arm.com] dkim=[1,1,header.d=arm.com] dmarc=[1,1,header.from=arm.com]) Received: from AS9PR04CA0140.eurprd04.prod.outlook.com (2603:10a6:20b:48a::8) by AM9PR08MB7133.eurprd08.prod.outlook.com (2603:10a6:20b:41e::22) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5314.12; Mon, 6 Jun 2022 09:47:27 +0000 Received: from AM5EUR03FT050.eop-EUR03.prod.protection.outlook.com (2603:10a6:20b:48a:cafe::ad) by AS9PR04CA0140.outlook.office365.com (2603:10a6:20b:48a::8) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5314.19 via Frontend Transport; Mon, 6 Jun 2022 09:47:27 +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 AM5EUR03FT050.mail.protection.outlook.com (10.152.17.47) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5314.12 via Frontend Transport; Mon, 6 Jun 2022 09:47:26 +0000 Received: ("Tessian outbound ff2e13d26e0f:v120"); Mon, 06 Jun 2022 09:47:26 +0000 X-CheckRecipientChecked: true X-CR-MTA-CID: 92b7186f92f98068 X-CR-MTA-TID: 64aa7808 Received: from 428cf48d9d6f.1 by 64aa7808-outbound-1.mta.getcheckrecipient.com id B51D7464-FE9B-4BF7-AC5D-C261109E6708.1; Mon, 06 Jun 2022 09:47:18 +0000 Received: from EUR04-VI1-obe.outbound.protection.outlook.com by 64aa7808-outbound-1.mta.getcheckrecipient.com with ESMTPS id 428cf48d9d6f.1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384); Mon, 06 Jun 2022 09:47:18 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=Wtx2jINm0Xu1SO8ZYuAkeo6KsCQJf7THL+UVCmkQXZnXOnVJ5tvvVPiNhVhXL8f/BHRBJSdEGbygUOubn8tkJ4cv06oQaGMAeQhDNpA70wIe3emBVr0yYVDwJCcSzhA2GEdoHMteRUyEYlYJs0QR8qDa/y1OIajwnZQO72Oc9APDcct3k7rxmbUC+0dJzziea6IgYALTzYGlKZan6qLu3k4vW1UVJWSJ7Ny1lRWixIFH95mfq8ycsf/8wvH4peVbUXdsVzEiZLgyg2CUZn4xP8lYvX51vtjQzx7ZROOxk4zxTRRcizBfDWBwKYAYLEJYndV2Ju23RPGMnE9wRgQmpQ== 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=UYAS9UlDk7CqvhJ+vWJzReB9UeewcihxgbmFWcp1++g=; b=G/YXp7PV3Fk4OObGO2kgmE1PYK1a8EGrZvHLozDJkbm9mwOpo8JLeEjOYmeywL5UjwcFy0i4CYmx0++rhiuuOdkslbWMho89lkctS4L4NfU2b6u2ZX1YcYw7P/VQ2GkCqa757ioxSUrWgt75Vwe9og9nNcmekBkiP0Mk5k4ynhsFqI2/Xxbc+YaX8XZdkynQlN1EUPivnPVa1eV3rUfvkYBkDdBNmVa4Ydh60DBd18AsTJCenK4857WgMrYh3c61CEDAhHtJjWoJ8kje6Sr7fOdDeEDtQD2b7zjTazMCLUPL4F0FzCqKD9tZMqxkCXLAEVEMRaBNPTFDtaR8BXhr0g== 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 Authentication-Results-Original: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=arm.com; Received: from VI1PR08MB3919.eurprd08.prod.outlook.com (2603:10a6:803:c4::31) by AM0PR08MB5236.eurprd08.prod.outlook.com (2603:10a6:208:155::17) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5314.13; Mon, 6 Jun 2022 09:47:15 +0000 Received: from VI1PR08MB3919.eurprd08.prod.outlook.com ([fe80::9545:ff73:df89:3e50]) by VI1PR08MB3919.eurprd08.prod.outlook.com ([fe80::9545:ff73:df89:3e50%7]) with mapi id 15.20.5314.019; Mon, 6 Jun 2022 09:47:15 +0000 Message-ID: Date: Mon, 6 Jun 2022 10:47:13 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Thunderbird/91.9.1 Subject: Re: [PATCH, v4] [AArch64] MTE corefile support Content-Language: en-US To: Kuan-Ying Lee , "gdb-patches@sourceware.org" References: <20220331140343.9047-1-luis.machado@arm.com> <20220503215632.914608-1-luis.machado@arm.com> <1dd14ec1-b0e3-8c4b-678c-1c67341ef978@arm.com> <04febcab961d9ae834ffdea960a7469a3a309b13.camel@mediatek.com> From: Luis Machado In-Reply-To: <04febcab961d9ae834ffdea960a7469a3a309b13.camel@mediatek.com> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit X-ClientProxiedBy: LO2P265CA0429.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:a0::33) To VI1PR08MB3919.eurprd08.prod.outlook.com (2603:10a6:803:c4::31) MIME-Version: 1.0 X-MS-Office365-Filtering-Correlation-Id: cb1e6faf-30cc-4a65-d2d9-08da47a1904e X-MS-TrafficTypeDiagnostic: AM0PR08MB5236:EE_|AM5EUR03FT050:EE_|AM9PR08MB7133:EE_ X-Microsoft-Antispam-PRVS: 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: gRkEEx5RUkaNgQyjGS/M6WLVQiiANMsX7e18wEEjf/wyTn0xmxDADcKMj4GPECejvYOO79Xc4PfvNN75IMwSeT5K4Jky8vD6kbPO94dmZikDh7FHPQSxNdsINaazygT25g7McMyZwW2/Rak6G2Q1wWE2Rn1twD735r8AW94nRFeL8QHHu+95RZEXWTsOLDAd/2RE5Xt+eazR+wf7uC5o5KZ1n3CAcoU5TCp8AnVDvy0kuTl2wrzkfIjicqzbVq4ODUZy/NvBWyqWCsAuV+KGublCJZ6JEyOx8+xsWUq3iuvcKR3UYsEgC1+O2AwYgSiB6Lf5HLSk9hORgtAgMpurG3MoKC9FpYazlhaxJdmoLNy8l9ttGUE28D6tn9Z7IIuaXpm8W+0aBEaChKF/n6zwxY2BNu4c+Rdn0rKUoPuILcxEqi9sW0tmdtZDfolF0LVPJanyQONZ8lZQ61IS9YQq8GoA9OrKZEZj7P0aWY0ggqhlxFg7nQXXWq30bI4xttZw6Knpa9GD77DJIKxAbLzQ3BTfynSULOJGSRwZqDcmcaQdxnIxFzJMguvV+HvLJtv/V0vT+73eCWmigeZqJpO5f7OOpmSmXG/Wkw0RpmlNQ/A4FY4x5rmGRWBIPwpV08Y/8xQtL9dvvfMX2iG6Njn3uAbJuZKtXwJmTXR1JCL3S6/4Pj21URDFTj99DHKS0w0oLp0/d1g64pNQjfqAauJkrAmyPK5bMd5liDRuSsIeMXxprFfRD9WabvCKTCCjs3IftgTvYbCDBvAIBaxaHUHlMNzrGnEoCTOyONe6hMOmSJtroA1H4MZMTf7+5/PcwLSxEkJ8BM5nP+sdOM874pfCYg== X-Forefront-Antispam-Report-Untrusted: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:VI1PR08MB3919.eurprd08.prod.outlook.com; PTR:; CAT:NONE; SFS:(13230001)(4636009)(366004)(53546011)(26005)(44832011)(6506007)(6512007)(31696002)(2906002)(83380400001)(38100700002)(2616005)(86362001)(110136005)(186003)(508600001)(966005)(5660300002)(8936002)(6486002)(316002)(66476007)(66556008)(36756003)(30864003)(31686004)(66946007)(8676002)(2004002)(45980500001)(43740500002)(579004)(559001); DIR:OUT; SFP:1101; X-MS-Exchange-Transport-CrossTenantHeadersStamped: AM0PR08MB5236 Original-Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=arm.com; X-EOPAttributedMessage: 0 X-MS-Exchange-Transport-CrossTenantHeadersStripped: AM5EUR03FT050.eop-EUR03.prod.protection.outlook.com X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id-Prvs: 4f005156-44b1-4c20-a152-08da47a189c8 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: 4HdE3CORohW+17WEVqlbzM/YY/lHBeSr0umPSdQx3qOrxs2qW+3tOi17o7LYBbtjzDSLK75Dp4j4opwB2nnrgq1EVcxq9TIZ6kohFYFtCOVVo7Ay+R7VuDTDHFAgCoZOqkcY5eX5TzRxCwV2jHX7jVMBckQ7QesUcQynpESLlmkhmnuhEBcW9js2FFOUzrfXU3Gua7jgXHWMZt94YnWVxStlkFPr2G+uYpw/a+C3Xn5K7vca7uHDeuzKqdbonzBPB53iyshbDjDsNbldYHsQf+Qmf5trpHb93vb03p+Y/AqGWo08UgXqb0DDy/VXZLrdGrg3hh1VOVpVsInxtSt8cnG+BjytDzU8EYPm3o251Cye0Bg8OtuMvtxFXhxkqdjvP36jCvUHvkr9xUwDg/X61+6S8cvoppTYKtumpxhIcNl8Rif9PjMILJc5C8ynlY3K6+0Ftk+UT4qdbq/Z5d4tynVFnx1C9piQGGkDmfElFpVPWbT58BtbfUobjwjRDE+dneeATfG/9aLN2PSFCAvEwQvB9ij7IGhh/GZtWlsofn2nptPq/WfmrAEWujs6QMCz8MWcii1D37um6beuXcNirpjhi7f4rUfzKNkSKw4dfraJBvs1dr4s1+V/n7U2p4RpNuvJ8bYTNMs3ikk5h5aAJT/12bFlPC/nN/57UR39wmI0tACZ3R4MVl8JSKlSS1DR4MWXhhnkEAOO318OcBJmPGya3Vi0eW+qZByPlyv60GKRLmR+mM+kA9sPrpGlomVZ1U9YY7aNW6Ph3lu+HzjxLbcBpur4Me0iAti36NaWZiymG45oUmc90pNHMnTA8u81 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:(13230001)(4636009)(36840700001)(40470700004)(46966006)(110136005)(40460700003)(36756003)(81166007)(44832011)(316002)(31686004)(82310400005)(36860700001)(356005)(6506007)(53546011)(30864003)(70206006)(47076005)(336012)(2906002)(31696002)(70586007)(8936002)(186003)(8676002)(508600001)(26005)(2616005)(5660300002)(6512007)(6486002)(966005)(86362001)(83380400001)(2004002)(43740500002)(559001)(579004); DIR:OUT; SFP:1101; X-OriginatorOrg: arm.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 06 Jun 2022 09:47:26.1956 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: cb1e6faf-30cc-4a65-d2d9-08da47a1904e 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: AM5EUR03FT050.eop-EUR03.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: AM9PR08MB7133 X-Spam-Status: No, score=-14.0 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, FORGED_SPF_HELO, GIT_PATCH_0, KAM_DMARC_NONE, KAM_SHORT, NICE_REPLY_A, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, SPF_HELO_PASS, SPF_NONE, TXREP, T_SCC_BODY_TEXT_LINE, 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-List-Received-Date: Mon, 06 Jun 2022 09:47:38 -0000 On 6/6/22 10:42, Kuan-Ying Lee wrote: > On Mon, 2022-06-06 at 17:28 +0800, Luis Machado via Gdb-patches wrote: >> Ping? >> > > Hi Luis, > > I don't see PT_AARCH64_MEMTAG_MTE in include/elf/common.h. > > I think we need to add below in include/elf/common.h. Based on binutils@ feedback, this constant was moved to include/elf/aarch64.h, and is part of the binutils patch. > > #define PT_AARCH64_MEMTAG_MTE (PT_LOPROC + 0x2) > > Or do I miss something? > > Best regards, > Kuan-Ying Lee > >> On 5/3/22 22:56, Luis Machado via Gdb-patches wrote: >>> v4: >>> >>> - Updated documentation (added cross-references). >>> - Updated the segment name from PT_ARM_MEMTAG_MTE to >>> PT_AARCH64_MEMTAG_MTE. >>> >>> v3: >>> >>> - Updated NEWS and documentation to be more thorough. >>> >>> v2: >>> >>> - Rework memory tag section handling to use generic section fields. >>> >>> -- >>> >>> Teach GDB how to dump memory tags for AArch64 when using the gcore >>> command >>> and how to read memory tag data back from a core file generated by >>> GDB >>> (via gcore) or by the Linux kernel. >>> >>> The format is documented in the Linux Kernel documentation [1]. >>> >>> Each tagged memory range (listed in /proc//smaps) gets dumped >>> to its >>> own PT_AARCH64_MEMTAG_MTE segment. A section named ".memtag" is >>> created for each >>> of those segments when reading the core file back. >>> >>> To save a little bit of space, given MTE tags only take 4 bits, the >>> memory tags >>> are stored packed as 2 tags per byte. >>> >>> When reading the data back, the tags are unpacked. >>> >>> I've added a new testcase to exercise the feature. >>> >>> Build-tested with --enable-targets=all and regression tested on >>> aarch64-linux >>> Ubuntu 20.04. >>> >>> [1] Documentation/arm64/memory-tagging-extension.rst (Core Dump >>> Support) >>> --- >>> gdb/Makefile.in | 1 + >>> gdb/NEWS | 10 ++ >>> gdb/aarch64-linux-tdep.c | 167 >>> +++++++++++++++++++ >>> gdb/arch/aarch64-mte-linux.c | 56 +++++++ >>> gdb/arch/aarch64-mte-linux.h | 10 ++ >>> gdb/corelow.c | 62 +++++++ >>> gdb/defs.h | 3 +- >>> gdb/doc/gdb.texinfo | 19 +++ >>> gdb/gcore.c | 83 ++++++++- >>> gdb/gdbarch-components.py | 35 ++++ >>> gdb/gdbarch-gen.h | 26 +++ >>> gdb/gdbarch.c | 96 +++++++++++ >>> gdb/linux-tdep.c | 39 ++++- >>> gdb/memtag.c | 61 +++++++ >>> gdb/memtag.h | 50 ++++++ >>> gdb/testsuite/gdb.arch/aarch64-mte-gcore.c | 93 +++++++++++ >>> gdb/testsuite/gdb.arch/aarch64-mte-gcore.exp | 107 ++++++++++++ >>> 17 files changed, 910 insertions(+), 8 deletions(-) >>> create mode 100644 gdb/memtag.c >>> create mode 100644 gdb/memtag.h >>> create mode 100644 gdb/testsuite/gdb.arch/aarch64-mte-gcore.c >>> create mode 100644 gdb/testsuite/gdb.arch/aarch64-mte-gcore.exp >>> >>> diff --git a/gdb/Makefile.in b/gdb/Makefile.in >>> index 418094775a5..fac9364bea4 100644 >>> --- a/gdb/Makefile.in >>> +++ b/gdb/Makefile.in >>> @@ -1120,6 +1120,7 @@ COMMON_SFILES = \ >>> memattr.c \ >>> memory-map.c \ >>> memrange.c \ >>> + memtag.c \ >>> minidebug.c \ >>> minsyms.c \ >>> mipsread.c \ >>> diff --git a/gdb/NEWS b/gdb/NEWS >>> index 982f4a1a18c..3d925dc3663 100644 >>> --- a/gdb/NEWS >>> +++ b/gdb/NEWS >>> @@ -3,6 +3,16 @@ >>> >>> *** Changes since GDB 12 >>> >>> +* GDB now supports dumping memory tag data for AArch64 MTE. It >>> also supports >>> + reading memory tag data for AArch64 MTE from core files >>> generated by >>> + the gcore command or the Linux kernel. >>> + >>> + When a process uses memory-mapped pages protected by memory tags >>> (for >>> + example, AArch64 MTE), this additional information will be >>> recorded in >>> + the core file in the event of a crash or if GDB generates a core >>> file >>> + from the current process state. GDB will show this additional >>> information >>> + automatically, or through one of the memory-tag subcommands. >>> + >>> * GDB now supports hardware watchpoints on FreeBSD/Aarch64. >>> >>> * Remove support for building against Python 2, it is now only >>> possible to >>> diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c >>> index 55094b3d88b..12d98e71796 100644 >>> --- a/gdb/aarch64-linux-tdep.c >>> +++ b/gdb/aarch64-linux-tdep.c >>> @@ -53,6 +53,9 @@ >>> >>> #include "gdbsupport/selftest.h" >>> >>> +#include "elf/common.h" >>> +#include "elf/aarch64.h" >>> + >>> /* Signal frame handling. >>> >>> +------------+ ^ >>> @@ -1781,6 +1784,155 @@ aarch64_linux_report_signal_info (struct >>> gdbarch *gdbarch, >>> } >>> } >>> >>> +/* AArch64 Linux implementation of the >>> gdbarch_create_memtag_section hook. */ >>> + >>> +static asection * >>> +aarch64_linux_create_memtag_section (struct gdbarch *gdbarch, bfd >>> *obfd, >>> + CORE_ADDR address, size_t size) >>> +{ >>> + gdb_assert (obfd != nullptr); >>> + gdb_assert (size > 0); >>> + >>> + /* Create the section and associated program header. */ >>> + asection *mte_section = bfd_make_section_anyway (obfd, >>> "memtag"); >>> + >>> + if (mte_section == nullptr) >>> + return nullptr; >>> + >>> + bfd_set_section_vma (mte_section, address); >>> + /* The size of the memory range covered by the memory tags. We >>> reuse the >>> + section's rawsize field for this purpose. */ >>> + mte_section->rawsize = size; >>> + /* Tags are stored packed as 2 tags per byte. */ >>> + bfd_set_section_size (mte_section, (size / >>> AARCH64_MTE_GRANULE_SIZE) / 2); >>> + /* Make sure the section's flags has SEC_HAS_CONTENTS, otherwise >>> BFD will >>> + refuse to write data to this section. */ >>> + bfd_set_section_flags (mte_section, SEC_HAS_CONTENTS); >>> + >>> + /* Store program header information. */ >>> + bfd_record_phdr (obfd, PT_AARCH64_MEMTAG_MTE, 1, 0, 0, 0, 0, 0, >>> 1, >>> + &mte_section); >>> + >>> + return mte_section; >>> +} >>> + >>> +/* Maximum number of tags to request. */ >>> +#define MAX_TAGS_TO_TRANSFER 1024 >>> + >>> +/* AArch64 Linux implementation of the gdbarch_fill_memtag_section >>> hook. */ >>> + >>> +static bool >>> +aarch64_linux_fill_memtag_section (struct gdbarch *gdbarch, >>> asection *osec) >>> +{ >>> + /* We only handle MTE tags for now. */ >>> + >>> + size_t segment_size = osec->rawsize; >>> + CORE_ADDR start_address = bfd_section_vma (osec); >>> + CORE_ADDR end_address = start_address + segment_size; >>> + >>> + /* Figure out how many tags we need to store in this memory >>> range. */ >>> + size_t granules = aarch64_mte_get_tag_granules (start_address, >>> segment_size, >>> + AARCH64_MTE_GRANULE_S >>> IZE); >>> + >>> + /* If there are no tag granules to fetch, just return. */ >>> + if (granules == 0) >>> + return true; >>> + >>> + CORE_ADDR address = start_address; >>> + >>> + /* Vector of tags. */ >>> + gdb::byte_vector tags; >>> + >>> + while (granules > 0) >>> + { >>> + /* Transfer tags in chunks. */ >>> + gdb::byte_vector tags_read; >>> + size_t xfer_len >>> + = (granules >= MAX_TAGS_TO_TRANSFER)? >>> + MAX_TAGS_TO_TRANSFER * AARCH64_MTE_GRANULE_SIZE : >>> + granules * AARCH64_MTE_GRANULE_SIZE; >>> + >>> + if (!target_fetch_memtags (address, xfer_len, tags_read, >>> + static_cast >>> (memtag_type::allocation))) >>> + { >>> + warning (_("Failed to read MTE tags from memory range >>> [%s,%s)."), >>> + phex_nz (start_address, sizeof (start_address)), >>> + phex_nz (end_address, sizeof (end_address))); >>> + return false; >>> + } >>> + >>> + /* Transfer over the tags that have been read. */ >>> + tags.insert (tags.end (), tags_read.begin (), tags_read.end >>> ()); >>> + >>> + /* Adjust the remaining granules and starting address. */ >>> + granules -= tags_read.size (); >>> + address += tags_read.size () * AARCH64_MTE_GRANULE_SIZE; >>> + } >>> + >>> + /* Pack the MTE tag bits. */ >>> + aarch64_mte_pack_tags (tags); >>> + >>> + if (!bfd_set_section_contents (osec->owner, osec, tags.data (), >>> + 0, tags.size ())) >>> + { >>> + warning (_("Failed to write %s bytes of corefile memory " >>> + "tag content (%s)."), >>> + pulongest (tags.size ()), >>> + bfd_errmsg (bfd_get_error ())); >>> + } >>> + return true; >>> +} >>> + >>> +/* AArch64 Linux implementation of the >>> gdbarch_decode_memtag_section >>> + hook. Decode a memory tag section and return the requested >>> tags. >>> + >>> + The section is guaranteed to cover the [ADDRESS, ADDRESS + >>> length) >>> + range. */ >>> + >>> +static gdb::byte_vector >>> +aarch64_linux_decode_memtag_section (struct gdbarch *gdbarch, >>> + bfd_section *section, >>> + int type, >>> + CORE_ADDR address, size_t length) >>> +{ >>> + gdb_assert (section != nullptr); >>> + >>> + /* The requested address must not be less than section->vma. */ >>> + gdb_assert (section->vma <= address); >>> + >>> + /* Figure out how many tags we need to fetch in this memory >>> range. */ >>> + size_t granules = aarch64_mte_get_tag_granules (address, length, >>> + AARCH64_MTE_GRANULE_S >>> IZE); >>> + /* Sanity check. */ >>> + gdb_assert (granules > 0); >>> + >>> + /* Fetch the total number of tags in the range [VMA, address + >>> length). */ >>> + size_t granules_from_vma >>> + = aarch64_mte_get_tag_granules (section->vma, >>> + address - section->vma + length, >>> + AARCH64_MTE_GRANULE_SIZE); >>> + >>> + /* Adjust the tags vector to contain the exact number of packed >>> bytes. */ >>> + gdb::byte_vector tags (((granules - 1) >> 1) + 1); >>> + >>> + /* Figure out the starting offset into the packed tags data. */ >>> + file_ptr offset = ((granules_from_vma - granules) >> 1); >>> + >>> + if (!bfd_get_section_contents (section->owner, section, >>> tags.data (), >>> + offset, tags.size ())) >>> + error (_("Couldn't read contents from memtag section.")); >>> + >>> + /* At this point, the tags are packed 2 per byte. Unpack them >>> before >>> + returning. */ >>> + bool skip_first = ((granules_from_vma - granules) % 2) != 0; >>> + aarch64_mte_unpack_tags (tags, skip_first); >>> + >>> + /* Resize to the exact number of tags that was requested. */ >>> + tags.resize (granules); >>> + >>> + return tags; >>> +} >>> + >>> static void >>> aarch64_linux_init_abi (struct gdbarch_info info, struct gdbarch >>> *gdbarch) >>> { >>> @@ -1864,6 +2016,21 @@ aarch64_linux_init_abi (struct gdbarch_info >>> info, struct gdbarch *gdbarch) >>> >>> set_gdbarch_report_signal_info (gdbarch, >>> aarch64_linux_report_signal_info) >>> ; >>> + >>> + /* Core file helpers. */ >>> + >>> + /* Core file helper to create a memory tag section for a >>> particular >>> + PT_LOAD segment. */ >>> + set_gdbarch_create_memtag_section >>> + (gdbarch, aarch64_linux_create_memtag_section); >>> + >>> + /* Core file helper to fill a memory tag section with tag >>> data. */ >>> + set_gdbarch_fill_memtag_section >>> + (gdbarch, aarch64_linux_fill_memtag_section); >>> + >>> + /* Core file helper to decode a memory tag section. */ >>> + set_gdbarch_decode_memtag_section (gdbarch, >>> + aarch64_linux_decode_memtag_se >>> ction); >>> } >>> >>> /* Initialize the aarch64_linux_record_tdep. */ >>> diff --git a/gdb/arch/aarch64-mte-linux.c b/gdb/arch/aarch64-mte- >>> linux.c >>> index fc7a8cc00f7..3af6f364e91 100644 >>> --- a/gdb/arch/aarch64-mte-linux.c >>> +++ b/gdb/arch/aarch64-mte-linux.c >>> @@ -21,6 +21,62 @@ >>> >>> /* See arch/aarch64-mte-linux.h */ >>> >>> +void >>> +aarch64_mte_pack_tags (gdb::byte_vector &tags) >>> +{ >>> + /* Nothing to pack? */ >>> + if (tags.empty ()) >>> + return; >>> + >>> + /* If the tags vector has an odd number of elements, add another >>> + zeroed-out element to make it even. This facilitates >>> packing. */ >>> + if ((tags.size () % 2) != 0) >>> + tags.emplace_back (0); >>> + >>> + for (int unpacked = 0, packed = 0; unpacked < tags.size (); >>> + unpacked += 2, packed++) >>> + tags[packed] = (tags[unpacked + 1] << 4) | tags[unpacked]; >>> + >>> + /* Now we have half the size. */ >>> + tags.resize (tags.size () / 2); >>> +} >>> + >>> +/* See arch/aarch64-mte-linux.h */ >>> + >>> +void >>> +aarch64_mte_unpack_tags (gdb::byte_vector &tags, bool skip_first) >>> +{ >>> + /* Nothing to unpack? */ >>> + if (tags.empty ()) >>> + return; >>> + >>> + /* An unpacked MTE tags vector will have twice the number of >>> elements >>> + compared to an unpacked one. */ >>> + gdb::byte_vector unpacked_tags (tags.size () * 2); >>> + >>> + int unpacked = 0, packed = 0; >>> + >>> + if (skip_first) >>> + { >>> + /* We are not interested in the first unpacked element, just >>> discard >>> + it. */ >>> + unpacked_tags[unpacked] = (tags[packed] >> 4) & 0xf; >>> + unpacked++; >>> + packed++; >>> + } >>> + >>> + for (; packed < tags.size (); unpacked += 2, packed++) >>> + { >>> + unpacked_tags[unpacked] = tags[packed] & 0xf; >>> + unpacked_tags[unpacked + 1] = (tags[packed] >> 4) & 0xf; >>> + } >>> + >>> + /* Update the original tags vector. */ >>> + tags = std::move (unpacked_tags); >>> +} >>> + >>> +/* See arch/aarch64-mte-linux.h */ >>> + >>> size_t >>> aarch64_mte_get_tag_granules (CORE_ADDR addr, size_t len, size_t >>> granule_size) >>> { >>> diff --git a/gdb/arch/aarch64-mte-linux.h b/gdb/arch/aarch64-mte- >>> linux.h >>> index d158926feff..8a145b447aa 100644 >>> --- a/gdb/arch/aarch64-mte-linux.h >>> +++ b/gdb/arch/aarch64-mte-linux.h >>> @@ -32,6 +32,7 @@ >>> >>> /* We have one tag per 16 bytes of memory. */ >>> #define AARCH64_MTE_GRANULE_SIZE 16 >>> +#define AARCH64_MTE_TAG_BIT_SIZE 4 >>> #define AARCH64_MTE_LOGICAL_TAG_START_BIT 56 >>> #define AARCH64_MTE_LOGICAL_MAX_VALUE 0xf >>> >>> @@ -71,4 +72,13 @@ extern CORE_ADDR aarch64_mte_set_ltag (CORE_ADDR >>> address, CORE_ADDR tag); >>> It is always possible to get the logical tag. */ >>> extern CORE_ADDR aarch64_mte_get_ltag (CORE_ADDR address); >>> >>> +/* Given a TAGS vector containing 1 MTE tag per byte, pack the >>> data as >>> + 2 tags per byte and resize the vector. */ >>> +void aarch64_mte_pack_tags (gdb::byte_vector &tags); >>> + >>> +/* Given a TAGS vector containing 2 MTE tags per byte, unpack the >>> data as >>> + 1 tag per byte and resize the vector. If SKIP_FIRST is TRUE, >>> skip the >>> + first unpacked element. Otherwise leave it in the unpacked >>> vector. */ >>> +void aarch64_mte_unpack_tags (gdb::byte_vector &tags, bool >>> skip_first); >>> + >>> #endif /* ARCH_AARCH64_LINUX_H */ >>> diff --git a/gdb/corelow.c b/gdb/corelow.c >>> index 8c33fb7ebb2..8b8994f80db 100644 >>> --- a/gdb/corelow.c >>> +++ b/gdb/corelow.c >>> @@ -52,6 +52,7 @@ >>> #include >>> #include "gdbcmd.h" >>> #include "xml-tdesc.h" >>> +#include "memtag.h" >>> >>> #ifndef O_LARGEFILE >>> #define O_LARGEFILE 0 >>> @@ -101,6 +102,13 @@ class core_target final : public >>> process_stratum_target >>> >>> bool info_proc (const char *, enum info_proc_what) override; >>> >>> + bool supports_memory_tagging () override; >>> + >>> + /* Core file implementation of fetch_memtags. Fetch the memory >>> tags from >>> + core file notes. */ >>> + bool fetch_memtags (CORE_ADDR address, size_t len, >>> + gdb::byte_vector &tags, int type) override; >>> + >>> /* A few helpers. */ >>> >>> /* Getter, see variable definition. */ >>> @@ -1162,6 +1170,60 @@ core_target::info_proc (const char *args, >>> enum info_proc_what request) >>> return true; >>> } >>> >>> +/* Implementation of the "supports_memory_tagging" target_ops >>> method. */ >>> + >>> +bool >>> +core_target::supports_memory_tagging () >>> +{ >>> + /* Look for memory tag sections. If they exist, that means this >>> core file >>> + supports memory tagging. */ >>> + >>> + return (bfd_get_section_by_name (core_bfd, "memtag") != >>> nullptr); >>> +} >>> + >>> +/* Implementation of the "fetch_memtags" target_ops method. */ >>> + >>> +bool >>> +core_target::fetch_memtags (CORE_ADDR address, size_t len, >>> + gdb::byte_vector &tags, int type) >>> +{ >>> + struct gdbarch *gdbarch = target_gdbarch (); >>> + >>> + /* Make sure we have a way to decode the memory tag notes. */ >>> + if (!gdbarch_decode_memtag_section_p (gdbarch)) >>> + error (_("gdbarch_decode_memtag_section not implemented for >>> this " >>> + "architecture.")); >>> + >>> + memtag_section_info info; >>> + info.memtag_section = nullptr; >>> + >>> + while (get_next_core_memtag_section (core_bfd, >>> info.memtag_section, >>> + address, info)) >>> + { >>> + size_t adjusted_length >>> + = (address + len < info.end_address)? len : >>> (info.end_address - address); >>> + >>> + /* Decode the memory tag note and return the tags. */ >>> + gdb::byte_vector tags_read >>> + = gdbarch_decode_memtag_section (gdbarch, >>> info.memtag_section, type, >>> + address, adjusted_length); >>> + >>> + /* Transfer over the tags that have been read. */ >>> + tags.insert (tags.end (), tags_read.begin (), tags_read.end >>> ()); >>> + >>> + /* ADDRESS + LEN may cross the boundaries of a particular >>> memory tag >>> + segment. Check if we need to fetch tags from a different >>> section. */ >>> + if (!tags_read.empty () && (address + len) < info.end_address) >>> + return true; >>> + >>> + /* There are more tags to fetch. Update ADDRESS and LEN. */ >>> + len -= (info.end_address - address); >>> + address = info.end_address; >>> + } >>> + >>> + return false; >>> +} >>> + >>> /* Get a pointer to the current core target. If not connected to >>> a >>> core target, return NULL. */ >>> >>> diff --git a/gdb/defs.h b/gdb/defs.h >>> index 99bfdd526ff..51a7576a56a 100644 >>> --- a/gdb/defs.h >>> +++ b/gdb/defs.h >>> @@ -344,7 +344,8 @@ extern const char *pc_prefix (CORE_ADDR); >>> >>> typedef int (*find_memory_region_ftype) (CORE_ADDR addr, unsigned >>> long size, >>> int read, int write, int exec, >>> - int modified, void *data); >>> + int modified, bool >>> memory_tagged, >>> + void *data); >>> >>> /* * Possible lvalue types. Like enum language, this should be >>> in >>> value.h, but needs to be here for the same reason. */ >>> diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo >>> index 38ad2ac32b0..36f10f20cfb 100644 >>> --- a/gdb/doc/gdb.texinfo >>> +++ b/gdb/doc/gdb.texinfo >>> @@ -25555,6 +25555,25 @@ options that can be controlled at runtime >>> and emulates the @code{prctl} >>> option @code{PR_SET_TAGGED_ADDR_CTRL}. For further information, >>> see the >>> documentation in the Linux kernel. >>> >>> +@value{GDBN} supports dumping memory tag data to core files >>> through the >>> +@command{gcore} command and reading memory tag data from core >>> files generated >>> +by the @command{gcore} command or the Linux kernel. >>> + >>> +When a process uses memory-mapped pages protected by memory tags >>> (for >>> +example, AArch64 MTE), this additional information will be >>> recorded in >>> +the core file in the event of a crash or if @value{GDBN} generates >>> a core file >>> +from the current process state. >>> + >>> +The memory tag data will be used so developers can display the >>> memory >>> +tags from a particular memory region (using the @samp{m} modifier >>> to the >>> +@command{x} command, using the @command{print} command or using >>> the various >>> +@command{memory-tag} subcommands. >>> + >>> +In the case of a crash, @value{GDBN} will attempt to retrieve the >>> memory tag >>> +information automatically from the core file, and will show one of >>> the above >>> +messages depending on whether the synchronous or asynchronous mode >>> is selected. >>> +@xref{Memory Tagging}. @xref{Memory}. >>> + >>> @node i386 >>> @subsection x86 Architecture-specific Issues >>> >>> diff --git a/gdb/gcore.c b/gdb/gcore.c >>> index fdb22b72a07..b81ef81ab84 100644 >>> --- a/gdb/gcore.c >>> +++ b/gdb/gcore.c >>> @@ -349,6 +349,12 @@ make_output_phdrs (bfd *obfd, asection *osec) >>> int p_flags = 0; >>> int p_type = 0; >>> >>> + /* Memory tag segments have already been handled by the >>> architecture, as >>> + those contain arch-specific information. If we have one of >>> those, just >>> + return. */ >>> + if (startswith (bfd_section_name (osec), "memtag")) >>> + return; >>> + >>> /* FIXME: these constants may only be applicable for ELF. */ >>> if (startswith (bfd_section_name (osec), "load")) >>> p_type = PT_LOAD; >>> @@ -371,7 +377,8 @@ make_output_phdrs (bfd *obfd, asection *osec) >>> >>> static int >>> gcore_create_callback (CORE_ADDR vaddr, unsigned long size, int >>> read, >>> - int write, int exec, int modified, void *data) >>> + int write, int exec, int modified, bool >>> memory_tagged, >>> + void *data) >>> { >>> bfd *obfd = (bfd *) data; >>> asection *osec; >>> @@ -454,6 +461,45 @@ gcore_create_callback (CORE_ADDR vaddr, >>> unsigned long size, int read, >>> return 0; >>> } >>> >>> +/* gdbarch_find_memory_region callback for creating a memory tag >>> section. >>> + DATA is 'bfd *' for the core file GDB is creating. */ >>> + >>> +static int >>> +gcore_create_memtag_section_callback (CORE_ADDR vaddr, unsigned >>> long size, >>> + int read, int write, int exec, >>> + int modified, bool memory_tagged, >>> + void *data) >>> +{ >>> + /* Are there memory tags in this particular memory map >>> entry? */ >>> + if (!memory_tagged) >>> + return 0; >>> + >>> + bfd *obfd = (bfd *) data; >>> + >>> + /* Ask the architecture to create a memory tag section for this >>> particular >>> + memory map entry. It will be populated with contents later, >>> as we can't >>> + start writing the contents before we have all the sections >>> sorted out. */ >>> + asection *memtag_section >>> + = gdbarch_create_memtag_section (target_gdbarch (), obfd, >>> vaddr, size); >>> + >>> + if (memtag_section == nullptr) >>> + { >>> + warning (_("Couldn't make gcore memory tag segment: %s"), >>> + bfd_errmsg (bfd_get_error ())); >>> + return 1; >>> + } >>> + >>> + if (info_verbose) >>> + { >>> + gdb_printf (gdb_stdout, "Saved memory tag segment, %s bytes >>> " >>> + "at %s\n", >>> + plongest (bfd_section_size (memtag_section)), >>> + paddress (target_gdbarch (), vaddr)); >>> + } >>> + >>> + return 0; >>> +} >>> + >>> int >>> objfile_find_memory_regions (struct target_ops *self, >>> find_memory_region_ftype func, void *obfd) >>> @@ -483,6 +529,7 @@ objfile_find_memory_regions (struct target_ops >>> *self, >>> (flags & SEC_READONLY) == 0, /* >>> Writable. */ >>> (flags & SEC_CODE) != 0, /* Executable. */ >>> 1, /* MODIFIED is unknown, pass it as >>> true. */ >>> + false, /* No memory tags in the object >>> file. */ >>> obfd); >>> if (ret != 0) >>> return ret; >>> @@ -496,6 +543,7 @@ objfile_find_memory_regions (struct target_ops >>> *self, >>> 1, /* Stack section will be writable. */ >>> 0, /* Stack section will not be executable. */ >>> 1, /* Stack section will be modified. */ >>> + false, /* No memory tags in the object file. */ >>> obfd); >>> >>> /* Make a heap segment. */ >>> @@ -506,6 +554,7 @@ objfile_find_memory_regions (struct target_ops >>> *self, >>> 1, /* Heap section will be writable. */ >>> 0, /* Heap section will not be executable. */ >>> 1, /* Heap section will be modified. */ >>> + false, /* No memory tags in the object file. */ >>> obfd); >>> >>> return 0; >>> @@ -555,6 +604,20 @@ gcore_copy_callback (bfd *obfd, asection >>> *osec) >>> } >>> } >>> >>> +/* Callback to copy contents to a particular memory tag >>> section. */ >>> + >>> +static void >>> +gcore_copy_memtag_section_callback (bfd *obfd, asection *osec) >>> +{ >>> + /* We are only interested in "memtag" sections. */ >>> + if (!startswith (bfd_section_name (osec), "memtag")) >>> + return; >>> + >>> + /* Fill the section with memory tag contents. */ >>> + if (!gdbarch_fill_memtag_section (target_gdbarch (), osec)) >>> + error (_("Failed to fill memory tag section for core file.")); >>> +} >>> + >>> static int >>> gcore_memory_sections (bfd *obfd) >>> { >>> @@ -567,13 +630,27 @@ gcore_memory_sections (bfd *obfd) >>> return 0; /* FIXME: error return/msg? */ >>> } >>> >>> + /* Take care of dumping memory tags, if there are any. */ >>> + if (!gdbarch_find_memory_regions_p (target_gdbarch ()) >>> + || gdbarch_find_memory_regions (target_gdbarch (), >>> + gcore_create_memtag_section_callb >>> ack, >>> + obfd) != 0) >>> + { >>> + if (target_find_memory_regions >>> (gcore_create_memtag_section_callback, >>> + obfd) != 0) >>> + return 0; >>> + } >>> + >>> /* Record phdrs for section-to-segment mapping. */ >>> for (asection *sect : gdb_bfd_sections (obfd)) >>> make_output_phdrs (obfd, sect); >>> >>> - /* Copy memory region contents. */ >>> + /* Copy memory region and memory tag contents. */ >>> for (asection *sect : gdb_bfd_sections (obfd)) >>> - gcore_copy_callback (obfd, sect); >>> + { >>> + gcore_copy_callback (obfd, sect); >>> + gcore_copy_memtag_section_callback (obfd, sect); >>> + } >>> >>> return 1; >>> } >>> diff --git a/gdb/gdbarch-components.py b/gdb/gdbarch-components.py >>> index e8f20c83ff0..6fa1b7591db 100644 >>> --- a/gdb/gdbarch-components.py >>> +++ b/gdb/gdbarch-components.py >>> @@ -1522,6 +1522,41 @@ Find core file memory regions >>> invalid=True, >>> ) >>> >>> +Method( >>> + comment=""" >>> +Given a bfd OBFD, segment ADDRESS and SIZE, create a memory tag >>> section to be dumped to a core file >>> +""", >>> + type="asection *", >>> + name="create_memtag_section", >>> + params=[("bfd *", "obfd"), ("CORE_ADDR", "address"), >>> ("size_t", "size")], >>> + predicate=True, >>> + invalid=True, >>> +) >>> + >>> +Method( >>> + comment=""" >>> +Given a memory tag section OSEC, fill OSEC's contents with the >>> appropriate tag data >>> +""", >>> + type="bool", >>> + name="fill_memtag_section", >>> + params=[("asection *", "osec")], >>> + predicate=True, >>> + invalid=True, >>> +) >>> + >>> +Method( >>> + comment=""" >>> +Decode a memory tag SECTION and return the tags of type TYPE >>> contained in >>> +the memory range [ADDRESS, ADDRESS + LENGTH). >>> +If no tags were found, return an empty vector. >>> +""", >>> + type="gdb::byte_vector", >>> + name="decode_memtag_section", >>> + params=[("bfd_section *", "section"), ("int", "type"), >>> ("CORE_ADDR", "address"), ("size_t", "length")], >>> + predicate=True, >>> + invalid=True, >>> +) >>> + >>> Method( >>> comment=""" >>> Read offset OFFSET of TARGET_OBJECT_LIBRARIES formatted shared >>> libraries list from >>> diff --git a/gdb/gdbarch-gen.h b/gdb/gdbarch-gen.h >>> index 882b9057b1a..1d19f51f21d 100644 >>> --- a/gdb/gdbarch-gen.h >>> +++ b/gdb/gdbarch-gen.h >>> @@ -874,6 +874,32 @@ typedef int >>> (gdbarch_find_memory_regions_ftype) (struct gdbarch *gdbarch, >>> find_m >>> extern int gdbarch_find_memory_regions (struct gdbarch *gdbarch, >>> find_memory_region_ftype func, void *data); >>> extern void set_gdbarch_find_memory_regions (struct gdbarch >>> *gdbarch, gdbarch_find_memory_regions_ftype *find_memory_regions); >>> >>> +/* Given a bfd OBFD, segment ADDRESS and SIZE, create a memory tag >>> section to be dumped to a core file */ >>> + >>> +extern bool gdbarch_create_memtag_section_p (struct gdbarch >>> *gdbarch); >>> + >>> +typedef asection * (gdbarch_create_memtag_section_ftype) (struct >>> gdbarch *gdbarch, bfd *obfd, CORE_ADDR address, size_t size); >>> +extern asection * gdbarch_create_memtag_section (struct gdbarch >>> *gdbarch, bfd *obfd, CORE_ADDR address, size_t size); >>> +extern void set_gdbarch_create_memtag_section (struct gdbarch >>> *gdbarch, gdbarch_create_memtag_section_ftype >>> *create_memtag_section); >>> + >>> +/* Given a memory tag section OSEC, fill OSEC's contents with the >>> appropriate tag data */ >>> + >>> +extern bool gdbarch_fill_memtag_section_p (struct gdbarch >>> *gdbarch); >>> + >>> +typedef bool (gdbarch_fill_memtag_section_ftype) (struct gdbarch >>> *gdbarch, asection *osec); >>> +extern bool gdbarch_fill_memtag_section (struct gdbarch *gdbarch, >>> asection *osec); >>> +extern void set_gdbarch_fill_memtag_section (struct gdbarch >>> *gdbarch, gdbarch_fill_memtag_section_ftype *fill_memtag_section); >>> + >>> +/* Decode a memory tag SECTION and return the tags of type TYPE >>> contained in >>> + the memory range [ADDRESS, ADDRESS + LENGTH). >>> + If no tags were found, return an empty vector. */ >>> + >>> +extern bool gdbarch_decode_memtag_section_p (struct gdbarch >>> *gdbarch); >>> + >>> +typedef gdb::byte_vector (gdbarch_decode_memtag_section_ftype) >>> (struct gdbarch *gdbarch, bfd_section *section, int type, CORE_ADDR >>> address, size_t length); >>> +extern gdb::byte_vector gdbarch_decode_memtag_section (struct >>> gdbarch *gdbarch, bfd_section *section, int type, CORE_ADDR >>> address, size_t length); >>> +extern void set_gdbarch_decode_memtag_section (struct gdbarch >>> *gdbarch, gdbarch_decode_memtag_section_ftype >>> *decode_memtag_section); >>> + >>> /* Read offset OFFSET of TARGET_OBJECT_LIBRARIES formatted shared >>> libraries list from >>> core file into buffer READBUF with length LEN. Return the >>> number of bytes read >>> (zero indicates failure). >>> diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c >>> index a588bdef61a..f5dbacb14e7 100644 >>> --- a/gdb/gdbarch.c >>> +++ b/gdb/gdbarch.c >>> @@ -171,6 +171,9 @@ struct gdbarch >>> gdbarch_iterate_over_regset_sections_ftype >>> *iterate_over_regset_sections; >>> gdbarch_make_corefile_notes_ftype *make_corefile_notes; >>> gdbarch_find_memory_regions_ftype *find_memory_regions; >>> + gdbarch_create_memtag_section_ftype *create_memtag_section; >>> + gdbarch_fill_memtag_section_ftype *fill_memtag_section; >>> + gdbarch_decode_memtag_section_ftype *decode_memtag_section; >>> gdbarch_core_xfer_shared_libraries_ftype >>> *core_xfer_shared_libraries; >>> gdbarch_core_xfer_shared_libraries_aix_ftype >>> *core_xfer_shared_libraries_aix; >>> gdbarch_core_pid_to_str_ftype *core_pid_to_str; >>> @@ -527,6 +530,9 @@ verify_gdbarch (struct gdbarch *gdbarch) >>> /* Skip verify of iterate_over_regset_sections, has >>> predicate. */ >>> /* Skip verify of make_corefile_notes, has predicate. */ >>> /* Skip verify of find_memory_regions, has predicate. */ >>> + /* Skip verify of create_memtag_section, has predicate. */ >>> + /* Skip verify of fill_memtag_section, has predicate. */ >>> + /* Skip verify of decode_memtag_section, has predicate. */ >>> /* Skip verify of core_xfer_shared_libraries, has >>> predicate. */ >>> /* Skip verify of core_xfer_shared_libraries_aix, has >>> predicate. */ >>> /* Skip verify of core_pid_to_str, has predicate. */ >>> @@ -1096,6 +1102,24 @@ gdbarch_dump (struct gdbarch *gdbarch, >>> struct ui_file *file) >>> gdb_printf (file, >>> "gdbarch_dump: find_memory_regions = >>> <%s>\n", >>> host_address_to_string (gdbarch- >>>> find_memory_regions)); >>> + gdb_printf (file, >>> + "gdbarch_dump: >>> gdbarch_create_memtag_section_p() = %d\n", >>> + gdbarch_create_memtag_section_p (gdbarch)); >>> + gdb_printf (file, >>> + "gdbarch_dump: create_memtag_section = >>> <%s>\n", >>> + host_address_to_string (gdbarch- >>>> create_memtag_section)); >>> + gdb_printf (file, >>> + "gdbarch_dump: >>> gdbarch_fill_memtag_section_p() = %d\n", >>> + gdbarch_fill_memtag_section_p (gdbarch)); >>> + gdb_printf (file, >>> + "gdbarch_dump: fill_memtag_section = >>> <%s>\n", >>> + host_address_to_string (gdbarch- >>>> fill_memtag_section)); >>> + gdb_printf (file, >>> + "gdbarch_dump: >>> gdbarch_decode_memtag_section_p() = %d\n", >>> + gdbarch_decode_memtag_section_p (gdbarch)); >>> + gdb_printf (file, >>> + "gdbarch_dump: decode_memtag_section = >>> <%s>\n", >>> + host_address_to_string (gdbarch- >>>> decode_memtag_section)); >>> gdb_printf (file, >>> "gdbarch_dump: >>> gdbarch_core_xfer_shared_libraries_p() = %d\n", >>> gdbarch_core_xfer_shared_libraries_p >>> (gdbarch)); >>> @@ -3744,6 +3768,78 @@ set_gdbarch_find_memory_regions (struct >>> gdbarch *gdbarch, >>> gdbarch->find_memory_regions = find_memory_regions; >>> } >>> >>> +bool >>> +gdbarch_create_memtag_section_p (struct gdbarch *gdbarch) >>> +{ >>> + gdb_assert (gdbarch != NULL); >>> + return gdbarch->create_memtag_section != NULL; >>> +} >>> + >>> +asection * >>> +gdbarch_create_memtag_section (struct gdbarch *gdbarch, bfd *obfd, >>> CORE_ADDR address, size_t size) >>> +{ >>> + gdb_assert (gdbarch != NULL); >>> + gdb_assert (gdbarch->create_memtag_section != NULL); >>> + if (gdbarch_debug >= 2) >>> + gdb_printf (gdb_stdlog, "gdbarch_create_memtag_section >>> called\n"); >>> + return gdbarch->create_memtag_section (gdbarch, obfd, address, >>> size); >>> +} >>> + >>> +void >>> +set_gdbarch_create_memtag_section (struct gdbarch *gdbarch, >>> + gdbarch_create_memtag_section_f >>> type create_memtag_section) >>> +{ >>> + gdbarch->create_memtag_section = create_memtag_section; >>> +} >>> + >>> +bool >>> +gdbarch_fill_memtag_section_p (struct gdbarch *gdbarch) >>> +{ >>> + gdb_assert (gdbarch != NULL); >>> + return gdbarch->fill_memtag_section != NULL; >>> +} >>> + >>> +bool >>> +gdbarch_fill_memtag_section (struct gdbarch *gdbarch, asection >>> *osec) >>> +{ >>> + gdb_assert (gdbarch != NULL); >>> + gdb_assert (gdbarch->fill_memtag_section != NULL); >>> + if (gdbarch_debug >= 2) >>> + gdb_printf (gdb_stdlog, "gdbarch_fill_memtag_section >>> called\n"); >>> + return gdbarch->fill_memtag_section (gdbarch, osec); >>> +} >>> + >>> +void >>> +set_gdbarch_fill_memtag_section (struct gdbarch *gdbarch, >>> + gdbarch_fill_memtag_section_ftype >>> fill_memtag_section) >>> +{ >>> + gdbarch->fill_memtag_section = fill_memtag_section; >>> +} >>> + >>> +bool >>> +gdbarch_decode_memtag_section_p (struct gdbarch *gdbarch) >>> +{ >>> + gdb_assert (gdbarch != NULL); >>> + return gdbarch->decode_memtag_section != NULL; >>> +} >>> + >>> +gdb::byte_vector >>> +gdbarch_decode_memtag_section (struct gdbarch *gdbarch, >>> bfd_section *section, int type, CORE_ADDR address, size_t length) >>> +{ >>> + gdb_assert (gdbarch != NULL); >>> + gdb_assert (gdbarch->decode_memtag_section != NULL); >>> + if (gdbarch_debug >= 2) >>> + gdb_printf (gdb_stdlog, "gdbarch_decode_memtag_section >>> called\n"); >>> + return gdbarch->decode_memtag_section (gdbarch, section, type, >>> address, length); >>> +} >>> + >>> +void >>> +set_gdbarch_decode_memtag_section (struct gdbarch *gdbarch, >>> + gdbarch_decode_memtag_section_f >>> type decode_memtag_section) >>> +{ >>> + gdbarch->decode_memtag_section = decode_memtag_section; >>> +} >>> + >>> bool >>> gdbarch_core_xfer_shared_libraries_p (struct gdbarch *gdbarch) >>> { >>> diff --git a/gdb/linux-tdep.c b/gdb/linux-tdep.c >>> index 4e728a06e7e..8a83ed320cf 100644 >>> --- a/gdb/linux-tdep.c >>> +++ b/gdb/linux-tdep.c >>> @@ -42,6 +42,7 @@ >>> #include "gcore.h" >>> #include "gcore-elf.h" >>> #include "solib-svr4.h" >>> +#include "memtag.h" >>> >>> #include >>> #include >>> @@ -1320,6 +1321,7 @@ typedef int linux_find_memory_region_ftype >>> (ULONGEST vaddr, ULONGEST size, >>> ULONGEST offset, ULONGEST >>> inode, >>> int read, int write, >>> int exec, int modified, >>> + bool memory_tagged, >>> const char *filename, >>> void *data); >>> >>> @@ -1470,10 +1472,11 @@ parse_smaps_data (const char *data, >>> return smaps; >>> } >>> >>> -/* See linux-tdep.h. */ >>> +/* Helper that checks if an address is in a memory tag page for a >>> live >>> + process. */ >>> >>> -bool >>> -linux_address_in_memtag_page (CORE_ADDR address) >>> +static bool >>> +linux_process_address_in_memtag_page (CORE_ADDR address) >>> { >>> if (current_inferior ()->fake_pid_p) >>> return false; >>> @@ -1505,6 +1508,30 @@ linux_address_in_memtag_page (CORE_ADDR >>> address) >>> return false; >>> } >>> >>> +/* Helper that checks if an address is in a memory tag page for a >>> core file >>> + process. */ >>> + >>> +static bool >>> +linux_core_file_address_in_memtag_page (CORE_ADDR address) >>> +{ >>> + if (core_bfd == nullptr) >>> + return false; >>> + >>> + memtag_section_info info; >>> + return get_next_core_memtag_section (core_bfd, nullptr, address, >>> info); >>> +} >>> + >>> +/* See linux-tdep.h. */ >>> + >>> +bool >>> +linux_address_in_memtag_page (CORE_ADDR address) >>> +{ >>> + if (!target_has_execution ()) >>> + return linux_core_file_address_in_memtag_page (address); >>> + >>> + return linux_process_address_in_memtag_page (address); >>> +} >>> + >>> /* List memory regions in the inferior for a corefile. */ >>> >>> static int >>> @@ -1593,6 +1620,7 @@ linux_find_memory_regions_full (struct >>> gdbarch *gdbarch, >>> map.offset, map.inode, map.read, map.write, map.exec, >>> 1, /* MODIFIED is true because we want to dump >>> the mapping. */ >>> + map.vmflags.memory_tagging != 0, >>> map.filename.c_str (), obfd); >>> } >>> } >>> @@ -1621,12 +1649,14 @@ static int >>> linux_find_memory_regions_thunk (ULONGEST vaddr, ULONGEST size, >>> ULONGEST offset, ULONGEST inode, >>> int read, int write, int exec, int >>> modified, >>> + bool memory_tagged, >>> const char *filename, void *arg) >>> { >>> struct linux_find_memory_regions_data *data >>> = (struct linux_find_memory_regions_data *) arg; >>> >>> - return data->func (vaddr, size, read, write, exec, modified, >>> data->obfd); >>> + return data->func (vaddr, size, read, write, exec, modified, >>> memory_tagged, >>> + data->obfd); >>> } >>> >>> /* A variant of linux_find_memory_regions_full that is suitable >>> as the >>> @@ -1675,6 +1705,7 @@ static int >>> linux_make_mappings_callback (ULONGEST vaddr, ULONGEST size, >>> ULONGEST offset, ULONGEST inode, >>> int read, int write, int exec, int >>> modified, >>> + bool memory_tagged, >>> const char *filename, void *data) >>> { >>> struct linux_make_mappings_data *map_data >>> diff --git a/gdb/memtag.c b/gdb/memtag.c >>> new file mode 100644 >>> index 00000000000..af86137c49d >>> --- /dev/null >>> +++ b/gdb/memtag.c >>> @@ -0,0 +1,61 @@ >>> +/* GDB generic memory tagging functions. >>> + >>> + Copyright (C) 2022 Free Software Foundation, Inc. >>> + >>> + This file is part of GDB. >>> + >>> + This program is free software; you can redistribute it and/or >>> modify >>> + it under the terms of the GNU General Public License as >>> published by >>> + the Free Software Foundation; either version 3 of the License, >>> or >>> + (at your option) any later version. >>> + >>> + This program is distributed in the hope that it will be useful, >>> + but WITHOUT ANY WARRANTY; without even the implied warranty of >>> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >>> + GNU General Public License for more details. >>> + >>> + You should have received a copy of the GNU General Public >>> License >>> + along with this program. If not, see < >>> https://urldefense.com/v3/__http://www.gnu.org/licenses/__;!!CTRNKA9wMg0ARbw!0jBVgsoE-RaTGT098YRLfC3gcQJlvfuMujbUqmtqoh3JjeD2BI4JNxmWCGaefncNfKBbmw$ >>> >. */ >>> + >>> +#include "defs.h" >>> +#include "memtag.h" >>> +#include "bfd.h" >>> + >>> +/* See memtag.h */ >>> + >>> +bool >>> +get_next_core_memtag_section (bfd *abfd, asection *section, >>> + CORE_ADDR address, memtag_section_info >>> &info) >>> +{ >>> + /* If the caller provided no SECTION to start from, search from >>> the >>> + beginning. */ >>> + if (section == nullptr) >>> + section = bfd_get_section_by_name (abfd, "memtag"); >>> + >>> + /* Go through all the memtag sections and figure out if ADDRESS >>> + falls within one of the memory ranges that contain tags. */ >>> + while (section != nullptr) >>> + { >>> + size_t memtag_range_size = section->rawsize; >>> + size_t tags_size = bfd_section_size (section); >>> + >>> + /* Empty memory range and empty tag dump should not >>> happen. */ >>> + gdb_assert (memtag_range_size != 0); >>> + gdb_assert (tags_size != 0); >>> + >>> + CORE_ADDR start_address = bfd_section_vma (section); >>> + CORE_ADDR end_address = start_address + memtag_range_size; >>> + >>> + /* Is the address within [start_address, end_address)? */ >>> + if (address >= start_address >>> + && address < end_address) >>> + { >>> + info.start_address = start_address; >>> + info.end_address = end_address; >>> + info.memtag_section = section; >>> + return true; >>> + } >>> + section = bfd_get_next_section_by_name (abfd, section); >>> + } >>> + return false; >>> +} >>> diff --git a/gdb/memtag.h b/gdb/memtag.h >>> new file mode 100644 >>> index 00000000000..fe908c1e5e3 >>> --- /dev/null >>> +++ b/gdb/memtag.h >>> @@ -0,0 +1,50 @@ >>> +/* GDB generic memory tagging definitions. >>> + Copyright (C) 2022 Free Software Foundation, Inc. >>> + >>> + This file is part of GDB. >>> + >>> + This program is free software; you can redistribute it and/or >>> modify >>> + it under the terms of the GNU General Public License as >>> published by >>> + the Free Software Foundation; either version 3 of the License, >>> or >>> + (at your option) any later version. >>> + >>> + This program is distributed in the hope that it will be useful, >>> + but WITHOUT ANY WARRANTY; without even the implied warranty of >>> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >>> + GNU General Public License for more details. >>> + >>> + You should have received a copy of the GNU General Public >>> License >>> + along with this program. If not, see < >>> https://urldefense.com/v3/__http://www.gnu.org/licenses/__;!!CTRNKA9wMg0ARbw!0jBVgsoE-RaTGT098YRLfC3gcQJlvfuMujbUqmtqoh3JjeD2BI4JNxmWCGaefncNfKBbmw$ >>> >. */ >>> + >>> +#ifndef MEMTAG_H >>> +#define MEMTAG_H >>> + >>> +#include "bfd.h" >>> + >>> +struct memtag_section_info >>> +{ >>> + /* The start address of the tagged memory range. */ >>> + CORE_ADDR start_address; >>> + /* The final address of the tagged memory range. */ >>> + CORE_ADDR end_address; >>> + /* The section containing tags for the memory range >>> + [start_address, end_address). */ >>> + asection *memtag_section; >>> +}; >>> + >>> +/* Helper function to walk through memory tag sections in a core >>> file. >>> + >>> + Return TRUE if there is a "memtag" section containing >>> ADDRESS. Return FALSE >>> + otherwise. >>> + >>> + If SECTION is provided, search from that section onwards. If >>> SECTION is >>> + nullptr, then start a new search. >>> + >>> + If a "memtag" section containing ADDRESS is found, fill INFO >>> with data >>> + about such section. Otherwise leave it unchanged. */ >>> + >>> +bool get_next_core_memtag_section (bfd *abfd, asection *section, >>> + CORE_ADDR address, >>> + memtag_section_info &info); >>> + >>> +#endif /* MEMTAG_H */ >>> diff --git a/gdb/testsuite/gdb.arch/aarch64-mte-gcore.c >>> b/gdb/testsuite/gdb.arch/aarch64-mte-gcore.c >>> new file mode 100644 >>> index 00000000000..b20ebcff424 >>> --- /dev/null >>> +++ b/gdb/testsuite/gdb.arch/aarch64-mte-gcore.c >>> @@ -0,0 +1,93 @@ >>> +/* This test program is part of GDB, the GNU debugger. >>> + >>> + Copyright 2021 Free Software Foundation, Inc. >>> + >>> + This program is free software; you can redistribute it and/or >>> modify >>> + it under the terms of the GNU General Public License as >>> published by >>> + the Free Software Foundation; either version 3 of the License, >>> or >>> + (at your option) any later version. >>> + >>> + This program is distributed in the hope that it will be useful, >>> + but WITHOUT ANY WARRANTY; without even the implied warranty of >>> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >>> + GNU General Public License for more details. >>> + >>> + You should have received a copy of the GNU General Public >>> License >>> + along with this program. If not, see < >>> https://urldefense.com/v3/__http://www.gnu.org/licenses/__;!!CTRNKA9wMg0ARbw!0jBVgsoE-RaTGT098YRLfC3gcQJlvfuMujbUqmtqoh3JjeD2BI4JNxmWCGaefncNfKBbmw$ >>> >. */ >>> + >>> +/* Exercise AArch64's Memory Tagging Extension with tagged >>> pointers. */ >>> + >>> +/* This test was based on the documentation for the AArch64 Memory >>> Tagging >>> + Extension from the Linux Kernel, found in the sources in >>> + Documentation/arm64/memory-tagging-extension.rst. */ >>> + >>> +#include >>> +#include >>> +#include >>> +#include >>> +#include >>> +#include >>> +#include >>> + >>> +/* From arch/arm64/include/uapi/asm/hwcap.h */ >>> +#define HWCAP2_MTE (1 << 18) >>> + >>> +/* From arch/arm64/include/uapi/asm/mman.h */ >>> +#define PROT_MTE 0x20 >>> + >>> +/* From include/uapi/linux/prctl.h */ >>> +#define PR_SET_TAGGED_ADDR_CTRL 55 >>> +#define PR_GET_TAGGED_ADDR_CTRL 56 >>> +#define PR_TAGGED_ADDR_ENABLE (1UL << 0) >>> +#define PR_MTE_TCF_SHIFT 1 >>> +#define PR_MTE_TCF_SYNC (1UL << PR_MTE_TCF_SHIFT) >>> +#define PR_MTE_TAG_SHIFT 3 >>> + >>> +void >>> +access_memory (unsigned char *tagged_ptr) >>> +{ >>> + tagged_ptr[0] = 'a'; >>> +} >>> + >>> +int >>> +main (int argc, char **argv) >>> +{ >>> + unsigned char *tagged_ptr; >>> + unsigned long page_sz = sysconf (_SC_PAGESIZE); >>> + unsigned long hwcap2 = getauxval(AT_HWCAP2); >>> + >>> + /* Bail out if MTE is not supported. */ >>> + if (!(hwcap2 & HWCAP2_MTE)) >>> + return 1; >>> + >>> + /* Enable the tagged address ABI, synchronous MTE tag check >>> faults and >>> + allow all non-zero tags in the randomly generated set. */ >>> + if (prctl (PR_SET_TAGGED_ADDR_CTRL, >>> + PR_TAGGED_ADDR_ENABLE | PR_MTE_TCF_SYNC >>> + | (0xfffe << PR_MTE_TAG_SHIFT), >>> + 0, 0, 0)) >>> + { >>> + perror ("prctl () failed"); >>> + return 1; >>> + } >>> + >>> + /* Create a mapping that will have PROT_MTE set. */ >>> + tagged_ptr = mmap (0, page_sz, PROT_READ | PROT_WRITE, >>> + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); >>> + if (tagged_ptr == MAP_FAILED) >>> + { >>> + perror ("mmap () failed"); >>> + return 1; >>> + } >>> + >>> + /* Enable MTE on the above anonymous mmap. */ >>> + if (mprotect (tagged_ptr, page_sz, PROT_READ | PROT_WRITE | >>> PROT_MTE)) >>> + { >>> + perror ("mprotect () failed"); >>> + return 1; >>> + } >>> + >>> + access_memory (tagged_ptr); >>> + >>> + return 0; >>> +} >>> diff --git a/gdb/testsuite/gdb.arch/aarch64-mte-gcore.exp >>> b/gdb/testsuite/gdb.arch/aarch64-mte-gcore.exp >>> new file mode 100644 >>> index 00000000000..8a19c4b449e >>> --- /dev/null >>> +++ b/gdb/testsuite/gdb.arch/aarch64-mte-gcore.exp >>> @@ -0,0 +1,107 @@ >>> +# Copyright (C) 2018-2021 Free Software Foundation, Inc. >>> +# >>> +# This program is free software; you can redistribute it and/or >>> modify >>> +# it under the terms of the GNU General Public License as >>> published by >>> +# the Free Software Foundation; either version 3 of the License, >>> or >>> +# (at your option) any later version. >>> +# >>> +# This program is distributed in the hope that it will be useful, >>> +# but WITHOUT ANY WARRANTY; without even the implied warranty of >>> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >>> +# GNU General Public License for more details. >>> +# >>> +# You should have received a copy of the GNU General Public >>> License >>> +# along with this program. If not, see < >>> https://urldefense.com/v3/__http://www.gnu.org/licenses/__;!!CTRNKA9wMg0ARbw!0jBVgsoE-RaTGT098YRLfC3gcQJlvfuMujbUqmtqoh3JjeD2BI4JNxmWCGaefncNfKBbmw$ >>> >. >>> + >>> +# This file is part of the gdb testsuite. >>> + >>> +# Test generating and reading a core file with MTE memory tags. >>> + >>> +if {![is_aarch64_target]} { >>> + verbose "Skipping ${gdb_test_file_name}." >>> + return >>> +} >>> + >>> +standard_testfile >>> +if { [prepare_for_testing "failed to prepare" ${testfile} >>> ${srcfile}] } { >>> + return -1 >>> +} >>> + >>> +if ![runto_main] { >>> + untested "could not run to main" >>> + return -1 >>> +} >>> + >>> +# Targets that don't support memory tagging should not execute the >>> +# runtime memory tagging tests. >>> +if {![supports_memtag]} { >>> + unsupported "memory tagging unsupported" >>> + return -1 >>> +} >>> + >>> +gdb_breakpoint "access_memory" >>> + >>> +if [gdb_continue "access_memory"] { >>> + return -1 >>> +} >>> + >>> +# Set each tag granule to a different tag value, from 0x0 to 0xf. >>> +set atag_msg "Allocation tag\\(s\\) updated successfully\." >>> +for {set i 15} {$i >= 0} {incr i -1} { >>> + set index [expr [expr 15 - $i] * 16] >>> + set tag [format "%02x" $i] >>> + gdb_test "memory-tag set-allocation-tag &tagged_ptr\[$index\] >>> 1 $tag" \ >>> + $atag_msg \ >>> + "set memory tag of &tagged_ptr\[$index\] to $tag" >>> +} >>> + >>> +# Run until a crash and confirm GDB displays memory tag violation >>> +# information. >>> +gdb_test "continue" \ >>> + [multi_line \ >>> + "Program received signal SIGSEGV, Segmentation fault" \ >>> + "Memory tag violation while accessing address $hex" \ >>> + "Allocation tag $hex" \ >>> + "Logical tag $hex\." \ >>> + "$hex in access_memory \\(.*\\) at .*" \ >>> + ".*tagged_ptr\\\[0\\\] = 'a';"] \ >>> + "display tag violation information for live process" >>> + >>> +# Generate the core file. >>> +set core_filename [standard_output_file "$testfile.core"] >>> +set core_generated [gdb_gcore_cmd "$core_filename" "generate core >>> file"] >>> + >>> +if { !$core_generated } { >>> + return -1 >>> +} >>> + >>> +clean_restart $binfile >>> + >>> +# Load the core file and make sure we see the tag violation fault >>> +# information. >>> +gdb_test "core $core_filename" \ >>> + [multi_line \ >>> + "Core was generated by.*\." \ >>> + "Program terminated with signal SIGSEGV, Segmentation fault" \ >>> + "Memory tag violation while accessing address $hex" \ >>> + "Allocation tag 0xf" \ >>> + "Logical tag 0x0\." \ >>> + "#0.*$hex in access_memory \\(.*\\) at .*" \ >>> + ".*tagged_ptr\\\[0\\\] = 'a';"] \ >>> + "core file shows tag violation information" >>> + >>> +# Make sure we have the tag_ctl register. >>> +gdb_test "info register tag_ctl" \ >>> + "tag_ctl.*$hex.*${::decimal}" \ >>> + "tag_ctl is available" >>> + >>> +# Check if the tag granules have the expected values. If they do, >>> that >>> +# means the core file saved the tags properly and GDB has read >>> them >>> +# correctly. >>> +for {set i 15} {$i >= 0} {incr i -1} { >>> + set index [expr [expr 15 - $i] * 16] >>> + set tag [format "%x" $i] >>> + gdb_test "memory-tag print-allocation-tag >>> &tagged_ptr\[$index\]" \ >>> + "= 0x$tag" \ >>> + "memory tag of &tagged_ptr\[$index\] is correct" >>> +} >