From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from EUR05-VI1-obe.outbound.protection.outlook.com (mail-vi1eur05on2089.outbound.protection.outlook.com [40.107.21.89]) by sourceware.org (Postfix) with ESMTPS id 4139D3858417 for ; Fri, 6 Jan 2023 10:42:29 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 4139D3858417 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=arm.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=armh.onmicrosoft.com; s=selector2-armh-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=cnxcGM8ZMFVbRWttu+mzQXm1/vH+4GemAdXW6lLP9O8=; b=ILZKNQNAKh4HOVrrh7BqbqxFPLxXO/bFlHjlPeguqowvlYq+kLmIHIqrSrKHlriKQJb1gs0mz0624JczJqfSt+YrA2QI7DPWs/u2jmv9y/DfFRcqckpxoqgZDhde3vsklnpJhD815oz+N+TbLakTdDjewC1QpXFxTGqPfUzYeSI= Received: from ZR2P278CA0006.CHEP278.PROD.OUTLOOK.COM (2603:10a6:910:50::12) by PA4PR08MB7617.eurprd08.prod.outlook.com (2603:10a6:102:272::12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5986.14; Fri, 6 Jan 2023 10:42:24 +0000 Received: from VI1EUR03FT047.eop-EUR03.prod.protection.outlook.com (2603:10a6:910:50:cafe::6b) by ZR2P278CA0006.outlook.office365.com (2603:10a6:910:50::12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5986.15 via Frontend Transport; Fri, 6 Jan 2023 10:42:24 +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 VI1EUR03FT047.mail.protection.outlook.com (100.127.144.198) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5944.16 via Frontend Transport; Fri, 6 Jan 2023 10:42:24 +0000 Received: ("Tessian outbound 0d7b2ab0f13d:v132"); Fri, 06 Jan 2023 10:42:23 +0000 X-CheckRecipientChecked: true X-CR-MTA-CID: 23a29b9d8559acde X-CR-MTA-TID: 64aa7808 Received: from 945e150334f3.1 by 64aa7808-outbound-1.mta.getcheckrecipient.com id 506521BF-4A66-42C8-B40C-CA03193D0D88.1; Fri, 06 Jan 2023 10:42:13 +0000 Received: from EUR02-DB5-obe.outbound.protection.outlook.com by 64aa7808-outbound-1.mta.getcheckrecipient.com with ESMTPS id 945e150334f3.1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384); Fri, 06 Jan 2023 10:42:13 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=ZnQJZdtwQKDgGin91kbHVwbR9O5fEgxxDewwotfOP+dVv1Bx1rwKJcIU2XDsmXGl2Vvk3W8OzfkvPKUVMhgz61IRp5AFjJeRT4twnlGz/rW9bPQdpzbpEgCy3ieQNCVrEPwqAeagjWQlqUKx37dtZcjPF8lrM1OPoMFcb3EbjVvt6fGav0GGWc0QJsU66JGktljM3XWI/v1L9t8Q9airnJZ+CohbfuNnyxS9kWnqHVJr7qE5lOHhnPU8nneHJ+4zluu9Maw05f2EDj8lptfc/cUtAUa0uy+0jM8PDuUHVe6yYuOuEQjrSTbDMuVqHrP7iu67hBuRGIYZNHYXkIekvg== 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=cnxcGM8ZMFVbRWttu+mzQXm1/vH+4GemAdXW6lLP9O8=; b=kYB5rgKgfyRvcFRpUE3CUZvPxgz9GfS3f1quX1u3UUw9zlgPbClNRo3ztzjtvMlHsYAI6palB20LYMoF6TWmLQDOAn0BwRe+dU/hYfDZ+xj7KYDtnyyNjt8vLn41j9bz9J31GyK4FDinPF4V7xAVIi+SxPeuIb+sFrhlcC3pSLFNIxNy+j03YxBT4V423QXkhZhnM5E4XRJd0GP1wBEPdcnVfJ1fnZzM71YFR+KTYJVJDSB7cUwKxHS4UUZWvAD6cO4R1nmX3kPT7rM0gioNIZhHUFVq56+UvrI2Nba//y7tKgaLOnYOEQYlQ/6cV9x4rmZg3+tdLbSJawQ2FTuSvQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=arm.com; dmarc=pass action=none header.from=arm.com; dkim=pass header.d=arm.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=armh.onmicrosoft.com; s=selector2-armh-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=cnxcGM8ZMFVbRWttu+mzQXm1/vH+4GemAdXW6lLP9O8=; b=ILZKNQNAKh4HOVrrh7BqbqxFPLxXO/bFlHjlPeguqowvlYq+kLmIHIqrSrKHlriKQJb1gs0mz0624JczJqfSt+YrA2QI7DPWs/u2jmv9y/DfFRcqckpxoqgZDhde3vsklnpJhD815oz+N+TbLakTdDjewC1QpXFxTGqPfUzYeSI= Authentication-Results-Original: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=arm.com; Received: from VI1PR08MB3390.eurprd08.prod.outlook.com (2603:10a6:803:7d::27) by PAVPR08MB9602.eurprd08.prod.outlook.com (2603:10a6:102:310::7) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5986.9; Fri, 6 Jan 2023 10:42:10 +0000 Received: from VI1PR08MB3390.eurprd08.prod.outlook.com ([fe80::d034:a319:3a2a:7897]) by VI1PR08MB3390.eurprd08.prod.outlook.com ([fe80::d034:a319:3a2a:7897%6]) with mapi id 15.20.5986.014; Fri, 6 Jan 2023 10:42:09 +0000 Message-ID: <1eb8069a-5c19-5d2e-4706-5673b45075f1@arm.com> Date: Fri, 6 Jan 2023 11:42:02 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Thunderbird/102.4.2 Subject: Re: [PATCH v5 1/8] newlib: libc: define M-profile PACBTI-enablement macros Content-Language: en-US To: "Victor L. Do Nascimento" , newlib@sourceware.org Cc: Richard Earnshaw References: From: Christophe Lyon In-Reply-To: Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit X-ClientProxiedBy: SN7PR18CA0002.namprd18.prod.outlook.com (2603:10b6:806:f3::25) To VI1PR08MB3390.eurprd08.prod.outlook.com (2603:10a6:803:7d::27) MIME-Version: 1.0 X-MS-TrafficTypeDiagnostic: VI1PR08MB3390:EE_|PAVPR08MB9602:EE_|VI1EUR03FT047:EE_|PA4PR08MB7617:EE_ X-MS-Office365-Filtering-Correlation-Id: d42728c6-ec6f-4bb3-5a6b-08daefd2b28a 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: vJyOKXKdVwwA21z2RJoy1KoVANNZAKJgxuw8z9PEyMaUPldZGElq0wcAyoHW0H/07XYSafeMScJZRR/h07MZTtoMvCJYz6PNVQ8atkDUj342AzMAyGBBKlvokS/yteIujVwaKjeE/4BDWzSTXpVXTI+iCouMLjM0L0uKhNAxZeT6MXNNo9HsFu2Y/Ipcf1V+72gJJKE4TxO4yGT52R4DwUqJMyJ4Iaau/57yb79q+Ryu90IP6+k+3kSziSJ4138zYtvBmh4YdinbciuIypB/zx+lZp1t45H92LrPVqNFzVsS70rFF1tT5Wpzc+kiC/gTAeHUZmaEpXk9EygoiR40yn0NGK+MLmQKmaN61v1Y0SYZaQUDbElpWDHWZAMS1sLe4I+7X0N9sPOz67JSPBj6gQwa7vu4nfr82uiwpR3wl5siClijbQkIZo+etL/7KrCFxUIzP5N+OjjwePV4l4wh5cpvwltFsrvqONqAWCUhx3b6Pq2KlcOwW1EDykxPDVqlOy9EqCi+rzXpUKN7hYSvGkmMVJBW9sosiOx0BMkXCMq3XcbwS25IV4EehqmfeAXX0yK9bO1V7qJEy3eEiON9VyPwV2voTzC00jXHcwHy3t7BrTbLp5xGyo7LpDnaWFDBN2zE7SBGjSjVYijdcs3yZ0qNXVpQeZGltb/X3BH1Fi3nEsU+BTiKrvWBLF2fAs19GNTbVIfhatYP3aqeEMT7MFQw0yuQn6sjl7iXg5XmnIo= X-Forefront-Antispam-Report-Untrusted: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:VI1PR08MB3390.eurprd08.prod.outlook.com;PTR:;CAT:NONE;SFS:(13230022)(4636009)(346002)(366004)(39860400002)(376002)(136003)(396003)(451199015)(31686004)(86362001)(36756003)(66476007)(41300700001)(4326008)(66946007)(8676002)(66556008)(38100700002)(26005)(6506007)(186003)(478600001)(6512007)(31696002)(6666004)(6486002)(30864003)(83380400001)(2906002)(53546011)(316002)(5660300002)(2616005)(44832011)(8936002)(45980500001)(43740500002);DIR:OUT;SFP:1101; X-MS-Exchange-Transport-CrossTenantHeadersStamped: PAVPR08MB9602 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: VI1EUR03FT047.eop-EUR03.prod.protection.outlook.com X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id-Prvs: 53430728-b3c3-488e-9e61-08daefd2a97d X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: lwyqFMOXm+s1qJvSUq0nPwhuD43hra+4Y67qdVf52ofdmzANbks4ukl2rGC3ZM4ImASKHJHDaTLlzerdr06TzdwSzsOhYgARaqDMFhcvPfHNZy1ETJ6Gzsm69Yi7nlvAmdRi9YnZ3sKdNjoNROJBfmDXQlaRMdmz029LgJ1I3it+9+FipuoZpKJKHOkfpovw+wBGjHXobClR8t+kMVCM5wydPIYM1akxfKgOFs6RN61FPTltH//fmqdD6guPXzTnqx0WCbSA0j0lCQ2Rmu5HhcTo50ckgek25taP4OgSO75jBL+6pRts1o8ItF60RBb266h4CXJ8cBWpkv2Yfepnyj/w4F2Zu8MPSLKUzJ+KVV3lWD9J8wH8EE8Em5pugnnjaRy5B7EDaqwB7sVa+o/fzi2qZb5uFnIWAw1770T0IldmgnLTqpaszOreOIxRq4IeXrWMJek5r39+AfioQnFwW1nJ8xMoQz7ZSNwHuMHlJ8SavxIpn8NyujRm7nsNt1W22dqp/wbEhswLpEnKLJ9MRVLvJ4MPi9/8nVbBuIecRSvpS+qXQLpp4KJrYK/SpPRvtwiRvJUxz6z0HEJWNAkLWBeXeUnIvonk9LuIP0GLe9Z/o0k5Kl3BCiFqeu6+axNQ2fp6N1ei+2zJmNNQkVfvKtfuFYIs9Dl53l8EiojqxmmeWdkLchcYH15kZNs3NaVgwJ+NHDdA65s8G/cNv6LgoDRdyqM3YbWZhtqEyblgFYY= X-Forefront-Antispam-Report: CIP:63.35.35.123;CTRY:IE;LANG:en;SCL:1;SRV:;IPV:CAL;SFV:NSPM;H:64aa7808-outbound-1.mta.getcheckrecipient.com;PTR:ec2-63-35-35-123.eu-west-1.compute.amazonaws.com;CAT:NONE;SFS:(13230022)(4636009)(136003)(39860400002)(376002)(396003)(346002)(451199015)(46966006)(36840700001)(40470700004)(31686004)(36756003)(31696002)(36860700001)(82740400003)(4326008)(41300700001)(70586007)(81166007)(356005)(8676002)(70206006)(40480700001)(53546011)(186003)(6486002)(478600001)(6666004)(6512007)(86362001)(26005)(2616005)(82310400005)(8936002)(2906002)(316002)(40460700003)(6506007)(83380400001)(336012)(5660300002)(44832011)(30864003)(47076005)(43740500002);DIR:OUT;SFP:1101; X-OriginatorOrg: arm.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 06 Jan 2023 10:42:24.2366 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: d42728c6-ec6f-4bb3-5a6b-08daefd2b28a 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: VI1EUR03FT047.eop-EUR03.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: PA4PR08MB7617 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,NICE_REPLY_A,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_PASS,SPF_NONE,TXREP,UNPARSEABLE_RELAY autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: Hi Victor, Thanks for the patch series, a few comments/questions below. Christophe On 12/21/22 12:19, Victor L. Do Nascimento wrote: > Augment the arm_asm.h header file to simplify function prologues and > epilogues whilst adding support for PACBTI enablement via macros for > hand-written assembly functions. For PACBTI, both prologues/epilogues > as well as cfi-related directives are automatically amended > accordingly, depending on the compile-time mbranch-protection argument > values. > > It defines the following preprocessor macros: > * HAVE_PAC_LEAF: Indicates whether pac-signing has been requested for > leaf functions. > * PAC_LEAF_PUSH_IP: Whether leaf functions should push the pac code > to the stack irrespective of whether the ip register is clobbered in > the function or not. > * STACK_ALIGN_ENFORCE: Whether a dummy register should be added to > the push list as necessary in the prologue to ensure stack > alignment preservation at the start of assembly function. The > epilogue behavior is likewise affected by this flag, ensuring any > pushed dummy registers also get popped on function return. IIUC, these new macros are meant for general usage outside of newlib, do they need proper documentation? Or maybe an entry in the "News" section? I don't know. Otherwise, I think they should not appear in the user naming space. > It also defines the following assembler macros: > * prologue: In addition to pushing any callee-saved registers onto > the stack, it generates any requested pacbti instructions. > Pushed registers are specified via the optional `first', `last', > `push_ip' and `push_lr' macro argument parameters. Maybe you should quote 'first' and 'last' differently from 'push_ip' and 'push_lr', since the example below shows that 'first' and 'last' are in fact register numbers (IIUC) > when a single register number is provided, it pushes that Typo: "When" (with a capital) > register. When two register numbers are provided, they specify a > rage to save. If push_ip and/or push_lr are non-zero, the Typo: "range" > respective registers are also saved. Stack alignment is requested > via the `align` argument, which defaults to the value of > STACK_ALIGN_ENFORCE, unless manually overridden. > > For example: > > prologue push_ip=1 -> push {ip} > prologue push_ip=1, align8=1 -> push {r2, ip} > prologue push_ip=1, push_lr=1 -> push {ip, lr} > prologue 1 -> push {r1} > prologue 1, align8=1 -> push {r0, r1} > prologue 1 push_ip=1 -> push {r1, ip} > prologue 1 4 -> push {r1-r4} > prologue 1 4 push_ip=1 -> push {r1-r4, ip} can you include an example with pacbti? > * epilogue: pops registers off the stack and emits pac key signing > instruction, if requested. The `first', `last', `push_ip', > `push_lr' and `align' function as per the prologue macro, > generating pop instead of push instructions. > > Stack alignment is enforced via the following helper macro > call-chain: > > {prologue|epilogue} ->_align8 -> _preprocess_reglist -> > _preprocess_reglist1 -> {_prologue|_epilogue} > > Finally, the necessary cfi directives for adding debug information > to prologue and epilogue are generated via the following macros: > > * cfisavelist - prologue macro helper function, generating > necessary .cfi_offset directives associated with push instruction. > Therefore, the net effect of calling `prologue 1 2 push_ip=1' is > to generate the following: > > push {r1-r2, ip} > .cfi_adjust_cfa_offset 12 > .cfi_offset 143, -4 > .cfi_offset 2, -8 > .cfi_offset 1, -12 > > * cfirestorelist - epilogue macro helper function, emitting > .cfi_restore instructions prior to resetting the cfa offset. As > such, calling `epilogue 1 2 push_ip=1' will produce: > > pop {r1-r2, ip} > .cfi_register 143, 12 > .cfi_restore 2 > .cfi_restore 1 > .cfi_def_cfa_offset 0 > --- > newlib/libc/machine/arm/arm_asm.h | 441 ++++++++++++++++++++++++++++++ > 1 file changed, 441 insertions(+) > > diff --git a/newlib/libc/machine/arm/arm_asm.h b/newlib/libc/machine/arm/arm_asm.h > index 2708057de..94fa77b4d 100644 > --- a/newlib/libc/machine/arm/arm_asm.h > +++ b/newlib/libc/machine/arm/arm_asm.h > @@ -60,4 +60,445 @@ > # define _ISA_THUMB_1 > #endif > > +/* Check whether leaf function PAC signing has been requested in the > + -mbranch-protect compile-time option. */ > +#define LEAF_PROTECT_BIT 2 Shouldn't this start with '__' or be #undefed at the end of this file to avoid polluting user naming space? (I noticed it's not used outside this file in this patch series) > + > +#ifdef __ARM_FEATURE_PAC_DEFAULT > +# define HAVE_PAC_LEAF \ > + ((__ARM_FEATURE_PAC_DEFAULT & (1 << LEAF_PROTECT_BIT)) && 1) > +#else > +# define HAVE_PAC_LEAF 0 > +#endif > + > +/* Provide default parameters for PAC-code handling in leaf-functions. */ > +#if HAVE_PAC_LEAF > +# ifndef PAC_LEAF_PUSH_IP > +# define PAC_LEAF_PUSH_IP 1 > +# endif > +#else /* !HAVE_PAC_LEAF */ > +# undef PAC_LEAF_PUSH_IP > +# define PAC_LEAF_PUSH_IP 0 > +#endif /* HAVE_PAC_LEAF */ > + > +#define STACK_ALIGN_ENFORCE 0 > + > +#ifdef __ASSEMBLER__ > + > +/****************************************************************************** > +* Implementation of the prologue and epilogue assembler macros and their > +* associated helper functions. > +* > +* These functions add support for the following: > +* > +* - M-profile branch target identification (BTI) landing-pads when compiled > +* with `-mbranch-protection=bti'. > +* - PAC-signing and verification instructions, depending on hardware support > +* and whether the PAC-signing of leaf functions has been requested via the > +* `-mbranch-protection=pac-ret+leaf' compiler argument. > +* - 8-byte stack alignment preservation at function entry, defaulting to the > +* value of STACK_ALIGN_ENFORCE. > +* > +* Notes: > +* - Prologue stack alignment is implemented by detecting a push with an odd > +* number of registers and prepending a dummy register to the list. > +* - If alignment is attempted on a list containing r0, compilation will result > +* in an error. > +* - If alignment is attempted in a list containing r1, r0 will be prepended to > +* the register list and r0 will be restored prior to function return. for > +* functions with non-void return types, this will result in the corruption of > +* the result register. > +* - Stack alignment is enforced via the following helper macro call-chain: > +* > +* {prologue|epilogue} ->_align8 -> _preprocess_reglist -> > +* _preprocess_reglist1 -> {_prologue|_epilogue} > +* > +* - Debug CFI directives are automatically added to prologues and epilogues, > +* assisted by `cfisavelist' and `cfirestorelist', respectively. > +* > +* Arguments: > +* prologue > +* -------- > +* - first - If `last' specified, this serves as start of general-purpose > +* register (GPR) range to push onto stack, otherwise represents > +* single GPR to push onto stack. If omitted, no GPRs pushed > +* onto stack at prologue. > +* - last - If given, specifies inclusive upper-bound of GPR range. > +* - push_ip - Determines whether IP register is to be pushed to stack at > +* prologue. When pac-signing is requested, this holds the > +* the pac-key. Either 1 or 0 to push or not push, respectively. > +* Default behavior: Set to value of PAC_LEAF_PUSH_IP macro. > +* - push_lr - Determines whether to push lr to the stack on function entry. > +* Either 1 or 0 to push or not push, respectively. > +* - align8 - Whether to enforce alignment. Either 1 or 0, with 1 requesting > +* alignment. > +* > +* epilogue > +* -------- > +* The epilogue should be called passing the same arguments as those passed to > +* the prologue to ensure the stack is not corrupted on function return. > +* > +* Usage examples: > +* > +* prologue push_ip=1 -> push {ip} > +* epilogue push_ip=1, align8=1 -> pop {r2, ip} > +* prologue push_ip=1, push_lr=1 -> push {ip, lr} > +* epilogue 1 -> pop {r1} > +* prologue 1, align8=1 -> push {r0, r1} > +* epilogue 1, push_ip=1 -> pop {r1, ip} > +* prologue 1, 4 -> push {r1-r4} > +* epilogue 1, 4 push_ip=1 -> pop {r1-r4, ip} > +* > +******************************************************************************/ > + > +/* Emit .cfi_restore directives for a consecutive sequence of registers. */ > + .macro cfirestorelist first, last > + .cfi_restore \last > + .if \last-\first > + cfirestorelist \first, \last-1 > + .endif > + .endm > + > +/* Emit .cfi_offset directives for a consecutive sequence of registers. */ > + .macro cfisavelist first, last, index=1 > + .cfi_offset \last, -4*(\index) > + .if \last-\first > + cfisavelist \first, \last-1, \index+1 > + .endif > + .endm > + > +.macro _prologue first=-1, last=-1, push_ip=PAC_LEAF_PUSH_IP, push_lr=0 > + .if \push_ip & 1 != \push_ip > + .error "push_ip may be either 0 or 1" > + .endif > + .if \push_lr & 1 != \push_lr > + .error "push_lr may be either 0 or 1" > + .endif > + .if \first != -1 > + .if \last == -1 > + /* Upper-bound not provided: Set upper = lower. */ > + _prologue \first, \first, \push_ip, \push_lr > + .exitm > + .endif > + .endif > +#if HAVE_PAC_LEAF > +#if __ARM_FEATURE_BTI_DEFAULT > + pacbti ip, lr, sp > +#else > + pac ip, lr, sp > +#endif /* __ARM_FEATURE_BTI_DEFAULT */ > + .cfi_register 143, 12 > +#else > +#if __ARM_FEATURE_BTI_DEFAULT > + bti > +#endif /* __ARM_FEATURE_BTI_DEFAULT */ > +#endif /* HAVE_PAC_LEAF */ > + .if \first != -1 > + .if \last != \first > + .if \last >= 13 > + .error "SP cannot be in the save list" > + .endif I think you should also check that IP (r12) is not in the range, otherwise I think nothing prevents from doing prologue 12, push_ip=1 which will result in emitting push {r12, ip} (I suppose gas would complain?) .... scratch that, I saw later that this sanity checking is performed in _preprocess_reglist1 :-) > + .if \push_ip > + .if \push_lr > + /* Case 1: push register range, ip and lr registers. */ > + push {r\first-r\last, ip, lr} > + .cfi_adjust_cfa_offset ((\last-\first)+3)*4 > + .cfi_offset 14, -4 > + .cfi_offset 143, -8 > + cfisavelist \first, \last, 3 > + .else // !\push_lr > + /* Case 2: push register range and ip register. */ > + push {r\first-r\last, ip} > + .cfi_adjust_cfa_offset ((\last-\first)+2)*4 > + .cfi_offset 143, -4 > + cfisavelist \first, \last, 2 > + .endif > + .else // !\push_ip > + .if \push_lr > + /* Case 3: push register range and lr register. */ > + push {r\first-r\last, lr} > + .cfi_adjust_cfa_offset ((\last-\first)+2)*4 > + .cfi_offset 14, -4 > + cfisavelist \first, \last, 2 > + .else // !\push_lr > + /* Case 4: push register range. */ > + push {r\first-r\last} > + .cfi_adjust_cfa_offset ((\last-\first)+1)*4 > + cfisavelist \first, \last, 1 > + .endif > + .endif > + .else // \last == \first > + .if \push_ip > + .if \push_lr > + /* Case 5: push single GP register plus ip and lr registers. */ > + push {r\first, ip, lr} > + .cfi_adjust_cfa_offset 12 > + .cfi_offset 14, -4 > + .cfi_offset 143, -8 > + cfisavelist \first, \first, 3 > + .else // !\push_lr > + /* Case 6: push single GP register plus ip register. */ > + push {r\first, ip} > + .cfi_adjust_cfa_offset 8 > + .cfi_offset 143, -4 > + cfisavelist \first, \first, 2 > + .endif > + .else // !\push_ip > + .if \push_lr > + /* Case 7: push single GP register plus lr register. */ > + push {r\first, lr} > + .cfi_adjust_cfa_offset 8 > + .cfi_offset 14, -4 > + cfisavelist \first, \first, 2 > + .else // !\push_lr > + /* Case 8: push single GP register. */ > + push {r\first} > + .cfi_adjust_cfa_offset 4 > + cfisavelist \first, \first, 1 > + .endif > + .endif > + .endif > + .else // \first == -1 > + .if \push_ip > + .if \push_lr > + /* Case 9: push ip and lr registers. */ > + push {ip, lr} > + .cfi_adjust_cfa_offset 8 > + .cfi_offset 14, -4 > + .cfi_offset 143, -8 > + .else // !\push_lr > + /* Case 10: push ip register. */ > + push {ip} > + .cfi_adjust_cfa_offset 4 > + .cfi_offset 143, -4 > + .endif > + .else // !\push_ip > + .if \push_lr > + /* Case 11: push lr register. */ > + push {lr} > + .cfi_adjust_cfa_offset 4 > + .cfi_offset 14, -4 > + .endif > + .endif > + .endif > +.endm > + > +.macro _epilogue first=-1, last=-1, push_ip=PAC_LEAF_PUSH_IP, push_lr=0 > + .if \push_ip & 1 != \push_ip > + .error "push_ip may be either 0 or 1" > + .endif > + .if \push_lr & 1 != \push_lr > + .error "push_lr may be either 0 or 1" > + .endif > + .if \first != -1 > + .if \last == -1 > + /* Upper-bound not provided: Set upper = lower. */ > + _epilogue \first, \first, \push_ip, \push_lr > + .exitm > + .endif > + .if \last != \first > + .if \last >= 13 > + .error "SP cannot be in the save list" > + .endif > + .if \push_ip > + .if \push_lr > + /* Case 1: pop register range, ip and lr registers. */ > + pop {r\first-r\last, ip, lr} > + .cfi_restore 14 > + .cfi_register 143, 12 > + cfirestorelist \first, \last > + .else // !\push_lr > + /* Case 2: pop register range and ip register. */ > + pop {r\first-r\last, ip} > + .cfi_register 143, 12 > + cfirestorelist \first, \last > + .endif > + .else // !\push_ip > + .if \push_lr > + /* Case 3: pop register range and lr register. */ > + pop {r\first-r\last, lr} > + .cfi_restore 14 > + cfirestorelist \first, \last > + .else // !\push_lr > + /* Case 4: pop register range. */ > + pop {r\first-r\last} > + cfirestorelist \first, \last > + .endif > + .endif > + .else // \last == \first > + .if \push_ip > + .if \push_lr > + /* Case 5: pop single GP register plus ip and lr registers. */ > + pop {r\first, ip, lr} > + .cfi_restore 14 > + .cfi_register 143, 12 > + cfirestorelist \first, \first > + .else // !\push_lr > + /* Case 6: pop single GP register plus ip register. */ > + pop {r\first, ip} > + .cfi_register 143, 12 > + cfirestorelist \first, \first > + .endif > + .else // !\push_ip > + .if \push_lr > + /* Case 7: pop single GP register plus lr register. */ > + pop {r\first, lr} > + .cfi_restore 14 > + cfirestorelist \first, \first > + .else // !\push_lr > + /* Case 8: pop single GP register. */ > + pop {r\first} > + cfirestorelist \first, \first > + .endif > + .endif > + .endif > + .else // \first == -1 > + .if \push_ip > + .if \push_lr > + /* Case 9: pop ip and lr registers. */ > + pop {ip, lr} > + .cfi_restore 14 > + .cfi_register 143, 12 > + .else // !\push_lr > + /* Case 10: pop ip register. */ > + pop {ip} > + .cfi_register 143, 12 > + .endif > + .else // !\push_ip > + .if \push_lr > + /* Case 11: pop lr register. */ > + pop {lr} > + .cfi_restore 14 > + .endif > + .endif > + .endif > +#if HAVE_PAC_LEAF > + aut ip, lr, sp > +#endif /* HAVE_PAC_LEAF */ > + bx lr > +.endm > + > +# clean up expressions in 'last' > +.macro _preprocess_reglist1 first:req, last:req, push_ip:req, push_lr:req, reglist_op:req > + .if \last == 0 > + \reglist_op \first, 0, \push_ip, \push_lr > + .elseif \last == 1 > + \reglist_op \first, 1, \push_ip, \push_lr > + .elseif \last == 2 > + \reglist_op \first, 2, \push_ip, \push_lr > + .elseif \last == 3 > + \reglist_op \first, 3, \push_ip, \push_lr > + .elseif \last == 4 > + \reglist_op \first, 4, \push_ip, \push_lr > + .elseif \last == 5 > + \reglist_op \first, 5, \push_ip, \push_lr > + .elseif \last == 6 > + \reglist_op \first, 6, \push_ip, \push_lr > + .elseif \last == 7 > + \reglist_op \first, 7, \push_ip, \push_lr > + .elseif \last == 8 > + \reglist_op \first, 8, \push_ip, \push_lr > + .elseif \last == 9 > + \reglist_op \first, 9, \push_ip, \push_lr > + .elseif \last == 10 > + \reglist_op \first, 10, \push_ip, \push_lr > + .elseif \last == 11 > + \reglist_op \first, 11, \push_ip, \push_lr > + .else > + .error "last (\last) out of range" > + .endif > +.endm > + > +# clean up expressions in 'first' > +.macro _preprocess_reglist first:req, last, push_ip=0, push_lr=0, reglist_op:req > + .ifb \last > + _preprocess_reglist \first \first \push_ip \push_lr > + .else > + .if \first > \last > + .error "last (\last) must be at least as great as first (\first)" > + .endif > + .if \first == 0 > + _preprocess_reglist1 0, \last, \push_ip, \push_lr, \reglist_op > + .elseif \first == 1 > + _preprocess_reglist1 1, \last, \push_ip, \push_lr, \reglist_op > + .elseif \first == 2 > + _preprocess_reglist1 2, \last, \push_ip, \push_lr, \reglist_op > + .elseif \first == 3 > + _preprocess_reglist1 3, \last, \push_ip, \push_lr, \reglist_op > + .elseif \first == 4 > + _preprocess_reglist1 4, \last, \push_ip, \push_lr, \reglist_op > + .elseif \first == 5 > + _preprocess_reglist1 5, \last, \push_ip, \push_lr, \reglist_op > + .elseif \first == 6 > + _preprocess_reglist1 6, \last, \push_ip, \push_lr, \reglist_op > + .elseif \first == 7 > + _preprocess_reglist1 7, \last, \push_ip, \push_lr, \reglist_op > + .elseif \first == 8 > + _preprocess_reglist1 8, \last, \push_ip, \push_lr, \reglist_op > + .elseif \first == 9 > + _preprocess_reglist1 9, \last, \push_ip, \push_lr, \reglist_op > + .elseif \first == 10 > + _preprocess_reglist1 10, \last, \push_ip, \push_lr, \reglist_op > + .elseif \first == 11 > + _preprocess_reglist1 11, \last, \push_ip, \push_lr, \reglist_op > + .else > + .error "first (\first) out of range" > + .endif > + .endif > +.endm > + > +.macro _align8 first, last, push_ip=0, push_lr=0, reglist_op=_prologue > + .ifb \first > + .ifnb \last > + .error "can't have last (\last) without specifying first" > + .else // \last not blank > + .if ((\push_ip + \push_lr) % 2) == 0 > + \reglist_op first=-1, last=-1, push_ip=\push_ip, push_lr=\push_lr > + .exitm > + .else // ((\push_ip + \push_lr) % 2) odd > + _align8 2, 2, \push_ip, \push_lr, \reglist_op > + .exitm > + .endif // ((\push_ip + \push_lr) % 2) == 0 > + .endif // .ifnb \last > + .endif // .ifb \first > + > + .ifb \last > + _align8 \first, \first, \push_ip, \push_lr, \reglist_op > + .else > + .if \push_ip & 1 <> \push_ip > + .error "push_ip may be 0 or 1" > + .endif > + .if \push_lr & 1 <> \push_lr > + .error "push_lr may be 0 or 1" > + .endif > + .ifeq (\last - \first + \push_ip + \push_lr) % 2 > + .if \first == 0 > + .error "Alignment required and first register is r0" > + .exitm > + .endif > + _preprocess_reglist \first-1, \last, \push_ip, \push_lr, \reglist_op > + .else > + _preprocess_reglist \first \last, \push_ip, \push_lr, \reglist_op > + .endif > + .endif > +.endm > + > +.macro prologue first, last, push_ip=PAC_LEAF_PUSH_IP, push_lr=0, align8=STACK_ALIGN_ENFORCE > + .if \align8 > + _align8 \first, \last, \push_ip, \push_lr, _prologue > + .else > + _prologue first=\first, last=\last, push_ip=\push_ip, push_lr=\push_lr > + .endif > +.endm > + > +.macro epilogue first, last, push_ip=PAC_LEAF_PUSH_IP, push_lr=0, align8=STACK_ALIGN_ENFORCE > + .if \align8 > + _align8 \first, \last, \push_ip, \push_lr, reglist_op=_epilogue > + .else > + _epilogue first=\first, last=\last, push_ip=\push_ip, push_lr=\push_lr > + .endif > +.endm > + > +#endif /* __ASSEMBLER__ */ > + > #endif /* ARM_ASM__H */