From 9d7a84b96980d357bb9a3d368044fb18aab4aade Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Fri, 21 Jan 2022 12:09:34 +0000 Subject: [ARM] Add support for TLS register based stack protector canary access Add support for accessing the stack canary value via the TLS register, so that multiple threads running in the same address space can use distinct canary values. This is intended for the Linux kernel running in SMP mode, where processes entering the kernel are essentially threads running the same program concurrently: using a global variable for the canary in that context is problematic because it can never be rotated, and so the OS is forced to use the same value as long as it remains up. Using the TLS register to index the stack canary helps with this, as it allows each CPU to context switch the TLS register along with the rest of the process, permitting each process to use its own value for the stack canary. gcc/ChangeLog: * config/arm/arm-opts.h (enum stack_protector_guard): New. * config/arm/arm-protos.h (arm_stack_protect_tls_canary_mem): New. * config/arm/arm.cc (TARGET_STACK_PROTECT_GUARD): Define. (arm_option_override_internal): Handle and put in error checks. for stack protector guard options. (arm_option_reconfigure_globals): Likewise. (arm_stack_protect_tls_canary_mem): New. (arm_stack_protect_guard): New. * config/arm/arm.md (stack_protect_set): New. (stack_protect_set_tls): Likewise. (stack_protect_test): Likewise. (stack_protect_test_tls): Likewise. (reload_tp_hard): Likewise. * config/arm/arm.opt (-mstack-protector-guard): New (-mstack-protector-guard-offset): New. * doc/invoke.texi: Document new options. gcc/testsuite/ChangeLog: * gcc.target/arm/stack-protector-7.c: New test. * gcc.target/arm/stack-protector-8.c: New test. --- gcc/doc/invoke.texi | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'gcc/doc') diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 67693d6..309f5e3 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -823,6 +823,7 @@ Objective-C and Objective-C++ Dialects}. -mpure-code @gol -mcmse @gol -mfix-cmse-cve-2021-35465 @gol +-mstack-protector-guard=@var{guard} -mstack-protector-guard-offset=@var{offset} @gol -mfdpic} @emph{AVR Options} @@ -21366,6 +21367,16 @@ enabled by default when the option @option{-mcpu=} is used with @code{cortex-m33}, @code{cortex-m35p} or @code{cortex-m55}. The option @option{-mno-fix-cmse-cve-2021-35465} can be used to disable the mitigation. +@item -mstack-protector-guard=@var{guard} +@itemx -mstack-protector-guard-offset=@var{offset} +@opindex mstack-protector-guard +@opindex mstack-protector-guard-offset +Generate stack protection code using canary at @var{guard}. Supported +locations are @samp{global} for a global canary or @samp{tls} for a +canary accessible via the TLS register. The option +@option{-mstack-protector-guard-offset=} is for use with +@option{-fstack-protector-guard=tls} and not for use in user-land code. + @item -mfdpic @itemx -mno-fdpic @opindex mfdpic -- cgit v1.1 From 886e9779581102caf97cd05dea80d9be87c24784 Mon Sep 17 00:00:00 2001 From: Roger Sayle Date: Fri, 21 Jan 2022 18:42:30 +0000 Subject: PR middle-end/104140: bootstrap ICE on riscv. This patch resolves the P1 "ice-on-valid-code" regression boostrapping GCC on risv-unknown-linux-gnu caused by my recent MULT_HIGHPART_EXPR functionality. RISC-V differs from x86_64 and many targets by supporting a usmusidi3 instruction, basically a widening multiply where one operand is signed and the other is unsigned. Alas the final version of my patch to recognize MULT_HIGHPART_EXPR didn't sufficiently defend against the operands of WIDEN_MULT_EXPR having different signedness. This is fixed by the two-line change to tree-ssa-math-opts.cc's convert_mult_to_highpart in the patch below. The majority of the rest of the patch is to the documentation (in tree.def and generic.texi). It turns out that WIDEN_MULT_EXPR wasn't previously documented in generic.texi, let alone the slightly unusual semantics of allowing mismatched (signed vs unsigned) operands. This also clarifies that MULT_HIGHPART_EXPR currently requires the signedness of operands to match [but this might change in a future release of GCC to support targets with usmul3_highpart]. The one final chunk of this patch (that is hopefully sufficiently close to obvious for stage 4) is a similar (NULL pointer) sanity check in riscv_cpu_cpp_builtins. Currently running cc1 from the command line (or from gdb) without specifying -march results in a segmentation fault (ICE). This is a minor annoyance tracking down issues (in cross compilers) for riscv, and trivially fixed as below. 2022-01-22 Roger Sayle gcc/ChangeLog PR middle-end/104140 * tree-ssa-math-opts.cc (convert_mult_to_highpart): Check that the operands of the widening multiplication are either both signed or both unsigned, and abort the conversion if mismatched. * doc/generic.texi (WIDEN_MULT_EXPR): Describe expression node. (MULT_HIGHPART_EXPR): Clarify that operands must have the same signedness. * tree.def (MULT_HIGHPART_EXPR): Document both operands must have integer types with the same precision and signedness. (WIDEN_MULT_EXPR): Document that operands must have integer types with the same precision, but possibly differing signedness. * config/riscv/riscv-c.cc (riscv_cpu_cpp_builtins): Defend against riscv_current_subset_list returning a NULL pointer (empty list). gcc/testsuite/ChangeLog PR middle-end/104140 * gcc.target/riscv/pr104140.c: New test case. --- gcc/doc/generic.texi | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'gcc/doc') diff --git a/gcc/doc/generic.texi b/gcc/doc/generic.texi index 3e5b06a..e5f9d1b 100644 --- a/gcc/doc/generic.texi +++ b/gcc/doc/generic.texi @@ -1318,6 +1318,7 @@ The type of the node specifies the alignment of the access. @tindex PLUS_EXPR @tindex MINUS_EXPR @tindex MULT_EXPR +@tindex WIDEN_MULT_EXPR @tindex MULT_HIGHPART_EXPR @tindex RDIV_EXPR @tindex TRUNC_DIV_EXPR @@ -1532,10 +1533,18 @@ one operand is of floating type and the other is of integral type. The behavior of these operations on signed arithmetic overflow is controlled by the @code{flag_wrapv} and @code{flag_trapv} variables. +@item WIDEN_MULT_EXPR +This node represents a widening multiplication. The operands have +integral types with same @var{b} bits of precision, producing an +integral type result with at least @math{2@var{b}} bits of precision. +The behaviour is equivalent to extending both operands, possibly of +different signedness, to the result type, then multiplying them. + @item MULT_HIGHPART_EXPR This node represents the ``high-part'' of a widening multiplication. For an integral type with @var{b} bits of precision, the result is the most significant @var{b} bits of the full @math{2@var{b}} product. +Both operands must have the same precision and same signedness. @item RDIV_EXPR This node represents a floating point division operation. -- cgit v1.1 From 385196adb52d854ebf4f9237e8a521a17c5524c5 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Mon, 24 Jan 2022 11:50:15 +0100 Subject: options: Add EnumSet and Set property support [PR104158] The following patch is infrastructure support for at least 3 different options that need changes: 1) PR104158 talks about a regression with the -fsanitizer-coverage= option; in GCC 11 and older and on trunk prior to r12-1177, this option behaved similarly to -f{,no-}sanitizer{,-recover}= options, namely that the option allows negative and argument of the option is a list of strings, each of them has some enumerator and -fsanitize-coverage= enabled those bits in the underlying flag_sanitize_coverage, while -fno-sanitize-coverage= disabled them. So, -fsanitize-coverage=trace-pc,trace-cmp was equivalent to -fsanitize-coverage=trace-pc -fsanitize-coverage=trace-cmp and both set flag_sanitize_coverage to (SANITIZE_COV_TRACE_PC | SANITIZE_COV_TRACE_CMP) Also, e.g. -fsanitize-coverage=trace-pc,trace-cmp -fno-sanitize-coverage=trace-pc would in the end set flag_sanitize_coverage to SANITIZE_COV_TRACE_CMP (first set both bits, then subtract one) The r12-1177 change, I think done to improve argument misspelling diagnostic, changed the option incompatibly in multiple ways, -fno-sanitize-coverage= is now rejected, only a single argument is allowed, not multiple and -fsanitize-coverage=trace-pc -fsanitize-coverage=trace-cmp enables just SANITIZE_COV_TRACE_CMP and not both (each option overrides the previous value) 2) Thomas Koenig wants to extend Fortran -fconvert= option for the ppc64le real(kind=16) swapping support; currently the option accepts -fconvert={native,swap,big-endian,little-endian} and the intent is to add support for -fconvert=r16_ibm and -fconvert=r16_ieee (that alone is just normal Enum), but also to handle -fconvert=swap,r16_ieee or -fconvert=r16_ieee,big-endian but not -fconvert=big-endian,little-endian - the native/swap/big-endian/little-endian are one mutually exclusive set and r16_ieee/r16_ibm another one. See https://gcc.gnu.org/pipermail/gcc-patches/2022-January/587943.html and thread around that. 3) Similarly Marek Polacek wants to extend the -Wbidi-chars= option, such that it will handle not just the current -Wbidi-chars={none,bidirectional,any}, but also -Wbidi-chars=ucn and bidirectional,ucn and ucn,any etc. Again two separate sets, one none/bidirectional/any and another one ucn. See https://gcc.gnu.org/pipermail/gcc-patches/2022-January/588960.html The following patch adds framework for this and I'll post incremental patches for 1) and 2). As I've tried to document, such options are marked by additional EnumSet property on the option and in that case all the EnumValues in the Enum referenced from it must use a new Set property with set number (initially I wanted just mark last enumerator in each mutually exclusive set, but optionlist is sorted and so it doesn't really work well). So e.g. for the Fortran -fconvert=, one specifies: fconvert= Fortran RejectNegative Joined Enum(gfc_convert) EnumSet Var(flag_convert) Init(GFC_FLAG_CONVERT_NATIVE) -fconvert= The endianness used for unformatted files. Enum Name(gfc_convert) Type(enum gfc_convert) UnknownError(Unrecognized option to endianness value: %qs) EnumValue Enum(gfc_convert) String(big-endian) Value(GFC_FLAG_CONVERT_BIG) Set(1) EnumValue Enum(gfc_convert) String(little-endian) Value(GFC_FLAG_CONVERT_LITTLE) Set(1) EnumValue Enum(gfc_convert) String(native) Value(GFC_FLAG_CONVERT_NATIVE) Set(1) EnumValue Enum(gfc_convert) String(swap) Value(GFC_FLAG_CONVERT_SWAP) Set(1) EnumValue Enum(gfc_convert) String(r16_ieee) Value(GFC_FLAG_CONVERT_R16_IEEE) Set(2) EnumValue Enum(gfc_convert) String(r16_ibm) Value(GFC_FLAG_CONVERT_R16_IBM) Set(2) and this says to the option handling code that 1) if only one arg is specified to one instance of the option, it can be any of those 6 2) if two args are specified, one has to be from the first 4 and another from the last 2, in any order 3) at most 2 args may be specified (there are just 2 sets) There is a requirement on the Value values checked in self-test, the values from one set ored together must be disjunct from values from another set ored together. In the Fortran case, the first 4 are 0-3 so mask is 3, and the last 2 are 4 and 8, so mask is 12. When say -fconvert=big-endian is specified, it sets the first set to GFC_FLAG_CONVERT_BIG (2) but doesn't modify whatever value the other set had, so e.g. -fconvert=big-endian -fconvert=r16_ieee -fconvert=r16_ieee -fconvert=big-endian -fconvert=r16_ieee,big_endian -fconvert=big_endian,r16_ieee all behave the same. Also, with the EnumSet support, it is now possible to allow not specifying RejectNegative - we can set some set's value and then clear it and set it again to some other value etc. I think with the 2) patch I achieve what we want for Fortran, for 1) the only behavior from gcc 11 is that -fsanitize-coverage=trace-cmp,trace-cmp is now rejected. This is mainly from the desire to disallow -fconvert=big-endian,little-endian or -Wbidi-chars=bidirectional,any etc. where it would be confusing to users what exactly it means. But it is the only from these options that actually acts as an Enum bit set, each enumerator can be specified with all the others. So one option would be stop requiring the EnumSet implies Set properties must be specified and just require that either they are specified on all EnumValues, or on none of them; the latter case would be for -fsanitize-coverage= and the non-Set case would mean that all the EnumValues need to have disjoint Value bitmasks and that they can be all specified and unlike the Set case also repeated. Thoughts on this? 2022-01-24 Jakub Jelinek PR sanitizer/104158 * opt-functions.awk (var_set): Handle EnumSet property. * optc-gen.awk: Don't disallow RejectNegative if EnumSet is specified. * opt-read.awk: Handle Set property. * opts.h (CL_ENUM_SET_SHIFT, CL_ERR_ENUM_SET_ARG): Define. (struct cl_decoded_option): Mention enum in value description. Add mask member. (set_option): Add mask argument defaulted to 0. * opts.cc (test_enum_sets): New function. (opts_cc_tests): Call it. * opts-common.cc (enum_arg_to_value): Change return argument from bool to int, on success return index into the cl_enum_arg array, on failure -1. Add len argument, if non-0, use strncmp instead of strcmp. (opt_enum_arg_to_value): Adjust caller. (decode_cmdline_option): Handle EnumSet represented as CLVC_ENUM with non-zero var_value. Initialize decoded->mask. (decode_cmdline_options_to_array): CLear opt_array[0].mask. (handle_option): Pass decoded->mask to set_options last argument. (generate_option): Clear decoded->mask. (generate_option_input_file): Likewise. (cmdline_handle_error): Handle CL_ERR_ENUM_SET_ARG. (set_option): Add mask argument, use it for CLVC_ENUM. (control_warning_option): Adjust enum_arg_to_value caller. * doc/options.texi: Document Set and EnumSet properties. --- gcc/doc/options.texi | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'gcc/doc') diff --git a/gcc/doc/options.texi b/gcc/doc/options.texi index d552b64..9387c82 100644 --- a/gcc/doc/options.texi +++ b/gcc/doc/options.texi @@ -132,6 +132,21 @@ be accepted by the driver. This is used for cases such as @option{-march=native} that are processed by the driver so that @samp{gcc -v} shows how the options chosen depended on the system on which the compiler was run. + +@item Set(@var{number}) +This property is optional, required for enumerations used in +@code{EnumSet} options. @var{number} should be decimal number between +1 and 64 inclusive and divides the enumeration into a set of +sets of mutually exclusive arguments. Arguments with the same +@var{number} can't be specified together in the same option, but +arguments with different @var{number} can. @var{value} needs to be +chosen such that a mask of all @var{value} values from the same set +@var{number} bitwise ored doesn't overlap with masks for other sets. +When @code{-foption=arg_from_set1,arg_from_set4} and +@code{-fno-option=arg_from_set3} are used, the effect is that previous +value of the @code{Var} will get bits from set 1 and 4 masks cleared, +ored @code{Value} of @code{arg_from_set1} and @code{arg_from_set4} +and then will get bits from set 3 mask cleared. @end table @item @@ -396,6 +411,16 @@ with the corresponding @samp{Enum} record. The string is checked and converted to the integer specified in the corresponding @samp{EnumValue} record before being passed to option handlers. +@item EnumSet +Must be used together with the @code{Enum(@var{name})} property. +Corresponding @samp{Enum} record must use @code{Set} properties. +The option's argument is either a string from the set like for +@code{Enum(@var{name})}, but with a slightly different behavior that +the whole @code{Var} isn't overwritten, but only the bits in all the +enumeration values with the same set bitwise ored together. +Or option's argument can be a comma separated list of strings where +each string is from a different @code{Set(@var{number})}. + @item Defer The option should be stored in a vector, specified with @code{Var}, for later processing. -- cgit v1.1 From 0ebb09f5e49c8ca06728bb791415d985df01f6d8 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Mon, 24 Jan 2022 11:53:08 +0100 Subject: options: Add EnumBitSet property support [PR104158] On Sat, Jan 22, 2022 at 01:47:08AM +0100, Jakub Jelinek via Gcc-patches wrote: > I think with the 2) patch I achieve what we want for Fortran, for 1) > the only behavior from gcc 11 is that > -fsanitize-coverage=trace-cmp,trace-cmp is now rejected. > This is mainly from the desire to disallow > -fconvert=big-endian,little-endian or -Wbidi-chars=bidirectional,any > etc. where it would be confusing to users what exactly it means. > But it is the only from these options that actually acts as an Enum > bit set, each enumerator can be specified with all the others. > So one option would be stop requiring the EnumSet implies Set properties > must be specified and just require that either they are specified on all > EnumValues, or on none of them; the latter case would be for > -fsanitize-coverage= and the non-Set case would mean that all the > EnumValues need to have disjoint Value bitmasks and that they can > be all specified and unlike the Set case also repeated. > Thoughts on this? Here is an incremental patch to the first two patches of the series that implements EnumBitSet that fully restores the -fsanitize-coverage GCC 11 behavior. 2022-01-24 Jakub Jelinek PR sanitizer/104158 * opt-functions.awk (var_set): Handle EnumBitSet property. * optc-gen.awk: Don't disallow RejectNegative if EnumBitSet is specified. * opts.h (enum cl_enum_var_value): New type. * opts-common.cc (decode_cmdline_option): Use CLEV_* values. Handle CLEV_BITSET. (cmdline_handle_error): Handle CLEV_BITSET. * opts.cc (test_enum_sets): Also test EnumBitSet requirements. * doc/options.texi (EnumBitSet): Document. * common.opt (fsanitize-coverage=): Use EnumBitSet instead of EnumSet. (trace-pc, trace-cmp): Drop Set properties. * gcc.dg/sancov/pr104158-7.c: Adjust for repeating of arguments being allowed. --- gcc/doc/options.texi | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'gcc/doc') diff --git a/gcc/doc/options.texi b/gcc/doc/options.texi index 9387c82..50674938 100644 --- a/gcc/doc/options.texi +++ b/gcc/doc/options.texi @@ -421,6 +421,14 @@ enumeration values with the same set bitwise ored together. Or option's argument can be a comma separated list of strings where each string is from a different @code{Set(@var{number})}. +@item EnumBitSet +Must be used together with the @code{Enum(@var{name})} property. +Similar to @samp{EnumSet}, but corresponding @samp{Enum} record must +not use @code{Set} properties, each @code{EnumValue} should have +@code{Value} that is a power of 2, each value is treated as its own +set and its value as the set's mask, so there are no mutually +exclusive arguments. + @item Defer The option should be stored in a vector, specified with @code{Var}, for later processing. -- cgit v1.1