From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 111972 invoked by alias); 29 Sep 2016 15:14:35 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 111957 invoked by uid 89); 29 Sep 2016 15:14:34 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-4.9 required=5.0 tests=BAYES_00,RP_MATCHES_RCVD,SPF_PASS autolearn=ham version=3.3.2 spammy=profiler, Automatically, Nothing, Hook X-HELO: mx2.suse.de Received: from mx2.suse.de (HELO mx2.suse.de) (195.135.220.15) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 29 Sep 2016 15:14:24 +0000 Received: from relay2.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id EF138AABE; Thu, 29 Sep 2016 15:14:20 +0000 (UTC) Date: Thu, 29 Sep 2016 15:18:00 -0000 From: Torsten Duwe To: GCC Patches Cc: Szabolcs Nagy , nd@arm.com, Maxim Kuvyrkov , Li Bin , Jiri Kosina , Marcus Shawcroft , Takahiro Akashi , Andrew Wafaa Subject: [PATCH v2] add -fprolog-pad=N option to c-family Message-ID: <20160929151419.GE32544@suse.de> References: <20160427152217.GA2637@suse.de> <5720E81D.9060409@arm.com> <7134BE21-ACFB-4C45-871A-FADFA2973040@linaro.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <7134BE21-ACFB-4C45-871A-FADFA2973040@linaro.org> User-Agent: Mutt/1.5.24 (2015-08-30) X-SW-Source: 2016-09/txt/msg02259.txt.bz2 In case anybody missed it, the Linux kernel side to make use of this has also been finished meanwhile. Of course it can not be accepted without compiler support; and this feature patch is much more versatile than just Linux kernel live patching on a single architecture. Changes since the previous version (which in turn was based on Maxim's suggestion): * Document the feature in *.texi * Automatically disable IPA-RA, like normal profiling does. You never know in advance what the code patched in at run time will do. Any optimisation here is potentially wrong. * record a prolog_nop_pad_size value specified on the command line in each function's attributes, so that it survives an LTO pipe. Signed-off-by: Torsten Duwe diff --git a/gcc/attribs.c b/gcc/attribs.c index 16996e9..a5cf2aa 100644 --- a/gcc/attribs.c +++ b/gcc/attribs.c @@ -365,6 +365,21 @@ decl_attributes (tree *node, tree attributes, int flags) if (!attributes_initialized) init_attributes (); + /* If we're building NOP pads because of a command line arg, note the size + for LTO builds, unless the attribute has already been overridden. */ + if (TREE_CODE (*node) == FUNCTION_DECL && prolog_nop_pad_size > 0) + { + tree pp_attr = lookup_attribute ("prolog_pad", attributes); + if (! pp_attr ) + { + tree pp_size = build_int_cstu (integer_type_node, prolog_nop_pad_size); + + attributes = tree_cons (get_identifier ("prolog_pad"), + tree_cons ( NULL_TREE, pp_size, NULL_TREE), + attributes); + } + } + /* If this is a function and the user used #pragma GCC optimize, add the options to the attribute((optimize(...))) list. */ if (TREE_CODE (*node) == FUNCTION_DECL && current_optimize_pragma) diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index f2846bb..278a99e 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -393,6 +393,7 @@ static tree handle_designated_init_attribute (tree *, tree, tree, int, bool *); static tree handle_bnd_variable_size_attribute (tree *, tree, tree, int, bool *); static tree handle_bnd_legacy (tree *, tree, tree, int, bool *); static tree handle_bnd_instrument (tree *, tree, tree, int, bool *); +static tree handle_prolog_pad_attribute (tree *, tree, tree, int, bool *); static void check_nonnull_arg (void *, tree, unsigned HOST_WIDE_INT); static bool nonnull_check_p (tree, unsigned HOST_WIDE_INT); @@ -834,6 +835,8 @@ const struct attribute_spec c_common_attribute_table[] = handle_bnd_legacy, false }, { "bnd_instrument", 0, 0, true, false, false, handle_bnd_instrument, false }, + { "prolog_pad", 1, 1, false, true, true, + handle_prolog_pad_attribute, false }, { NULL, 0, 0, false, false, false, NULL, false } }; @@ -9687,6 +9690,14 @@ handle_designated_init_attribute (tree *node, tree name, tree, int, return NULL_TREE; } +static tree +handle_prolog_pad_attribute (tree *, tree, tree, int, + bool *) +{ + /* Nothing to be done here. */ + return NULL_TREE; +} + /* Check for valid arguments being passed to a function with FNTYPE. There are NARGS arguments in the array ARGARRAY. LOC should be used for diff --git a/gcc/c-family/c-opts.c b/gcc/c-family/c-opts.c index fec58bc..0220faa 100644 --- a/gcc/c-family/c-opts.c +++ b/gcc/c-family/c-opts.c @@ -536,6 +536,10 @@ c_common_handle_option (size_t scode, const char *arg, int value, cpp_opts->ext_numeric_literals = value; break; + case OPT_fprolog_pad_: + prolog_nop_pad_size = value; + break; + case OPT_idirafter: add_path (xstrdup (arg), AFTER, 0, true); break; diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt index 88038a0..804c654 100644 --- a/gcc/c-family/c.opt +++ b/gcc/c-family/c.opt @@ -1427,6 +1427,10 @@ fpreprocessed C ObjC C++ ObjC++ Treat the input file as already preprocessed. +fprolog-pad= +C ObjC C++ ObjC++ RejectNegative Joined UInteger Var(prolog_nop_pad_size) Init(0) +Pad NOPs before each function prolog + ftrack-macro-expansion C ObjC C++ ObjC++ JoinedOrMissing RejectNegative UInteger ; converted into ftrack-macro-expansion= diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 2ed9285..463a5a5 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -10387,6 +10387,16 @@ of the function name, it is considered to be a match. For C99 and C++ extended identifiers, the function name must be given in UTF-8, not using universal character names. +@item -fprolog-pad=N +@opindex fprolog-pad +Generate a pad of N nops right at the beginning +of each function, which can be used to patch in any desired +instrumentation at run time, provided that the code segment +is writeable. For run time identification, the starting addresses +of these pads, which correspond to their respective functions, +are additionally collected in the @code{__prolog_pads_loc} section +of the resulting binary. + @end table diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index 745910f..f6f9d59 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -4553,6 +4553,10 @@ will select the smallest suitable mode. This section describes the macros that output function entry (@dfn{prologue}) and exit (@dfn{epilogue}) code. +@deftypefn {Target Hook} void TARGET_ASM_PRINT_PROLOG_PAD (FILE *@var{file}, unsigned HOST_WIDE_INT @var{pad_size}, bool @var{record_p}) +Generate prologue pad +@end deftypefn + @deftypefn {Target Hook} void TARGET_ASM_FUNCTION_PROLOGUE (FILE *@var{file}, HOST_WIDE_INT @var{size}) If defined, a function that outputs the assembler code for entry to a function. The prologue is responsible for setting up the stack frame, diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in index f31c763..b9585da 100644 --- a/gcc/doc/tm.texi.in +++ b/gcc/doc/tm.texi.in @@ -3662,6 +3662,8 @@ will select the smallest suitable mode. This section describes the macros that output function entry (@dfn{prologue}) and exit (@dfn{epilogue}) code. +@hook TARGET_ASM_PRINT_PROLOG_PAD + @hook TARGET_ASM_FUNCTION_PROLOGUE @hook TARGET_ASM_FUNCTION_END_PROLOGUE diff --git a/gcc/final.c b/gcc/final.c index 55cf509..94bbf8f 100644 --- a/gcc/final.c +++ b/gcc/final.c @@ -1754,6 +1754,7 @@ void final_start_function (rtx_insn *first, FILE *file, int optimize_p ATTRIBUTE_UNUSED) { + unsigned HOST_WIDE_INT pad_size = prolog_nop_pad_size; block_depth = 0; this_is_asm_operands = 0; @@ -1766,6 +1767,21 @@ final_start_function (rtx_insn *first, FILE *file, high_block_linenum = high_function_linenum = last_linenum; + tree prolog_pad_attr + = lookup_attribute ("prolog_pad", TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl))); + if (prolog_pad_attr) + { + tree prolog_pad_value = TREE_VALUE (TREE_VALUE (prolog_pad_attr)); + + if (tree_fits_uhwi_p (prolog_pad_value)) + pad_size = tree_to_uhwi (prolog_pad_value); + else + gcc_unreachable (); + + } + if (pad_size > 0) + targetm.asm_out.print_prolog_pad (file, pad_size, true); + if (flag_sanitize & SANITIZE_ADDRESS) asan_function_start (); diff --git a/gcc/target.def b/gcc/target.def index 20f2b32..e0a4cc4 100644 --- a/gcc/target.def +++ b/gcc/target.def @@ -288,6 +288,12 @@ hidden, protected or internal visibility as specified by @var{visibility}.", void, (tree decl, int visibility), default_assemble_visibility) +DEFHOOK +(print_prolog_pad, + "Generate prologue pad", + void, (FILE *file, unsigned HOST_WIDE_INT pad_size, bool record_p), + default_print_prolog_pad) + /* Output the assembler code for entry to a function. */ DEFHOOK (function_prologue, diff --git a/gcc/targhooks.c b/gcc/targhooks.c index a342277..41e9850 100644 --- a/gcc/targhooks.c +++ b/gcc/targhooks.c @@ -1503,6 +1503,22 @@ default_use_by_pieces_infrastructure_p (unsigned HOST_WIDE_INT size, return move_by_pieces_ninsns (size, alignment, max_size + 1) < ratio; } +void +default_print_prolog_pad (FILE *file, unsigned HOST_WIDE_INT pad_size, + bool record_p) +{ + if (record_p) + fprintf (file, "1:"); + for (unsigned i = 0; i < pad_size; ++i) + fprintf (file, "\tnop\n"); + if (record_p) + { + fprintf (file, "\t.section __prolog_pads_loc, \"a\",@progbits\n"); + fprintf (file, "\t.quad 1b\n"); + fprintf (file, "\t.previous\n"); + } +} + bool default_profile_before_prologue (void) { diff --git a/gcc/targhooks.h b/gcc/targhooks.h index 7687c39..6bb41c4 100644 --- a/gcc/targhooks.h +++ b/gcc/targhooks.h @@ -200,6 +200,7 @@ extern bool default_use_by_pieces_infrastructure_p (unsigned HOST_WIDE_INT, enum by_pieces_operation, bool); +extern void default_print_prolog_pad (FILE *, unsigned HOST_WIDE_INT , bool); extern bool default_profile_before_prologue (void); extern reg_class_t default_preferred_reload_class (rtx, reg_class_t); extern reg_class_t default_preferred_output_reload_class (rtx, reg_class_t); diff --git a/gcc/testsuite/c-c++-common/attribute-prolog_pad-1.c b/gcc/testsuite/c-c++-common/attribute-prolog_pad-1.c new file mode 100644 index 0000000..7404dc5 --- /dev/null +++ b/gcc/testsuite/c-c++-common/attribute-prolog_pad-1.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ + +void f1(void) __attribute__((prolog_pad(1))); +void f2(void) __attribute__((prolog_pad(2))); + +void +f1 (void) +{ + f2 (); +} + +void f2 (void) +{ + f1 (); +} diff --git a/gcc/toplev.c b/gcc/toplev.c index 8979d26..2339ce8 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -1580,8 +1580,10 @@ process_options (void) } /* Do not use IPA optimizations for register allocation if profiler is active + or prolog-pads are inserted for run-time instrumentation or port does not emit prologue and epilogue as RTL. */ - if (profile_flag || !targetm.have_prologue () || !targetm.have_epilogue ()) + if (profile_flag || prolog_nop_pad_size || + !targetm.have_prologue () || !targetm.have_epilogue ()) flag_ipa_ra = 0; /* Enable -Werror=coverage-mismatch when -Werror and -Wno-error