From patchwork Wed Apr 9 14:11:17 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Evgeny Karpov X-Patchwork-Id: 110120 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 8FA6E3850227 for ; Wed, 9 Apr 2025 14:12:59 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 8FA6E3850227 Authentication-Results: sourceware.org; dkim=pass (1024-bit key, unprotected) header.d=microsoft.com header.i=@microsoft.com header.a=rsa-sha256 header.s=selector2 header.b=Q0zXM3qI X-Original-To: binutils@sourceware.org Delivered-To: binutils@sourceware.org Received: from EUR02-VI1-obe.outbound.protection.outlook.com (mail-vi1eur02on20723.outbound.protection.outlook.com [IPv6:2a01:111:f403:2607::723]) by sourceware.org (Postfix) with ESMTPS id E3BA0384DEC5 for ; Wed, 9 Apr 2025 14:11:20 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org E3BA0384DEC5 Authentication-Results: sourceware.org; dmarc=pass (p=reject dis=none) header.from=microsoft.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=microsoft.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org E3BA0384DEC5 Authentication-Results: server2.sourceware.org; arc=pass smtp.remote-ip=2a01:111:f403:2607::723 ARC-Seal: i=2; a=rsa-sha256; d=sourceware.org; s=key; t=1744207881; cv=pass; b=gPBT4h1jRCuOEDTLxbUt+wbFBtGDEmm9dTVDfa7AbjHbtqJ3NVmTDimosDkpqtWEHwAKOYJMdeAro1T5V56AQ/zP9RdtEqTw3svA8Z7RziNPSS7KBlVXKobdzilU1+upadLBQ+9S8xJpOopjOHyhGvMcatThulALHVF5JPiODRs= ARC-Message-Signature: i=2; a=rsa-sha256; d=sourceware.org; s=key; t=1744207881; c=relaxed/simple; bh=dj+PgrbkFZ09wEqwu328peUdhS38FOhHq2CSuj8FkbY=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=dsMcXXrPIP99rgzw/2dsM3wd6eZTed+5mh1QWQ3WpWUsp0yJPj+39oneE2YiqQNdTimylgdHNo0IiTLl2wvb10BwHlVMdQ2yjAxbdUAWwCH+5ki2mmYkHKiRQkvyqs11dCJ1ztCbz3Wa4rv70ZZE9E3GT2zLK45gpRaAN3x/LJU= ARC-Authentication-Results: i=2; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org E3BA0384DEC5 ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=iAjxavhBSQyeEPCIqtAyFtt9+OiJrOOYtiqai3oRmEgTRweeiRhTjviy3kxYAR6o6g5wLEdKFiBePJnRoidS702DpGUxfze5laj2if/snsA7B7Hr/HD3gfz9OTlTbaCY2uPBr56rVknfn3ijd2IQL43/n2ohHEM/D7+DRvVjVgYwG3xyjRRgXInrvtvIzFs1bBqxSakL8qdhjFksXcWCzxKA6Myb1iFTxUMMW49lK6+Y/9VBuArJWKVZqGXpEdOB2IkbJu9xlcjAomerRpaj1/aEx/DMHP9w/ktupIL9QZid3SOaocVR+lQgaaOPBdt9+4whEHHPIV/ns54E2kAFsQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; 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=lJ3pi+C3ZAWh5sOi8MWorStEQmRilerBxY0klfKchc4=; b=FSkr/RsSBAZdM0LEw3tEo/y4ckW7zLF95EgA5teAfkBmq5inwWc3tKILMu3XePRZoEcAGKlmJFwusFjtdNUHQTfcHH/G51US9x85HtBgsz/PdHZ3xNL6HiVTr46xL9a6In4KBmeUzz17dp8cyfu1Z12PCAfMCqWHcq+gmbGd7v8N6D7rc4+VSZoY7T2pglSa6cFYVhRKVClnwKb37BnykhF5DqGUZbkVUdEKoDPuR0macIwLn/lWMtZ40L3rds5ETrXj3gpVVEBhL7Zvhn0oPlYBjDeAmqbMxrPKDBamLhhU+peHC3WEcjwL/Wt/xLgHjnOgvAxZrbKXN5Tf8kxWVw== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=microsoft.com; dmarc=pass action=none header.from=microsoft.com; dkim=pass header.d=microsoft.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=lJ3pi+C3ZAWh5sOi8MWorStEQmRilerBxY0klfKchc4=; b=Q0zXM3qIcdQkYbyGGnxYYRL0GclXiAn7vEZk28GSOXnX3eFYnfYI5v2c4hGv4chUhNd27xW+HxcRTAUyYOILGfoCxVrJs+msNYIag/xjPRhS6N3LBvi/+rHMsK9sFsHyZIxsqpvefuocHjkQ7B2kql54Wn1UU89CqKr5E2z9q5Q= Received: from VI2PR83MB0718.EURPRD83.prod.outlook.com (2603:10a6:800:270::12) by GV2PR83MB0901.EURPRD83.prod.outlook.com (2603:10a6:150:277::7) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.8655.5; Wed, 9 Apr 2025 14:11:18 +0000 Received: from VI2PR83MB0718.EURPRD83.prod.outlook.com ([fe80::9b44:280f:9a72:cfb]) by VI2PR83MB0718.EURPRD83.prod.outlook.com ([fe80::9b44:280f:9a72:cfb%5]) with mapi id 15.20.8655.002; Wed, 9 Apr 2025 14:11:18 +0000 From: Evgeny Karpov To: Binutils CC: "Richard Earnshaw (lists)" , "amodra@gmail.com" , Radek Barton Subject: [PATCH v1 5/7] Write SEH records to pdata/xdata Thread-Topic: [PATCH v1 5/7] Write SEH records to pdata/xdata Thread-Index: AQHbqVlCqJzLLz4RdkKMNyxD4OQslA== Date: Wed, 9 Apr 2025 14:11:17 +0000 Message-ID: References: In-Reply-To: Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: msip_labels: MSIP_Label_f42aa342-8706-4288-bd11-ebb85995028c_Enabled=True; MSIP_Label_f42aa342-8706-4288-bd11-ebb85995028c_SiteId=72f988bf-86f1-41af-91ab-2d7cd011db47; MSIP_Label_f42aa342-8706-4288-bd11-ebb85995028c_SetDate=2025-04-09T14:10:55.747Z; MSIP_Label_f42aa342-8706-4288-bd11-ebb85995028c_Name=General; MSIP_Label_f42aa342-8706-4288-bd11-ebb85995028c_ContentBits=0; MSIP_Label_f42aa342-8706-4288-bd11-ebb85995028c_Method=Standard; authentication-results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=microsoft.com; x-ms-publictraffictype: Email x-ms-traffictypediagnostic: VI2PR83MB0718:EE_|GV2PR83MB0901:EE_ x-ms-office365-filtering-correlation-id: 3d4ca662-c80f-4902-2082-08dd77706547 x-ms-exchange-senderadcheck: 1 x-ms-exchange-antispam-relay: 0 x-microsoft-antispam: BCL:0; ARA:13230040|376014|366016|1800799024|38070700018; x-microsoft-antispam-message-info: =?iso-8859-1?q?3LKAEldX0WaWOtH2JlzKPnqmOO?= =?iso-8859-1?q?w3KMhc0/HWV8GzYh/a5/e0w7XG1IHRJOnKaDpb4mjR850mQXEZ+Jexnb6Mti?= =?iso-8859-1?q?hyDT4QeEew+y9vktraNarB0do/yPStOFWgx8pDYKGD+DwrneMz+iIlMXFsP6?= =?iso-8859-1?q?9609+OwZzL5FL9WKVXM9jjRMmOY5EmoCvDKGPOu7IfJShtdRtWX4z7w+lY+Z?= =?iso-8859-1?q?L0htfYuPKZd0Uja5irVRDn0M71RLz8/bpgIS508a7f40WKi7z220YgDTtEZB?= =?iso-8859-1?q?4uV4sXs1Y4aKt2iilSlMSuHcNSXVeQ/f+KIcnyynFO53m1zfQbzwEgt0atui?= =?iso-8859-1?q?expqLeIB/rbvpqmD3i/Kh7lSWMvdWgPY4S1oadUUOwHoTMZOOFypnDaqnIe9?= =?iso-8859-1?q?zEEdPCBfXE3bwF617oq37zelscMVGaRlP74TSvKnVDw+rHitT3w7URDPu6jV?= =?iso-8859-1?q?dja6VcY8yCnGw/83zYEaDPcslf2av1ppbEgKP1EFvU8zoyRgxISZoqVbjDkw?= =?iso-8859-1?q?C540WNxc2FNFfZLLZFvPtmmU3XW+VY4RotPPP1wjZdLx+WmNaJS/dGY4Av4s?= =?iso-8859-1?q?nHGKxk4T+CBI34/Q41Zqg0oyheJ6z4e0wG2/JIsRahXD0G9BPPeIT5EAKdH+?= =?iso-8859-1?q?8VEhgXdNKFQaU/GBbe0CxNsaTJNX4y1FBD5S/wCYCg0HziHvwUSNJmocrD/p?= =?iso-8859-1?q?kVipjJ1a5vbCrRqGrZPsIadAWKPGVahK7v3rFahWu6MblnlzWVNMokQoU7K/?= =?iso-8859-1?q?UtiI8bAUiLmZv3nKtuJX1jyHJ+exP89jnXB3ldv5+KLmPsV/D+vXL07wmd4S?= =?iso-8859-1?q?rKwJM6St5DmOupO8h88BtqKqUTz0C/b9ExGkoWPaXVrrcJ6pLhdn/G8aB6wK?= =?iso-8859-1?q?gLKYvGrmnfkpMHabTxbO6/SxfwYk7C0l8suw7y6YrSA34iBI9nW4h1211Wbk?= =?iso-8859-1?q?EptB3XcdT6oG9gVdfj7geOTG13ymtB3tu/W+NYcH1IvkFeWQvD+JfGMZml82?= =?iso-8859-1?q?fueAKV7mLBLu8PHJV6nxpS4Zv4gq5wZxmEeD8xz1Y1FONHd/6PiXrKaE36oW?= =?iso-8859-1?q?6zXAriyHUGQ32UZFSx/G8SjpoxHF1wtjtnJw9BmXENGN67Vv3X7tVOE+pKD8?= =?iso-8859-1?q?+YvXYbT1zb91LCW2tsXM/ZwInnXrbmDQPoFTcslE6EqXKGlJZp6FivPg08sj?= =?iso-8859-1?q?2E3PxfDwWG5dlqCENlx5Fart0h+CesdsRrbxB4cni8Aos/VSevzO1V8/Hg63?= =?iso-8859-1?q?XVdDESaNDz8xv3vpZcWT0eg1sraV/xETVNTeWmJc/NeXefVoLYSZR7ORB1pn?= =?iso-8859-1?q?qQJGcxrwCWnio5CN2cf93pI9MJyJSzaDj8IMejOYCMr0EQmQrGJVi+Ws+GmD?= =?iso-8859-1?q?UMwUIgstPVa32kPRTBKm0g9LOt2wwH3r8+x1wN0kEc5ITNrpKr2rovZjhcHC?= =?iso-8859-1?q?hDTNtuYP2+IPF27V4wpKP8yemQxcFU3k+/DgNaBPJM8Q5CyxKlb1Kx19uV5i?= =?iso-8859-1?q?x57bSIrZlXwHT0tLKJVDiZXOmEDDfzov3Ldh4PwcAAzQ1j13k=3D?= x-forefront-antispam-report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:VI2PR83MB0718.EURPRD83.prod.outlook.com; PTR:; CAT:NONE; SFS:(13230040)(376014)(366016)(1800799024)(38070700018); DIR:OUT; SFP:1102; x-ms-exchange-antispam-messagedata-chunkcount: 1 x-ms-exchange-antispam-messagedata-0: =?iso-8859-1?q?TyodUjD6yhwoz6JuddWofat?= =?iso-8859-1?q?nNakNPHHDrg73ru2hjjM+aX03qxFyVMEFd11ZWvda5l+kG0zTMVccdmrPXRG?= =?iso-8859-1?q?qmHd2MCPmm7v1qbcwIeUT6D64dsi1plq2D4CoJUP0AQeDCR0MWth79NVpDSz?= =?iso-8859-1?q?bhkL/9w6mZNrHL7N//3MHFa5vH1pEd2bXfM5Q4Ob+a5UwtweajkEYwTq94+u?= =?iso-8859-1?q?kmBLrpk7G2izwGMo7pNVxGKFy150lh/joOP5v7KpZrAACGtkThyJS04HBzIL?= =?iso-8859-1?q?EsROgJjzxMHfQ2gOY1o+Cppml7PpNUEFZf+VoJ/TLJJAab5dxvB9xGjTLvCG?= =?iso-8859-1?q?dWZU4CQb/ATv0YDyGABkSTNICXJC56RiKglguQViSy/9WNV/67/aHNTZklap?= =?iso-8859-1?q?vOkZ+FIIQo/r/JoIcTeJ46nwuiOjwZM3xlI29VrcmaDORw2CrceWiPgyB6Gb?= =?iso-8859-1?q?b9k3lY2zJux5tq0hFFXWzxj55XAppE/0n5xREkolsWPSD10z/lNOhSXTAaSA?= =?iso-8859-1?q?Z8tgzvdu9F1rHqy6UgjYqqEKmSIUhYWKcU6PWysNdngaf+yyQLqiYYYGpij8?= =?iso-8859-1?q?NFiEptgWQ9JDA/iQ9Zqb8d+2YPZ/0VpecCNH3i3fSGFywFp+Xhz09YA+1Hoz?= =?iso-8859-1?q?BAYl37z+28m5MH9V7KVXgAe9of8pDn24VzJZGwSXteeAFv1qQSCnDknP5ADE?= =?iso-8859-1?q?aX1FaS/lq7YqVPKCIWfxZnEuE2lOxtTrhFQ8AZUV+frCirNhkE2y9xPr4gex?= =?iso-8859-1?q?6CsunJWCkAZ4QREx8eK9VE0JnqeIcBxyAxu6keMcC++QmNolYWC12kgSUXiw?= =?iso-8859-1?q?nNiWkmqtyttiisbOYHbUJ5Rjxa/I+DUCizxSQF74neYVbMf4zuM0O5PV2g8p?= =?iso-8859-1?q?q1sZkDtYwTMkTHNAnMfg4ZUsnUpz4JewJ1jYEANG4EZpUqYN5fk7CbYG2mT8?= =?iso-8859-1?q?qdj6Zp+xfZX5TKOk6yng0EKcrGlVf+Bi82UrnoEGh3v5VzlnuwJqFbfDYPXo?= =?iso-8859-1?q?Wi64o6syxocRHwdp9Am+TWGolngY0LG3UImoPboecq7DkGcuYOloWKLzwcOj?= =?iso-8859-1?q?opKF3Gh8IjQviFH5qdBx64t35c7sn9j8dObrsZUe0sEQ5Tmr6het1aC7+0a9?= =?iso-8859-1?q?6lWZ+2IpDnYrubSYF8cy7FwIeHfMC05/eSytr7wq+KkaNk/DAsTDbAuN9x2x?= =?iso-8859-1?q?YjEBEnW+mSVScFOXRJovlE9ANXHYlu/9odNrRaIFIK+OtE3Eeg0JsGza21ze?= =?iso-8859-1?q?edzoiIdoLiT2pdU0fnTRjH7ZMUp+MESyRiOYGB1PeI9vaa94Kt2+VdQfU5rX?= =?iso-8859-1?q?+vlS03eHxjzTBgvfOnKqLd1K90jPEQm29YPIQzoOVh0R9scVTnhcLPm0kBo9?= =?iso-8859-1?q?GhAYoh09TCYxOHbZtiLJKT7LgrQiGHu8l2N5rsOYbWmgprk+Ntq9fP5XG5Ld?= =?iso-8859-1?q?UCX/J1/7S60M4J4HxBXYMfNqg00RE0ArwDhi8NuUm385Ij8QSAHHjKp4h80y?= =?iso-8859-1?q?uen4C/lW/sef8TUv2GxTaDrt4ncDQZSWCKhhumR/1c+oCXt+9q69lKOetqyE?= =?iso-8859-1?q?0tQHhEl7+6WxCvJTemaUMTgCUxL2jfTZ+/oQo4LFApnbIyIUfAxL+s0OCHBv?= =?iso-8859-1?q?cmYDA2E3jUtvwdQkC?= MIME-Version: 1.0 X-OriginatorOrg: microsoft.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-AuthSource: VI2PR83MB0718.EURPRD83.prod.outlook.com X-MS-Exchange-CrossTenant-Network-Message-Id: 3d4ca662-c80f-4902-2082-08dd77706547 X-MS-Exchange-CrossTenant-originalarrivaltime: 09 Apr 2025 14:11:17.5432 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: 72f988bf-86f1-41af-91ab-2d7cd011db47 X-MS-Exchange-CrossTenant-mailboxtype: HOSTED X-MS-Exchange-CrossTenant-userprincipalname: Zvz8oPdhey+L0XiSk8Xs5ebsAntEJrZbCCXuVosZp7Hp29ngj+MS8UCr3k7z04fpVECS3EKaxjxm8NGZbNXQSA== X-MS-Exchange-Transport-CrossTenantHeadersStamped: GV2PR83MB0901 X-Spam-Status: No, score=-10.9 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FORGED_SPF_HELO, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_PASS, SPF_NONE, TXREP 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: binutils@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Binutils mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: binutils-bounces~patchwork=sourceware.org@sourceware.org The patch emits the required records to the pdata/xdata sections that contain unwinding information for SEH. gas/ChangeLog: * config/obj-coff-seh.c (do_seh_endproc): Update. (seh_arm64_emit_epilog_scopes): New. (seh_arm64_emit_unwind_codes): New. (seh_arm64_write_function_xdata): New. (write_function_xdata): Update. (write_function_pdata): Update. --- gas/config/obj-coff-seh.c | 312 +++++++++++++++++++++++++++++++++++++- 1 file changed, 304 insertions(+), 8 deletions(-) diff --git a/gas/config/obj-coff-seh.c b/gas/config/obj-coff-seh.c index 96ddfd51a82..f9a8ea80c28 100644 --- a/gas/config/obj-coff-seh.c +++ b/gas/config/obj-coff-seh.c @@ -557,13 +557,23 @@ static void do_seh_endproc (void) { seh_ctx_cur->end_addr = symbol_temp_new_now (); + const seh_kind kind = seh_get_target_kind (); - write_function_xdata (seh_ctx_cur); - write_function_pdata (seh_ctx_cur); - free (seh_ctx_cur->elems); - free (seh_ctx_cur->func_name); - free (seh_ctx_cur); - seh_ctx_cur = NULL; + if (kind != seh_kind_arm64 + || seh_ctx_cur->arm64_ctx.unwind_codes_byte_count > 0) + { + write_function_xdata (seh_ctx_cur); + write_function_pdata (seh_ctx_cur); + } + + while (seh_ctx_cur) + { + seh_context *ctx = seh_ctx_cur; + seh_ctx_cur = seh_ctx_cur->next; + free (ctx->elems); + free (ctx->func_name); + XDELETE (ctx); + } } static void @@ -1169,6 +1179,74 @@ seh_x64_write_prologue_data (const seh_context *c) } } +static void +seh_arm64_emit_epilog_scopes (const seh_context *c, uint64_t fragment_offset, + uint32_t prolog_size, + uint32_t first_fragment_scope, + uint32_t last_fragment_scope, + bool has_phantom_prolog) +{ + int32_t start_index_offset = 0; + const + seh_arm64_epilogue_scope* scopes = seh_ctx_cur->arm64_ctx.epilogue_scopes; + if (first_fragment_scope < seh_ctx_cur->arm64_ctx.epilogue_scopes_count) + start_index_offset = scopes[first_fragment_scope].epilogue_start_index + - prolog_size; + if (has_phantom_prolog) + start_index_offset -= 1; + for (int i = first_fragment_scope; i < last_fragment_scope; ++i) + { + seh_arm64_epilogue_scope scope = seh_ctx_cur->arm64_ctx.epilogue_scopes[i]; + scope.epilogue_start_offset_reduced = (scope.epilogue_start_offset + - fragment_offset) >> 2; + scope.epilogue_start_index -= start_index_offset; + out_four (*(uint32_t*) &scope); + } +} + +static void +seh_arm64_emit_unwind_codes (const seh_context *c, uint32_t prolog_size, + uint32_t first_epilog_index, + uint32_t last_epilog_index, + bool has_phantom_prolog) +{ + uint32_t total_byte_count = 0; + + if (has_phantom_prolog) + { + ++total_byte_count; + md_number_to_chars (frag_more (1), ARM64_UNOP_ENDC, 1); + } + + uint32_t unwind_bytes_offset = 0; + for (int i = 0; i < (int)c->arm64_ctx.unwind_codes_count; ++i) + { + const seh_arm64_unwind_code *code = c->arm64_ctx.unwind_codes + i; + const int byte_count = unwind_code_pack_infos[code->type].size; + unwind_bytes_offset += byte_count; + + if (unwind_bytes_offset > last_epilog_index) + break; + + if (unwind_bytes_offset > prolog_size + && unwind_bytes_offset <= first_epilog_index) + continue; + + /* emit unwind code bytes in big endian. */ + number_to_chars_bigendian (frag_more (byte_count), code->value, byte_count); + total_byte_count += byte_count; + } + + /* handle word alignment. */ + int required_padding = (4 - total_byte_count % 4) % 4; + if (required_padding) + { + const uint32_t nop_chain = 0xe3e3e3e3; + md_number_to_chars (frag_more (required_padding), nop_chain, + required_padding); + } +} + static int seh_x64_size_prologue_data (const seh_context *c) { @@ -1263,6 +1341,195 @@ seh_x64_write_function_xdata (seh_context *c) /* Handler data will be tacked in here by subsections. */ } +/* Write out the xdata information for one function (arm64). */ +static void +seh_arm64_write_function_xdata (seh_context *c) +{ + /* Set 4-byte alignment. */ + frag_align (2, 0, 0); + + uintptr_t func_length = 0; + expressionS exp; + exp.X_op = O_subtract; + exp.X_add_symbol = c->end_addr; + exp.X_op_symbol = c->start_addr; + exp.X_add_number = 0; + if (!resolve_expression (&exp) || exp.X_op != O_constant + || exp.X_add_number < 0) + as_bad (_("the function size expression for %s " + "does not evaluate to a non-negative constant"), + S_GET_NAME (c->start_addr)); + + func_length = exp.X_add_number; + + const uint32_t max_frag_size = ((1 << 18) - 1) << 2; + uintptr_t fragment_offset = 0; + bool is_fragmented_function = func_length > max_frag_size; + + /* [first_fragment_scope, last_fragment_scope). */ + uint32_t first_fragment_scope = 0; + uint32_t last_fragment_scope = 0; + uint32_t prolog_size = 0; + uint32_t prolog_insruction_count = 0; + for (int i = 0; i < c->arm64_ctx.unwind_codes_count; ++i) + { + if (c->arm64_ctx.unwind_codes[i].type == end) + { + prolog_insruction_count = i + 1; + break; + } + } + + if (c->arm64_ctx.epilogue_scopes_count) + prolog_size = c->arm64_ctx.epilogue_scopes[0].epilogue_start_index; + else + prolog_size = c->arm64_ctx.unwind_codes_byte_count; + + while (true) + { + c->xdata_addr = symbol_temp_new_now (); + c->next = NULL; + c->arm64_ctx.fragment_offset = fragment_offset; + + uintptr_t frag_size = func_length - fragment_offset; + if (frag_size > max_frag_size) + frag_size = max_frag_size; + + bool is_first_frag = fragment_offset == 0; + bool is_last_frag = (fragment_offset + frag_size) == func_length; + + if (!is_fragmented_function) + last_fragment_scope = c->arm64_ctx.epilogue_scopes_count; + else + { + first_fragment_scope = last_fragment_scope; + for (int i = first_fragment_scope; i < c->arm64_ctx.epilogue_scopes_count; + ++i) + { + const seh_arm64_epilogue_scope *scope = c->arm64_ctx.epilogue_scopes; + scope += i; + if (scope->epilogue_start_offset >= (fragment_offset + frag_size)) + break; + + if (scope->epilogue_end_offset >= (fragment_offset + frag_size)) + { + frag_size = scope->epilogue_start_offset - fragment_offset; + break; + } + + last_fragment_scope = i + 1; + } + } + + seh_arm64_xdata_header* header = &c->arm64_ctx.xdata_header; + const + seh_arm64_epilogue_scope* scopes = seh_ctx_cur->arm64_ctx.epilogue_scopes; + + header->func_length = frag_size >> 2; + header->vers = 0; + header->e = 0; + header->code_words = 0; + header->epilogue_count = 0; + + header->ext_code_words = 0; + header->ext_epilogue_count = last_fragment_scope + - first_fragment_scope; + header->reserved = 0; + + uint32_t first_epilog_index = 0; + uint32_t last_epilog_index = 0; + if (!header->ext_epilogue_count) + { + first_epilog_index = prolog_size; + last_epilog_index = prolog_size; + } + else + { + first_epilog_index = scopes[first_fragment_scope].epilogue_start_index; + if (last_fragment_scope == c->arm64_ctx.epilogue_scopes_count) + last_epilog_index = c->arm64_ctx.unwind_codes_byte_count; + else + last_epilog_index = scopes[last_fragment_scope].epilogue_start_index; + } + + uint32_t unwind_bytes = 0; + if (is_first_frag || is_last_frag) + unwind_bytes += prolog_size; + + if (header->ext_epilogue_count) + unwind_bytes += last_epilog_index - first_epilog_index; + + if (is_fragmented_function && is_last_frag && unwind_bytes) + { + unwind_bytes += 1; + ++header->ext_epilogue_count; + } + + header->ext_code_words = (unwind_bytes + 3) / 4; + + if (header->ext_code_words == 0 && header->ext_epilogue_count == 0 + || header->ext_code_words > 31 + || header->ext_epilogue_count > 31) + md_number_to_chars (frag_more (8), c->arm64_ctx.xdata_header_value, 8); + else + { + header->code_words = header->ext_code_words; + header->epilogue_count = header->ext_epilogue_count; + if (header->epilogue_count == 1) + { + header->e = 1; + if (is_fragmented_function && is_last_frag) + header->ext_epilogue_count = 0; + else + { + uint32_t start_index; + start_index = scopes[first_fragment_scope].epilogue_start_index; + header->ext_epilogue_count = start_index; + } + } + out_four (c->arm64_ctx.xdata_header_value); + } + + bool has_phantom_prolog = is_fragmented_function && is_last_frag; + if (header->ext_epilogue_count && !header->e) + { + seh_arm64_emit_epilog_scopes (c, fragment_offset, prolog_size, + first_fragment_scope, last_fragment_scope, + has_phantom_prolog); + if (is_fragmented_function && is_last_frag) + { + uint32_t epilog_start_offset = frag_size - prolog_insruction_count * 4; + md_number_to_chars (frag_more (4), + (1 << 22) | (epilog_start_offset >> 2), 4); + } + } + + if (header->ext_code_words) + seh_arm64_emit_unwind_codes (c, prolog_size, first_epilog_index, + last_epilog_index, has_phantom_prolog); + + if (header->x == 1) + { + if (c->handler.X_op == O_symbol) + c->handler.X_op = O_symbol_rva; + + emit_expr (&c->handler, 4); + } + + fragment_offset += frag_size; + if (fragment_offset == func_length) + break; + + seh_context *next = XCNEW (seh_context); + memcpy (next, c, sizeof (seh_context)); + next->elems = NULL; + next->func_name = NULL; + + c->next = next; + c = next; + } +} + /* Write out xdata for one function. */ static void @@ -1271,13 +1538,25 @@ write_function_xdata (seh_context *c) segT save_seg = now_seg; int save_subseg = now_subseg; + seh_kind target_kind = seh_get_target_kind (); + /* MIPS, SH, ARM don't have xdata. */ - if (seh_get_target_kind () != seh_kind_x64) + if ((target_kind != seh_kind_x64) && (target_kind != seh_kind_arm64)) return; switch_xdata (c->subsection, c->code_seg); - seh_x64_write_function_xdata (c); + switch (target_kind) + { + case seh_kind_x64: + seh_x64_write_function_xdata (c); + break; + case seh_kind_arm64: + seh_arm64_write_function_xdata (c); + break; + default: + break; + } subseg_set (save_seg, save_subseg); } @@ -1362,6 +1641,23 @@ write_function_pdata (seh_context *c) emit_expr (&exp, 4); break; + case seh_kind_arm64: + while (c) + { + exp.X_op = O_symbol_rva; + exp.X_add_number = c->arm64_ctx.fragment_offset; + exp.X_add_symbol = c->start_addr; + emit_expr (&exp, 4); + + exp.X_op = O_symbol_rva; + /* TODO: Implementing packed unwind data. */ + exp.X_add_number = 0; + exp.X_add_symbol = c->xdata_addr; + emit_expr (&exp, 4); + c = c->next; + } + break; + case seh_kind_mips: exp.X_op = O_symbol; exp.X_add_number = 0;