From patchwork Fri Jan 6 11:47:31 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiong Wang X-Patchwork-Id: 90150 Delivered-To: patch@linaro.org Received: by 10.182.224.138 with SMTP id rc10csp295400obc; Fri, 6 Jan 2017 03:48:46 -0800 (PST) X-Received: by 10.99.241.21 with SMTP id f21mr140950841pgi.110.1483703326781; Fri, 06 Jan 2017 03:48:46 -0800 (PST) Return-Path: Received: from sourceware.org (server1.sourceware.org. [209.132.180.131]) by mx.google.com with ESMTPS id o33si79342945plb.300.2017.01.06.03.48.46 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 06 Jan 2017 03:48:46 -0800 (PST) Received-SPF: pass (google.com: domain of gcc-patches-return-445526-patch=linaro.org@gcc.gnu.org designates 209.132.180.131 as permitted sender) client-ip=209.132.180.131; Authentication-Results: mx.google.com; dkim=pass header.i=@gcc.gnu.org; spf=pass (google.com: domain of gcc-patches-return-445526-patch=linaro.org@gcc.gnu.org designates 209.132.180.131 as permitted sender) smtp.mailfrom=gcc-patches-return-445526-patch=linaro.org@gcc.gnu.org DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :subject:to:references:cc:from:message-id:date:mime-version :in-reply-to:content-type; q=dns; s=default; b=Pd8hrb6B9dxgr1i8z un3vIIbkM3oqOp53GnudjXAC5Ew4NlSAQOMhfef6qDHuHZMm1hHt7aEE/D/TU1Vm dtkcMG/hnWP/55p5U7VqMgQ4Sh09EvOyQ/Rwasqr5hRJcUNWozdMXTRkeAX5LSRd CA3AIDOrFNRSwsW006WnoaJUfk= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :subject:to:references:cc:from:message-id:date:mime-version :in-reply-to:content-type; s=default; bh=5qYjLo9IgLBAbePMUC2Vuly /Xfw=; b=odBFV2XnTM3dLHPgWCdBeq/+bDZBVEBf4gSta215v5GX+8DQ2rL2FF3 J/tQgmX6y2/cpDiZxSLT1uqVpZJ656PC+MJZRAjtGzX6cqyuitnIjAkH+1x7UfeB W5ezrcWu+zLpDSXD+6LyQwz1TlMpc6RIAqpv6QvuwVmKTcTmDItc= Received: (qmail 20561 invoked by alias); 6 Jan 2017 11:47:46 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 20457 invoked by uid 89); 6 Jan 2017 11:47:45 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-4.1 required=5.0 tests=BAYES_00, KAM_LAZY_DOMAIN_SECURITY, RP_MATCHES_RCVD autolearn=ham version=3.3.2 spammy=encouraged, cie, multi, resign X-HELO: foss.arm.com Received: from foss.arm.com (HELO foss.arm.com) (217.140.101.70) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 06 Jan 2017 11:47:35 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id B6473152D; Fri, 6 Jan 2017 03:47:33 -0800 (PST) Received: from [10.2.206.198] (e104437-lin.cambridge.arm.com [10.2.206.198]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 0329A3F220; Fri, 6 Jan 2017 03:47:32 -0800 (PST) Subject: [5/5][AArch64, libgcc] Runtime support for AArch64 DWARF operations To: gcc-patches References: <4cf21d03-0a88-c6fa-df37-59ec4edf1d89@foss.arm.com> <60457276-8566-8bef-6073-4b00dd975759@foss.arm.com> <1e3f0dce-74c8-5a80-ed5a-7e6feeec1e63@foss.arm.com> <97fad7f9-cb42-ab1c-f039-ba42d5dc72c8@foss.arm.com> Cc: James Greenhalgh , "Richard Earnshaw (lists)" , Ian Lance Taylor From: Jiong Wang Message-ID: Date: Fri, 6 Jan 2017 11:47:31 +0000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.6.0 MIME-Version: 1.0 In-Reply-To: X-IsSubscribed: yes On 11/11/16 18:22, Jiong Wang wrote: > This patch add AArch64 specific runtime EH unwinding support for > DW_OP_AARCH64_pauth, DW_OP_AARCH64_paciasp and DW_OP_AARCH64_paciasp_deref. > > The semantics of them are described at the specification in patch [1/9]. > > The support includes: > * Parsing these DWARF operations. Perform unwinding actions according to > their semantics. > > * Handling eh_return multi return paths. > Function calling __builtin_eh_return (_Unwind_RaiseException*) will have > multiple return paths. One is for normal exit, the other is for install > EH handler. If the _Unwind_RaiseException itself is return address signed, > then there will always be return address authentication before return, > however, if the return path in _Unwind_RaiseException if from installing EH > handler the address of which has already been authenticated during > unwinding, then we need to re-sign that address, so when the execution flow > continues at _Unwind_RaiseException's epilogue, the authentication still > works correctly. > > > OK for trunk? > > libgcc/ > 2016-11-11 Jiong Wang > > * config/aarch64/unwind-aarch64.c (RA_SIGN_BIT): New flag to indicate > one frame is return address signed. > (execute_stack_op): Handle DW_OP_AARCH64_pauth, DW_OP_AARCH64_paciasp, > DW_OP_AARCH64_paciasp_deref. > (uw_init_context): Call aarch64_uw_init_context_1. > (uw_init_context_1): Rename to aarch64_uw_init_context_1. Strip > signature for seed address. > (uw_install_context): Re-sign handler's address so it works correctly > with caller's context. > (uw_install_context_1): by_value[LR] can be true, after return address > signing LR will come from DWARF value expression rule which is a > by_value true rule. > > This is the update on libgcc unwinder support according to new DWARF proposal. As Joseph commented, duplication of unwind-dw2.c is not encouraged in libgcc, But from this patch, you can see there are a few places we need to modify for AArch64 in unwind-aarch64.c, so the file duplication approach is acceptable? libgcc/ 2017-01-06 Jiong Wang * config/aarch64/unwind-aarch64.c (DWARF_REGNUM_AARCH64_RA_STATE, RA_A_SIGNED_BIT): New macros. (execute_cfa_program): Multiplex DW_CFA_GNU_window_save on AArch64. (uw_frame_state_for): Clear bit[0] of DWARF_REGNUM_AARCH64_RA_STATE. (uw_update_context): Authenticate return address according to DWARF_REGNUM_AARCH64_RA_STATE. (uw_init_context_1): Strip signature of seed address. (uw_install_context): Re-authenticate EH handler's address. diff --git a/libgcc/config/aarch64/unwind-aarch64.c b/libgcc/config/aarch64/unwind-aarch64.c index 1fb6026d123f8e7fc676f5e95e8e66caccf3d6ff..11e3c9f724c9bc5796103a0d973bfe769d23b6e7 100644 --- a/libgcc/config/aarch64/unwind-aarch64.c +++ b/libgcc/config/aarch64/unwind-aarch64.c @@ -37,6 +37,9 @@ #include "gthr.h" #include "unwind-dw2.h" +/* This is a copy of libgcc/unwind-dw2.c with AArch64 return address signing + support. */ + #ifdef HAVE_SYS_SDT_H #include #endif @@ -55,6 +58,8 @@ #define PRE_GCC3_DWARF_FRAME_REGISTERS __LIBGCC_DWARF_FRAME_REGISTERS__ #endif +#define DWARF_REGNUM_AARCH64_RA_STATE 32 + /* ??? For the public function interfaces, we tend to gcc_assert that the column numbers are in range. For the dwarf2 unwind info this does happen, although so far in a case that doesn't actually matter. @@ -136,6 +141,8 @@ struct _Unwind_Context #define SIGNAL_FRAME_BIT ((~(_Unwind_Word) 0 >> 1) + 1) /* Context which has version/args_size/by_value fields. */ #define EXTENDED_CONTEXT_BIT ((~(_Unwind_Word) 0 >> 2) + 1) + /* Return address has been signed with A key. */ +#define RA_A_SIGNED_BIT ((~(_Unwind_Word) 0 >> 3) + 1) _Unwind_Word flags; /* 0 for now, can be increased when further fields are added to struct _Unwind_Context. */ @@ -1185,13 +1192,9 @@ execute_cfa_program (const unsigned char *insn_ptr, break; case DW_CFA_GNU_window_save: - /* ??? Hardcoded for SPARC register window configuration. */ - if (__LIBGCC_DWARF_FRAME_REGISTERS__ >= 32) - for (reg = 16; reg < 32; ++reg) - { - fs->regs.reg[reg].how = REG_SAVED_OFFSET; - fs->regs.reg[reg].loc.offset = (reg - 16) * sizeof (void *); - } + /* This CFA is multiplexed with Sparc. On AArch64 it's used to toggle + return address signing status. */ + fs->regs.reg[DWARF_REGNUM_AARCH64_RA_STATE].loc.offset ^= 1; break; case DW_CFA_GNU_args_size: @@ -1263,6 +1266,8 @@ uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs) /* First decode all the insns in the CIE. */ end = (const unsigned char *) next_fde ((const struct dwarf_fde *) cie); execute_cfa_program (insn, end, context, fs); + /* Clear bit 0 of RA_STATE pseudo register. */ + fs->regs.reg[DWARF_REGNUM_AARCH64_RA_STATE].loc.offset &= ~0x1; /* Locate augmentation for the fde. */ aug = (const unsigned char *) fde + sizeof (*fde); @@ -1513,10 +1518,19 @@ uw_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs) stack frame. */ context->ra = 0; else - /* Compute the return address now, since the return address column - can change from frame to frame. */ - context->ra = __builtin_extract_return_addr - (_Unwind_GetPtr (context, fs->retaddr_column)); + { + /* Compute the return address now, since the return address column + can change from frame to frame. */ + context->ra + = __builtin_extract_return_addr (_Unwind_GetPtr (context, + fs->retaddr_column)); + if (fs->regs.reg[DWARF_REGNUM_AARCH64_RA_STATE].loc.offset & 0x1) + { + _Unwind_Word salt = (_Unwind_Word) context->cfa; + context->ra + = (void *) __builtin_aarch64_autia1716 (context->ra, salt); + } + } } static void @@ -1550,6 +1564,11 @@ uw_init_context_1 (struct _Unwind_Context *context, void *outer_cfa, void *outer_ra) { void *ra = __builtin_extract_return_addr (__builtin_return_address (0)); + /* Drop authentication signature for inner RA. It's anyway will be + authenticated later before return if return addresss signing is enabled for + libgcc. Here it's served as the seed address which will be used for table + searching, we need the original address. */ + ra = __builtin_aarch64_xpaclri (ra); _Unwind_FrameState fs; _Unwind_SpTmp sp_slot; _Unwind_Reason_Code code; @@ -1586,6 +1605,10 @@ uw_init_context_1 (struct _Unwind_Context *context, initialization context, then we can't see it in the given call frame data. So have the initialization context tell us. */ context->ra = __builtin_extract_return_addr (outer_ra); + context->ra = __builtin_aarch64_xpaclri (context->ra); + if (fs.regs.reg[DWARF_REGNUM_AARCH64_RA_STATE].loc.offset & 0x1) + /* The flag is used for re-authenticating EH handler's address. */ + context->flags |= RA_A_SIGNED_BIT; } static void _Unwind_DebugHook (void *, void *) @@ -1610,13 +1633,22 @@ _Unwind_DebugHook (void *cfa __attribute__ ((__unused__)), /* Install TARGET into CURRENT so that we can return to it. This is a macro because __builtin_eh_return must be invoked in the context of - our caller. */ + our caller. + + For AArch64 pointer authentication, as target EH handler's address is + already authenticated, we need to sign it again with the original SP + of CURRENT. */ #define uw_install_context(CURRENT, TARGET) \ do \ { \ long offset = uw_install_context_1 ((CURRENT), (TARGET)); \ void *handler = __builtin_frob_return_addr ((TARGET)->ra); \ + if ((CURRENT)->flags & RA_A_SIGNED_BIT) \ + handler \ + = __builtin_aarch64_pacia1716 (handler, \ + (_Unwind_Word) \ + (CURRENT)->cfa); \ _Unwind_DebugHook ((TARGET)->cfa, handler); \ __builtin_eh_return (offset, handler); \ } \