From patchwork Thu Jan 12 18:10:36 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiong Wang X-Patchwork-Id: 91202 Delivered-To: patch@linaro.org Received: by 10.140.20.99 with SMTP id 90csp1747374qgi; Thu, 12 Jan 2017 10:11:29 -0800 (PST) X-Received: by 10.84.218.77 with SMTP id f13mr23437551plm.141.1484244689243; Thu, 12 Jan 2017 10:11:29 -0800 (PST) Return-Path: Received: from sourceware.org (server1.sourceware.org. [209.132.180.131]) by mx.google.com with ESMTPS id z4si9970425pgb.25.2017.01.12.10.11.28 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 12 Jan 2017 10:11:29 -0800 (PST) Received-SPF: pass (google.com: domain of gcc-patches-return-445991-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-445991-patch=linaro.org@gcc.gnu.org designates 209.132.180.131 as permitted sender) smtp.mailfrom=gcc-patches-return-445991-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=mIZiYYJDc06PKgeYD lsik3vO4j09lf69VrARoEgaD5ZzRk8MggwGKJ+i7rC64fHSl/uDKdor4Agugigcx HlRKzHdoMir1wLaW8SmWy1Q5bcSen0VaHx3IHrg6spUZw2bcy7tSioX8HGiOsPya /A2JHweOGxpuJQebZANJiMo6sk= 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=T30juTCf9vif++MIA7dPlPi w7dU=; b=TUUyR9eUfQd5Dx7Nw0VseT/ejZVBtDJOOsGpmtIhl1tiPsnuw9tjYQ6 b7bF6BgBH+5Df+wWBdqE62Lo4RcxDafGWIi7czctYB9EY8qrVwndqc5C1hZcculd enkhpsz9Bui0hUT21nrSX4M7KZ5uBzQu0Mg395XCrFXzjsAerrow= Received: (qmail 76436 invoked by alias); 12 Jan 2017 18:10:52 -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 76324 invoked by uid 89); 12 Jan 2017 18:10:51 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.1 required=5.0 tests=BAYES_50, KAM_LAZY_DOMAIN_SECURITY, KAM_LOTSOFHASH, RP_MATCHES_RCVD autolearn=ham version=3.3.2 spammy=11856, 1185, 6, tmake_file, sk:signal_ 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; Thu, 12 Jan 2017 18:10:41 +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 C3E8AAD7; Thu, 12 Jan 2017 10:10:39 -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 E2A5B3F24D; Thu, 12 Jan 2017 10:10:38 -0800 (PST) Subject: [Ping~]Re: [5/5][AArch64, libgcc] Runtime support for AArch64 return address signing (also attached target macros version) 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 , Joseph Myers From: Jiong Wang Message-ID: Date: Thu, 12 Jan 2017 18:10:36 +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 06/01/17 11:47, Jiong Wang wrote: > 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. > Ping~ For comparision, I have also attached the patch using the target macros. Four new target macros are introduced: MD_POST_EXTRACT_ROOT_ADDR MD_POST_EXTRACT_FRAME_ADDR MD_POST_FROB_EH_HANDLER_ADDR MD_POST_INIT_CONTEXT MD_POST_EXTRACT_ROOT_ADDR is to do target private post processing on the address inside _Unwind* functions, they are serving as root address to start the unwinding. MD_POST_EXTRACT_FRAME_ADDR is to do target private post processing on th address inside the real user program which throws the exceptions. MD_POST_FROB_EH_HANDLER_ADDR is to do target private frob on the EH handler's address before we install it into current context. MD_POST_INIT_CONTEXT it to do target private initialization on the context structure after common initialization. One "__aarch64__" macro check is needed to multiplex DW_CFA_window_save. libgcc/ChangeLog: 2017-01-11 Jiong Wang * config/aarch64/aarch64-unwind.h: New file. (DWARF_REGNUM_AARCH64_RA_STATE): Define. (MD_POST_EXTRACT_ROOT_ADDR): Define. (MD_POST_EXTRACT_FRAME_ADDR): Define. (MD_POST_FROB_EH_HANDLER_ADDR): Define. (MD_POST_INIT_CONTEXT): Define. * config/aarch64/linux-unwind.h: Include aarch64-unwind.h * config.host (aarch64*-*-elf, aarch64*-*-rtems*, aarch64*-*-freebsd*): Initialize md_unwind_header to include aarch64-unwind.h. * unwind-dw2.c (struct _Unwind_Context): Define "RA_A_SIGNED_BIT". (execute_cfa_program): Multiplex DW_CFA_GNU_window_save for __aarch64__. (uw_update_context): Honor MD_POST_EXTRACT_FRAME_ADDR. (uw_init_context_1): Honor MD_POST_EXTRACT_ROOT_ADDR and MD_POST_INIT_CONTEXT. (uw_frob_return_addr): New function. (_Unwind_DebugHook): Use uw_frob_return_addr. diff --git a/libgcc/unwind-dw2.c b/libgcc/unwind-dw2.c index 8085a42ace15d53f4cb0c6681717012d906a6d47..35010a4065bb83f706701cb05392193f0ffa1f11 100644 --- a/libgcc/unwind-dw2.c +++ b/libgcc/unwind-dw2.c @@ -136,6 +136,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) + /* Bit reserved on AArch64, 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,6 +1187,11 @@ execute_cfa_program (const unsigned char *insn_ptr, break; case DW_CFA_GNU_window_save: +#ifdef __aarch64__ + /* 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; +#else /* ??? Hardcoded for SPARC register window configuration. */ if (__LIBGCC_DWARF_FRAME_REGISTERS__ >= 32) for (reg = 16; reg < 32; ++reg) @@ -1192,6 +1199,7 @@ execute_cfa_program (const unsigned char *insn_ptr, fs->regs.reg[reg].how = REG_SAVED_OFFSET; fs->regs.reg[reg].loc.offset = (reg - 16) * sizeof (void *); } +#endif break; case DW_CFA_GNU_args_size: @@ -1513,10 +1521,15 @@ 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)); +#ifdef MD_POST_EXTRACT_FRAME_ADDR + context->ra = MD_POST_EXTRACT_FRAME_ADDR (context, fs, context->ra); +#endif + } } static void @@ -1550,6 +1563,9 @@ uw_init_context_1 (struct _Unwind_Context *context, void *outer_cfa, void *outer_ra) { void *ra = __builtin_extract_return_addr (__builtin_return_address (0)); +#ifdef MD_POST_EXTRACT_ROOT_ADDR + ra = MD_POST_EXTRACT_ROOT_ADDR (ra); +#endif _Unwind_FrameState fs; _Unwind_SpTmp sp_slot; _Unwind_Reason_Code code; @@ -1586,6 +1602,12 @@ 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); +#ifdef MD_POST_EXTRACT_ROOT_ADDR + context->ra = MD_POST_EXTRACT_ROOT_ADDR (context->ra); +#endif +#ifdef MD_POST_INIT_CONTEXT + MD_POST_INIT_CONTEXT (context, &fs); +#endif } static void _Unwind_DebugHook (void *, void *) @@ -1608,6 +1630,20 @@ _Unwind_DebugHook (void *cfa __attribute__ ((__unused__)), #endif } +/* Frob exception handler's address kept in TARGET before installing into + CURRENT context. */ + +static void * +uw_frob_return_addr (struct _Unwind_Context *current, + struct _Unwind_Context *target) +{ + void *ret_addr = __builtin_frob_return_addr (target->ra); +#ifdef MD_POST_FROB_EH_HANDLER_ADDR + ret_addr = MD_POST_FROB_EH_HANDLER_ADDR (current, target, ret_addr); +#endif + return ret_addr; +} + /* 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. */ @@ -1616,7 +1652,7 @@ _Unwind_DebugHook (void *cfa __attribute__ ((__unused__)), do \ { \ long offset = uw_install_context_1 ((CURRENT), (TARGET)); \ - void *handler = __builtin_frob_return_addr ((TARGET)->ra); \ + void *handler = uw_frob_return_addr ((CURRENT), (TARGET)); \ _Unwind_DebugHook ((TARGET)->cfa, handler); \ __builtin_eh_return (offset, handler); \ } \ diff --git a/libgcc/config.host b/libgcc/config.host index 6f2e458e74e776a6b7a310919558bcca76389232..540bfa9635802adabb36a2d1b7cf3416462c59f3 100644 --- a/libgcc/config.host +++ b/libgcc/config.host @@ -331,11 +331,13 @@ aarch64*-*-elf | aarch64*-*-rtems*) extra_parts="$extra_parts crtfastmath.o" tmake_file="${tmake_file} ${cpu_type}/t-aarch64" tmake_file="${tmake_file} ${cpu_type}/t-softfp t-softfp t-crtfm" + md_unwind_header=aarch64/aarch64-unwind.h ;; aarch64*-*-freebsd*) extra_parts="$extra_parts crtfastmath.o" tmake_file="${tmake_file} ${cpu_type}/t-aarch64" tmake_file="${tmake_file} ${cpu_type}/t-softfp t-softfp t-crtfm" + md_unwind_header=aarch64/aarch64-unwind.h ;; aarch64*-*-linux*) extra_parts="$extra_parts crtfastmath.o" diff --git a/libgcc/config/aarch64/aarch64-unwind.h b/libgcc/config/aarch64/aarch64-unwind.h new file mode 100644 index 0000000000000000000000000000000000000000..fd20feb0ce061c82c9134609438c84bc161670f9 --- /dev/null +++ b/libgcc/config/aarch64/aarch64-unwind.h @@ -0,0 +1,87 @@ +/* Copyright (C) 2017 Free Software Foundation, Inc. + Contributed by ARM Ltd. + +This file is part of GCC. + +GCC 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, or (at your option) any later +version. + +GCC 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. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + +#ifndef AARCH64_UNWIND_H +#define AARCH64_UNWIND_H + +#define DWARF_REGNUM_AARCH64_RA_STATE 34 + +#define MD_POST_EXTRACT_ROOT_ADDR(addr) __builtin_aarch64_xpaclri (addr) +#define MD_POST_EXTRACT_FRAME_ADDR(context, fs, addr) \ + aarch64_post_extract_frame_addr (context, fs, addr) +#define MD_POST_FROB_EH_HANDLER_ADDR(current, target, addr) \ + aarch64_post_frob_eh_handler_addr (current, target, addr) +#define MD_POST_INIT_CONTEXT(context, fs) \ + aarch64_post_init_context (context, fs) + +/* Do AArch64 private extraction on ADDR based on context info CONTEXT and + unwind frame info FS. If ADDR is signed, we do address authentication on it + using CFA of current frame. */ + +static void * +aarch64_post_extract_frame_addr (struct _Unwind_Context *context, + _Unwind_FrameState *fs, void *addr) +{ + if (fs->regs.reg[DWARF_REGNUM_AARCH64_RA_STATE].loc.offset & 0x1) + { + _Unwind_Word salt = (_Unwind_Word) context->cfa; + return __builtin_aarch64_autia1716 (addr, salt); + } + else + return addr; +} + +/* Do AArch64 private frob on exception handler's address HANDLER_ADDR before + installing it into current context CURRENT. TARGET is currently not used. + We need to sign exception handler's address if CURRENT itself is signed. */ + +static void * +aarch64_post_frob_eh_handler_addr (struct _Unwind_Context *current, + struct _Unwind_Context *target + ATTRIBUTE_UNUSED, + void *handler_addr) +{ + if (current->flags & RA_A_SIGNED_BIT) + return __builtin_aarch64_pacia1716 (handler_addr, + (_Unwind_Word) current->cfa); + else + return handler_addr; +} + +/* Do AArch64 private initialization on CONTEXT based on frame info FS. Mark + CONTEXT as return address signed if bit 0 of DWARF_REGNUM_AARCH64_RA_STATE is + set. */ + +static void +aarch64_post_init_context (struct _Unwind_Context *context, + _Unwind_FrameState *fs) +{ + 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; + + return; +} + +#endif /* defined AARCH64_UNWIND_H */ diff --git a/libgcc/config/aarch64/linux-unwind.h b/libgcc/config/aarch64/linux-unwind.h index 1256f010007ac964de8bb895379a7d893a446bd9..75774b30c080ad2361fb37c7208bcf3d3b57d77a 100644 --- a/libgcc/config/aarch64/linux-unwind.h +++ b/libgcc/config/aarch64/linux-unwind.h @@ -24,6 +24,7 @@ #include #include +#include "aarch64-unwind.h" /* Since insns are always stored LE, on a BE system the opcodes will