From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from EUR05-AM6-obe.outbound.protection.outlook.com (mail-am6eur05on2065.outbound.protection.outlook.com [40.107.22.65]) by sourceware.org (Postfix) with ESMTPS id 9B6AC3AAB000 for ; Thu, 24 Jun 2021 14:00:54 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 9B6AC3AAB000 Received: from AM6P194CA0084.EURP194.PROD.OUTLOOK.COM (2603:10a6:209:8f::25) by DB9PR08MB6457.eurprd08.prod.outlook.com (2603:10a6:10:23e::17) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4242.18; Thu, 24 Jun 2021 14:00:51 +0000 Received: from AM5EUR03FT004.eop-EUR03.prod.protection.outlook.com (2603:10a6:209:8f:cafe::21) by AM6P194CA0084.outlook.office365.com (2603:10a6:209:8f::25) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4264.18 via Frontend Transport; Thu, 24 Jun 2021 14:00:51 +0000 X-MS-Exchange-Authentication-Results: spf=pass (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=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; Received: from 64aa7808-outbound-1.mta.getcheckrecipient.com (63.35.35.123) by AM5EUR03FT004.mail.protection.outlook.com (10.152.16.163) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4264.18 via Frontend Transport; Thu, 24 Jun 2021 14:00:51 +0000 Received: ("Tessian outbound 7799c3c2ab28:v96"); Thu, 24 Jun 2021 14:00:50 +0000 X-CheckRecipientChecked: true X-CR-MTA-CID: cfe993e2e5431c6c X-CR-MTA-TID: 64aa7808 Received: from bf0ee1bfb6ec.1 by 64aa7808-outbound-1.mta.getcheckrecipient.com id E4E7BF15-827E-406A-AEA0-B508D00E0ED7.1; Thu, 24 Jun 2021 14:00:07 +0000 Received: from EUR05-AM6-obe.outbound.protection.outlook.com by 64aa7808-outbound-1.mta.getcheckrecipient.com with ESMTPS id bf0ee1bfb6ec.1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384); Thu, 24 Jun 2021 14:00:07 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=WwLEfvhrULkEnxHm8/jiIrxqEswUCTKCcwmxJ5sA2M2DHxM3g9eUoP6mddqA7dubbJZxUY36YNw+Y0+5IFEyKPVPJH3gODVbehDpjxPUh7L5r54n8tH7SqdY2U8lxzH2Kjl5dpnfpT7MvHozGPreJUHbuceSWi0K49/sSxIhkYvBxaeuUGMpwh5d7QDNFlMEwmQrojwOV6AoBxBWhDx5gfzL94kXJuPySbQoUeytnEnmUISpWFA14mhIusBaC1t+pYtmMOFVdJXlq+Odurk2OVg8lVLqczoBMiAOWpvZcUVN8KoDl8gkgVZDyAdL0plVvGYyM/5b5fJA2fNtARhqRw== 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=PkzJv/T9hoPYcDll6+e6O/C36YBx1fy38pDJg0iDVOA=; b=MfeHDhsTGsEwa/at5mqoZb6hWknbq2gx6j6s8M57WWrxoJj3GTZzj5T+qCuf3tPWqCP9LGVdP+J0a6x0dfsIY+XsJYdQRHltoHbWZA2k7b4UTmymOjghxV7dlLAe7IctOasSEOwBy8G5HXkB4ftSgj7YNL9cJGVYBt2vNSV7zhQx2TnQ2Kv/4er58p3dVgDEAPWjTbI6vyKNs6X1yXFhlxk8qzbNXNERrAhGdjCXKQ31kPtYY8N6vDZ2goZhVirJIBMqWsuCEMKhvPJJhxwzSkxvldb+KW6vTIkkIn/YMwc4bnWj+2eof3LHTiuDuMfzWyYtjCk4VfUgTGrB1d+cWw== 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 Received: from AM6PR08MB3957.eurprd08.prod.outlook.com (2603:10a6:20b:a2::14) by AM5PR0801MB1842.eurprd08.prod.outlook.com (2603:10a6:203:3c::19) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4264.18; Thu, 24 Jun 2021 14:00:06 +0000 Received: from AM6PR08MB3957.eurprd08.prod.outlook.com ([fe80::2ddf:ff23:4d65:c35]) by AM6PR08MB3957.eurprd08.prod.outlook.com ([fe80::2ddf:ff23:4d65:c35%7]) with mapi id 15.20.4242.023; Thu, 24 Jun 2021 14:00:05 +0000 From: Alan Hayward To: Luis Machado CC: "gdb-patches\\@sourceware.org" , Simon Marchi , "jhb@freebsd.org" , "david.spickett@linaro.org" , Catalin Marinas Subject: Re: [PATCH,v5][AArch64] MTE corefile support Thread-Topic: [PATCH,v5][AArch64] MTE corefile support Thread-Index: AQHXVw3u8p4jXheddkKwkmsJmFa2rasjVFmA Date: Thu, 24 Jun 2021 14:00:05 +0000 Message-ID: References: <20210518202047.3492211-1-luis.machado@linaro.org> <20210601174519.4157316-1-luis.machado@linaro.org> In-Reply-To: <20210601174519.4157316-1-luis.machado@linaro.org> Accept-Language: en-GB, en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-mailer: Apple Mail (2.3654.100.0.2.22) Authentication-Results-Original: linaro.org; dkim=none (message not signed) header.d=none;linaro.org; dmarc=none action=none header.from=arm.com; x-originating-ip: [82.24.190.200] x-ms-publictraffictype: Email X-MS-Office365-Filtering-Correlation-Id: d7a20ad0-e38e-4037-1ffb-08d9371879fb x-ms-traffictypediagnostic: AM5PR0801MB1842:|DB9PR08MB6457: x-ms-exchange-transport-forked: True X-Microsoft-Antispam-PRVS: x-checkrecipientrouted: true nodisclaimer: true x-ms-oob-tlc-oobclassifiers: OLM:3826;OLM:3826; X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam-Untrusted: BCL:0; X-Microsoft-Antispam-Message-Info-Original: y3eZ6FtB7r5E4C8I7xswDXr8HcCHfZYlXAxC28Sh0ahEF8EKdDOFYK48TT1yjb2AqWr8i+bwitv+Z7ARU9n8HXxFIaZBMb0wnzelnoiNvEybujPshVHuPZBajhbzgdAf70pH5gmzxN4Bx+G3iJkY3cwCbmogJzs5/1uJhT7kwBR12oBR6gF7mPFZDXLpQWFvxXSHCX84QyF34W5vij3EgaCg7/Wke5l95qBWBEqmravoxLu6058a387cOz1ciiwjmoGfGim4Q5AUx4OkXhADfqAJ5UakP2YCjlI0wSzMJTNLvw55AJutYtdfmYxJj3Vz2HPLzhj+ZIYIHbovS0U1WLdMG6eiXmdzjwqKMzYPHom4GlQ7o8agYY+wakCcjffymqngmfRrOh3pB4qy51etsujulrloD0WGATv6gGM1Zehll8YV2edfy3yOd2713L7ZSru8xQpqSJgw0Zzr8YUYbmlwB4QKBQEa61UXF16PD3RQjgvO2temgU4wH0GrL4i1QPnXDnX/PfY79p4BRuKw4vJJylFOivX5SP0qj9bA9ik4O41atb+8tp4PMgkAR6BuVa9GjV6h6dfzqiNd/njLbi/6X5/b6u0rgqYZ4CWiluRWQkwPHRrfMG3616D6pcUSE+n2A5Z3z+hONQ6jMCYUsCCxvbXwyX3R9T2T+RqqPUQJvuZ9+6o7icNTR62jtJgFbkCDAH35uqv8raNnU0/94LC+QvpXfPDAEETsTgQdn12Ei5H741VEdxn/3FqDJJDGgbJpLq1ATBAlCw5XOr/So2Vqg3pQh7RleXp8z8ndy1R5itNm8DzrW7D1c1OXi6DkoSHndwHYYByAIfTd8hVIiA== X-Forefront-Antispam-Report-Untrusted: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:AM6PR08MB3957.eurprd08.prod.outlook.com; PTR:; CAT:NONE; SFS:(4636009)(376002)(366004)(136003)(39850400004)(346002)(396003)(6512007)(6916009)(316002)(71200400001)(122000001)(54906003)(4326008)(38100700002)(5660300002)(36756003)(478600001)(30864003)(2616005)(83380400001)(91956017)(6506007)(33656002)(8676002)(86362001)(66556008)(66476007)(66946007)(53546011)(8936002)(64756008)(66446008)(26005)(76116006)(6486002)(186003)(2906002)(45980500001)(559001)(579004); DIR:OUT; SFP:1101; x-ms-exchange-antispam-messagedata-chunkcount: 1 x-ms-exchange-antispam-messagedata-0: =?us-ascii?Q?278aVrd2HX/Xr72y7SenSbfBkDYGf0nHr9HU0vGtniE/khiP0D6v3cpyAu+V?= =?us-ascii?Q?1MaEGARmPLSfdiUOR/Mgg1Pf5zZS9o+EhyBLeujU1q87qY2LIsOIjshdqsgG?= =?us-ascii?Q?Eq6G6Lyy1PtT4bXrLFuF13FhN1cTMYnWhzUpJjrEbBYk6P2ZPH69n1Zre5Ri?= =?us-ascii?Q?gGbDU7JkRWa/g3eR1sDRUOQ64TbO/lk/VVUmcQwVgiqBmKRGTm/IyCAbuJAR?= =?us-ascii?Q?eDuVGQ0Zlrj8UWY0wvP5iHqIIFDRk030qLWNaUO8juLUd6KXkErnSsNvAde+?= =?us-ascii?Q?em8H6Td+wZulernYhKAkgIqEp2QBWjdnjI8FN6DC8z0nJjA1lqjABVwcGzq7?= =?us-ascii?Q?5ix+81vevgtFifQI5XlswFpkVwBMzS4Vs4FxotjTXZpIS9UAVyABG5CcWkTC?= =?us-ascii?Q?JweMQzJxb18vkZkvQnJJ52Tm6ryyA/JZVydDiZznUBPpeliAsCGimhh/y+CS?= =?us-ascii?Q?JtldOK8yLfwX/lNl/iWNlqfkoxKV9QB/4v+kKcjEF8alu1rQW3jA4h0tZyVt?= =?us-ascii?Q?3vNipzBnm06Zj8gfuO99Oa82lpJXsjtW+NbcgekjLYpMCIhnyXf5q+Z2NfiG?= =?us-ascii?Q?sgFG/8DC82M9yFh8Zxmbu5u+/GTBUxzapU2LkXVhTfgf+NpwfCErSy977JnM?= =?us-ascii?Q?aR4GWmvSrFV0f1uJOT9lw2WmEw0bX1lAiO+YVV6WNj7gF6kh5gKPQ6miM6h4?= =?us-ascii?Q?TR2vkJGXA5SmnsEr8X+1122r7aQBROY1kjB+OkIMtqP8Bwo7iQTuwic72OAZ?= =?us-ascii?Q?9dKMg0I697qjbvt5zq8JkP8DNJMosmV6+Jvl5rGrFAAg/pnsf3aVlDSCV4OL?= =?us-ascii?Q?UoxUPgNT6o96V/+eL0JaAihJNoYLV8NR5WkFxImeiknY8VwAC4lWgoP3va3C?= =?us-ascii?Q?C5ivw1SGrMFlbx24lHb1Utd0p8kvwsrfpKof272pJznN6tfVXivGoE/0Q6TP?= =?us-ascii?Q?Ai3M2Uanzd4xio0Apc2CWXp6wBqWLDSRW/OtgWVVJSbcjYaCRt7dfAofqz9Q?= =?us-ascii?Q?W2Os0ll7ZUDwGpQ8wDvIWHaAiQlQ/wRXL09+9Zz3/7VnwUEooManju/FK/Py?= =?us-ascii?Q?/6gtSg7crMoiSeH4Qd+ljZ3kpXJ9qa+F1vu1chMP9u6z8azbDcWWNsW50gbE?= =?us-ascii?Q?czlewEzz3X8q1m8boH2OPRJJfum4bXaO57UMmow8XrUuTOWO6rzwVqJReDX1?= =?us-ascii?Q?tawKJS3wv5PMZT2PBZTKIZrvmTcTtN9yQJv6xKfgXTJH0eehTILQOYd9MAv2?= =?us-ascii?Q?gD/dMMj2FPJUtdvVOR2DQyHkqGCkLISTMCdu/29CS6JL4BOFnfRunj55BnHj?= =?us-ascii?Q?ePn1Li5f9COx4cL26iotlMhG?= Content-Type: text/plain; charset="us-ascii" Content-ID: Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 X-MS-Exchange-Transport-CrossTenantHeadersStamped: AM5PR0801MB1842 Original-Authentication-Results: linaro.org; dkim=none (message not signed) header.d=none;linaro.org; dmarc=none action=none header.from=arm.com; X-EOPAttributedMessage: 0 X-MS-Exchange-Transport-CrossTenantHeadersStripped: AM5EUR03FT004.eop-EUR03.prod.protection.outlook.com X-MS-Office365-Filtering-Correlation-Id-Prvs: 3e63299b-2637-497b-52f3-08d937185e75 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: yLq+/r4YIbd6menOyaMB9ncp4zoNtxNUoplJVZZf0eAvFXdfI9XbLi6WFYwg5aB7KNNCHuOS7RWT17tvNdv+AUhcUt+CU2llV7auxyfxwsWVmha4lqQBFvIia2G8NIB1UT8pSJvjPBfOpccnY6Nrs716ApdDdEgg2XibNwpOP0q9UZp+NBLJKzCsA+yk5CV3tVKz1jJw5wkauECLLdUtGFEWn4kXsioCVtdISJTakSpd+ntYbxPR2NVHKmd0tnZhcK4FBaGOVQrnDd2r6neLvqUTrwqp3lqYVpcK2xygW9M9Tf8NDAVM+3FEDEyTyOx/oh6HyoYhltbvNYxwZ081IJg09sB3jyQbi7pX+kfcMak68iuMiCxt0Y1AbieNaZPSuZpYn8oN9geqgDtmKE1xvcLNIVssfiW2x7uCz6LyPYq16Ye/RzfRRlhUZjUGUL0xVY2gGwZdAUxHowxXk/W64KgETm6srNOVscZ/moKWjgDClZVC+UF9gRARanJ90MxTjUyeZOTeknS63kQtfiqgFOYive7FuWHAITfBJq2WQMw8BRz1/nc3n+8Sqt0Wzr2EZe04871S9x8cNTC8n8WypepCH5uUaupAImxlTw7f1foW/5Ztcv/42Nqb3haHipMsdd1oH+2JPLb9KCSeyFqm8DP1k65pIU5zx+5quUuK8hLFsnmCeEYh4wWO5uMeHF9UPjLO1JAiMmuN8TWyLPdG5w9fD/ub2hJyt6oPM2Imzd4u6sIROkltT8A3FOWNXonjok24zfevHpVwRSEMlT2QczSc2ofJRBni0W0/9rr7/mDngCTs+ZfEQ/fwdrh7oh85wqCsWqBNGkf/t4vFr+geRxHvLjsc1hupNhXQbhWA03w= 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:(4636009)(396003)(346002)(136003)(39840400004)(376002)(36840700001)(46966006)(316002)(6486002)(36860700001)(86362001)(54906003)(33656002)(26005)(186003)(8936002)(2906002)(8676002)(81166007)(4326008)(2616005)(356005)(5660300002)(336012)(83380400001)(47076005)(478600001)(30864003)(70586007)(6506007)(6862004)(6512007)(53546011)(36756003)(70206006)(82310400003)(2004002)(579004); DIR:OUT; SFP:1101; X-OriginatorOrg: arm.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 24 Jun 2021 14:00:51.4039 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: d7a20ad0-e38e-4037-1ffb-08d9371879fb 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: AM5EUR03FT004.eop-EUR03.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: DB9PR08MB6457 X-Spam-Status: No, score=-14.3 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H2, SPF_HELO_PASS, SPF_PASS, TXREP, UNPARSEABLE_RELAY autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) 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: Thu, 24 Jun 2021 14:01:04 -0000 > On 1 Jun 2021, at 18:45, Luis Machado wrote: >=20 > Updates on v5: >=20 > - Fixed format warning output. >=20 > Updates on v4: >=20 > - Calculate sizes based on individual struct field sizes. >=20 > Updates on v3: >=20 > - Addressed review comments. > - New files gdbsupport/memtag.h, gdb/memtag.h and gdb/memtag.c. > - Updated code documentation. > - Removed code duplication. >=20 > Updates on v2: >=20 > - Reworked core_target::fetch_memtags to handle cases where address + len= runs > over the NT_MEMTAG note. > - Turned a few magic numbers into constants. There is an unfortunate dupl= ication > of a constant (NT_MEMTAG_HEADER_SIZE). It is a generic constant, but the= re is > no file generic enough that gets included by both corelow and linux-tdep= . > - More sanity checks to make sure the note format is correct. > - Documented aarch64_linux_decode_memtag_note a little more. >=20 > --- >=20 > Teach GDB how to dump memory tags when using the gcore command and how > to read them back from a core file generated via gcore or the kernel. >=20 > Each tagged memory range (listed in /proc//smaps) gets dumped to its > own NT_MEMTAG note. A section named ".memtag" is created for each of thos= e > when reading the core file back. >=20 > Dumping memory tags > - >=20 > When using the gcore command to dump a core file, GDB will go through the= maps > in /proc//smaps looking for tagged ranges. Each of those entries get= s > passed to an arch-specific gdbarch hook that generates a vector of blobs = of > memory tag data that are blindly put into a NT_MEMTAG note. >=20 > The vector is used because we may have, in the future, multiple tag type= s for > a particular memory range. >=20 > Each of the NT_MEMTAG notes have a generic header and a arch-specific hea= der, > like so: >=20 > struct tag_dump_header > { > uint16_t format; // Only NT_MEMTAG_TYPE_AARCH_MTE at present > uint64_t start_vma; > uint64_t end_vma; > }; >=20 > struct tag_dump_mte > { > uint16_t granule_byte_size; > uint16_t tag_bit_size; > uint16_t __unused; > }; >=20 > The only bits meant to be generic are the tag_dump_format, start_vma and > end_vma fields. >=20 > The format-specific data is supposed to be opaque and only useful for the > arch-specific code. >=20 > We can extend the format in the future to make room for other memory tag > layouts. >=20 > Reading memory tags > - >=20 > When reading a core file that contains NT_MEMTAG entries, GDB will use > a different approach to check for tagged memory range. Rather than lookin= g > at /proc//smaps, it will now look for ".memtag" sections with the ri= ght > memory range. >=20 > When reading tags, GDB will now use the core target's implementation of > fetch_memtags (store_memtags doesn't exist for core targets). Then the da= ta > is fed into an arch-specific hook that will decode the memory tag format = and > return a vector of tags. >=20 > I've added a test to exercise writing and reading of memory tags in core > files. >=20 > gdb/ChangeLog: >=20 > YYYY-MM-DD Luis Machado >=20 > * Makefile.in (COMMON_SFILES): Add memtag.c. > * NEWS: Mention core file support for memory tagging. > * aarch64-linux-tdep.c: Include elf/common.h. > Include gdbsupport/memtag.h. > (MAX_TAGS_TO_TRANSFER): New constant. > (aarch64_linux_create_memtag_notes_from_range): New function. > (aarch64_linux_decode_memtag_note): Likewise. > (aarch64_linux_init_abi): Register new core file hooks. > (NT_MEMTAG_TOTAL_HEADER_SIZE): New constant. > * arch/aarch64-mte-linux.h (tag_dump_mte): New struct. > (AARCH64_MTE_TAG_BIT_SIZE): New constant. > * corelow.c: Include gdbsupport/memtag.h and memtag.h. > (core_target) : New > method overrides. > * gdbarch.c: Regenerate. > * gdbarch.h: Likewise. > * gdbarch.sh (create_memtag_notes_from_range): New hook. > (decode_memtag_note): Likewise. > * linux-tdep.c: Include gdbsupport/memtag.h and memtag.h. > (linux_address_in_memtag_page): Renamed to... > (linux_process_address_in_memtag_page): ... this. > (linux_core_file_address_in_memtag_page): New function. > (linux_address_in_memtag_page): Likewise. > (linux_make_memtag_corefile_notes): Likewise. > (linux_make_corefile_notes): Handle memory tag notes. > * memtag.c: New file. > * memtag.h: New file. >=20 > gdb/doc/ChangeLog: >=20 > YYYY-MM-DD Luis Machado >=20 > * gdb.texinfo (AArch64 Memory Tagging Extension): Mention support > for memory tagging in core files. >=20 > gdb/testsuite/ChangeLog: >=20 > YYYY-MM-DD Luis Machado >=20 > * gdb.arch/aarch64-mte-gcore.c: New file. > * gdb.arch/aarch64-mte-gcore.exp: New file. >=20 > gdbsupport/ChangeLog: >=20 > YYYY-MM-DD Luis Machado >=20 > * memtag.h: New file. > --- > gdb/Makefile.in | 1 + > gdb/NEWS | 4 + > gdb/aarch64-linux-tdep.c | 221 +++++++++++++++++++ > gdb/arch/aarch64-mte-linux.h | 17 ++ > gdb/corelow.c | 63 ++++++ > gdb/doc/gdb.texinfo | 4 + > gdb/gdbarch.c | 64 ++++++ > gdb/gdbarch.h | 16 ++ > gdb/gdbarch.sh | 6 + > gdb/linux-tdep.c | 97 +++++++- > gdb/memtag.c | 88 ++++++++ > gdb/memtag.h | 46 ++++ > gdb/testsuite/gdb.arch/aarch64-mte-gcore.c | 93 ++++++++ > gdb/testsuite/gdb.arch/aarch64-mte-gcore.exp | 111 ++++++++++ > gdbsupport/memtag.h | 39 ++++ > 15 files changed, 867 insertions(+), 3 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 > create mode 100644 gdbsupport/memtag.h >=20 Note there were a few minor merge conflicts, nothing to worry about though. > diff --git a/gdb/Makefile.in b/gdb/Makefile.in > index f664d964536..12fb3b390b1 100644 > --- a/gdb/Makefile.in > +++ b/gdb/Makefile.in > @@ -1100,6 +1100,7 @@ COMMON_SFILES =3D \ > memattr.c \ > memory-map.c \ > memrange.c \ > + memtag.c \ > minidebug.c \ > minsyms.c \ > mipsread.c \ > diff --git a/gdb/NEWS b/gdb/NEWS > index ab678acec8b..58b9f739d4f 100644 > --- a/gdb/NEWS > +++ b/gdb/NEWS > @@ -3,6 +3,10 @@ >=20 > *** Changes since GDB 10 >=20 > +* GDB now supports dumping memory tag data for AArch64 MTE. It also sup= ports > + reading memory tag data for AArch64 MTE from core files generated by > + the gcore command or the Linux kernel. > + > * GDB now supports general memory tagging functionality if the underlying > architecture supports the proper primitives and hooks. Currently this = is > enabled only for AArch64 MTE. > diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c > index e9761ed2189..04498f3b6c0 100644 > --- a/gdb/aarch64-linux-tdep.c > +++ b/gdb/aarch64-linux-tdep.c > @@ -52,6 +52,9 @@ > #include "value.h" >=20 > #include "gdbsupport/selftest.h" > +#include "gdbsupport/memtag.h" > + > +#include "elf/common.h" >=20 > /* Signal frame handling. >=20 > @@ -1779,6 +1782,213 @@ aarch64_linux_report_signal_info (struct gdbarch = *gdbarch, > } > } >=20 > +/* Memory tag note header size. Includes both the generic and the > + arch-specific parts. */ > +#define NT_MEMTAG_TOTAL_HEADER_SIZE (NT_MEMTAG_GENERIC_HEADER_SIZE \ > + + NT_MEMTAG_MTE_HEADER_SIZE) > + > +/* Maximum number of tags to request. */ > +#define MAX_TAGS_TO_TRANSFER 1024 > + > +/* AArch64 Linux implementation of the aarch64_create_memtag_notes_from_= range > + gdbarch hook. Create core file notes for memory tags. */ > + > +static std::vector > +aarch64_linux_create_memtag_notes_from_range (struct gdbarch *gdbarch, > + CORE_ADDR start_address, > + CORE_ADDR end_address) > +{ > + /* We only handle MTE tags for now. */ > + > + /* Figure out how many tags we need to store in this memory range. */ > + size_t granules =3D aarch64_mte_get_tag_granules (start_address, > + end_address - start_address, > + AARCH64_MTE_GRANULE_SIZE); > + > + /* Vector of memory tag notes. Add the MTE note (we only have MTE tags > + at the moment). */ > + std::vector notes (1); > + > + /* If there are no tag granules to fetch, just return. */ > + if (granules =3D=3D 0) > + return notes; > + > + /* Adjust the MTE note size to hold the header + tags. */ > + notes[0].resize (NT_MEMTAG_TOTAL_HEADER_SIZE + granules); Should this be NT_MEMTAG_TOTAL_HEADER_SIZE + (granules * AARCH64_MTE_GRANUL= E_SIZE) Get_granules has already divided by the granule size. > + > + CORE_ADDR address =3D 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 > + =3D (granules >=3D 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))); > + notes.resize (0); If you do the original resize after the while loop, then there would be no = need to resize here. > + return notes; > + } > + > + /* 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 -=3D tags_read.size (); > + address +=3D tags_read.size () * AARCH64_MTE_GRANULE_SIZE; > + } > + > + /* Create the header. */ > + enum bfd_endian byte_order =3D gdbarch_byte_order (gdbarch); > + gdb_byte *buf =3D notes[0].data (); > + > + /* Generic header. */ > + /* Tag dump format */ > + store_unsigned_integer (buf, sizeof (tag_dump_header::format), > + byte_order, NT_MEMTAG_TYPE_AARCH_MTE); > + buf +=3D sizeof (tag_dump_header::format); > + > + /* Start address */ > + store_unsigned_integer (buf, sizeof (tag_dump_header::start_vma), > + byte_order, start_address); > + buf +=3D sizeof (tag_dump_header::start_vma); > + > + /* End address */ > + store_unsigned_integer (buf, sizeof (tag_dump_header::end_vma), > + byte_order, end_address); > + buf +=3D sizeof (tag_dump_header::end_vma); > + > + /* MTE-specific header. */ > + /* Granule byte size */ > + store_unsigned_integer (buf, sizeof (tag_dump_mte::granule_byte_size), > + byte_order, AARCH64_MTE_GRANULE_SIZE); > + buf +=3D sizeof (tag_dump_mte::granule_byte_size); > + > + /* Tag bit size */ > + store_unsigned_integer (buf, sizeof (tag_dump_mte::tag_bit_size), > + byte_order, AARCH64_MTE_TAG_BIT_SIZE); > + buf +=3D sizeof (tag_dump_mte::tag_bit_size); > + > + /* Unused value */ > + store_unsigned_integer (buf, sizeof (tag_dump_mte::__unused), byte_ord= er, 0); > + > + /* Store the tags. */ > + memcpy (notes[0].data () + NT_MEMTAG_TOTAL_HEADER_SIZE, tags.data (), > + tags.size ()); > + > + return notes; > +} > + > +/* AArch64 Linux implementation of the decode_memtag_note gdbarch > + hook. Decode a memory tag note and return the requested tags. > + > + The note is guaranteed to cover the [ADDRESS, ADDRESS + length) > + range. */ > + > +static gdb::byte_vector > +aarch64_linux_decode_memtag_note (struct gdbarch *gdbarch, > + gdb::array_view note, > + CORE_ADDR address, size_t length) > +{ > + gdb::byte_vector tags; > + > + /* Sanity check. */ > + if (note.size () < NT_MEMTAG_TOTAL_HEADER_SIZE) > + { > + warning (_("Malformed core note - too short for MTE header.\n" > + "Expected %s bytes but got %s bytes."), > + pulongest (NT_MEMTAG_TOTAL_HEADER_SIZE), > + pulongest (note.size ())); > + return tags; > + } > + > + /* The amount of memory tag granules we need to fetch. */ > + size_t granules > + =3D aarch64_mte_get_tag_granules (address, length, AARCH64_MTE_GRANU= LE_SIZE); > + > + /* If there are no tag granules to decode, just return. */ > + if (granules =3D=3D 0) > + return tags; > + > + /* Read the generic header. */ > + enum bfd_endian byte_order =3D gdbarch_byte_order (gdbarch); > + const gdb_byte *buf =3D note.data (); > + > + unsigned int format > + =3D extract_unsigned_integer (buf, sizeof (tag_dump_header::format), > + byte_order); > + buf +=3D sizeof (tag_dump_header::format); > + > + CORE_ADDR start_vma > + =3D extract_unsigned_integer (buf, sizeof (tag_dump_header::start_vm= a), > + byte_order); > + buf +=3D sizeof (tag_dump_header::start_vma); > + > + CORE_ADDR end_vma > + =3D extract_unsigned_integer (buf, sizeof (tag_dump_header::end_vma)= , > + byte_order); > + buf +=3D sizeof (tag_dump_header::end_vma); > + > + /* Validate that ADDRESS + LENGTH doesn't fall outside of this note's > + range of addresses. */ > + gdb_assert (address + length < end_vma); > + > + /* Is the tag header format correct for this note? */ > + if (format !=3D NT_MEMTAG_TYPE_AARCH_MTE) > + { > + warning (_("Unexpected memory tag note format.\n" > + "Expected %x but got %x."), NT_MEMTAG_TYPE_AARCH_MTE, > + format); > + return tags; > + } > + > + size_t expected_tag_bytes =3D (end_vma - start_vma)/AARCH64_MTE_GRANUL= E_SIZE; > + > + /* Does the number of tag bytes in this note match the expected number > + of tag bytes the note says it has? */ > + if (note.size () < (NT_MEMTAG_TOTAL_HEADER_SIZE + expected_tag_bytes)) > + { > + warning (_("Unexpected tag data size.\n" > + "Expected %s but got %s."), pulongest (expected_tag_bytes), > + pulongest (note.size () - NT_MEMTAG_TOTAL_HEADER_SIZE)); > + return tags; > + } > + > + /* Calculate how many granules we need to skip to get to the granule o= f > + ADDRESS. Align both the start address and the requested address > + so it is easier to get the number of granules to skip. This way we > + don't need to consider cases where ADDRESS falls in the middle of a > + tag granule range. */ > + CORE_ADDR aligned_start_address > + =3D align_down (start_vma, AARCH64_MTE_GRANULE_SIZE); > + CORE_ADDR aligned_address =3D align_down (address, AARCH64_MTE_GRANULE= _SIZE); > + > + size_t skipped_granules > + =3D aarch64_mte_get_tag_granules (aligned_start_address, > + aligned_address - aligned_start_address, > + AARCH64_MTE_GRANULE_SIZE); > + > + /* Point to the block of data that contains the first granule we are > + interested in. */ > + const gdb::array_view tags_data > + =3D note.slice (NT_MEMTAG_TOTAL_HEADER_SIZE + skipped_granules, gran= ules); > + > + /* Read the tag granules. */ > + for (size_t i =3D 0; i < granules; i++) > + tags.push_back (tags_data[i]); > + > + return tags; > +} > + > static void > aarch64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch= ) > { > @@ -1862,6 +2072,17 @@ aarch64_linux_init_abi (struct gdbarch_info info, = struct gdbarch *gdbarch) >=20 > set_gdbarch_report_signal_info (gdbarch, > aarch64_linux_report_signal_info); > + > + /* Core file helpers. */ > + > + /* Core file helper to create memory tag notes for a particular ra= nge of > + addresses. */ > + set_gdbarch_create_memtag_notes_from_range > + (gdbarch, aarch64_linux_create_memtag_notes_from_range); > + > + /* Core file helper to decode a memory tag note. */ > + set_gdbarch_decode_memtag_note (gdbarch, > + aarch64_linux_decode_memtag_note); > } >=20 > /* Initialize the aarch64_linux_record_tdep. */ > diff --git a/gdb/arch/aarch64-mte-linux.h b/gdb/arch/aarch64-mte-linux.h > index 2aa97eb861a..7da9de4aefb 100644 > --- a/gdb/arch/aarch64-mte-linux.h > +++ b/gdb/arch/aarch64-mte-linux.h > @@ -32,6 +32,7 @@ >=20 > /* 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 >=20 > @@ -71,4 +72,20 @@ extern CORE_ADDR aarch64_mte_set_ltag (CORE_ADDR addre= ss, CORE_ADDR tag); > It is always possible to get the logical tag. */ > extern CORE_ADDR aarch64_mte_get_ltag (CORE_ADDR address); >=20 > +/* NT_MEMTAG header for MTE tags. */ > +struct tag_dump_mte > +{ > + /* Size of the tag granule in bytes. */ > + uint16_t granule_byte_size; > + /* Size of the tag in bits. */ > + uint16_t tag_bit_size; > + /* Reserved field for the future. */ > + uint16_t __unused; > +}; > + > +/* Size of the MTE header for a NT_MEMTAG note. */ > +#define NT_MEMTAG_MTE_HEADER_SIZE (sizeof (tag_dump_mte::granule_byte_si= ze) \ > + + sizeof (tag_dump_mte::tag_bit_size) \ > + + sizeof (tag_dump_mte::__unused)) > + > #endif /* ARCH_AARCH64_LINUX_H */ > diff --git a/gdb/corelow.c b/gdb/corelow.c > index 452b4dd4f9a..24c5bf29a11 100644 > --- a/gdb/corelow.c > +++ b/gdb/corelow.c > @@ -51,6 +51,8 @@ > #include "gdbcmd.h" > #include "xml-tdesc.h" > #include "observable.h" > +#include "gdbsupport/memtag.h" > +#include "memtag.h" >=20 > #ifndef O_LARGEFILE > #define O_LARGEFILE 0 > @@ -100,6 +102,13 @@ class core_target final : public process_stratum_tar= get >=20 > bool info_proc (const char *, enum info_proc_what) override; >=20 > + bool supports_memory_tagging () override; > + > + /* Core file implementation of fetch_memtags. Fetch the memory tags f= rom > + core file notes. */ > + bool fetch_memtags (CORE_ADDR address, size_t len, > + gdb::byte_vector &tags, int type) override; > + > /* A few helpers. */ >=20 > /* Getter, see variable definition. */ > @@ -1115,6 +1124,60 @@ core_target::info_proc (const char *args, enum inf= o_proc_what request) > return true; > } >=20 > +/* Implementation of the "supports_memory_tagging" target_ops method. *= / > + > +bool > +core_target::supports_memory_tagging () > +{ > + /* Look for memory tag notes. If they exist, that means this core fil= e > + supports memory tagging. */ > + > + return (bfd_get_section_by_name (core_bfd, ".memtag") !=3D 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 =3D target_gdbarch (); > + > + /* Make sure we have a way to decode the memory tag notes. */ > + if (!gdbarch_decode_memtag_note_p (gdbarch)) > + error (_("gdbarch_decode_memtag_note not implemented for this " > + "architecture.")); > + > + memtag_note_info info; > + info.memtag_section =3D nullptr; > + > + while (get_next_core_memtag_section (core_bfd, info.memtag_section, > + address, info)) > + { > + size_t adjusted_length > + =3D (address + len < info.end_address)? len : (info.end_address - = address); > + > + /* Decode the memory tag note and return the tags. */ > + gdb::byte_vector tags_read > + =3D gdbarch_decode_memtag_note (gdbarch, info.note, 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 NT_MEMTAG > + note. Check if we need to fetch tags from a different section. = */ > + if (address + len < info.end_address) > + return true; > + > + /* There are more tags to fetch. Update ADDRESS and LEN. */ > + len -=3D (info.end_address - address); > + address =3D info.end_address; > + } > + > + return false; > +} > + > /* Get a pointer to the current core target. If not connected to a > core target, return NULL. */ >=20 > diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo > index 90d827a50e7..1b001e6cacb 100644 > --- a/gdb/doc/gdb.texinfo > +++ b/gdb/doc/gdb.texinfo > @@ -25257,6 +25257,10 @@ options that can be controlled at runtime and em= ulates the @code{prctl} > option @code{PR_SET_TAGGED_ADDR_CTRL}. For further information, see the > documentation in the Linux kernel. >=20 > +@value{GDBN} supports dumping memory tag data to core files through the > +@command{gcore} command and reading memory tag data from core files gene= rated > +by the @command{gcore} command or the Linux kernel. > + > @node i386 > @subsection x86 Architecture-specific Issues >=20 > diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c > index 208cf4b5aaa..de384da2e9a 100644 > --- a/gdb/gdbarch.c > +++ b/gdb/gdbarch.c > @@ -283,6 +283,8 @@ struct gdbarch > gdbarch_iterate_over_regset_sections_ftype *iterate_over_regset_section= s; > gdbarch_make_corefile_notes_ftype *make_corefile_notes; > gdbarch_find_memory_regions_ftype *find_memory_regions; > + gdbarch_create_memtag_notes_from_range_ftype *create_memtag_notes_from= _range; > + gdbarch_decode_memtag_note_ftype *decode_memtag_note; > gdbarch_core_xfer_shared_libraries_ftype *core_xfer_shared_libraries; > gdbarch_core_xfer_shared_libraries_aix_ftype *core_xfer_shared_librarie= s_aix; > gdbarch_core_pid_to_str_ftype *core_pid_to_str; > @@ -667,6 +669,8 @@ 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_notes_from_range, has predicate. */ > + /* Skip verify of decode_memtag_note, 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. */ > @@ -925,6 +929,18 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_fil= e *file) > fprintf_unfiltered (file, > "gdbarch_dump: core_xfer_siginfo =3D <%s>\n", > host_address_to_string (gdbarch->core_xfer_siginfo)= ); > + fprintf_unfiltered (file, > + "gdbarch_dump: gdbarch_create_memtag_notes_from_ra= nge_p() =3D %d\n", > + gdbarch_create_memtag_notes_from_range_p (gdbarch)= ); > + fprintf_unfiltered (file, > + "gdbarch_dump: create_memtag_notes_from_range =3D = <%s>\n", > + host_address_to_string (gdbarch->create_memtag_not= es_from_range)); > + fprintf_unfiltered (file, > + "gdbarch_dump: gdbarch_decode_memtag_note_p() =3D = %d\n", > + gdbarch_decode_memtag_note_p (gdbarch)); > + fprintf_unfiltered (file, > + "gdbarch_dump: decode_memtag_note =3D <%s>\n", > + host_address_to_string (gdbarch->decode_memtag_not= e)); > fprintf_unfiltered (file, > "gdbarch_dump: decr_pc_after_break =3D %s\n", > core_addr_to_string_nz (gdbarch->decr_pc_after_brea= k)); > @@ -3898,6 +3914,54 @@ set_gdbarch_find_memory_regions (struct gdbarch *g= dbarch, > gdbarch->find_memory_regions =3D find_memory_regions; > } >=20 > +bool > +gdbarch_create_memtag_notes_from_range_p (struct gdbarch *gdbarch) > +{ > + gdb_assert (gdbarch !=3D NULL); > + return gdbarch->create_memtag_notes_from_range !=3D NULL; > +} > + > +std::vector > +gdbarch_create_memtag_notes_from_range (struct gdbarch *gdbarch, CORE_AD= DR start_address, CORE_ADDR end_address) > +{ > + gdb_assert (gdbarch !=3D NULL); > + gdb_assert (gdbarch->create_memtag_notes_from_range !=3D NULL); > + if (gdbarch_debug >=3D 2) > + fprintf_unfiltered (gdb_stdlog, "gdbarch_create_memtag_notes_from_ra= nge called\n"); > + return gdbarch->create_memtag_notes_from_range (gdbarch, start_address= , end_address); > +} > + > +void > +set_gdbarch_create_memtag_notes_from_range (struct gdbarch *gdbarch, > + gdbarch_create_memtag_notes_= from_range_ftype create_memtag_notes_from_range) > +{ > + gdbarch->create_memtag_notes_from_range =3D create_memtag_notes_from_r= ange; > +} > + > +bool > +gdbarch_decode_memtag_note_p (struct gdbarch *gdbarch) > +{ > + gdb_assert (gdbarch !=3D NULL); > + return gdbarch->decode_memtag_note !=3D NULL; > +} > + > +gdb::byte_vector > +gdbarch_decode_memtag_note (struct gdbarch *gdbarch, gdb::array_view note, CORE_ADDR address, size_t length) > +{ > + gdb_assert (gdbarch !=3D NULL); > + gdb_assert (gdbarch->decode_memtag_note !=3D NULL); > + if (gdbarch_debug >=3D 2) > + fprintf_unfiltered (gdb_stdlog, "gdbarch_decode_memtag_note called\n= "); > + return gdbarch->decode_memtag_note (gdbarch, note, address, length); > +} > + > +void > +set_gdbarch_decode_memtag_note (struct gdbarch *gdbarch, > + gdbarch_decode_memtag_note_ftype decode_= memtag_note) > +{ > + gdbarch->decode_memtag_note =3D decode_memtag_note; > +} > + > bool > gdbarch_core_xfer_shared_libraries_p (struct gdbarch *gdbarch) > { > diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h > index 7157e5596fd..80e244624de 100644 > --- a/gdb/gdbarch.h > +++ b/gdb/gdbarch.h > @@ -980,6 +980,22 @@ typedef int (gdbarch_find_memory_regions_ftype) (str= uct gdbarch *gdbarch, find_m > extern int gdbarch_find_memory_regions (struct gdbarch *gdbarch, find_mem= ory_region_ftype func, void *data); > extern void set_gdbarch_find_memory_regions (struct gdbarch *gdbarch, gdb= arch_find_memory_regions_ftype *find_memory_regions); >=20 > +/* Create memory tag core file notes given a range of addresses. */ > + > +extern bool gdbarch_create_memtag_notes_from_range_p (struct gdbarch *gd= barch); > + > +typedef std::vector (gdbarch_create_memtag_notes_from_= range_ftype) (struct gdbarch *gdbarch, CORE_ADDR start_address, CORE_ADDR e= nd_address); > +extern std::vector gdbarch_create_memtag_notes_from_ra= nge (struct gdbarch *gdbarch, CORE_ADDR start_address, CORE_ADDR end_addres= s); > +extern void set_gdbarch_create_memtag_notes_from_range (struct gdbarch *= gdbarch, gdbarch_create_memtag_notes_from_range_ftype *create_memtag_notes_= from_range); > + > +/* Decode a memory tag note and return the tags that it contains. */ > + > +extern bool gdbarch_decode_memtag_note_p (struct gdbarch *gdbarch); > + > +typedef gdb::byte_vector (gdbarch_decode_memtag_note_ftype) (struct gdba= rch *gdbarch, gdb::array_view note, CORE_ADDR address, size= _t length); > +extern gdb::byte_vector gdbarch_decode_memtag_note (struct gdbarch *gdba= rch, gdb::array_view note, CORE_ADDR address, size_t length= ); > +extern void set_gdbarch_decode_memtag_note (struct gdbarch *gdbarch, gdb= arch_decode_memtag_note_ftype *decode_memtag_note); > + > /* Read offset OFFSET of TARGET_OBJECT_LIBRARIES formatted shared librari= es list from > core file into buffer READBUF with length LEN. Return the number of b= ytes read > (zero indicates failure). > diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh > index 43e51341f97..7c5eed0780c 100755 > --- a/gdb/gdbarch.sh > +++ b/gdb/gdbarch.sh > @@ -745,6 +745,12 @@ M;gdb::unique_xmalloc_ptr;make_corefile_notes;= bfd *obfd, int *note_size;ob > # Find core file memory regions > M;int;find_memory_regions;find_memory_region_ftype func, void *data;func,= data >=20 > +# Create memory tag core file notes given a range of addresses. > +M;std::vector;create_memtag_notes_from_range;CORE_ADDR= start_address, CORE_ADDR end_address;start_address, end_address > + > +# Decode a memory tag note and return the tags that it contains. > +M;gdb::byte_vector;decode_memtag_note;gdb::array_view no= te, CORE_ADDR address, size_t length;note, address, length > + > # Read offset OFFSET of TARGET_OBJECT_LIBRARIES formatted shared librarie= s list from > # core file into buffer READBUF with length LEN. Return the number of by= tes read > # (zero indicates failure). > diff --git a/gdb/linux-tdep.c b/gdb/linux-tdep.c > index 927e69bf1e1..6192cc4421b 100644 > --- a/gdb/linux-tdep.c > +++ b/gdb/linux-tdep.c > @@ -41,6 +41,8 @@ > #include "gdbsupport/gdb_optional.h" > #include "gcore.h" > #include "gcore-elf.h" > +#include "gdbsupport/memtag.h" > +#include "memtag.h" >=20 > #include >=20 > @@ -1438,10 +1440,11 @@ parse_smaps_data (const char *data, > return smaps; > } >=20 > -/* See linux-tdep.h. */ > +/* Helper that checks if an address is in a memory tag page for a live > + process. */ >=20 > -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; > @@ -1473,6 +1476,91 @@ linux_address_in_memtag_page (CORE_ADDR address) > return false; > } >=20 > +/* Helper that checks if an address is in a memory tag page for a core f= ile > + process. */ > + > +static bool > +linux_core_file_address_in_memtag_page (CORE_ADDR address) > +{ > + if (core_bfd =3D=3D nullptr) > + return false; > + > + memtag_note_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); > +} > + > +/* For each memory map entry that has memory tagging enabled, create a n= ew > + core file note that contains all of its memory tags. Save the data t= o > + NOTE_DATA and update NOTE_SIZE accordingly. */ > + > +static void > +linux_make_memtag_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, > + gdb::unique_xmalloc_ptr ¬e_data, > + int *note_size) > +{ > + if (current_inferior ()->fake_pid_p) > + return; > + > + /* If the architecture doesn't have a hook to return memory tag notes, > + there is nothing left to do. */ > + if (!gdbarch_create_memtag_notes_from_range_p (gdbarch)) > + return; > + > + pid_t pid =3D current_inferior ()->pid; > + > + std::string smaps_file =3D string_printf ("/proc/%d/smaps", pid); > + > + gdb::unique_xmalloc_ptr data > + =3D target_fileio_read_stralloc (NULL, smaps_file.c_str ()); > + > + if (data =3D=3D nullptr) > + return; > + > + /* Parse the contents of smaps into a vector. */ > + std::vector smaps > + =3D parse_smaps_data (data.get (), smaps_file); > + > + for (const smaps_data &map : smaps) > + { > + /* Does this mapping have memory tagging enabled? If so, save the > + memory tags to the core file note. */ > + if (map.vmflags.memory_tagging =3D=3D 0) > + continue; > + > + /* Ask the architecture to create (one or more) NT_MEMTAG notes fo= r > + this particular memory range, including the header. > + > + If the notes are too big, we may need to break up the transfer > + into smaller chunks. > + > + If the architecture returns an empty vector, that means there are > + no memory tag notes to write. */ > + std::vector memory_tag_notes > + =3D gdbarch_create_memtag_notes_from_range (gdbarch, > + map.start_address, > + map.end_address); > + /* Write notes to the core file. */ > + for (const gdb::byte_vector ¬e : memory_tag_notes) > + { > + note_data.reset (elfcore_write_note (obfd, note_data.release (), > + note_size, "CORE", > + NT_MEMTAG, note.data (), > + note.size ())); > + } > + } > +} > + > /* List memory regions in the inferior for a corefile. */ >=20 > static int > @@ -2051,6 +2139,9 @@ linux_make_corefile_notes (struct gdbarch *gdbarch,= bfd *obfd, int *note_size) > return NULL; > } >=20 > + /* Dump the memory tags, if any. */ > + linux_make_memtag_corefile_notes (gdbarch, obfd, note_data, note_size)= ; > + > /* File mappings. */ > linux_make_mappings_corefile_notes (gdbarch, obfd, note_data, note_size= ); >=20 > diff --git a/gdb/memtag.c b/gdb/memtag.c > new file mode 100644 > index 00000000000..4d92ecde84a > --- /dev/null > +++ b/gdb/memtag.c > @@ -0,0 +1,88 @@ > +/* GDB generic memory tagging functions. > + > + Copyright (C) 2021 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 .= */ > + > +#include "defs.h" > +#include "memtag.h" > +#include "gdbsupport/memtag.h" > +#include "bfd.h" > + > +/* Helper function to walk through NT_MEMTAG notes in a core file. > + > + Return a pointer to a .memtag section containing ADDRESS or nullptr > + of none are found. > + > + If SECTION is provided, search from that section onwards. */ > + > +bool > +get_next_core_memtag_section (bfd *abfd, asection *section, > + CORE_ADDR address, memtag_note_info &info) > +{ > + /* If SECTION is nullptr, start a fresh lookup. */ > + if (section =3D=3D nullptr) > + section =3D 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 !=3D nullptr) > + { > + size_t note_size =3D bfd_section_size (section); > + > + /* If the note is smaller than the size of the header, this core n= ote > + is malformed. */ > + if (note_size < NT_MEMTAG_GENERIC_HEADER_SIZE) > + { > + warning (_("Malformed core note - too short for NT_MEMTAG generic " > + "header.\n" > + "Expected %s bytes but got %s bytes."), > + pulongest (NT_MEMTAG_GENERIC_HEADER_SIZE), > + pulongest (note_size)); > + return false; > + } > + > + gdb::byte_vector note (note_size); > + > + /* Fetch the contents of this particular memtag note. */ > + if (!bfd_get_section_contents (abfd, section, > + note.data (), 0, note_size)) > + { > + warning (_("could not get core note contents.")); > + return false; > + } > + > + /* Read the generic header of the note. It contains the format, > + start address and end address. */ > + uint64_t start_address > + =3D bfd_get_64 (abfd, note.data () + sizeof (tag_dump_header::format)); > + uint64_t end_address > + =3D bfd_get_64 (abfd, note.data () + sizeof (tag_dump_header::format) > + + sizeof (tag_dump_header::start_vma)); > + > + /* Is the address within [start_address, end_address)? */ > + if (address >=3D start_address > + && address < end_address) > + { > + info.start_address =3D start_address; > + info.end_address =3D end_address; > + info.note =3D note; > + info.memtag_section =3D section; > + return true; > + } > + } > + return false; > +} > diff --git a/gdb/memtag.h b/gdb/memtag.h > new file mode 100644 > index 00000000000..43c9efb39a3 > --- /dev/null > +++ b/gdb/memtag.h > @@ -0,0 +1,46 @@ > +/* GDB generic memory tagging definitions. > + Copyright (C) 2021 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 .= */ > + > +#ifndef MEMTAG_H > +#define MEMTAG_H > + > +#include "bfd.h" > + > +struct memtag_note_info > +{ > + CORE_ADDR start_address; > + CORE_ADDR end_address; > + gdb::byte_vector note; > + asection *memtag_section; > +}; > + > +/* Helper function to walk through NT_MEMTAG notes 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_note_info &info); > + > +#endif /* MEMTAG_H */ > diff --git a/gdb/testsuite/gdb.arch/aarch64-mte-gcore.c b/gdb/testsuite/g= db.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 .= */ > + > +/* Exercise AArch64's Memory Tagging Extension with tagged pointers. */ > + > +/* This test was based on the documentation for the AArch64 Memory Taggi= ng > + 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] =3D 'a'; > +} > + > +int > +main (int argc, char **argv) > +{ > + unsigned char *tagged_ptr; > + unsigned long page_sz =3D sysconf (_SC_PAGESIZE); > + unsigned long hwcap2 =3D 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 =3D mmap (0, page_sz, PROT_READ | PROT_WRITE, > + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); > + if (tagged_ptr =3D=3D 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..d0bcd036972 > --- /dev/null > +++ b/gdb/testsuite/gdb.arch/aarch64-mte-gcore.exp > @@ -0,0 +1,111 @@ > +# 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 . > + > +# 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 >=3D 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\\\] =3D '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 > + > +if { $program_loaded } { > + return -1 > +} > + > +# 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\\\] =3D '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 >=3D 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\]" \ > + "=3D 0x$tag" \ > + "memory tag of &tagged_ptr\[$index\] is correct" > +} > diff --git a/gdbsupport/memtag.h b/gdbsupport/memtag.h > new file mode 100644 > index 00000000000..bb47eed220b > --- /dev/null > +++ b/gdbsupport/memtag.h > @@ -0,0 +1,39 @@ > +/* Generic memory tagging definitions. > + Copyright (C) 2021 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 .= */ > + > +#ifndef GDBSUPPORT_MEMTAG_H > +#define GDBSUPPORT_MEMTAG_H > + > +/* Generic NT_MEMTAG header. */ > +struct tag_dump_header > +{ > + /* Tag format. */ > + uint16_t format; > + /* Start address of the tagged range. */ > + uint64_t start_vma; > + /* End address of the tagged range. */ > + uint64_t end_vma; > +}; > + > +/* Size of the generic header for the NT_MEMTAG note. This is OS-indepe= ndent > + and should be shared with OS-specific and arch-specific code. */ > +#define NT_MEMTAG_GENERIC_HEADER_SIZE (sizeof (tag_dump_header::format) = \ > + + sizeof (tag_dump_header::start_vma) \ > + + sizeof (tag_dump_header::end_vma)) > + > +#endif /* GDBSUPPORT_MEMTAG_H */ > --=20 > 2.25.1 >=20