From patchwork Wed Nov 30 12:05:34 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Andre Vieira (lists)" X-Patchwork-Id: 700997 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3tTJzF5vQtz9t15 for ; Wed, 30 Nov 2016 23:06:01 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="pKNso+J9"; dkim-atps=neutral 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=PSkG8nMDdZSNN7WCl 1K6DQmRDDM1kR71zfSNZ1ou66yDa2k5UEvoEpBv/StL3bmEjCUToIq/iNksCY+pL a6GQGjnnfTT8yHWews1WFfToQaSt1mGUzSSrTNy1QuhPRwy8GkNSPW+KuFCBtJtq +tiGlqjgaeEPYIn1hfny8TYteQ= 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=+WBxSDTvQsl/Qy7QQ74/QYQ 7vSs=; b=pKNso+J9cB7bTk5D/CALpSaAUFhP1EoAB9pRe2cMLhFvtOQqitRoRfM tPoINiz5jZEWk6PveknCOsnrUJNFbURe5BeeIgRWrMBCCKT466rhPF80oJYaOpT4 OW6RG5EvC01RU8G0y8nURW8X+kjDJL/R4P98AyKK9ToVZxiR18aQ= Received: (qmail 52520 invoked by alias); 30 Nov 2016 12:05:51 -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 52486 invoked by uid 89); 30 Nov 2016 12:05:49 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-4.5 required=5.0 tests=BAYES_00, KAM_LOTSOFHASH, RP_MATCHES_RCVD, SPF_PASS autolearn=ham version=3.3.2 spammy=deny, UD:arm.com, Engineering 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; Wed, 30 Nov 2016 12:05:38 +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 B5982AD7; Wed, 30 Nov 2016 04:05:36 -0800 (PST) Received: from [10.2.206.251] (e107157-lin.cambridge.arm.com [10.2.206.251]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 43C983F318; Wed, 30 Nov 2016 04:05:36 -0800 (PST) Subject: [PATCHv3 5/7, GCC, ARM, V8M] Handling ARMv8-M Security Extension's cmse_nonsecure_call attribute To: gcc-patches@gcc.gnu.org References: <5796116C.6010100@arm.com> <57961342.4080108@arm.com> <57BD7E93.5000108@arm.com> <580F8876.7040303@arm.com> <581C5531.1080807@foss.arm.com> Cc: Kyrill Tkachov From: "Andre Vieira (lists)" Message-ID: <583EC08E.3000403@arm.com> Date: Wed, 30 Nov 2016 12:05:34 +0000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.2.0 MIME-Version: 1.0 In-Reply-To: <581C5531.1080807@foss.arm.com> X-IsSubscribed: yes Hi, I got a bug report against the old version of this patch and fixed it here. This had to do with GCC optimizations sharing types with and without the 'cmse_nonsecure_call' attribute. The patch now no longer sets the main variant, this didn't seem to do what I thought it did. Instead the patch now creates distinct type copies for every declared pointer that eventually points to the function type with the attribute, it will also create a distinct copy for the function type itself. Another change in this patch was to make 'arm_comp_type_attributes', the ARM implementation of TARGET_COMP_TYPE_ATTRIBUTES, deny compatibility between function types with the attribute and without. I added a test case to test the issue solved with these changes. *** gcc/ChangeLog *** 2016-11-xx Andre Vieira Thomas Preud'homme * config/arm/arm.c (gimplify.h): New include. (arm_handle_cmse_nonsecure_call): New. (arm_attribute_table): Added cmse_nonsecure_call. (arm_comp_type_attributes): Deny compatibility of function types with without the cmse_nonsecure_call attribute. * doc/extend.texi (ARM ARMv8-M Security Extensions): New attribute. *** gcc/testsuite/ChangeLog *** 2016-11-xx Andre Vieira Thomas Preud'homme * gcc.target/arm/cmse/cmse-3.c: Add tests. * gcc.target/arm/cmse/cmse-4.c: Add tests. * gcc.target/arm/cmse/cmse-15.c: New. Cheers, Andre diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 9509b0e25c19f35ed312efa1d86efc18a0db7674..d1160d5001830beea981df7454f09daf7fac2c5a 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -63,6 +63,7 @@ #include "tm-constrs.h" #include "rtl-iter.h" #include "optabs-libfuncs.h" +#include "gimplify.h" /* This file should be included last. */ #include "target-def.h" @@ -137,6 +138,7 @@ static tree arm_handle_isr_attribute (tree *, tree, tree, int, bool *); static tree arm_handle_notshared_attribute (tree *, tree, tree, int, bool *); #endif static tree arm_handle_cmse_nonsecure_entry (tree *, tree, tree, int, bool *); +static tree arm_handle_cmse_nonsecure_call (tree *, tree, tree, int, bool *); static void arm_output_function_epilogue (FILE *, HOST_WIDE_INT); static void arm_output_function_prologue (FILE *, HOST_WIDE_INT); static int arm_comp_type_attributes (const_tree, const_tree); @@ -348,6 +350,8 @@ static const struct attribute_spec arm_attribute_table[] = /* ARMv8-M Security Extensions support. */ { "cmse_nonsecure_entry", 0, 0, true, false, false, arm_handle_cmse_nonsecure_entry, false }, + { "cmse_nonsecure_call", 0, 0, true, false, false, + arm_handle_cmse_nonsecure_call, true }, { NULL, 0, 0, false, false, false, NULL, false } }; @@ -6753,6 +6757,78 @@ arm_handle_cmse_nonsecure_entry (tree *node, tree name, return NULL_TREE; } + +/* Called upon detection of the use of the cmse_nonsecure_call attribute, this + function will check whether the attribute is allowed here and will add the + attribute to the function type tree or otherwise issue a diagnostic. The + reason we check this at declaration time is to only allow the use of the + attribute with declarations of function pointers and not function + declarations. This function checks NODE is of the expected type and issues + diagnostics otherwise using NAME. If it is not of the expected type + *NO_ADD_ATTRS will be set to true. */ + +static tree +arm_handle_cmse_nonsecure_call (tree *node, tree name, + tree /* args */, + int /* flags */, + bool *no_add_attrs) +{ + tree decl = NULL_TREE, fntype = NULL_TREE; + tree main_variant, type; + + if (!use_cmse) + { + *no_add_attrs = true; + warning (OPT_Wattributes, "%qE attribute ignored without -mcmse option.", + name); + return NULL_TREE; + } + + if (TREE_CODE (*node) == VAR_DECL || TREE_CODE (*node) == TYPE_DECL) + { + decl = *node; + fntype = TREE_TYPE (decl); + } + + while (fntype != NULL_TREE && TREE_CODE (fntype) == POINTER_TYPE) + fntype = TREE_TYPE (fntype); + + if (!decl || TREE_CODE (fntype) != FUNCTION_TYPE) + { + warning (OPT_Wattributes, "%qE attribute only applies to base type of a " + "function pointer", name); + *no_add_attrs = true; + return NULL_TREE; + } + + *no_add_attrs |= cmse_func_args_or_return_in_stack (NULL, name, fntype); + + if (*no_add_attrs) + return NULL_TREE; + + /* Prevent trees being shared among function types with and without + cmse_nonsecure_call attribute. */ + type = TREE_TYPE (decl); + + type = build_distinct_type_copy (type); + TREE_TYPE (decl) = type; + fntype = type; + + while (TREE_CODE (fntype) != FUNCTION_TYPE) + { + type = fntype; + fntype = TREE_TYPE (fntype); + fntype = build_distinct_type_copy (fntype); + TREE_TYPE (type) = fntype; + } + + /* Construct a type attribute and add it to the function type. */ + tree attrs = tree_cons (get_identifier ("cmse_nonsecure_call"), NULL_TREE, + TYPE_ATTRIBUTES (fntype)); + TYPE_ATTRIBUTES (fntype) = attrs; + return NULL_TREE; +} + /* Return 0 if the attributes for two types are incompatible, 1 if they are compatible, and 2 if they are nearly compatible (which causes a warning to be generated). */ @@ -6793,6 +6869,14 @@ arm_comp_type_attributes (const_tree type1, const_tree type2) if (l1 != l2) return 0; + l1 = lookup_attribute ("cmse_nonsecure_call", + TYPE_ATTRIBUTES (type1)) != NULL; + l2 = lookup_attribute ("cmse_nonsecure_call", + TYPE_ATTRIBUTES (type2)) != NULL; + + if (l1 != l2) + return 0; + return 1; } diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index e8d9d90c0ac98a2b50aad60edf01e16dfa480db7..e8d8deefca87eacbdde6042fc1885c0d0a85a5b8 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -12622,8 +12622,8 @@ Security Extensions: Requiremenets on Development Tools Engineering Specification, which can be found at @uref{http://infocenter.arm.com/help/topic/com.arm.doc.ecm0359818/ECM0359818_armv8m_security_extensions_reqs_on_dev_tools_1_0.pdf}. -As part of the Security Extensions GCC implements a new function attribute -@code{cmse_nonsecure_entry}. +As part of the Security Extensions GCC implements two new function attributes: +@code{cmse_nonsecure_entry} and @code{cmse_nonsecure_call}. As part of the Security Extensions GCC implements the intrinsics below. FPTR is used here to mean any function pointer type. diff --git a/gcc/testsuite/gcc.target/arm/cmse/cmse-15.c b/gcc/testsuite/gcc.target/arm/cmse/cmse-15.c new file mode 100644 index 0000000000000000000000000000000000000000..4e9ace1f3f33b8a8653797e29ca62eb3dd7ae918 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/cmse/cmse-15.c @@ -0,0 +1,72 @@ +/* { dg-do compile } */ +/* { dg-options "-mcmse" } */ + +int __attribute__ ((cmse_nonsecure_call)) (*ns_foo) (void); +int (*s_bar) (void); +int __attribute__ ((cmse_nonsecure_call)) (**ns_foo2) (void); +int (**s_bar2) (void); + +typedef int __attribute__ ((cmse_nonsecure_call)) ns_foo_t (void); +typedef int s_bar_t (void); +typedef int __attribute__ ((cmse_nonsecure_call)) (* ns_foo_ptr) (void); +typedef int (*s_bar_ptr) (void); + +int nonsecure0 (ns_foo_t * ns_foo_p) +{ + return ns_foo_p (); +} + +int nonsecure1 (ns_foo_t ** ns_foo_p) +{ + return (*ns_foo_p) (); +} + +int nonsecure2 (ns_foo_ptr ns_foo_p) +{ + return ns_foo_p (); +} +int nonsecure3 (ns_foo_ptr * ns_foo_p) +{ + return (*ns_foo_p) (); +} + +int secure0 (s_bar_t * s_bar_p) +{ + return s_bar_p (); +} + +int secure1 (s_bar_t ** s_bar_p) +{ + return (*s_bar_p) (); +} + +int secure2 (s_bar_ptr s_bar_p) +{ + return s_bar_p (); +} + +int secure3 (s_bar_ptr * s_bar_p) +{ + return (*s_bar_p) (); +} + +int nonsecure4 (void) +{ + return ns_foo (); +} + +int nonsecure5 (void) +{ + return (*ns_foo2) (); +} + +int secure4 (void) +{ + return s_bar (); +} + +int secure5 (void) +{ + return (*s_bar2) (); +} +/* { dg-final { scan-assembler-times "bl\\s+__gnu_cmse_nonsecure_call" 6 } } */ diff --git a/gcc/testsuite/gcc.target/arm/cmse/cmse-3.c b/gcc/testsuite/gcc.target/arm/cmse/cmse-3.c index 2c2920e1dc310106d83203eb51e1a68a275d0152..7f92a4c28b3333e4c8fdc256211f3ed74a383cd4 100644 --- a/gcc/testsuite/gcc.target/arm/cmse/cmse-3.c +++ b/gcc/testsuite/gcc.target/arm/cmse/cmse-3.c @@ -35,3 +35,11 @@ norf (struct span2 a) {} void __attribute__ ((cmse_nonsecure_entry)) foo2 (long long a, int b, union test_union c) {} /* { dg-error "not available to functions with arguments passed on the stack" } */ + +typedef void __attribute__ ((cmse_nonsecure_call)) bar2 (long long a, int b, long long c); /* { dg-error "not available to functions with arguments passed on the stack" } */ + +typedef void __attribute__ ((cmse_nonsecure_call)) baz2 (long long a, int b, struct span c); /* { dg-error "not available to functions with arguments passed on the stack" } */ + +typedef struct span __attribute__ ((cmse_nonsecure_call)) qux2 (void); /* { dg-error "not available to functions that return value on the stack" } */ + +typedef void __attribute__ ((cmse_nonsecure_call)) norf2 (int a, ...); /* { dg-error "not available to functions with variable number of arguments" } */ diff --git a/gcc/testsuite/gcc.target/arm/cmse/cmse-4.c b/gcc/testsuite/gcc.target/arm/cmse/cmse-4.c index 6f930ab04a1097c64097a4e003296bbe85733319..d0999a4181ac022b115ae20cf3e1c8bf78f6becf 100644 --- a/gcc/testsuite/gcc.target/arm/cmse/cmse-4.c +++ b/gcc/testsuite/gcc.target/arm/cmse/cmse-4.c @@ -19,9 +19,16 @@ baz (void) return qux (); } +void __attribute__ ((cmse_nonsecure_call)) +quux (void) {} /* { dg-warning "attribute only applies to base type of a function pointer" } */ + +int __attribute__ ((cmse_nonsecure_call)) norf; /* { dg-warning "attribute only applies to base type of a function pointer" } */ + /* { dg-final { scan-assembler-times "bxns" 2 } } */ /* { dg-final { scan-assembler "foo:" } } */ /* { dg-final { scan-assembler "__acle_se_foo:" } } */ /* { dg-final { scan-assembler-not "__acle_se_bar:" } } */ /* { dg-final { scan-assembler "baz:" } } */ /* { dg-final { scan-assembler "__acle_se_baz:" } } */ +/* { dg-final { scan-assembler-not "__acle_se_quux:" } } */ +/* { dg-final { scan-assembler-not "__acle_se_norf:" } } */