[PATCH][GCC][AARCH64] Canonicalize aarch64 widening simd plus insns

2018-07-11 Thread Matthew Malcomson

Hi there,

The current RTL patterns for widening addition and subtraction 
instructions in

aarch64-simd.md use the code iterator attribute  to make their
definition more compact.
This approach means that the `minus` and `plus` cases have their operands in
the same order, which causes problems in matching.
The `minus` case needs the more complex operand second to be semantically
correct, but the `plus` case needs the more complex operand first to be in
canonical form.

This patch splits the RTL patterns into two, one for `plus` and one for
`minus` with differing operand order to match their differing requirements.


Ready for trunk?

Bootstrap and test on aarch64-none-linux-gnu

Changelog for gcc/testsuite/Changelog
2018-07-10  Matthew Malcomson  

    * gcc.target/aarch64/vect-su-add-sub.c: New.

Changelog for gcc/Changelog
2018-07-10  Matthew Malcomson  

    * config/aarch64/aarch64-simd.md
(aarch64_w): Split into...
    (aarch64_subw): ... This...
    (aarch64_addw): ... And this.
(aarch64_w_internal): Split into...
    (aarch64_subw_internal): ... This...
    (aarch64_addw_internal): ... And this.
(aarch64_w2_internal): Split into...
    (aarch64_subw2_internal): ... This...
    (aarch64_addw2_internal): ... And this.

diff --git a/gcc/config/aarch64/aarch64-simd.md b/gcc/config/aarch64/aarch64-simd.md
index aac5fa146ed8dde4507a0eb4ad6a07ce78d2f0cd..67b29cbe2cad91e031ee23be656ec61a403f2cf9 100644
--- a/gcc/config/aarch64/aarch64-simd.md
+++ b/gcc/config/aarch64/aarch64-simd.md
@@ -3302,38 +3302,78 @@
   DONE;
 })
 
-(define_insn "aarch64_w"
+(define_insn "aarch64_subw"
   [(set (match_operand: 0 "register_operand" "=w")
-(ADDSUB: (match_operand: 1 "register_operand" "w")
-			(ANY_EXTEND:
-			  (match_operand:VD_BHSI 2 "register_operand" "w"]
+			(minus:
+			 (match_operand: 1 "register_operand" "w")
+			 (ANY_EXTEND:
+			   (match_operand:VD_BHSI 2 "register_operand" "w"]
   "TARGET_SIMD"
-  "w\\t%0., %1., %2."
-  [(set_attr "type" "neon__widen")]
+  "subw\\t%0., %1., %2."
+  [(set_attr "type" "neon_sub_widen")]
 )
 
-(define_insn "aarch64_w_internal"
+(define_insn "aarch64_subw_internal"
   [(set (match_operand: 0 "register_operand" "=w")
-(ADDSUB: (match_operand: 1 "register_operand" "w")
-			(ANY_EXTEND:
-			  (vec_select:
-			   (match_operand:VQW 2 "register_operand" "w")
-			   (match_operand:VQW 3 "vect_par_cnst_lo_half" "")]
+		(minus:
+		 (match_operand: 1 "register_operand" "w")
+		 (ANY_EXTEND:
+		   (vec_select:
+		(match_operand:VQW 2 "register_operand" "w")
+		(match_operand:VQW 3 "vect_par_cnst_lo_half" "")]
   "TARGET_SIMD"
-  "w\\t%0., %1., %2."
-  [(set_attr "type" "neon__widen")]
+  "subw\\t%0., %1., %2."
+  [(set_attr "type" "neon_sub_widen")]
 )
 
-(define_insn "aarch64_w2_internal"
+(define_insn "aarch64_subw2_internal"
   [(set (match_operand: 0 "register_operand" "=w")
-(ADDSUB: (match_operand: 1 "register_operand" "w")
-			(ANY_EXTEND:
-			  (vec_select:
-			   (match_operand:VQW 2 "register_operand" "w")
-			   (match_operand:VQW 3 "vect_par_cnst_hi_half" "")]
+		(minus:
+		  (match_operand: 1 "register_operand" "w")
+		  (ANY_EXTEND:
+		(vec_select:
+		 (match_operand:VQW 2 "register_operand" "w")
+		 (match_operand:VQW 3 "vect_par_cnst_hi_half" "")]
+  "TARGET_SIMD"
+  "subw2\\t%0., %1., %2."
+  [(set_attr "type" "neon_sub_widen")]
+)
+
+(define_insn "aarch64_addw"
+  [(set (match_operand: 0 "register_operand" "=w")
+		(plus:
+		 (ANY_EXTEND:
+		  (match_operand:VD_BHSI 2 "register_operand" "w"))
+		 (match_operand: 1 "register_operand" "w")))]
   "TARGET_SIMD"
-  "w2\\t%0., %1., %2."
-  [(set_attr "type" "neon__widen")]
+  "addw\\t%0., %1., %2."
+  [(set_attr "type" "neon_add_widen")]
+)
+
+(define_insn "aarch64_addw_internal"
+  [(set (match_operand: 0 "register_operand" "=w")
+		(plus:
+		 (ANY_EXTEND:
+		  (vec_select:
+		   (match_operand:VQW 2 "register_operand" "w")
+		   (match_operand:VQW 3 "vect_par_cnst_lo_half" "")))
+		  (match_operand: 1 "register_operand" "w")))]
+  "TARGET_SIMD"
+  "addw\\t%0., %1., %2."
+  [(set_attr "type"

Re: [PATCH][GCC][AARCH64] Canonicalize aarch64 widening simd plus insns

2018-07-19 Thread Matthew Malcomson

Hi again.

Providing an updated patch to include the formatting suggestions.

Thanks,

Matthew


On 12/07/18 11:39, Sudakshina Das wrote:

Hi Matthew

On 12/07/18 11:18, Richard Sandiford wrote:

Looks good to me FWIW (not a maintainer), just a minor formatting thing:

Matthew Malcomson  writes:
diff --git a/gcc/config/aarch64/aarch64-simd.md 
b/gcc/config/aarch64/aarch64-simd.md
index 
aac5fa146ed8dde4507a0eb4ad6a07ce78d2f0cd..67b29cbe2cad91e031ee23be656ec61a403f2cf9 
100644

--- a/gcc/config/aarch64/aarch64-simd.md
+++ b/gcc/config/aarch64/aarch64-simd.md
@@ -3302,38 +3302,78 @@
    DONE;
  })
  -(define_insn "aarch64_w"
+(define_insn "aarch64_subw"
    [(set (match_operand: 0 "register_operand" "=w")
-    (ADDSUB: (match_operand: 1 "register_operand" 
"w")

-    (ANY_EXTEND:
-  (match_operand:VD_BHSI 2 "register_operand" "w"]
+    (minus:
+ (match_operand: 1 "register_operand" "w")
+ (ANY_EXTEND:
+   (match_operand:VD_BHSI 2 "register_operand" "w"]


The (minus should be under the "(match_operand":

(define_insn "aarch64_subw"
   [(set (match_operand: 0 "register_operand" "=w")
(minus: (match_operand: 1 "register_operand" "w")
   (ANY_EXTEND:
 (match_operand:VD_BHSI 2 "register_operand" "w"]

Same for the other patterns.

Thanks,
Richard



You will need a maintainer's approval but this looks good to me.
Thanks for doing this. I would only point out one other nit which you
can choose to ignore:

+/* Ensure
+   saddw2 and one saddw for the function add()
+   ssubw2 and one ssubw for the function subtract()
+   uaddw2 and one uaddw for the function uadd()
+   usubw2 and one usubw for the function usubtract() */
+
+/* { dg-final { scan-assembler-times "\[ \t\]ssubw2\[ \t\]+" 1 } } */
+/* { dg-final { scan-assembler-times "\[ \t\]ssubw\[ \t\]+" 1 } } */
+/* { dg-final { scan-assembler-times "\[ \t\]saddw2\[ \t\]+" 1 } } */
+/* { dg-final { scan-assembler-times "\[ \t\]saddw\[ \t\]+" 1 } } */
+/* { dg-final { scan-assembler-times "\[ \t\]usubw2\[ \t\]+" 1 } } */
+/* { dg-final { scan-assembler-times "\[ \t\]usubw\[ \t\]+" 1 } } */
+/* { dg-final { scan-assembler-times "\[ \t\]uaddw2\[ \t\]+" 1 } } */
+/* { dg-final { scan-assembler-times "\[ \t\]uaddw\[ \t\]+" 1 } } */

The scan-assembly directives for the different
functions can be placed right below each of them and that would
make it easier to read the expected results in the test and you
can get rid of the comments saying the same.

Thanks
Sudi


diff --git a/gcc/config/aarch64/aarch64-simd.md b/gcc/config/aarch64/aarch64-simd.md
index b5c551ad650e1a83416d5fbbbdd38e3fa3beb532..1f356d04d5b3542ac9ce51bc315c81d1fff91f21 100644
--- a/gcc/config/aarch64/aarch64-simd.md
+++ b/gcc/config/aarch64/aarch64-simd.md
@@ -3303,38 +3303,74 @@
   DONE;
 })
 
-(define_insn "aarch64_w"
+(define_insn "aarch64_subw"
   [(set (match_operand: 0 "register_operand" "=w")
-(ADDSUB: (match_operand: 1 "register_operand" "w")
-			(ANY_EXTEND:
-			  (match_operand:VD_BHSI 2 "register_operand" "w"]
+	(minus: (match_operand: 1 "register_operand" "w")
+	  (ANY_EXTEND:
+	(match_operand:VD_BHSI 2 "register_operand" "w"]
   "TARGET_SIMD"
-  "w\\t%0., %1., %2."
-  [(set_attr "type" "neon__widen")]
+  "subw\\t%0., %1., %2."
+  [(set_attr "type" "neon_sub_widen")]
 )
 
-(define_insn "aarch64_w_internal"
+(define_insn "aarch64_subw_internal"
   [(set (match_operand: 0 "register_operand" "=w")
-(ADDSUB: (match_operand: 1 "register_operand" "w")
-			(ANY_EXTEND:
-			  (vec_select:
-			   (match_operand:VQW 2 "register_operand" "w")
-			   (match_operand:VQW 3 "vect_par_cnst_lo_half" "")]
+	(minus: (match_operand: 1 "register_operand" "w")
+	  (ANY_EXTEND:
+	(vec_select:
+	  (match_operand:VQW 2 "register_operand" "w")
+	  (match_operand:VQW 3 "vect_par_cnst_lo_half" "")]
   "TARGET_SIMD"
-  "w\\t%0., %1., %2."
-  [(set_attr "type" "neon__widen")]
+  "subw\\t%0., %1., %2."
+  [(set_attr "type" "neon_sub_widen")]
 )
 
-(define_insn "aarch64_w2_internal"
+(define_insn "aarch64_subw2_internal"
   [(set (match_operand: 0 "register_operand" "=w")
-(ADDSUB: (match_operand: 1 "register_operand"

Re: [Patch 0/X] [WIP][RFC][libsanitizer] Introduce HWASAN to GCC

2019-10-23 Thread Matthew Malcomson
Hi Martin,

I'm getting close to putting up a patch series that I believe could go 
in before stage1 close.

I currently have to do testing on sanitizing the kernel, and track down 
a bootstrap comparison diff in the code handling shadow-stack cleanup 
during exception unwinding.

I just thought I'd answer these questions below to see if there's 
anything I extra could to do to make reviewing easier.

On 23/09/19 09:02, Martin Liška wrote:
> Hi.
> 
> As mentioned in the next email thread, there are main objectives
> that will help me to make a proper patch review:
> 
> 1) Make first libsanitizer merge from trunk, it will remove the need
> of the backports that you made. Plus I will be able to apply the
> patchset on the current master.
Done
> 2) I would exclude the setjmp/longjmp - these should be upstreamed first
> in libsanitizer.

Will exclude in the patch series, upstreaming under progress 
(https://reviews.llvm.org/D69045)

> 3) I would like to see a two HWASAN options that will clearly separate the
> 2 supported modes: TBI without MTE and MTE. Here I would appreciate to 
> have
> a compiler farm machine with TBI which we can use for testing.

I went back and looked at clang to see that it uses 
`-fsanitize=hwaddress` and `-fsanitize=memtag`, which are completely 
different options.

I'm now doing the same, with the two sanitizers just using similar code 
paths.

In fact, I'm not going to have the MTE instrumentation ready by the end 
of stage1, so my aim is to just put the `-fsanitize=hwaddress` sanitizer 
in, but send some outline code to the mailing list to demonstrate how 
`-fsanitize=memtag` would fit in.


## w.r.t. a compiler farm machine with TBI

Any AArch64 machine has this feature.  However in order to use the 
sanitizer the kernel needs to allow "tagged pointers" in syscalls.

The kernel has allowed these tagged pointers in syscalls (once it's been 
turned on with a relevant prctl) in mainline since 5.4-rc1 (i.e. the 
start of this month).

My testing has been on a virtual machine with a mainline kernel built 
from source.

Given that I'm not sure how you want to proceed.
Could we set up a virtual machine on the compiler farm?


> 4) About the BUILTIN expansion: you provided a patch for couple of them. My 
> question
> is whether the list is complete?

The list of BUILTINs was nowhere near complete at the time I posted the 
RFC patches.

Since then I've added features and correspondingly added BUILTINs.

Now I believe I've added all the BUILTIN's into sanitizer.def this 
sanitizer will need.

> 5) I would appreciate the patch set to be split into less logical parts, e.g.
> libsanitizer changes; option introduction; stack variable handling 
> (colour/uncolour/alignment);
> hwasan pass and other GIMPLE-related changes; RTL hooks, new RTL 
> instructions and expansion changes.
> 

Will do!

> Thank you,
> Martin
> 
> 



[PATCH 1/X][mid-end] Fix declared type of personality functions

2019-11-05 Thread Matthew Malcomson
`build_personality_function` generates a declaration for a personality
function.  The type it declares for these functions doesn't match the
type of the actual personality functions that are defined by the C++
unwinding ABI.

This doesn't cause any crashes since the compiler never generates a call
to these decl's, and hence the type of the function is never used.
Nonetheless, for the sake of consistency and readability we update the
type of this declaration.

(See libstdc++-v3/libsupc++/unwind-cxx.h for declaration of _gxx_personality_v0
to compare types).

gcc/ChangeLog:

2019-11-05  Matthew Malcomson  

* expr.c (build_personality_function): Fix generated type to
match actual personality functions.



### Attachment also inlined for ease of reply###


diff --git a/gcc/expr.c b/gcc/expr.c
index 
2f2b53f8b6905013b4214eea137d67c666b0c795..7dc37a288ebffb99c990442cf339b848c5fa9d2e
 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -12525,7 +12525,8 @@ build_personality_function (const char *lang)
 
   name = ACONCAT (("__", lang, "_personality", unwind_and_version, NULL));
 
-  type = build_function_type_list (integer_type_node, integer_type_node,
+  type = build_function_type_list (unsigned_type_node,
+  integer_type_node, integer_type_node,
   long_long_unsigned_type_node,
   ptr_type_node, ptr_type_node, NULL_TREE);
   decl = build_decl (UNKNOWN_LOCATION, FUNCTION_DECL,

diff --git a/gcc/expr.c b/gcc/expr.c
index 
2f2b53f8b6905013b4214eea137d67c666b0c795..7dc37a288ebffb99c990442cf339b848c5fa9d2e
 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -12525,7 +12525,8 @@ build_personality_function (const char *lang)
 
   name = ACONCAT (("__", lang, "_personality", unwind_and_version, NULL));
 
-  type = build_function_type_list (integer_type_node, integer_type_node,
+  type = build_function_type_list (unsigned_type_node,
+  integer_type_node, integer_type_node,
   long_long_unsigned_type_node,
   ptr_type_node, ptr_type_node, NULL_TREE);
   decl = build_decl (UNKNOWN_LOCATION, FUNCTION_DECL,



[PATCH 2/X] [libsanitizer] Introduce libhwasan to GCC tree

2019-11-05 Thread Matthew Malcomson
Takes the libhwasan library from LLVM and puts it into our source tree
excluding the build system files.

Tieing the source files into our build system is done in a later commit.

We have taken the libsanitizer library from the same SVN revision as
the other sanitizer libraries are taken from (SVN revision 368656 as
mentioned in libsanitizer/MERGE).

libsanitizer/ChangeLog:

2019-11-05  Matthew Malcomson  

* README.gcc: Mention now including lib/hwasan.
* hwasan/hwasan.cpp: New file.
* hwasan/hwasan.h: New file.
* hwasan/hwasan.syms.extra: New file.
* hwasan/hwasan_allocator.cpp: New file.
* hwasan/hwasan_allocator.h: New file.
* hwasan/hwasan_blacklist.txt: New file.
* hwasan/hwasan_checks.h: New file.
* hwasan/hwasan_dynamic_shadow.cpp: New file.
* hwasan/hwasan_dynamic_shadow.h: New file.
* hwasan/hwasan_flags.h: New file.
* hwasan/hwasan_flags.inc: New file.
* hwasan/hwasan_interceptors.cpp: New file.
* hwasan/hwasan_interceptors_vfork.S: New file.
* hwasan/hwasan_interface_internal.h: New file.
* hwasan/hwasan_linux.cpp: New file.
* hwasan/hwasan_malloc_bisect.h: New file.
* hwasan/hwasan_mapping.h: New file.
* hwasan/hwasan_memintrinsics.cpp: New file.
* hwasan/hwasan_new_delete.cpp: New file.
* hwasan/hwasan_poisoning.cpp: New file.
* hwasan/hwasan_poisoning.h: New file.
* hwasan/hwasan_report.cpp: New file.
* hwasan/hwasan_report.h: New file.
* hwasan/hwasan_tag_mismatch_aarch64.S: New file.
* hwasan/hwasan_thread.cpp: New file.
* hwasan/hwasan_thread.h: New file.
* hwasan/hwasan_thread_list.cpp: New file.
* hwasan/hwasan_thread_list.h: New file.


hwasan-patch02.patch.gz
Description: hwasan-patch02.patch.gz


[aarch64] Allocate enough space for err_str in aarch64_handle_attr_branch_protection

2019-11-05 Thread Matthew Malcomson
-fsanitize=hwaddress found a one-byte overwrite when running the
testsuite here.  aarch64_handle_attr_branch_protection allocates
`strlen(str)` bytes for an error string, which is populated by
`strcpy(..., str)` in the case where the branch protection string is
completely invalid.

Tested on aarch64 with hwasan (though not a full bootstrap since it's
obvious).

gcc/ChangeLog:

2019-11-05  Matthew Malcomson  

* config/aarch64/aarch64.c (aarch64_handle_attr_cpu): Allocate
enough bytes for the NULL character.



### Attachment also inlined for ease of reply###


diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 
232317d4a5a4a16529f573eef5a8d7a068068207..fc03faa8f8d459a84024d4394fff375b72d31264
 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -13298,7 +13298,7 @@ aarch64_handle_attr_cpu (const char *str)
  static bool
  aarch64_handle_attr_branch_protection (const char* str)
  {
-  char *err_str = (char *) xmalloc (strlen (str));
+  char *err_str = (char *) xmalloc (strlen (str) + 1);
   enum aarch64_parse_opt_result res = aarch64_parse_branch_protection (str,
  &err_str);
   bool success = false;

diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 
232317d4a5a4a16529f573eef5a8d7a068068207..fc03faa8f8d459a84024d4394fff375b72d31264
 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -13298,7 +13298,7 @@ aarch64_handle_attr_cpu (const char *str)
  static bool
  aarch64_handle_attr_branch_protection (const char* str)
  {
-  char *err_str = (char *) xmalloc (strlen (str));
+  char *err_str = (char *) xmalloc (strlen (str) + 1);
   enum aarch64_parse_opt_result res = aarch64_parse_branch_protection (str,
  &err_str);
   bool success = false;



[PATCH 5/X] [libsanitizer] Remove system allocator fallback

2019-11-05 Thread Matthew Malcomson
Backport from llvm-svn: 375296.
This was an experiment made possible by a non-standard feature of the
Android dynamic loader.

Going without that experiment makes implementation for glibc easier.

libsanitizer/ChangeLog:

2019-11-05  Matthew Malcomson  

* hwasan/hwasan_allocator.cpp (hwasan_realloc, hwasan_free,
__hwasan_disable_allocator_tagging): Remove allocator fallback.
* hwasan/hwasan_allocator.h (free, realloc): Remove REAL
declarations.
* hwasan/hwasan_interceptors.cpp (free, realloc): Remove
interceptors.



### Attachment also inlined for ease of reply###


diff --git a/libsanitizer/hwasan/hwasan_allocator.h 
b/libsanitizer/hwasan/hwasan_allocator.h
index 
3a50a11f352600d82aaaf73ddd7a5595e9f8a4d5..f62be269602143679f9f7abc9ec4a8a08dad207f
 100644
--- a/libsanitizer/hwasan/hwasan_allocator.h
+++ b/libsanitizer/hwasan/hwasan_allocator.h
@@ -13,7 +13,6 @@
 #ifndef HWASAN_ALLOCATOR_H
 #define HWASAN_ALLOCATOR_H
 
-#include "interception/interception.h"
 #include "sanitizer_common/sanitizer_allocator.h"
 #include "sanitizer_common/sanitizer_allocator_checks.h"
 #include "sanitizer_common/sanitizer_allocator_interface.h"
@@ -26,11 +25,6 @@
 #error Unsupported platform
 #endif
 
-#if HWASAN_WITH_INTERCEPTORS
-DECLARE_REAL(void *, realloc, void *ptr, uptr size)
-DECLARE_REAL(void, free, void *ptr)
-#endif
-
 namespace __hwasan {
 
 struct Metadata {
diff --git a/libsanitizer/hwasan/hwasan_allocator.cpp 
b/libsanitizer/hwasan/hwasan_allocator.cpp
index 
b4fae5820d0a1749663f251c7a3f1dc841741aed..81a57d3afd4d364dca96f20df3e94014483b6df1
 100644
--- a/libsanitizer/hwasan/hwasan_allocator.cpp
+++ b/libsanitizer/hwasan/hwasan_allocator.cpp
@@ -22,11 +22,6 @@
 #include "hwasan_thread.h"
 #include "hwasan_report.h"
 
-#if HWASAN_WITH_INTERCEPTORS
-DEFINE_REAL(void *, realloc, void *ptr, uptr size)
-DEFINE_REAL(void, free, void *ptr)
-#endif
-
 namespace __hwasan {
 
 static Allocator allocator;
@@ -301,14 +296,6 @@ void *hwasan_calloc(uptr nmemb, uptr size, StackTrace 
*stack) {
 void *hwasan_realloc(void *ptr, uptr size, StackTrace *stack) {
   if (!ptr)
 return SetErrnoOnNull(HwasanAllocate(stack, size, sizeof(u64), false));
-
-#if HWASAN_WITH_INTERCEPTORS
-  // A tag of 0 means that this is a system allocator allocation, so we must 
use
-  // the system allocator to realloc it.
-  if (!flags()->disable_allocator_tagging && GetTagFromPointer((uptr)ptr) == 0)
-return REAL(realloc)(ptr, size);
-#endif
-
   if (size == 0) {
 HwasanDeallocate(stack, ptr);
 return nullptr;
@@ -381,13 +368,6 @@ int hwasan_posix_memalign(void **memptr, uptr alignment, 
uptr size,
 }
 
 void hwasan_free(void *ptr, StackTrace *stack) {
-#if HWASAN_WITH_INTERCEPTORS
-  // A tag of 0 means that this is a system allocator allocation, so we must 
use
-  // the system allocator to free it.
-  if (!flags()->disable_allocator_tagging && GetTagFromPointer((uptr)ptr) == 0)
-return REAL(free)(ptr);
-#endif
-
   return HwasanDeallocate(stack, ptr);
 }
 
@@ -400,15 +380,6 @@ void __hwasan_enable_allocator_tagging() {
 }
 
 void __hwasan_disable_allocator_tagging() {
-#if HWASAN_WITH_INTERCEPTORS
-  // Allocator tagging must be enabled for the system allocator fallback to 
work
-  // correctly. This means that we can't disable it at runtime if it was 
enabled
-  // at startup since that might result in our deallocations going to the 
system
-  // allocator. If tagging was disabled at startup we avoid this problem by
-  // disabling the fallback altogether.
-  CHECK(flags()->disable_allocator_tagging);
-#endif
-
   atomic_store_relaxed(&hwasan_allocator_tagging_enabled, 0);
 }
 
diff --git a/libsanitizer/hwasan/hwasan_interceptors.cpp 
b/libsanitizer/hwasan/hwasan_interceptors.cpp
index 
f6758efa65c051376468d3cad2c1530fa7329627..4f9bd3469eb10ca2cf3108326308e45e7a9d38b6
 100644
--- a/libsanitizer/hwasan/hwasan_interceptors.cpp
+++ b/libsanitizer/hwasan/hwasan_interceptors.cpp
@@ -334,8 +334,6 @@ void InitializeInterceptors() {
 #if !defined(__aarch64__)
   INTERCEPT_FUNCTION(pthread_create);
 #endif  // __aarch64__
-  INTERCEPT_FUNCTION(realloc);
-  INTERCEPT_FUNCTION(free);
 #endif
 
   inited = 1;

diff --git a/libsanitizer/hwasan/hwasan_allocator.h 
b/libsanitizer/hwasan/hwasan_allocator.h
index 
3a50a11f352600d82aaaf73ddd7a5595e9f8a4d5..f62be269602143679f9f7abc9ec4a8a08dad207f
 100644
--- a/libsanitizer/hwasan/hwasan_allocator.h
+++ b/libsanitizer/hwasan/hwasan_allocator.h
@@ -13,7 +13,6 @@
 #ifndef HWASAN_ALLOCATOR_H
 #define HWASAN_ALLOCATOR_H
 
-#include "interception/interception.h"
 #include "sanitizer_common/sanitizer_allocator.h"
 #include "sanitizer_common/sanitizer_allocator_checks.h"
 #include "sanitizer_common/sanitizer_allocator_interface.h"
@@ -26,11 +25,6 @@
 #error Unsupported platform
 #e

[PATCH 3/X] [libsanitizer] libhwasan initialisation include kernel syscall ABI relaxation

2019-11-05 Thread Matthew Malcomson
Backported from LLVM-svn 375166.

libsanitizer/ChangeLog:

2019-11-05  Matthew Malcomson  

* hwasan/hwasan.cc (InitInstrumentation): Call InitPrctl.
* hwasan/hwasan.h (InitPrctl): New decl.
* hwasan/hwasan_linux.cc (InitPrctl): New function.



### Attachment also inlined for ease of reply###


diff --git a/libsanitizer/hwasan/hwasan.h b/libsanitizer/hwasan/hwasan.h
index 
817cee65016ee60f5cf6b5dc716a30e192e51e73..9e0ced93b55d361cd5aae787db7562741683944c
 100644
--- a/libsanitizer/hwasan/hwasan.h
+++ b/libsanitizer/hwasan/hwasan.h
@@ -74,6 +74,7 @@ extern int hwasan_report_count;
 
 bool ProtectRange(uptr beg, uptr end);
 bool InitShadow();
+void InitPrctl();
 void InitThreads();
 void MadviseShadow();
 char *GetProcSelfMaps();
diff --git a/libsanitizer/hwasan/hwasan.cpp b/libsanitizer/hwasan/hwasan.cpp
index 
999b51183f6184bb6564f3ec2f51f437e2598314..36d931caf7d4091480e1fc183a09d68735008b97
 100644
--- a/libsanitizer/hwasan/hwasan.cpp
+++ b/libsanitizer/hwasan/hwasan.cpp
@@ -312,6 +312,8 @@ static void InitLoadedGlobals() {
 static void InitInstrumentation() {
   if (hwasan_instrumentation_inited) return;
 
+  InitPrctl();
+
   if (!InitShadow()) {
 Printf("FATAL: HWAddressSanitizer cannot mmap the shadow memory.\n");
 DumpProcessMap();
diff --git a/libsanitizer/hwasan/hwasan_linux.cpp 
b/libsanitizer/hwasan/hwasan_linux.cpp
index 
051ec2fb9cc3aa333f4079dde6e5052173f84723..948e40154fec9295a451a3bc4e6a6914f619d6e3
 100644
--- a/libsanitizer/hwasan/hwasan_linux.cpp
+++ b/libsanitizer/hwasan/hwasan_linux.cpp
@@ -34,6 +34,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 
 #include "sanitizer_common/sanitizer_common.h"
 #include "sanitizer_common/sanitizer_procmaps.h"
@@ -144,6 +146,43 @@ static void InitializeShadowBaseAddress(uptr 
shadow_size_bytes) {
   FindDynamicShadowStart(shadow_size_bytes);
 }
 
+void InitPrctl() {
+#define PR_SET_TAGGED_ADDR_CTRL 55
+#define PR_GET_TAGGED_ADDR_CTRL 56
+#define PR_TAGGED_ADDR_ENABLE (1UL << 0)
+  // Check we're running on a kernel that can use the tagged address ABI.
+  if (internal_prctl(PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0) == (uptr)-1 &&
+  errno == EINVAL) {
+#if SANITIZER_ANDROID
+// Some older Android kernels have the tagged pointer ABI on
+// unconditionally, and hence don't have the tagged-addr prctl while still
+// allow the ABI.
+// If targeting Android and the prctl is not around we assume this is the
+// case.
+return;
+#else
+Printf(
+"FATAL: "
+"HWAddressSanitizer requires a kernel with tagged address ABI.\n");
+Die();
+#endif
+  }
+
+  // Turn on the tagged address ABI.
+  if (internal_prctl(PR_SET_TAGGED_ADDR_CTRL, PR_TAGGED_ADDR_ENABLE, 0, 0, 0) 
==
+  (uptr)-1 ||
+  !internal_prctl(PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0)) {
+Printf(
+"FATAL: HWAddressSanitizer failed to enable tagged address syscall "
+"ABI.\nSuggest check `sysctl abi.tagged_addr_disabled` "
+"configuration.\n");
+Die();
+  }
+#undef PR_SET_TAGGED_ADDR_CTRL
+#undef PR_GET_TAGGED_ADDR_CTRL
+#undef PR_TAGGED_ADDR_ENABLE
+}
+
 bool InitShadow() {
   // Define the entire memory range.
   kHighMemEnd = GetHighMemEnd();

diff --git a/libsanitizer/hwasan/hwasan.h b/libsanitizer/hwasan/hwasan.h
index 
817cee65016ee60f5cf6b5dc716a30e192e51e73..9e0ced93b55d361cd5aae787db7562741683944c
 100644
--- a/libsanitizer/hwasan/hwasan.h
+++ b/libsanitizer/hwasan/hwasan.h
@@ -74,6 +74,7 @@ extern int hwasan_report_count;
 
 bool ProtectRange(uptr beg, uptr end);
 bool InitShadow();
+void InitPrctl();
 void InitThreads();
 void MadviseShadow();
 char *GetProcSelfMaps();
diff --git a/libsanitizer/hwasan/hwasan.cpp b/libsanitizer/hwasan/hwasan.cpp
index 
999b51183f6184bb6564f3ec2f51f437e2598314..36d931caf7d4091480e1fc183a09d68735008b97
 100644
--- a/libsanitizer/hwasan/hwasan.cpp
+++ b/libsanitizer/hwasan/hwasan.cpp
@@ -312,6 +312,8 @@ static void InitLoadedGlobals() {
 static void InitInstrumentation() {
   if (hwasan_instrumentation_inited) return;
 
+  InitPrctl();
+
   if (!InitShadow()) {
 Printf("FATAL: HWAddressSanitizer cannot mmap the shadow memory.\n");
 DumpProcessMap();
diff --git a/libsanitizer/hwasan/hwasan_linux.cpp 
b/libsanitizer/hwasan/hwasan_linux.cpp
index 
051ec2fb9cc3aa333f4079dde6e5052173f84723..948e40154fec9295a451a3bc4e6a6914f619d6e3
 100644
--- a/libsanitizer/hwasan/hwasan_linux.cpp
+++ b/libsanitizer/hwasan/hwasan_linux.cpp
@@ -34,6 +34,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 
 #include "sanitizer_common/sanitizer_common.h"
 #include "sanitizer_common/sanitizer_procmaps.h"
@@ -144,6 +146,43 @@ static void InitializeShadowBaseAddress(uptr 
shadow_size_bytes) {
   FindDynamicShadowStart(shadow_size_bytes);
 }
 
+void InitPrctl() {
+#define PR_SET_T

[PATCH 4/X] [libsanitizer] libhwasan add longjmp & setjmp interceptors

2019-11-05 Thread Matthew Malcomson
Backported from LLVM git id 67474c60d

libsanitizer/ChangeLog:

2019-11-05  Matthew Malcomson  

* hwasan/hwasan.h (__hw_jmp_buf_struct, __hw_jmp_buf,
__hw_sigjmp_buf): Define new types for internal longjmp
implementation.
* hwasan/hwasan_interceptors.cpp (__sigjmp_save,
InternalLongjmp, siglongjmp, longjmp, __libc_longjmp): New.
* hwasan/hwasan_setjmp.S: New file.
* hwasan/hwasan_type_test.cpp: New file.



### Attachment also inlined for ease of reply###


diff --git a/libsanitizer/hwasan/hwasan.h b/libsanitizer/hwasan/hwasan.h
index 
9e0ced93b55d361cd5aae787db7562741683944c..64cdcf30f5c7059dcc1916f72e14b6649ca701f5
 100644
--- a/libsanitizer/hwasan/hwasan.h
+++ b/libsanitizer/hwasan/hwasan.h
@@ -172,4 +172,24 @@ void AndroidTestTlsSlot();
 RunFreeHooks(ptr);\
   } while (false)
 
+#if HWASAN_WITH_INTERCEPTORS && defined(__aarch64__)
+// For both bionic and glibc __sigset_t is an unsigned long.
+typedef unsigned long __hw_sigset_t;
+// Setjmp and longjmp implementations are platform specific, and hence the
+// interception code is platform specific too.  As yet we've only implemented
+// the interception for AArch64.
+typedef unsigned long long __hw_register_buf[22];
+struct __hw_jmp_buf_struct {
+  // NOTE: The machine-dependent definition of `__sigsetjmp'
+  // assume that a `__hw_jmp_buf' begins with a `__hw_register_buf' and that
+  // `__mask_was_saved' follows it.  Do not move these members or add others
+  // before it.
+  __hw_register_buf __jmpbuf; // Calling environment.
+  int __mask_was_saved;   // Saved the signal mask?
+  __hw_sigset_t __saved_mask; // Saved signal mask.
+};
+typedef struct __hw_jmp_buf_struct __hw_jmp_buf[1];
+typedef struct __hw_jmp_buf_struct __hw_sigjmp_buf[1];
+#endif // HWASAN_WITH_INTERCEPTORS && __aarch64__
+
 #endif  // HWASAN_H
diff --git a/libsanitizer/hwasan/hwasan_interceptors.cpp 
b/libsanitizer/hwasan/hwasan_interceptors.cpp
index 
47fed0fc9abb821996efcd8d12f7e5442916326d..f6758efa65c051376468d3cad2c1530fa7329627
 100644
--- a/libsanitizer/hwasan/hwasan_interceptors.cpp
+++ b/libsanitizer/hwasan/hwasan_interceptors.cpp
@@ -220,6 +220,80 @@ DEFINE_REAL(int, vfork)
 DECLARE_EXTERN_INTERCEPTOR_AND_WRAPPER(int, vfork)
 #endif
 
+#if HWASAN_WITH_INTERCEPTORS && defined(__aarch64__)
+// Get and/or change the set of blocked signals.
+extern "C" int sigprocmask(int __how, const __hw_sigset_t *__restrict __set,
+   __hw_sigset_t *__restrict __oset);
+#define SIG_BLOCK 0
+#define SIG_SETMASK 2
+extern "C" int __sigjmp_save(__hw_sigjmp_buf env, int savemask) {
+  env[0].__mask_was_saved =
+  (savemask && sigprocmask(SIG_BLOCK, (__hw_sigset_t *)0,
+   &env[0].__saved_mask) == 0);
+  return 0;
+}
+
+static void __attribute__((always_inline))
+InternalLongjmp(__hw_register_buf env, int retval) {
+  // Clear all memory tags on the stack between here and where we're going.
+  unsigned long long stack_pointer = env[13];
+  // The stack pointer should never be tagged, so we don't need to clear the
+  // tag for this function call.
+  __hwasan_handle_longjmp((void *)stack_pointer);
+
+  // Run code for handling a longjmp.
+  // Need to use a register that isn't going to be loaded from the environment
+  // buffer -- hence why we need to specify the register to use.
+  // Must implement this ourselves, since we don't know the order of registers
+  // in different libc implementations and many implementations mangle the
+  // stack pointer so we can't use it without knowing the demangling scheme.
+  register long int retval_tmp asm("x1") = retval;
+  register void *env_address asm("x0") = &env[0];
+  asm volatile("ldpx19, x20, [%0, #0<<3];"
+   "ldpx21, x22, [%0, #2<<3];"
+   "ldpx23, x24, [%0, #4<<3];"
+   "ldpx25, x26, [%0, #6<<3];"
+   "ldpx27, x28, [%0, #8<<3];"
+   "ldpx29, x30, [%0, #10<<3];"
+   "ldp d8,  d9, [%0, #14<<3];"
+   "ldpd10, d11, [%0, #16<<3];"
+   "ldpd12, d13, [%0, #18<<3];"
+   "ldpd14, d15, [%0, #20<<3];"
+   "ldrx5, [%0, #13<<3];"
+   "movsp, x5;"
+   // Return the value requested to return through arguments.
+   // This should be in x1 given what we requested above.
+   "cmp%1, #0;"
+   "movx0, #1;"
+   "csel   x0, %1, x0, ne;"
+   "br x30;"
+   : "+r"(env_ad

[PATCH 9/X] [libsanitizer] Remove lazy thread initialisation

2019-11-05 Thread Matthew Malcomson
Backport from llvm upstream (monorepo revision 91167e2).
This was an experiment made possible by a non-standard feature of the
Android dynamic loader.

libsanitizer/ChangeLog:

2019-11-05  Matthew Malcomson  

* hwasan/hwasan_interceptors.cpp (HwasanThreadStartFunc):
Re-introduce.
(pthread_create): Use HwasanThreadStartFunc to initialise the
sanitizer for each thread as it starts.
* hwasan/hwasan_linux.cpp (GetCurrentThread): Assume thread is
initialised.



### Attachment also inlined for ease of reply###


diff --git a/libsanitizer/hwasan/hwasan_interceptors.cpp 
b/libsanitizer/hwasan/hwasan_interceptors.cpp
index 
4f9bd3469eb10ca2cf3108326308e45e7a9d38b6..44e569ee6d721a99aa21ebf1a51fb33b6e7a
 100644
--- a/libsanitizer/hwasan/hwasan_interceptors.cpp
+++ b/libsanitizer/hwasan/hwasan_interceptors.cpp
@@ -202,23 +202,33 @@ INTERCEPTOR_ALIAS(__sanitizer_struct_mallinfo, mallinfo);
 INTERCEPTOR_ALIAS(int, mallopt, int cmd, int value);
 INTERCEPTOR_ALIAS(void, malloc_stats, void);
 #endif
-#endif // HWASAN_WITH_INTERCEPTORS
 
+struct ThreadStartArg {
+  thread_callback_t callback;
+  void *param;
+};
+
+static void *HwasanThreadStartFunc(void *arg) {
+  __hwasan_thread_enter();
+  ThreadStartArg A = *reinterpret_cast(arg);
+  UnmapOrDie(arg, GetPageSizeCached());
+  return A.callback(A.param);
+}
 
-#if HWASAN_WITH_INTERCEPTORS && !defined(__aarch64__)
-INTERCEPTOR(int, pthread_create, void *th, void *attr,
-void *(*callback)(void *), void *param) {
+INTERCEPTOR(int, pthread_create, void *th, void *attr, void 
*(*callback)(void*),
+void * param) {
   ScopedTaggingDisabler disabler;
+  ThreadStartArg *A = reinterpret_cast (MmapOrDie(
+  GetPageSizeCached(), "pthread_create"));
+  *A = {callback, param};
   int res = REAL(pthread_create)(UntagPtr(th), UntagPtr(attr),
- callback, param);
+ &HwasanThreadStartFunc, A);
   return res;
 }
-#endif
 
-#if HWASAN_WITH_INTERCEPTORS
 DEFINE_REAL(int, vfork)
 DECLARE_EXTERN_INTERCEPTOR_AND_WRAPPER(int, vfork)
-#endif
+#endif // HWASAN_WITH_INTERCEPTORS
 
 #if HWASAN_WITH_INTERCEPTORS && defined(__aarch64__)
 // Get and/or change the set of blocked signals.
@@ -331,9 +341,7 @@ void InitializeInterceptors() {
 #if defined(__linux__)
   INTERCEPT_FUNCTION(vfork);
 #endif  // __linux__
-#if !defined(__aarch64__)
   INTERCEPT_FUNCTION(pthread_create);
-#endif  // __aarch64__
 #endif
 
   inited = 1;
diff --git a/libsanitizer/hwasan/hwasan_linux.cpp 
b/libsanitizer/hwasan/hwasan_linux.cpp
index 
dfef11883a284dae0c96cfcc6a8fd1cc06c24d71..ed0f30161b023bf5927aa4a471f6a7c3edc8edf6
 100644
--- a/libsanitizer/hwasan/hwasan_linux.cpp
+++ b/libsanitizer/hwasan/hwasan_linux.cpp
@@ -354,12 +354,7 @@ void AndroidTestTlsSlot() {}
 #endif
 
 Thread *GetCurrentThread() {
-  uptr *ThreadLong = GetCurrentThreadLongPtr();
-#if HWASAN_WITH_INTERCEPTORS
-  if (!*ThreadLong)
-__hwasan_thread_enter();
-#endif
-  auto *R = (StackAllocationsRingBuffer *)ThreadLong;
+  auto *R = (StackAllocationsRingBuffer *)GetCurrentThreadLongPtr();
   return hwasanThreadList().GetThreadByBufferAddress((uptr)(R->Next()));
 }
 

diff --git a/libsanitizer/hwasan/hwasan_interceptors.cpp 
b/libsanitizer/hwasan/hwasan_interceptors.cpp
index 
4f9bd3469eb10ca2cf3108326308e45e7a9d38b6..44e569ee6d721a99aa21ebf1a51fb33b6e7a
 100644
--- a/libsanitizer/hwasan/hwasan_interceptors.cpp
+++ b/libsanitizer/hwasan/hwasan_interceptors.cpp
@@ -202,23 +202,33 @@ INTERCEPTOR_ALIAS(__sanitizer_struct_mallinfo, mallinfo);
 INTERCEPTOR_ALIAS(int, mallopt, int cmd, int value);
 INTERCEPTOR_ALIAS(void, malloc_stats, void);
 #endif
-#endif // HWASAN_WITH_INTERCEPTORS
 
+struct ThreadStartArg {
+  thread_callback_t callback;
+  void *param;
+};
+
+static void *HwasanThreadStartFunc(void *arg) {
+  __hwasan_thread_enter();
+  ThreadStartArg A = *reinterpret_cast(arg);
+  UnmapOrDie(arg, GetPageSizeCached());
+  return A.callback(A.param);
+}
 
-#if HWASAN_WITH_INTERCEPTORS && !defined(__aarch64__)
-INTERCEPTOR(int, pthread_create, void *th, void *attr,
-void *(*callback)(void *), void *param) {
+INTERCEPTOR(int, pthread_create, void *th, void *attr, void 
*(*callback)(void*),
+void * param) {
   ScopedTaggingDisabler disabler;
+  ThreadStartArg *A = reinterpret_cast (MmapOrDie(
+  GetPageSizeCached(), "pthread_create"));
+  *A = {callback, param};
   int res = REAL(pthread_create)(UntagPtr(th), UntagPtr(attr),
- callback, param);
+ &HwasanThreadStartFunc, A);
   return res;
 }
-#endif
 
-#if HWASAN_WITH_INTERCEPTORS
 DEFINE_REAL(int, vfork)
 DECLARE_EXTERN_INTERCEPTOR_AND_WRAPPER(int, vfork)
-#endif
+#endif // HWASAN_WITH_INTERCEPTORS
 
 #if HWASAN_WITH_INTERCEPTORS && defined(__aarch64__)
 // Get and

[PATCH 7/X] [libsanitizer] Add missing SANITIZER_INTERFACE_ATTRIBUTE on __hwasan_personality_wrapper

2019-11-05 Thread Matthew Malcomson
Backport from llvm upstream llvm-svn: 375298.

libsanitizer/ChangeLog:

2019-11-05  Matthew Malcomson  

* hwasan/hwasan_exceptions.cpp (__hwasan_personality_wrapper):
Add missing interface attribute.



### Attachment also inlined for ease of reply###


diff --git a/libsanitizer/hwasan/hwasan_exceptions.cpp 
b/libsanitizer/hwasan/hwasan_exceptions.cpp
index 
57a1438064cd28bb609359a4c841acf78337ebc3..169e7876cb58a9dafb70973ed9fb1dfd815a7ceb
 100644
--- a/libsanitizer/hwasan/hwasan_exceptions.cpp
+++ b/libsanitizer/hwasan/hwasan_exceptions.cpp
@@ -32,10 +32,13 @@ typedef _Unwind_Reason_Code PersonalityFn(int version, 
_Unwind_Action actions,
 typedef _Unwind_Word GetGRFn(_Unwind_Context* context, int index);
 typedef _Unwind_Word GetCFAFn(_Unwind_Context* context);
 
-extern "C" _Unwind_Reason_Code __hwasan_personality_wrapper(
-int version, _Unwind_Action actions, uint64_t exception_class,
-_Unwind_Exception* unwind_exception, _Unwind_Context* context,
-PersonalityFn* real_personality, GetGRFn* get_gr, GetCFAFn* get_cfa) {
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE _Unwind_Reason_Code
+__hwasan_personality_wrapper(int version, _Unwind_Action actions,
+ uint64_t exception_class,
+ _Unwind_Exception* unwind_exception,
+ _Unwind_Context* context,
+ PersonalityFn* real_personality, GetGRFn* get_gr,
+ GetCFAFn* get_cfa) {
   _Unwind_Reason_Code rc;
   if (real_personality)
 rc = real_personality(version, actions, exception_class, unwind_exception,

diff --git a/libsanitizer/hwasan/hwasan_exceptions.cpp 
b/libsanitizer/hwasan/hwasan_exceptions.cpp
index 
57a1438064cd28bb609359a4c841acf78337ebc3..169e7876cb58a9dafb70973ed9fb1dfd815a7ceb
 100644
--- a/libsanitizer/hwasan/hwasan_exceptions.cpp
+++ b/libsanitizer/hwasan/hwasan_exceptions.cpp
@@ -32,10 +32,13 @@ typedef _Unwind_Reason_Code PersonalityFn(int version, 
_Unwind_Action actions,
 typedef _Unwind_Word GetGRFn(_Unwind_Context* context, int index);
 typedef _Unwind_Word GetCFAFn(_Unwind_Context* context);
 
-extern "C" _Unwind_Reason_Code __hwasan_personality_wrapper(
-int version, _Unwind_Action actions, uint64_t exception_class,
-_Unwind_Exception* unwind_exception, _Unwind_Context* context,
-PersonalityFn* real_personality, GetGRFn* get_gr, GetCFAFn* get_cfa) {
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE _Unwind_Reason_Code
+__hwasan_personality_wrapper(int version, _Unwind_Action actions,
+ uint64_t exception_class,
+ _Unwind_Exception* unwind_exception,
+ _Unwind_Context* context,
+ PersonalityFn* real_personality, GetGRFn* get_gr,
+ GetCFAFn* get_cfa) {
   _Unwind_Reason_Code rc;
   if (real_personality)
 rc = real_personality(version, actions, exception_class, unwind_exception,



[PATCH 6/X] [libsanitizer] Add hwasan_exceptions.cpp file

2019-11-05 Thread Matthew Malcomson
This is needed for the hwasan_personality instrumentation I've added.
Backported from llvm-svn: 369721

libsanitizer/ChangeLog:

2019-11-05  Matthew Malcomson  

* hwasan/hwasan_exceptions.cpp: New file.



### Attachment also inlined for ease of reply###


diff --git a/libsanitizer/hwasan/hwasan_exceptions.cpp 
b/libsanitizer/hwasan/hwasan_exceptions.cpp
new file mode 100644
index 
..57a1438064cd28bb609359a4c841acf78337ebc3
--- /dev/null
+++ b/libsanitizer/hwasan/hwasan_exceptions.cpp
@@ -0,0 +1,64 @@
+//===-- hwasan_exceptions.cpp 
-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+//
+// This file is a part of HWAddressSanitizer.
+//
+// HWAddressSanitizer runtime.
+//===--===//
+
+#include "hwasan_poisoning.h"
+#include "sanitizer_common/sanitizer_common.h"
+
+#include 
+
+using namespace __hwasan;
+using namespace __sanitizer;
+
+typedef _Unwind_Reason_Code PersonalityFn(int version, _Unwind_Action actions,
+  uint64_t exception_class,
+  _Unwind_Exception* unwind_exception,
+  _Unwind_Context* context);
+
+// Pointers to the _Unwind_GetGR and _Unwind_GetCFA functions are passed in
+// instead of being called directly. This is to handle cases where the unwinder
+// is statically linked and the sanitizer runtime and the program are linked
+// against different unwinders. The _Unwind_Context data structure is opaque so
+// it may be incompatible between unwinders.
+typedef _Unwind_Word GetGRFn(_Unwind_Context* context, int index);
+typedef _Unwind_Word GetCFAFn(_Unwind_Context* context);
+
+extern "C" _Unwind_Reason_Code __hwasan_personality_wrapper(
+int version, _Unwind_Action actions, uint64_t exception_class,
+_Unwind_Exception* unwind_exception, _Unwind_Context* context,
+PersonalityFn* real_personality, GetGRFn* get_gr, GetCFAFn* get_cfa) {
+  _Unwind_Reason_Code rc;
+  if (real_personality)
+rc = real_personality(version, actions, exception_class, unwind_exception,
+  context);
+  else
+rc = _URC_CONTINUE_UNWIND;
+
+  // We only untag frames without a landing pad because landing pads are
+  // responsible for untagging the stack themselves if they resume.
+  //
+  // Here we assume that the frame record appears after any locals. This is not
+  // required by AAPCS but is a requirement for HWASAN instrumented functions.
+  if ((actions & _UA_CLEANUP_PHASE) && rc == _URC_CONTINUE_UNWIND) {
+#if defined(__x86_64__)
+uptr fp = get_gr(context, 6); // rbp
+#elif defined(__aarch64__)
+uptr fp = get_gr(context, 29); // x29
+#else
+#error Unsupported architecture
+#endif
+uptr sp = get_cfa(context);
+TagMemory(sp, fp - sp, 0);
+  }
+
+  return rc;
+}

diff --git a/libsanitizer/hwasan/hwasan_exceptions.cpp 
b/libsanitizer/hwasan/hwasan_exceptions.cpp
new file mode 100644
index 
..57a1438064cd28bb609359a4c841acf78337ebc3
--- /dev/null
+++ b/libsanitizer/hwasan/hwasan_exceptions.cpp
@@ -0,0 +1,64 @@
+//===-- hwasan_exceptions.cpp 
-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+//
+// This file is a part of HWAddressSanitizer.
+//
+// HWAddressSanitizer runtime.
+//===--===//
+
+#include "hwasan_poisoning.h"
+#include "sanitizer_common/sanitizer_common.h"
+
+#include 
+
+using namespace __hwasan;
+using namespace __sanitizer;
+
+typedef _Unwind_Reason_Code PersonalityFn(int version, _Unwind_Action actions,
+  uint64_t exception_class,
+  _Unwind_Exception* unwind_exception,
+  _Unwind_Context* context);
+
+// Pointers to the _Unwind_GetGR and _Unwind_GetCFA functions are passed in
+// instead of being called directly. This is to handle cases where the unwinder
+// is statically linked and the sanitizer runtime and the program are linked
+// against different unwinders. The _Unwind_Context data structure is opaque so
+// it may be incompatible between unwinders.
+typedef _Unwind_Word GetGRFn(_Unwind_Context* 

[PATCH 8/X] [libsanitizer] Expose __hwasan_tag_mismatch_stub

2019-11-05 Thread Matthew Malcomson
Backport from llvm upstream (monorepo revision 612eadb).
This allows us to report tag mismatches without threading it through the
backend to generate assembly.

libsanitizer/ChangeLog:

2019-11-05  Matthew Malcomson  

* hwasan/hwasan_interface_internal.h (__hwasan_tag_mismatch4):
New exported symbol.
* hwasan/hwasan_linux.cpp (__hwasan_tag_mismatch_stub): Rename
to ...
(__hwasan_tag_mismatch4): ... this.  Also add "size" argument.
* hwasan/hwasan_tag_mismatch_aarch64.S: Update function call to
use new name.



### Attachment also inlined for ease of reply###


diff --git a/libsanitizer/hwasan/hwasan_interface_internal.h 
b/libsanitizer/hwasan/hwasan_interface_internal.h
index 
ca57f0fe437bfdbc3d490c1978985fc3ab64d4c5..aedda317497b61349050511a3d244f480fae5ba2
 100644
--- a/libsanitizer/hwasan/hwasan_interface_internal.h
+++ b/libsanitizer/hwasan/hwasan_interface_internal.h
@@ -112,6 +112,10 @@ SANITIZER_INTERFACE_ATTRIBUTE
 void __hwasan_tag_mismatch(uptr addr, u8 ts);
 
 SANITIZER_INTERFACE_ATTRIBUTE
+void __hwasan_tag_mismatch4(uptr addr, uptr access_info, uptr *registers_frame,
+size_t outsize);
+
+SANITIZER_INTERFACE_ATTRIBUTE
 u8 __hwasan_generate_tag();
 
 // Returns the offset of the first tag mismatch or -1 if the whole range is
diff --git a/libsanitizer/hwasan/hwasan_linux.cpp 
b/libsanitizer/hwasan/hwasan_linux.cpp
index 
948e40154fec9295a451a3bc4e6a6914f619d6e3..dfef11883a284dae0c96cfcc6a8fd1cc06c24d71
 100644
--- a/libsanitizer/hwasan/hwasan_linux.cpp
+++ b/libsanitizer/hwasan/hwasan_linux.cpp
@@ -460,21 +460,6 @@ static bool HwasanOnSIGTRAP(int signo, siginfo_t *info, 
ucontext_t *uc) {
   return true;
 }
 
-// Entry point stub for interoperability between __hwasan_tag_mismatch (ASM) 
and
-// the rest of the mismatch handling code (C++).
-extern "C" void __hwasan_tag_mismatch_stub(uptr addr, uptr access_info,
-   uptr *registers_frame) {
-  AccessInfo ai;
-  ai.is_store = access_info & 0x10;
-  ai.recover = false;
-  ai.addr = addr;
-  ai.size = 1 << (access_info & 0xf);
-
-  HandleTagMismatch(ai, (uptr)__builtin_return_address(0),
-(uptr)__builtin_frame_address(0), nullptr, 
registers_frame);
-  __builtin_unreachable();
-}
-
 static void OnStackUnwind(const SignalContext &sig, const void *,
   BufferedStackTrace *stack) {
   stack->Unwind(StackTrace::GetNextInstructionPc(sig.pc), sig.bp, sig.context,
@@ -493,4 +478,24 @@ void HwasanOnDeadlySignal(int signo, void *info, void 
*context) {
 
 } // namespace __hwasan
 
+// Entry point for interoperability between __hwasan_tag_mismatch (ASM) and the
+// rest of the mismatch handling code (C++).
+void __hwasan_tag_mismatch4(uptr addr, uptr access_info, uptr *registers_frame,
+size_t outsize) {
+  __hwasan::AccessInfo ai;
+  ai.is_store = access_info & 0x10;
+  ai.is_load = !ai.is_store;
+  ai.recover = access_info & 0x20;
+  ai.addr = addr;
+  if ((access_info & 0xf) == 0xf)
+ai.size = outsize;
+  else
+ai.size = 1 << (access_info & 0xf);
+
+  __hwasan::HandleTagMismatch(ai, (uptr)__builtin_return_address(0),
+  (uptr)__builtin_frame_address(0), nullptr,
+  registers_frame);
+  __builtin_unreachable();
+}
+
 #endif // SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD
diff --git a/libsanitizer/hwasan/hwasan_tag_mismatch_aarch64.S 
b/libsanitizer/hwasan/hwasan_tag_mismatch_aarch64.S
index 
92f62748048682f2e762a91050232fd3c65d538f..d1e0654cf715149d9ce6e3d8863ccd4f33745c95
 100644
--- a/libsanitizer/hwasan/hwasan_tag_mismatch_aarch64.S
+++ b/libsanitizer/hwasan/hwasan_tag_mismatch_aarch64.S
@@ -89,12 +89,12 @@ __hwasan_tag_mismatch:
   stp x4,  x5,  [sp, #32]
   stp x2,  x3,  [sp, #16]
 
-  // Pass the address of the frame to __hwasan_tag_mismatch_stub, so that it 
can
+  // Pass the address of the frame to __hwasan_tag_mismatch4, so that it can
   // extract the saved registers from this frame without having to worry about
   // finding this frame.
   mov x2, sp
 
-  bl __hwasan_tag_mismatch_stub
+  bl __hwasan_tag_mismatch4
   CFI_ENDPROC
 
 .Lfunc_end0:

diff --git a/libsanitizer/hwasan/hwasan_interface_internal.h 
b/libsanitizer/hwasan/hwasan_interface_internal.h
index 
ca57f0fe437bfdbc3d490c1978985fc3ab64d4c5..aedda317497b61349050511a3d244f480fae5ba2
 100644
--- a/libsanitizer/hwasan/hwasan_interface_internal.h
+++ b/libsanitizer/hwasan/hwasan_interface_internal.h
@@ -112,6 +112,10 @@ SANITIZER_INTERFACE_ATTRIBUTE
 void __hwasan_tag_mismatch(uptr addr, u8 ts);
 
 SANITIZER_INTERFACE_ATTRIBUTE
+void __hwasan_tag_mismatch4(uptr addr, uptr access_info, uptr *registers_frame,
+size_t outsize);
+
+SANITIZER_INTERFACE_ATTRIBUTE
 u8 __hwasan_generate_tag();

[PATCH 10/X] [libsanitizer] Tie the hwasan library into our build system

2019-11-05 Thread Matthew Malcomson
This patch does tries to tie libhwasan into the GCC build system in the
same way that the other sanitizer runtime libraries are handled.

libsanitizer/ChangeLog:

2019-11-05  Matthew Malcomson  

* Makefile.am:  Build libhwasan.
* Makefile.in:  Build libhwasan.
* asan/Makefile.in:  Build libhwasan.
* configure:  Build libhwasan.
* configure.ac:  Build libhwasan.
* hwasan/Makefile.am: New file.
* hwasan/Makefile.in: New file.
* hwasan/libtool-version: New file.
* interception/Makefile.in: Build libhwasan.
* libbacktrace/Makefile.in: Build libhwasan.
* libsanitizer.spec.in: Build libhwasan.
* lsan/Makefile.in: Build libhwasan.
* merge.sh: Build libhwasan.
* sanitizer_common/Makefile.in: Build libhwasan.
* tsan/Makefile.in: Build libhwasan.
* ubsan/Makefile.in: Build libhwasan.



### Attachment also inlined for ease of reply###


diff --git a/libsanitizer/Makefile.am b/libsanitizer/Makefile.am
index 
65ed1e712378ef453f820f86c4d3221f9dee5f2c..2a7e8e1debe838719db0f0fad218b2543cc3111b
 100644
--- a/libsanitizer/Makefile.am
+++ b/libsanitizer/Makefile.am
@@ -14,11 +14,12 @@ endif
 if LIBBACKTRACE_SUPPORTED
 SUBDIRS += libbacktrace
 endif
-SUBDIRS += lsan asan ubsan
+SUBDIRS += lsan asan ubsan hwasan
 nodist_saninclude_HEADERS += \
   include/sanitizer/lsan_interface.h \
   include/sanitizer/asan_interface.h \
-  include/sanitizer/tsan_interface.h
+  include/sanitizer/tsan_interface.h \
+  include/sanitizer/hwasan_interface.h
 if TSAN_SUPPORTED
 SUBDIRS += tsan
 endif
diff --git a/libsanitizer/Makefile.in b/libsanitizer/Makefile.in
index 
0d789b3a59d21ea2e5a23057ca3afe15425feec4..404ddcedde5428e0bc6d8ebc5f6568f99741ce2a
 100644
--- a/libsanitizer/Makefile.in
+++ b/libsanitizer/Makefile.in
@@ -92,7 +92,8 @@ target_triplet = @target@
 @SANITIZER_SUPPORTED_TRUE@am__append_1 = 
include/sanitizer/common_interface_defs.h \
 @SANITIZER_SUPPORTED_TRUE@ include/sanitizer/lsan_interface.h \
 @SANITIZER_SUPPORTED_TRUE@ include/sanitizer/asan_interface.h \
-@SANITIZER_SUPPORTED_TRUE@ include/sanitizer/tsan_interface.h
+@SANITIZER_SUPPORTED_TRUE@ include/sanitizer/tsan_interface.h \
+@SANITIZER_SUPPORTED_TRUE@ include/sanitizer/hwasan_interface.h
 @SANITIZER_SUPPORTED_TRUE@@USING_MAC_INTERPOSE_FALSE@am__append_2 = 
interception
 @LIBBACKTRACE_SUPPORTED_TRUE@@SANITIZER_SUPPORTED_TRUE@am__append_3 = 
libbacktrace
 @SANITIZER_SUPPORTED_TRUE@@TSAN_SUPPORTED_TRUE@am__append_4 = tsan
@@ -206,7 +207,7 @@ ETAGS = etags
 CTAGS = ctags
 CSCOPE = cscope
 DIST_SUBDIRS = sanitizer_common interception libbacktrace lsan asan \
-   ubsan tsan
+   ubsan hwasan tsan
 ACLOCAL = @ACLOCAL@
 ALLOC_FILE = @ALLOC_FILE@
 AMTAR = @AMTAR@
@@ -328,6 +329,7 @@ install_sh = @install_sh@
 libdir = @libdir@
 libexecdir = @libexecdir@
 link_libasan = @link_libasan@
+link_libhwasan = @link_libhwasan@
 link_liblsan = @link_liblsan@
 link_libtsan = @link_libtsan@
 link_libubsan = @link_libubsan@
@@ -341,6 +343,7 @@ pdfdir = @pdfdir@
 prefix = @prefix@
 program_transform_name = @program_transform_name@
 psdir = @psdir@
+runstatedir = @runstatedir@
 sbindir = @sbindir@
 sharedstatedir = @sharedstatedir@
 srcdir = @srcdir@
@@ -361,7 +364,7 @@ sanincludedir = 
$(libdir)/gcc/$(target_alias)/$(gcc_version)/include/sanitizer
 nodist_saninclude_HEADERS = $(am__append_1)
 @SANITIZER_SUPPORTED_TRUE@SUBDIRS = sanitizer_common $(am__append_2) \
 @SANITIZER_SUPPORTED_TRUE@ $(am__append_3) lsan asan ubsan \
-@SANITIZER_SUPPORTED_TRUE@ $(am__append_4)
+@SANITIZER_SUPPORTED_TRUE@ hwasan $(am__append_4)
 gcc_version := $(shell @get_gcc_base_ver@ $(top_srcdir)/../gcc/BASE-VER)
 
 # Work around what appears to be a GNU make bug handling MAKEFLAGS
diff --git a/libsanitizer/asan/Makefile.in b/libsanitizer/asan/Makefile.in
index 
00b6082da5372efd679ddc230f588bbc58161ef6..5ce6944a526418e484ee5925d2573248e168a736
 100644
--- a/libsanitizer/asan/Makefile.in
+++ b/libsanitizer/asan/Makefile.in
@@ -382,6 +382,7 @@ install_sh = @install_sh@
 libdir = @libdir@
 libexecdir = @libexecdir@
 link_libasan = @link_libasan@
+link_libhwasan = @link_libhwasan@
 link_liblsan = @link_liblsan@
 link_libtsan = @link_libtsan@
 link_libubsan = @link_libubsan@
@@ -395,6 +396,7 @@ pdfdir = @pdfdir@
 prefix = @prefix@
 program_transform_name = @program_transform_name@
 psdir = @psdir@
+runstatedir = @runstatedir@
 sbindir = @sbindir@
 sharedstatedir = @sharedstatedir@
 srcdir = @srcdir@
diff --git a/libsanitizer/configure b/libsanitizer/configure
index 
2d25147adbaaa3578388cf75763e6178302aa3dc..967efdb1f6f8ed30089ff73efc4e349a8bf9c1fc
 100755
--- a/libsanitizer/configure
+++ b/libsanitizer/configure
@@ -657,6 +657,7 @@ USING_MAC_INTERPOSE_TRUE
 link_liblsan
 link_libubsan
 link_libtsan
+link_libhwasan
 link_libasan
 LSAN_SUPPORTED_FALSE
 LSAN_SUPPORTED_TRUE
@@ -779,6 +780,7 @@ infodir
 docdir
 oldincludedir

[PATCH 12/X] [libsanitizer] Add option to bootstrap using HWASAN

2019-11-05 Thread Matthew Malcomson
This is an analogous option to --bootstrap-asan to configure.  It allows
bootstrapping GCC using HWASAN.

For the same reasons as for ASAN we have to avoid using the HWASAN
sanitizer when compiling libiberty and the lto-plugin.

Also add a function to query whether -fsanitize=hwaddress has been
passed.

ChangeLog:

2019-08-29  Matthew Malcomson  

* configure: Regenerate.
* configure.ac: Add --bootstrap-hwasan option.

config/ChangeLog:

2019-11-05  Matthew Malcomson  

* bootstrap-hwasan.mk: New file.

libiberty/ChangeLog:

2019-11-05  Matthew Malcomson  

* configure: Regenerate.
* configure.ac: Avoid using sanitizer.

lto-plugin/ChangeLog:

2019-11-05  Matthew Malcomson  

* Makefile.am: Avoid using sanitizer.
* Makefile.in: Regenerate.



### Attachment also inlined for ease of reply###


diff --git a/config/bootstrap-hwasan.mk b/config/bootstrap-hwasan.mk
new file mode 100644
index 
..4f60bed3fd6e98b47a3a38aea6eba2a7c320da25
--- /dev/null
+++ b/config/bootstrap-hwasan.mk
@@ -0,0 +1,8 @@
+# This option enables -fsanitize=hwaddress for stage2 and stage3.
+
+STAGE2_CFLAGS += -fsanitize=hwaddress
+STAGE3_CFLAGS += -fsanitize=hwaddress
+POSTSTAGE1_LDFLAGS += -fsanitize=hwaddress -static-libhwasan \
+ -B$$r/prev-$(TARGET_SUBDIR)/libsanitizer/ \
+ -B$$r/prev-$(TARGET_SUBDIR)/libsanitizer/hwasan/ \
+ -B$$r/prev-$(TARGET_SUBDIR)/libsanitizer/hwasan/.libs
diff --git a/configure b/configure
index 
aec9186b2b0123d3088b69eb1ee541567654953e..c1a2b7ed25b6b4f8edfd44ed9049270b7eec2317
 100755
--- a/configure
+++ b/configure
@@ -754,6 +754,7 @@ infodir
 docdir
 oldincludedir
 includedir
+runstatedir
 localstatedir
 sharedstatedir
 sysconfdir
@@ -920,6 +921,7 @@ datadir='${datarootdir}'
 sysconfdir='${prefix}/etc'
 sharedstatedir='${prefix}/com'
 localstatedir='${prefix}/var'
+runstatedir='${localstatedir}/run'
 includedir='${prefix}/include'
 oldincludedir='/usr/include'
 docdir='${datarootdir}/doc/${PACKAGE}'
@@ -1172,6 +1174,15 @@ do
   | -silent | --silent | --silen | --sile | --sil)
 silent=yes ;;
 
+  -runstatedir | --runstatedir | --runstatedi | --runstated \
+  | --runstate | --runstat | --runsta | --runst | --runs \
+  | --run | --ru | --r)
+ac_prev=runstatedir ;;
+  -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
+  | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
+  | --run=* | --ru=* | --r=*)
+runstatedir=$ac_optarg ;;
+
   -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
 ac_prev=sbindir ;;
   -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
@@ -1309,7 +1320,7 @@ fi
 for ac_var in  exec_prefix prefix bindir sbindir libexecdir datarootdir \
datadir sysconfdir sharedstatedir localstatedir includedir \
oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
-   libdir localedir mandir
+   libdir localedir mandir runstatedir
 do
   eval ac_val=\$$ac_var
   # Remove trailing slashes.
@@ -1469,6 +1480,7 @@ Fine tuning of the installation directories:
   --sysconfdir=DIRread-only single-machine data [PREFIX/etc]
   --sharedstatedir=DIRmodifiable architecture-independent data [PREFIX/com]
   --localstatedir=DIR modifiable single-machine data [PREFIX/var]
+  --runstatedir=DIR   modifiable per-process data [LOCALSTATEDIR/run]
   --libdir=DIRobject code libraries [EPREFIX/lib]
   --includedir=DIRC header files [PREFIX/include]
   --oldincludedir=DIR C header files for non-gcc [/usr/include]
@@ -7270,7 +7282,7 @@ fi
 # or bootstrap-ubsan, bootstrap it.
 if echo " ${target_configdirs} " | grep " libsanitizer " > /dev/null 2>&1; then
   case "$BUILD_CONFIG" in
-*bootstrap-asan* | *bootstrap-ubsan* )
+*bootstrap-hwasan* | *bootstrap-asan* | *bootstrap-ubsan* )
   bootstrap_target_libs=${bootstrap_target_libs}target-libsanitizer,
   bootstrap_fixincludes=yes
   ;;
diff --git a/configure.ac b/configure.ac
index 
b8ce2ad20b9d03e42731252a9ec2a8417c13e566..16bfdf164555dad94c789f17b6a63ba1a2e3e9f4
 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2775,7 +2775,7 @@ fi
 # or bootstrap-ubsan, bootstrap it.
 if echo " ${target_configdirs} " | grep " libsanitizer " > /dev/null 2>&1; then
   case "$BUILD_CONFIG" in
-*bootstrap-asan* | *bootstrap-ubsan* )
+*bootstrap-hwasan* | *bootstrap-asan* | *bootstrap-ubsan* )
   bootstrap_target_libs=${bootstrap_target_libs}target-libsanitizer,
   bootstrap_fixincludes=yes
   ;;
diff --git a/libiberty/configure b/libiberty/configure
index 
7a34dabec32b0b383bd33f07811757335f4dd39c..cb2dd4ff5295598343cc18b3a79a86a778f2261d
 1007

[PATCH 11/X] [libsanitizer] Only build libhwasan when targeting AArch64

2019-11-05 Thread Matthew Malcomson
Though the library has limited support for x86, we don't have any
support for generating code targeting x86 so there is no point building
for that target.

libsanitizer/ChangeLog:

2019-11-05  Matthew Malcomson  

* Makefile.am: Condition building hwasan directory.
* Makefile.in: Regenerate.
* configure: Regenerate.
* configure.ac: Set HWASAN_SUPPORTED based on target
architecture.
* configure.tgt: Likewise.



### Attachment also inlined for ease of reply###


diff --git a/libsanitizer/Makefile.am b/libsanitizer/Makefile.am
index 
2a7e8e1debe838719db0f0fad218b2543cc3111b..065a65e78d49f7689a01ecb64db1f07ca83aa987
 100644
--- a/libsanitizer/Makefile.am
+++ b/libsanitizer/Makefile.am
@@ -14,7 +14,7 @@ endif
 if LIBBACKTRACE_SUPPORTED
 SUBDIRS += libbacktrace
 endif
-SUBDIRS += lsan asan ubsan hwasan
+SUBDIRS += lsan asan ubsan
 nodist_saninclude_HEADERS += \
   include/sanitizer/lsan_interface.h \
   include/sanitizer/asan_interface.h \
@@ -23,6 +23,9 @@ nodist_saninclude_HEADERS += \
 if TSAN_SUPPORTED
 SUBDIRS += tsan
 endif
+if HWASAN_SUPPORTED
+SUBDIRS += hwasan
+endif
 endif
 
 ## May be used by toolexeclibdir.
diff --git a/libsanitizer/Makefile.in b/libsanitizer/Makefile.in
index 
404ddcedde5428e0bc6d8ebc5f6568f99741ce2a..3883c7d934884146763d2d751a7e88bdf31341fe
 100644
--- a/libsanitizer/Makefile.in
+++ b/libsanitizer/Makefile.in
@@ -97,6 +97,7 @@ target_triplet = @target@
 @SANITIZER_SUPPORTED_TRUE@@USING_MAC_INTERPOSE_FALSE@am__append_2 = 
interception
 @LIBBACKTRACE_SUPPORTED_TRUE@@SANITIZER_SUPPORTED_TRUE@am__append_3 = 
libbacktrace
 @SANITIZER_SUPPORTED_TRUE@@TSAN_SUPPORTED_TRUE@am__append_4 = tsan
+@HWASAN_SUPPORTED_TRUE@@SANITIZER_SUPPORTED_TRUE@am__append_5 = hwasan
 subdir = .
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
 am__aclocal_m4_deps = $(top_srcdir)/../config/acx.m4 \
@@ -207,7 +208,7 @@ ETAGS = etags
 CTAGS = ctags
 CSCOPE = cscope
 DIST_SUBDIRS = sanitizer_common interception libbacktrace lsan asan \
-   ubsan hwasan tsan
+   ubsan tsan hwasan
 ACLOCAL = @ACLOCAL@
 ALLOC_FILE = @ALLOC_FILE@
 AMTAR = @AMTAR@
@@ -364,7 +365,7 @@ sanincludedir = 
$(libdir)/gcc/$(target_alias)/$(gcc_version)/include/sanitizer
 nodist_saninclude_HEADERS = $(am__append_1)
 @SANITIZER_SUPPORTED_TRUE@SUBDIRS = sanitizer_common $(am__append_2) \
 @SANITIZER_SUPPORTED_TRUE@ $(am__append_3) lsan asan ubsan \
-@SANITIZER_SUPPORTED_TRUE@ hwasan $(am__append_4)
+@SANITIZER_SUPPORTED_TRUE@ $(am__append_4) $(am__append_5)
 gcc_version := $(shell @get_gcc_base_ver@ $(top_srcdir)/../gcc/BASE-VER)
 
 # Work around what appears to be a GNU make bug handling MAKEFLAGS
diff --git a/libsanitizer/configure b/libsanitizer/configure
index 
967efdb1f6f8ed30089ff73efc4e349a8bf9c1fc..f44fdb9485e7e00c2f3f98fac3f0e93a3ca6abb4
 100755
--- a/libsanitizer/configure
+++ b/libsanitizer/configure
@@ -659,6 +659,8 @@ link_libubsan
 link_libtsan
 link_libhwasan
 link_libasan
+HWASAN_SUPPORTED_FALSE
+HWASAN_SUPPORTED_TRUE
 LSAN_SUPPORTED_FALSE
 LSAN_SUPPORTED_TRUE
 TSAN_SUPPORTED_FALSE
@@ -12347,7 +12349,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 12350 "configure"
+#line 12352 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -12453,7 +12455,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 12456 "configure"
+#line 12458 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -15804,6 +15806,7 @@ fi
 # Get target configury.
 unset TSAN_SUPPORTED
 unset LSAN_SUPPORTED
+unset HWASAN_SUPPORTED
 . ${srcdir}/configure.tgt
  if test "x$TSAN_SUPPORTED" = "xyes"; then
   TSAN_SUPPORTED_TRUE=
@@ -15821,6 +15824,14 @@ else
   LSAN_SUPPORTED_FALSE=
 fi
 
+ if test "x$HWASAN_SUPPORTED" = "xyes"; then
+  HWASAN_SUPPORTED_TRUE=
+  HWASAN_SUPPORTED_FALSE='#'
+else
+  HWASAN_SUPPORTED_TRUE='#'
+  HWASAN_SUPPORTED_FALSE=
+fi
+
 
 # Check for functions needed.
 for ac_func in clock_getres clock_gettime clock_settime lstat readlink
@@ -16803,7 +16814,7 @@ ac_config_files="$ac_config_files Makefile 
libsanitizer.spec libbacktrace/backtr
 ac_config_headers="$ac_config_headers config.h"
 
 
-ac_config_files="$ac_config_files interception/Makefile 
sanitizer_common/Makefile libbacktrace/Makefile lsan/Makefile asan/Makefile 
hwasan/Makefile ubsan/Makefile"
+ac_config_files="$ac_config_files interception/Makefile 
sanitizer_common/Makefile libbacktrace/Makefile lsan/Makefile asan/Makefile 
ubsan/Makefile"
 
 
 if test "x$TSAN_SUPPORTED" = "xyes"; then
@@ -16811,6 +16822,11 @@ if test "x$TSAN_SUPPORTED" = "xyes"; then
 
 fi
 
+if test "x$HWASAN_SUPPOR

[PATCH 13/X] [libsanitizer][options] Add hwasan flags and argument parsing

2019-11-05 Thread Matthew Malcomson
These flags can't be used at the same time as any of the other
sanitizers.
We add an equivalent flag to -static-libasan in -static-libhwasan to
ensure static linking.

The -fsanitize=kernel-hwaddress option is for compiling targeting the
kernel.  This flag has defaults that allow compiling KASAN with tags as
it is currently implemented.
These defaults are that we do not sanitize variables on the stack and
always recover from a detected bug.
Stack tagging in the kernel is a future aim, stack instrumentation has
not yet been enabled for the kernel for clang either
(https://lists.infradead.org/pipermail/linux-arm-kernel/2019-October/687121.html).

We introduce a backend hook `targetm.memtag.can_tag_addresses` that
indicates to the mid-end whether a target has a feature like AArch64 TBI
where the top byte of an address is ignored.
Without this feature hwasan sanitization is not done.

NOTE:
--
I have defined a new macro of __SANITIZE_HWADDRESS__ that gets
automatically defined when compiling with hwasan.  This is analogous to
__SANITIZE_ADDRESS__ which is defined when compiling with asan.

Users in the kernel have expressed an interest in using
__SANITIZE_ADDRESS__ for both
(https://lists.infradead.org/pipermail/linux-arm-kernel/2019-October/690703.html).

One approach to do this could be to define __SANITIZE_ADDRESS__ with
different values depending on whether we are compiling with hwasan or
asan.

Using __SANITIZE_ADDRESS__ for both means that code like the kernel
which wants to treat the two sanitizers as alternate implementations of
the same thing gets that automatically.

My preference is to use __SANITIZE_HWADDRESS__ since that means any
existing code will not be predicated on this (and hence I guess less
surprises), but would appreciate feedback on this given the point above.
--

gcc/ChangeLog:

2019-11-05  Matthew Malcomson  

* asan.c (memory_tagging_p): New.
* asan.h (memory_tagging_p): New.
* common.opt (flag_sanitize_recover): Default for kernel
hwaddress.
(static-libhwasan): New cli option.
* config/aarch64/aarch64.c (aarch64_can_tag_addresses): New.
(TARGET_MEMTAG_CAN_TAG_ADDRESSES): New.
* config/gnu-user.h (LIBHWASAN_EARLY_SPEC): hwasan equivalent of
asan command line flags.
* cppbuiltin.c (define_builtin_macros_for_compilation_flags):
Add hwasan equivalent of __SANITIZE_ADDRESS__.
* doc/tm.texi: Document new hook.
* doc/tm.texi.in: Document new hook.
* flag-types.h (enum sanitize_code): New sanitizer values.
* gcc.c (STATIC_LIBHWASAN_LIBS): New macro.
(LIBHWASAN_SPEC): New macro.
(LIBHWASAN_EARLY_SPEC): New macro.
(SANITIZER_EARLY_SPEC): Update to include hwasan.
(SANITIZER_SPEC): Update to include hwasan.
(sanitize_spec_function): Use hwasan options.
* opts.c (finish_options): Describe conflicts between address
sanitizers.
(sanitizer_opts): Introduce new sanitizer flags.
(common_handle_option): Add defaults for kernel sanitizer.
* params.def (PARAM_HWASAN_RANDOM_FRAME_TAG): New.
(PARAM_HWASAN_STACK): New.
* params.h (HWASAN_STACK): New.
(HWASAN_RANDOM_FRAME_TAG): New.
* target.def (HOOK_PREFIX): Add new hook.
* targhooks.c (default_memtag_can_tag_addresses): New.
* toplev.c (process_options): Ensure hwasan only on TBI
architectures.

gcc/c-family/ChangeLog:

2019-11-05  Matthew Malcomson  

* c-attribs.c (handle_no_sanitize_hwaddress_attribute): New
attribute.



### Attachment also inlined for ease of reply###


diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c
index 
6500b998321419a1d8d57062534206c5909adb7a..2de94815f91da5a0fd06c30d0044f866084121b8
 100644
--- a/gcc/c-family/c-attribs.c
+++ b/gcc/c-family/c-attribs.c
@@ -54,6 +54,8 @@ static tree handle_cold_attribute (tree *, tree, tree, int, 
bool *);
 static tree handle_no_sanitize_attribute (tree *, tree, tree, int, bool *);
 static tree handle_no_sanitize_address_attribute (tree *, tree, tree,
  int, bool *);
+static tree handle_no_sanitize_hwaddress_attribute (tree *, tree, tree,
+   int, bool *);
 static tree handle_no_sanitize_thread_attribute (tree *, tree, tree,
 int, bool *);
 static tree handle_no_address_safety_analysis_attribute (tree *, tree, tree,
@@ -410,6 +412,8 @@ const struct attribute_spec c_common_attribute_table[] =
  handle_no_sanitize_attribute, NULL },
   { "no_sanitize_address",0, 0, true, false, false, false,
  handle_no_sanitize_address_attribute, NULL },
+  { "no_sanitize_hwaddress",0, 0, true, false, false, false,
+ handle_no_san

[PATCH 15/X] [libsanitizer] Add hwasan pass and associated gimple changes

2019-11-05 Thread Matthew Malcomson
There are four main features to this change:

1) Check pointer tags match address tags.

In the new `hwasan` pass we put HWASAN_CHECK internal functions around
all memory accesses, to check that tags in the pointer being used match
the tag stored in shadow memory for the memory region being used.

These internal functions are expanded into actual checks in the sanopt
pass that happens just before expansion into RTL.

We use the same mechanism that currently inserts ASAN_CHECK internal
functions to insert the new HWASAN_CHECK functions.

2) Instrument known builtin function calls.

Handle all builtin functions that we know use memory accesses.
This commit uses the machinery added for ASAN to identify builtin
functions that access memory.

The main differences between the approaches for HWASAN and ASAN are:
 - libhwasan intercepts much less builtin functions.
 - Alloca needs to be transformed differently (instead of adding
   redzones it needs to colour shadow memory and return a tagged
   pointer).
 - stack_restore needs to uncolour the shadow stack between the current
   position and where it's going.
 - `noreturn` functions can not be handled by simply unpoisoning the
   entire shadow stack -- there is no "always valid" colour.
   (exceptions and things such as longjmp need to be handled in a
   different way).

For hardware implemented checking (such as AArch64's memory tagging
extension) alloca and stack_restore will need to be handled by hooks in
the backend rather than transformation at the gimple level.  This will
allow architecture specific handling of such stack modifications.

3) Introduce HWASAN block-scope poisoning

Here we use exactly the same mechanism as ASAN_MARK to poison/unpoison
variables on entry/exit of a block.

In order to simply use the exact same machinery we're using the same
internal functions until the SANOPT pass.  This means that all handling
of ASAN_MARK is the same.
This has the negative that the naming may be a little confusing, but a
positive that handling of the internal function doesn't have to be
duplicated for a function that behaves exactly the same but has a
different name.

gcc/ChangeLog:

2019-11-05  Matthew Malcomson  

* asan.c (handle_builtin_stack_restore): Account for HWASAN.
(handle_builtin_alloca): Account for HWASAN.
(get_mem_refs_of_builtin_call): Special case strlen for HWASAN.
(report_error_func): Assert not HWASAN.
(build_check_stmt): Make HWASAN_CHECK instead of ASAN_CHECK.
(instrument_derefs): HWASAN does not tag globals.
(maybe_instrument_call): Don't instrument `noreturn` functions.
(initialize_sanitizer_builtins): Add new type.
(asan_expand_mark_ifn): Account for HWASAN.
(asan_expand_check_ifn): Assert never called by HWASAN.
(asan_expand_poison_ifn): Account for HWASAN.
(hwasan_instrument): New.
(hwasan_base): New.
(hwasan_emit_uncolour_frame): Free block-scope-var hash map.
(hwasan_check_func): New.
(hwasan_expand_check_ifn): New.
(hwasan_expand_mark_ifn): New.
(gate_hwasan): New.
(class pass_hwasan): New.
(make_pass_hwasan): New.
(class pass_hwasan_O0): New.
(make_pass_hwasan_O0): New.
* asan.h (hwasan_base): New decl.
(hwasan_expand_check_ifn): New decl.
(hwasan_expand_mark_ifn): New decl.
(gate_hwasan): New decl.
(enum hwasan_mark_flags): New.
(asan_intercepted_p): Always false for hwasan.
(asan_sanitize_use_after_scope): Account for HWASAN.
* builtin-types.def (BT_FN_PTR_CONST_PTR_UINT8): New.
* gimple-pretty-print.c (dump_gimple_call_args): Account for
HWASAN.
* gimplify.c (asan_poison_variable): Account for HWASAN.
(gimplify_function_tree): Remove requirement of
SANITIZE_ADDRESS, requiring asan or hwasan is accounted for in
`asan_sanitize_use_after_scope`.
* internal-fn.c (expand_HWASAN_CHECK): New.
(expand_HWASAN_CHOOSE_COLOUR): New.
(expand_HWASAN_MARK): New.
* internal-fn.def (HWASAN_CHOOSE_COLOUR): New.
(HWASAN_CHECK): New.
(HWASAN_MARK): New.
* passes.def: Add hwasan and hwasan_O0 passes.
* sanitizer.def (BUILT_IN_HWASAN_LOAD1): New.
(BUILT_IN_HWASAN_LOAD2): New.
(BUILT_IN_HWASAN_LOAD4): New.
(BUILT_IN_HWASAN_LOAD8): New.
(BUILT_IN_HWASAN_LOAD16): New.
(BUILT_IN_HWASAN_LOADN): New.
(BUILT_IN_HWASAN_STORE1): New.
(BUILT_IN_HWASAN_STORE2): New.
(BUILT_IN_HWASAN_STORE4): New.
(BUILT_IN_HWASAN_STORE8): New.
(BUILT_IN_HWASAN_STORE16): New.
(BUILT_IN_HWASAN_STOREN): New.
(BUILT_IN_HWASAN_LOAD1_NOABORT): New.
(BUILT_IN_HWASAN_LOAD2_NOABORT): New.
(BUILT_IN_HWASAN_LOAD4_NOABORT): New.
(BUILT_IN_HWASAN_LOAD8_NOABORT): New.
(B

[PATCH 14/X] [libsanitizer][mid-end] Introduce stack variable handling for HWASAN

2019-11-05 Thread Matthew Malcomson
Handling stack variables has three features.

1) Ensure HWASAN required alignment for stack variables

When colouring shadow memory, we need to ensure that each tag granule
is only used by one variable at a time.

This is done by ensuring that each coloured variable is aligned to the
tag granule representation size and also ensure that the end of each
variable as an alignment boundary between the end and the start of any
other data stored on the stack.

This patch ensures that by adding alignment requirements in
`align_local_variable` and forcing all stack variable allocation to be
deferred so that `expand_stack_vars` can ensure the stack pointer is
aligned before allocating any variable for the current frame.

2) Put tags into each stack variable pointer

Make sure that every pointer to a stack variable includes a tag of some
sort on it.

The way tagging works is:
  1) For every new stack frame, a random tag is generated.
  2) A base register is formed from the stack pointer value and this
 random tag.
  3) References to stack variables are now formed with RTL describing an
 offset from this base in both tag and value.

The random tag generation is handled by a backend hook.  This hook
decides whether to introduce a random tag or use the stack background
based on the parameter hwasan-random-frame-tag.  Using the stack
background is necessary for testing and bootstrap.  It is necessary
during bootstrap to avoid breaking the `configure` test program for
determining stack direction.

Using the stack background means that every stack frame has the initial
colour of zero and variables are coloured with incrementing tags from 1,
which also makes debugging a bit easier.

The tag&value offsets are also handled by a backend hook.

This patch also adds some macros defining how the HWASAN shadow memory
is stored and how a tag is stored in a pointer.

3) For each stack variable, colour and uncolour the shadow stack on
   function prologue and epilogue.

On entry to each function we colour the relevant shadow stack region for
each stack variable the colour to match the tag added to each pointer
for that variable.

This is the first patch where we use the HWASAN shadow space, so we need
to add in the libhwasan initialisation code that creates this shadow
memory region into the binary we produce.  This instrumentation is done
in `compile_file`.

When exiting a function we need to ensure the shadow stack for this
function has no remaining colour.  Without clearing the shadow stack
area for this stack frame, later function calls could get false
positives when those later function calls check untagged areas (such as
parameters passed on the stack) against a shadow stack area with
left-over colour.

Hence we ensure that the entire stack frame is cleared on function exit.

gcc/ChangeLog:

2019-11-05  Matthew Malcomson  

* asan.c (hwasan_record_base): New function.
(hwasan_emit_uncolour_frame): New.
(hwasan_increment_tag): New function.
(hwasan_with_tag): New function.
(hwasan_tag_init): New function.
(initialize_sanitizer_builtins): Define new builtins.
(ATTR_NOTHROW_LIST): New macro.
(hwasan_current_tag): New.
(hwasan_emit_prologue): New.
(hwasan_create_untagged_base): New.
(hwasan_finish_file): New.
(hwasan_sanitize_stack_p): New.
(memory_tagging_p): New.
* asan.h (hwasan_record_base): New declaration.
(hwasan_emit_uncolour_frame): New.
(hwasan_increment_tag): New declaration.
(hwasan_with_tag): New declaration.
(hwasan_sanitize_stack_p): New declaration.
(hwasan_tag_init): New declaration.
(memory_tagging_p): New declaration.
(HWASAN_TAG_SIZE): New macro.
(HWASAN_TAG_GRANULE_SIZE):New macro.
(HWASAN_SHIFT):New macro.
(HWASAN_SHIFT_RTX):New macro.
(HWASAN_STACK_BACKGROUND):New macro.
(hwasan_finish_file): New.
(hwasan_current_tag): New.
(hwasan_create_untagged_base): New.
(hwasan_emit_prologue): New.
* cfgexpand.c (struct stack_vars_data): Add information to
record hwasan variable stack offsets.
(expand_stack_vars): Ensure variables are offset from a tagged
base. Record offsets for hwasan. Ensure alignment.
(expand_used_vars): Call function to emit prologue, and get
uncolouring instructions for function exit.
(align_local_variable): Ensure alignment.
(defer_stack_allocation): Ensure all variables are deferred so
they can be handled by `expand_stack_vars`.
(expand_one_stack_var_at): Account for tags in
variables when using HWASAN.
(expand_one_stack_var_1): Pass new argument to
expand_one_stack_var_at.
(init_vars_expansion): Initialise hwasan internal variables when
starting variable expansion.
* doc/tm.texi (TARGET_MEMTAG_GENTAG): Document.
*

[PATCH 17/X] [libsanitizer] Add hwasan Exception handling

2019-11-05 Thread Matthew Malcomson
When tagging the stack we need to ensure that any stack frames are
untagged during unwinding of any sort.  If this is not done, then
functions called later which re-use the stack can observe tag mismatches
on accesses to memory they have not tagged but that has been tagged
previously.

This applies equally to C++ exceptions as it does to longjmp and normal
function return.
The approach that LLVM has taken to account for C++ exceptions, is to
add a new personality routine on every function.  This new personality
routine calls the original personality routine, then untags the stack of
that function.

In order to untag the stack of the function currently being unwound, the
new personality wrapper needs to know the start and end of the current
stack frame.  The current implementation in libhwasan uses the frame
pointer to find the start of the stack frame.
https://github.com/llvm-mirror/compiler-rt/blob/69445f095c22aac2388f939bedebf224a6efcdaf/lib/hwasan/hwasan_exceptions.cpp#L58
This does not work for GCC, where the frame pointer is usually the same
as the stack pointer.

This patch demonstrates how adding C++ exception handling into GCC might
work, but currently does not work.  I intend to work on getting this
functionality, but do not consider it a blocker.

The current implementation ensures every function has a wrapped
personality function by modifying `get_personality_function` to check
for if we're handling exceptions and sanitizing the code with hwasan.
If so it returns a specially generated personality function that calls
`__hwasan_personality_wrapper` in libhwasan.


I've been testing the compiler instrumentation with a hack in libhwasan shown
below and things are mostly working, but I don't feel it's a good way forward.

I was wondering -- does anyone have any better ideas to keep this personality
method working for gcc?
I've also included the people that worked on exception handling in LLVM.  I
figure you may have tried other things before and hence have a good idea of
the pitfalls in this area.

My main aim is to get software tagging working for the kernel, so to me
exception handling is not a deal-breaker, but I would really like to get this
feature working.


Patch to libhwasan that I've been testing the instrumentation with.
##
diff --git a/libsanitizer/hwasan/hwasan_exceptions.cpp 
b/libsanitizer/hwasan/hwasan_exceptions.cpp
index 169e787..faec2e8 100644
--- a/libsanitizer/hwasan/hwasan_exceptions.cpp
+++ b/libsanitizer/hwasan/hwasan_exceptions.cpp
@@ -52,14 +52,16 @@ __hwasan_personality_wrapper(int version, _Unwind_Action 
actions,
   // Here we assume that the frame record appears after any locals. This is not
   // required by AAPCS but is a requirement for HWASAN instrumented functions.
   if ((actions & _UA_CLEANUP_PHASE) && rc == _URC_CONTINUE_UNWIND) {
+uptr sp = get_cfa(context);
 #if defined(__x86_64__)
 uptr fp = get_gr(context, 6); // rbp
 #elif defined(__aarch64__)
-uptr fp = get_gr(context, 29); // x29
+uptr fp = *(uptr *)sp;
+if (fp == 0)
+  return rc;
 #else
 #error Unsupported architecture
 #endif
-uptr sp = get_cfa(context);
 TagMemory(sp, fp - sp, 0);
   }
######



gcc/ChangeLog:

2019-11-05  Matthew Malcomson  

* asan.c (hwasan_create_personality_thunk): New.
* asan.h (hwasan_create_personality_thunk): New.
* expr.c (get_personality_function): Add special function if
using hwasan.



### Attachment also inlined for ease of reply###


diff --git a/gcc/asan.h b/gcc/asan.h
index 
c27d679c117a9cc7b15b7b4c6710cf0b46050089..ff6adf2391ee1602a3c15755312a04f82d6369ce
 100644
--- a/gcc/asan.h
+++ b/gcc/asan.h
@@ -36,6 +36,7 @@ extern void hwasan_emit_prologue (rtx *, rtx *, poly_int64 *, 
uint8_t *, size_t)
 extern rtx_insn *hwasan_emit_uncolour_frame (rtx, rtx, rtx_insn *);
 extern bool hwasan_expand_check_ifn (gimple_stmt_iterator *, bool);
 extern bool hwasan_expand_mark_ifn (gimple_stmt_iterator *);
+extern tree hwasan_create_personality_thunk (tree);
 extern bool memory_tagging_p (void);
 extern bool hwasan_sanitize_stack_p (void);
 extern bool gate_hwasan (void);
diff --git a/gcc/asan.c b/gcc/asan.c
index 
edfbf2048b67d3dc7be78a8e9961152c4fb44902..ef7c90e3358c8fa880b8e4002996f27541c26953
 100644
--- a/gcc/asan.c
+++ b/gcc/asan.c
@@ -260,6 +260,10 @@ hash_set  *asan_used_labels = NULL;
 
 static uint8_t tag_offset = 0;
 static rtx hwasan_base_ptr = NULL_RTX;
+static hash_map , uintptr_t> >
+   *hwasan_wrapped_personalities = NULL;
+static tree hwasan_gr_decl = NULL_TREE;
+static tree hwasan_cfa_decl = NULL_TREE;
 
 /* Sets shadow offset to value in string VAL.  */
 
@@ -3951,6 +3955,220 @@ hwasan_tag_init ()
   tag_offset = HWASAN_STACK_BACKGROUND + 1;
 }
 
+tree
+hwasan_create_personality_thunk (tree orig_personality_decl)
+{
+  /* Only works with DWARF2 debugging.  */
+  /* Create a function called 
_

[PATCH 18/X] [libsanitizer] Add in MTE stubs

2019-11-05 Thread Matthew Malcomson
This patch in the series is just for demonstration, here we add stubs
where MTE would be implemented.

We also add a new flag to request memory tagging as a sanitizer option.
The new flag for memory tagging is `-fsanitize=memtag`, which is in line
with the flag clang uses to request memory tagging.

At the moment all implementations are dummies of some sort, the assembly
generated uses `mov` instead of `irg`, `add` instead of `addg`, and
`sub` instead of `subg`.  This should mean the binaries behave the same
as MTE binaries but for ignoring tags.

For a hardware implementation of memory tagging checks are done
automatically so adding HWASAN_CHECK is not needed.  This means that the
`hwasan` pass is not needed.
Similarly, much of the `sanopt` pass is not needed when compiling for
hardware memory tagging -- though there is still need for handling
HWASAN_MARK.

This patch gives backends extra control over how a tag is stored in a
pointer and how many real-memory bytes is represented by each byte in
the shadow space.

One final difference between memtag and hwasan is that memtag can't use
the ASAN_POISON optimisation.
This optimisation replaces accesses to a variable that has just been
poisoned with an internal function that will be used to report an error
without needing to check the access.

This provides no benefit for memtag since there tends to be no
instructions allowing a report of a memory fault outside of mis-tagging
some memory and attempting to access it.

The optimisation is hence disabled for memory tagging since it provides
no benefit and would require all backends that wanted this feature to
implement a similar dummy hook.

gcc/ChangeLog:

2019-11-05  Matthew Malcomson  

* asan.c (hwasan_tag_init): Choose initialisation value based on
memtag vs hwasan.
(memory_tagging_p): Check for either hwaddress or memtag.
(hwasan_emit_prologue): Account for memtag.
(hwasan_emit_uncolour_frame): Account for memtag.
(hwasan_finish_file): Assert not called for memtag.
(hwasan_expand_check_ifn): Assert not called for memtag.
(gate_hwasan): Don't run when have memtag.
* asan.h (HWASAN_TAG_SIZE): Use backend hook if memtag.
(HWASAN_TAG_GRANULE_SIZE): Use backend hook if memtag.
(HWASAN_SHIFT): New.
(HWASAN_SHIFT_RTX): New.
(HWASAN_TAG_SHIFT_SIZE): New.
* builtins.c (expand_builtin_alloca): Extra TODO comment.
(expand_stack_restore): Extra TODO comment.
* cfgexpand.c (expand_stack_vars): Only bother untagging bases
for hwasan.
* config/aarch64/aarch64.c (aarch64_classify_address): Account
for addtag unspec marker.
(aarch64_has_memtag_isa): New hook.
(aarch64_tag_memory): Add dummy hook.
(aarch64_gentag): Add dummy hook.
(aarch64_addtag): New hook.
(aarch64_addtag_force_operand): New hook.
(TARGET_MEMTAG_HAS_MEMORY_TAGGING): New.
(TARGET_MEMTAG_TAG): New.
(TARGET_MEMTAG_GENTAG): New.
(TARGET_MEMTAG_ADDTAG): New.
(TARGET_MEMTAG_ADDTAG_FORCE_OPERAND): New.
* config/aarch64/aarch64.h (AARCH64_ISA_MEMTAG): New macro.
* config/aarch64/aarch64.md (random_tag, plain_offset_tagdi):
New.
(unspec enum): Add GENTAG and ADDTAG markers.
* config/aarch64/predicates.md (aarch64_MTE_add_temp,
aarch64_MTE_tag_offset, aarch64_MTE_value_offset): New.
* doc/tm.texi: Document new hooks.
* doc/tm.texi.in: Document new hooks.
* flag-types.h (enum sanitize_code): Add MEMTAG enum.
* gcc.c (sanitize_spec_function): Account for MEMTAG option.
* internal-fn.c (expand_HWASAN_MARK): Account for memtag.
* opts.c (finish_options): Ensure MEMTAG conflicts with ASAN,
HWASAN, and THREAD.
(finish_options): Turn on stack tagging for memtag.
(sanitizer_opts): Add MEMTAG option.
* target.def (targetm.memtag.has_memory_tagging): New.
(targetm.memtag.tag_size): New.
(targetm.memtag.granule_size): New.
(targetm.memtag.copy_tag): New.
(targetm.memtag.tag): New.
* targhooks.c (default_memtag_has_memory_tagging): New.
(default_memtag_tag_size): New.
(default_memtag_granule_size): New.
(default_memtag_copy_tag): New.
* targhooks.h (default_memtag_tag_size): New decl.
(default_memtag_granule_size): New decl.
(default_memtag_copy_tag): New decl.
* tree-ssa.c (execute_update_addresses_taken): Avoid ASAN_POISON
optimisation for memtag.

gcc/testsuite/ChangeLog:

2019-11-05  Matthew Malcomson  

* gcc.dg/hwasan/poly-int-stack-vars.c: New test.



### Attachment also inlined for ease of reply###


diff --git a/gcc/asan.h b/gcc/asan.h
index 
ff6adf2391ee1602a3c15755312a04f82d6369ce..71dbaee708d0e64911f568503655478b8720f494
 100644
--- a/gcc/asan.h
+++ b/

[PATCH 16/X] [libsanitizer] Add tests

2019-11-05 Thread Matthew Malcomson
Adding hwasan tests.

Frankly, these could be tidied up a little.
I will be tidying them up while getting feedback on the hwasan introduction.


gcc/testsuite/ChangeLog:

2019-11-05  Matthew Malcomson  

* c-c++-common/hwasan/arguments.c: New test.
* c-c++-common/hwasan/halt_on_error-1.c: New test.
* g++.dg/hwasan/rvo-handled.c: New test.
* g++.dg/hwasan/try-catch-0.cpp: New test.
* g++.dg/hwasan/try-catch-1.cpp: New test.
* gcc.dg/hwasan/aligned-alloc.c: New test.
* gcc.dg/hwasan/alloca-array-accessible.c: New test.
* gcc.dg/hwasan/alloca-gets-different-tag.c: New test.
* gcc.dg/hwasan/alloca-outside-caught.c: New test.
* gcc.dg/hwasan/bitfield-1.c: New test.
* gcc.dg/hwasan/bitfield-2.c: New test.
* gcc.dg/hwasan/builtin-special-handling.c: New test.
* gcc.dg/hwasan/check-interface.c: New test.
* gcc.dg/hwasan/hwasan-poison-optimisation.c: New test.
* gcc.dg/hwasan/hwasan-thread-access-parent.c: New test.
* gcc.dg/hwasan/hwasan-thread-basic-failure.c: New test.
* gcc.dg/hwasan/hwasan-thread-clears-stack.c: New test.
* gcc.dg/hwasan/hwasan-thread-success.c: New test.
* gcc.dg/hwasan/hwasan.exp: New file.
* gcc.dg/hwasan/kernel-defaults.c: New test.
* gcc.dg/hwasan/large-aligned-0.c: New test.
* gcc.dg/hwasan/large-aligned-1.c: New test.
* gcc.dg/hwasan/macro-definition.c: New test.
* gcc.dg/hwasan/nested-functions-0.c: New test.
* gcc.dg/hwasan/nested-functions-1.c: New test.
* gcc.dg/hwasan/nested-functions-2.c: New test.
* gcc.dg/hwasan/no-sanitize-attribute.c: New test.
* gcc.dg/hwasan/random-frame-tag.c: New test.
* gcc.dg/hwasan/setjmp-longjmp-0.c: New test.
* gcc.dg/hwasan/setjmp-longjmp-1.c: New test.
* gcc.dg/hwasan/stack-tagging-basic-0.c: New test.
* gcc.dg/hwasan/stack-tagging-basic-1.c: New test.
* gcc.dg/hwasan/stack-tagging-disable.c: New test.
* gcc.dg/hwasan/vararray-outside-caught.c: New test.
* gcc.dg/hwasan/very-large-objects.c: New test.
* lib/hwasan-dg.exp: New file.



### Attachment also inlined for ease of reply###


diff --git a/gcc/testsuite/c-c++-common/hwasan/arguments.c 
b/gcc/testsuite/c-c++-common/hwasan/arguments.c
new file mode 100644
index 
..2d563eb8541694d501b021babd9452fd7fd502a3
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/hwasan/arguments.c
@@ -0,0 +1,7 @@
+/*
+   TODO
+   Somehow test the conflict of arguments
+   -fsanitize=hwaddress -fsanitize=kernel-address
+   -fsanitize=hwaddress -fsanitize=address
+   -fsanitize=hwaddress -fsanitize=thread
+ */
diff --git a/gcc/testsuite/c-c++-common/hwasan/halt_on_error-1.c 
b/gcc/testsuite/c-c++-common/hwasan/halt_on_error-1.c
new file mode 100644
index 
..118191e2e00bd07bd4839888d2fb29baec926c60
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/hwasan/halt_on_error-1.c
@@ -0,0 +1,25 @@
+/* Test recovery mode.  */
+/* { dg-do run } */
+/* { dg-options "-fsanitize-recover=hwaddress" } */
+/* { dg-set-target-env-var HWASAN_OPTIONS "halt_on_error=false" } */
+/* { dg-shouldfail "hwasan" } */
+
+#include 
+
+volatile int ten = 16;
+
+int main() {
+  char x[10];
+  __builtin_memset(x, 0, ten + 1);
+  asm volatile ("" : : : "memory");
+  volatile int res = x[ten];
+  x[ten] = res + 3;
+  res = x[ten];
+  return 0;
+}
+
+/* { dg-output "WRITE of size 17 at 0x\[0-9a-f\]+.*" } */
+/* { dg-output "READ of size 1 at 0x\[0-9a-f\]+.*" } */
+/* { dg-output "WRITE of size 1 at 0x\[0-9a-f\]+.*" } */
+/* { dg-output "READ of size 1 at 0x\[0-9a-f\]+.*" } */
+
diff --git a/gcc/testsuite/g++.dg/hwasan/rvo-handled.c 
b/gcc/testsuite/g++.dg/hwasan/rvo-handled.c
new file mode 100644
index 
..6e6934a0be1b0ce14c459555168f6a2590a8ec7f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/hwasan/rvo-handled.c
@@ -0,0 +1,56 @@
+/* { dg-do run } */
+/* TODO Ensure this test has enough optimisation to get RVO. */
+
+#define assert(x) if (!(x)) __builtin_abort ()
+
+struct big_struct {
+int left;
+int right;
+void *ptr;
+int big_array[100];
+};
+
+/*
+   Tests for RVO (basically, checking -fsanitize=hwaddress has not broken RVO
+   in any way).
+
+   0) The value is accessible in both functions without a hwasan complaint.
+   1) RVO does happen.
+ */
+
+struct big_struct __attribute__ ((noinline))
+return_on_stack()
+{
+  struct big_struct x;
+  x.left = 100;
+  x.right = 20;
+  x.big_array[10] = 30;
+  x.ptr = &x;
+  return x;
+}
+
+struct big_struct __attribute__ ((noinline))
+unnamed_return_on_stack()
+{
+  return (struct big_struct){
+  .left = 100,
+  .right = 20,
+  .ptr = __builtin_frame_address (0),
+ 

Re: [PATCH 0/X] Introduce HWASAN sanitizer to GCC

2019-11-05 Thread Matthew Malcomson
On 05/11/2019 11:32, Matthew Malcomson wrote:
> 
> Testing done:
> Full bootstrap and regtest on x86_64 (no difference -- hwasan not used).
> 
> Full bootstrap and regtest on AArch64 sanitizing with hwasan and running
> on recent kernel.
> Regressions all accounted for:
>1) tests under plugin/
>   testism where hwasan library is not linked in.
>   (same appears to happen for asan)
>2) branch-protection-attr.c
>   New bug found by hwasan, fix in this patch series.
>3) pr88597.c
>   timeout, can run manually and everything works (but is very slow)
>4) aarch64/long_branch_1.c
>   timeout, as above.
>5) gfortran/class_61.f90
>   bug already caught by ASAN and reported upstream
>   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89661
>6) gfortran/dec_type_print_2.f03
>   bug already caught by ASAN and reported upstream
>   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86657
>7) gfortran/minlocval_3.f90
>   timeout, can run manually and passes (but is very slow)
> 

Oh, and I also tested by compiling the kernel for software memory 
tagging (after a quick hack to use __SANITIZE_HWADDRESS__ and pass the 
correct flags for gcc) then using the kernel sanitizer testing module 
test_kasan.

The kernel was tested without stack-tagging, and we caught the tests 
which didn't access within a valid 16 byte granule (i.e. caught those 
that were expected).

I've been running this sanitized kernel on my test machine without 
problems for a week and a bit.

> 
> Entire patch series attached to cover letter.
> 



Re: [PATCH 0/X] Introduce HWASAN sanitizer to GCC

2019-11-05 Thread Matthew Malcomson
On 05/11/2019 15:10, Martin Liška wrote:
> On 11/5/19 12:32 PM, Matthew Malcomson wrote:
>> Hello,
>>
>> This patch series adds the LLVM hardware address sanitizer (HWASAN) to
>> GCC.  The document describing HWASAN can be found here
>> http://clang.llvm.org/docs/HardwareAssistedAddressSanitizerDesign.html.
> 
> Hello.
> 
> Thank you for the patch. I've just updated libsanitizer in GCC and I also
> prepared a patch which you have included in your series (but using an
> older libsanitizer):
> https://gcc.gnu.org/ml/gcc-patches/2019-11/msg00270.html.
> 
> Can you please rebase the series on top of the patch and exclude all the 
> cherry picks from
> upstream? Plus you can now install
> "[aarch64] Allocate enough space for err_str in 
> aarch64_handle_attr_branch_protection"
> patch and exclude it from the series as well.
Will do!

I'm currently rebasing, but thought I should mention just in case you 
didn't know that LLVM have fully moved over to git recently.

There seem to be no commits on the LLVM svn repo since 2019-10-22, so 
there are some cherry-picked hwasan patches that are not in at the point 
you merged.

Is this known, and we're taking the last SVN commit?

Cheers,
Matthew

> 
> Thanks,
> Martin



Re: [PATCH 0/X] Introduce HWASAN sanitizer to GCC

2019-11-05 Thread Matthew Malcomson
On 05/11/2019 17:22, Martin Liška wrote:
> On 11/5/19 5:11 PM, Matthew Malcomson wrote:
>> On 05/11/2019 15:10, Martin Liška wrote:
>>> On 11/5/19 12:32 PM, Matthew Malcomson wrote:
>>>> Hello,
>>>>
>>>> This patch series adds the LLVM hardware address sanitizer (HWASAN) to
>>>> GCC.  The document describing HWASAN can be found here
>>>> http://clang.llvm.org/docs/HardwareAssistedAddressSanitizerDesign.html.
>>>
>>> Hello.
>>>
>>> Thank you for the patch. I've just updated libsanitizer in GCC and I 
>>> also
>>> prepared a patch which you have included in your series (but using an
>>> older libsanitizer):
>>> https://gcc.gnu.org/ml/gcc-patches/2019-11/msg00270.html.
>>>
>>> Can you please rebase the series on top of the patch and exclude all the
>>> cherry picks from
>>> upstream? Plus you can now install
>>> "[aarch64] Allocate enough space for err_str in
>>> aarch64_handle_attr_branch_protection"
>>> patch and exclude it from the series as well.
>> Will do!
>>
>> I'm currently rebasing, but thought I should mention just in case you
>> didn't know that LLVM have fully moved over to git recently.
> 
> Hello.
> 
> You are right, I haven't noticed that.
> 
>>
>> There seem to be no commits on the LLVM svn repo since 2019-10-22, so
>> there are some cherry-picked hwasan patches that are not in at the point
>> you merged.
> 
> Do you miss any revisions that were installed in the new git repository
> and are not in current GCC master? If so, I can update the merge.sh script
> and do one more merge from trunk.
> 
> Martin

Yes, there are three commits in the new git repository and not in GCC 
master that I need.  The most recent commit I need is 91167e2.

Thanks,
Matthew.

> 
>>
>> Is this known, and we're taking the last SVN commit?
>>
>> Cheers,
>> Matthew
>>
>>>
>>> Thanks,
>>> Martin
>>
> 



Re: [PATCH 13/X] [libsanitizer][options] Add hwasan flags and argument parsing

2019-11-07 Thread Matthew Malcomson
On 05/11/2019 13:11, Andrey Konovalov wrote:
> On Tue, Nov 5, 2019 at 12:34 PM Matthew Malcomson
>  wrote:
>>
>> NOTE:
>> --
>> I have defined a new macro of __SANITIZE_HWADDRESS__ that gets
>> automatically defined when compiling with hwasan.  This is analogous to
>> __SANITIZE_ADDRESS__ which is defined when compiling with asan.
>>
>> Users in the kernel have expressed an interest in using
>> __SANITIZE_ADDRESS__ for both
>> (https://lists.infradead.org/pipermail/linux-arm-kernel/2019-October/690703.html).
>>
>> One approach to do this could be to define __SANITIZE_ADDRESS__ with
>> different values depending on whether we are compiling with hwasan or
>> asan.
>>
>> Using __SANITIZE_ADDRESS__ for both means that code like the kernel
>> which wants to treat the two sanitizers as alternate implementations of
>> the same thing gets that automatically.
>>
>> My preference is to use __SANITIZE_HWADDRESS__ since that means any
>> existing code will not be predicated on this (and hence I guess less
>> surprises), but would appreciate feedback on this given the point above.
> 
> +Evgenii Stepanov
> 
> (A repost from my answer from the mentioned thread):
> 
>> Similarly, I'm thinking I'll add no_sanitize_hwaddress as the hwasan
>> equivalent of no_sanitize_address, which will require an update in the
>> kernel given it seems you want KASAN to be used the same whether using
>> tags or not.
> 
> We have intentionally reused the same macros to simplify things. Is
> there any reason to use separate macros for GCC? Are there places
> where we need to use specifically no_sanitize_hwaddress and
> __SANITIZE_HWADDRESS__, but not no_sanitize_address and
> __SANITIZE_ADDRESS__?
> 
> 

I've just looked through some open source repositories (via github 
search) that used the existing __SANITIZE_ADDRESS__ macro.

There are a few repos that would want to use a feature macro for hwasan 
or asan in the exact same way as each other, but of the 31 truly 
different uses I found, 11 look like they would need to distinguish 
between hwasan and asan (where 4 uses I found I couldn't easily tell)

NOTE
- This is a count of unique uses, ignoring those repos which use a file 
from another repo.
- I'm just giving links to the first of the relevant kind that I found, 
not putting effort into finding the "canonical" source of each repository.


Places that need distinction (and their reasons):

There are quite a few that use the ASAN_POISON_MEMORY_REGION and 
ASAN_UNPOISON_MEMORY_REGION macros to poison/unpoison memory themselves. 
  This abstraction doesn't quite make sense in a hwasan environment, as 
there is not really a "poisoned/unpoisoned" concept.

https://github.com/laurynas-biveinis/unodb
https://github.com/darktable-org/rawspeed
https://github.com/MariaDB/server
https://github.com/ralfbrown/framepac-ng
https://github.com/peters/aom
https://github.com/pspacek/knot-resolver-docker-fix
https://github.com/harikrishnan94/sheap


Some use it to record their compilation "type" as `-fsanitize=address`
https://github.com/wallix/redemption

Or to decide to set the environment variable ASAN_OPTIONS
https://github.com/dephonatine/VBox5.2.18

Others worry about stack space due to asan's redzones (hwasan has a much 
smaller stack memory overhead).
https://github.com/fastbuild/fastbuild
https://github.com/scylladb/seastar
(n.b. seastar has a lot more conditioned code that would be the same 
between asan and hwasan).


Each of these needs to know the difference between compiling with asan 
and hwasan, so I'm confident that having some way to determine that in 
the source code is a good idea.


I also believe there could be code in the wild that would need to 
distinguish between hwasan and asan where the existence of tags could be 
problematic:

- code already using the top-byte-ignore feature may be able to be used 
with asan but not hwasan.
- Code that makes assumptions about pointer ordering (e.g. the autoconf 
program that looks for stack growth direction) could break on hwasan but 
not on asan.
- Code looking for the distance between two objects in memory would need 
to account for tags in pointers.


Hence I think this distinction is needed.

Matthew



v2 [PATCH 0/X] Introduce HWASAN sanitizer to GCC

2019-11-07 Thread Matthew Malcomson
I have rebased this series onto Martin Liska's patches that take the most
recent libhwasan from upstream LLVM.
https://gcc.gnu.org/ml/gcc-patches/2019-11/msg00340.html

I've also cleared up some nomenclature (I had previously used the word 'colour'
a few times instead of the word 'tag' and that clashes with other descriptions)
and based the patch series off a more recent GCC revision (r277678).

There's an ongoing discussion on whether to have __SANITIZER_ADDRESS__, or
__SANITIZER_HWADDRESS__, but I'm keeping that discussion to the existing
thread.

Similarly there's still the question around C++ exceptions that I'm keeping to
the existing thread (on the first patch series).


NOTE:
  Unfortunately, there's a bug in the more recent version of GCC I rebased
  onto.
  Hwasan catches this when bootstrapping, which means bootstrapping with hwasan
  fails.
  I'm working on tracking the bug down now, but sending this series upstream
  for visibility while that happens.

  Bugzilla link:
  https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92410

Entire patch series attached to cover letter.

all-patches.tar.gz
Description: all-patches.tar.gz


[PATCH 2/X] [libsanitizer] Only build libhwasan when targeting AArch64

2019-11-07 Thread Matthew Malcomson
Though the library has limited support for x86, we don't have any
support for generating code targeting x86 so there is no point building
for that target.

libsanitizer/ChangeLog:

2019-11-07  Matthew Malcomson  

* Makefile.am: Condition building hwasan directory.
* Makefile.in: Regenerate.
* configure: Regenerate.
* configure.ac: Set HWASAN_SUPPORTED based on target
architecture.
* configure.tgt: Likewise.



### Attachment also inlined for ease of reply###


diff --git a/libsanitizer/Makefile.am b/libsanitizer/Makefile.am
index 
2a7e8e1debe838719db0f0fad218b2543cc3111b..065a65e78d49f7689a01ecb64db1f07ca83aa987
 100644
--- a/libsanitizer/Makefile.am
+++ b/libsanitizer/Makefile.am
@@ -14,7 +14,7 @@ endif
 if LIBBACKTRACE_SUPPORTED
 SUBDIRS += libbacktrace
 endif
-SUBDIRS += lsan asan ubsan hwasan
+SUBDIRS += lsan asan ubsan
 nodist_saninclude_HEADERS += \
   include/sanitizer/lsan_interface.h \
   include/sanitizer/asan_interface.h \
@@ -23,6 +23,9 @@ nodist_saninclude_HEADERS += \
 if TSAN_SUPPORTED
 SUBDIRS += tsan
 endif
+if HWASAN_SUPPORTED
+SUBDIRS += hwasan
+endif
 endif
 
 ## May be used by toolexeclibdir.
diff --git a/libsanitizer/Makefile.in b/libsanitizer/Makefile.in
index 
36aa952af7e04bc0e4fb94cdcd584d539193d781..75a99491cb1d4422fd5e2d93cae93eb883ae0963
 100644
--- a/libsanitizer/Makefile.in
+++ b/libsanitizer/Makefile.in
@@ -97,6 +97,7 @@ target_triplet = @target@
 @SANITIZER_SUPPORTED_TRUE@@USING_MAC_INTERPOSE_FALSE@am__append_2 = 
interception
 @LIBBACKTRACE_SUPPORTED_TRUE@@SANITIZER_SUPPORTED_TRUE@am__append_3 = 
libbacktrace
 @SANITIZER_SUPPORTED_TRUE@@TSAN_SUPPORTED_TRUE@am__append_4 = tsan
+@HWASAN_SUPPORTED_TRUE@@SANITIZER_SUPPORTED_TRUE@am__append_5 = hwasan
 subdir = .
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
 am__aclocal_m4_deps = $(top_srcdir)/../config/acx.m4 \
@@ -207,7 +208,7 @@ ETAGS = etags
 CTAGS = ctags
 CSCOPE = cscope
 DIST_SUBDIRS = sanitizer_common interception libbacktrace lsan asan \
-   ubsan hwasan tsan
+   ubsan tsan hwasan
 ACLOCAL = @ACLOCAL@
 ALLOC_FILE = @ALLOC_FILE@
 AMTAR = @AMTAR@
@@ -363,7 +364,7 @@ sanincludedir = 
$(libdir)/gcc/$(target_alias)/$(gcc_version)/include/sanitizer
 nodist_saninclude_HEADERS = $(am__append_1)
 @SANITIZER_SUPPORTED_TRUE@SUBDIRS = sanitizer_common $(am__append_2) \
 @SANITIZER_SUPPORTED_TRUE@ $(am__append_3) lsan asan ubsan \
-@SANITIZER_SUPPORTED_TRUE@ hwasan $(am__append_4)
+@SANITIZER_SUPPORTED_TRUE@ $(am__append_4) $(am__append_5)
 gcc_version := $(shell @get_gcc_base_ver@ $(top_srcdir)/../gcc/BASE-VER)
 
 # Work around what appears to be a GNU make bug handling MAKEFLAGS
diff --git a/libsanitizer/configure b/libsanitizer/configure
index 
ff72af73e6f77aaf93bf39e6799f896851a377dd..4e95194fe3567b1227c4036c2f5bf6540f735975
 100755
--- a/libsanitizer/configure
+++ b/libsanitizer/configure
@@ -659,6 +659,8 @@ link_libubsan
 link_libtsan
 link_libhwasan
 link_libasan
+HWASAN_SUPPORTED_FALSE
+HWASAN_SUPPORTED_TRUE
 LSAN_SUPPORTED_FALSE
 LSAN_SUPPORTED_TRUE
 TSAN_SUPPORTED_FALSE
@@ -12335,7 +12337,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 12338 "configure"
+#line 12340 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -12441,7 +12443,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 12444 "configure"
+#line 12446 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -15792,6 +15794,7 @@ fi
 # Get target configury.
 unset TSAN_SUPPORTED
 unset LSAN_SUPPORTED
+unset HWASAN_SUPPORTED
 . ${srcdir}/configure.tgt
  if test "x$TSAN_SUPPORTED" = "xyes"; then
   TSAN_SUPPORTED_TRUE=
@@ -15809,6 +15812,14 @@ else
   LSAN_SUPPORTED_FALSE=
 fi
 
+ if test "x$HWASAN_SUPPORTED" = "xyes"; then
+  HWASAN_SUPPORTED_TRUE=
+  HWASAN_SUPPORTED_FALSE='#'
+else
+  HWASAN_SUPPORTED_TRUE='#'
+  HWASAN_SUPPORTED_FALSE=
+fi
+
 
 # Check for functions needed.
 for ac_func in clock_getres clock_gettime clock_settime lstat readlink
@@ -16791,7 +16802,7 @@ ac_config_files="$ac_config_files Makefile 
libsanitizer.spec libbacktrace/backtr
 ac_config_headers="$ac_config_headers config.h"
 
 
-ac_config_files="$ac_config_files interception/Makefile 
sanitizer_common/Makefile libbacktrace/Makefile lsan/Makefile asan/Makefile 
hwasan/Makefile ubsan/Makefile"
+ac_config_files="$ac_config_files interception/Makefile 
sanitizer_common/Makefile libbacktrace/Makefile lsan/Makefile asan/Makefile 
ubsan/Makefile"
 
 
 if test "x$TSAN_SUPPORTED" = "xyes"; then
@@ -16799,6 +16810,11 @@ if test "x$TSAN_SUPPORTED" = "xyes"; then
 
 fi
 
+if test "x$HWASAN_SUPPOR

[PATCH 3/X] [libsanitizer] Add option to bootstrap using HWASAN

2019-11-07 Thread Matthew Malcomson
This is an analogous option to --bootstrap-asan to configure.  It allows
bootstrapping GCC using HWASAN.

For the same reasons as for ASAN we have to avoid using the HWASAN
sanitizer when compiling libiberty and the lto-plugin.

Also add a function to query whether -fsanitize=hwaddress has been
passed.

ChangeLog:

2019-08-29  Matthew Malcomson  

* configure: Regenerate.
* configure.ac: Add --bootstrap-hwasan option.

config/ChangeLog:

2019-11-07  Matthew Malcomson  

* bootstrap-hwasan.mk: New file.

libiberty/ChangeLog:

2019-11-07  Matthew Malcomson  

* configure: Regenerate.
* configure.ac: Avoid using sanitizer.

lto-plugin/ChangeLog:

2019-11-07  Matthew Malcomson  

* Makefile.am: Avoid using sanitizer.
* Makefile.in: Regenerate.



### Attachment also inlined for ease of reply###


diff --git a/config/bootstrap-hwasan.mk b/config/bootstrap-hwasan.mk
new file mode 100644
index 
..4f60bed3fd6e98b47a3a38aea6eba2a7c320da25
--- /dev/null
+++ b/config/bootstrap-hwasan.mk
@@ -0,0 +1,8 @@
+# This option enables -fsanitize=hwaddress for stage2 and stage3.
+
+STAGE2_CFLAGS += -fsanitize=hwaddress
+STAGE3_CFLAGS += -fsanitize=hwaddress
+POSTSTAGE1_LDFLAGS += -fsanitize=hwaddress -static-libhwasan \
+ -B$$r/prev-$(TARGET_SUBDIR)/libsanitizer/ \
+ -B$$r/prev-$(TARGET_SUBDIR)/libsanitizer/hwasan/ \
+ -B$$r/prev-$(TARGET_SUBDIR)/libsanitizer/hwasan/.libs
diff --git a/configure b/configure
index 
aec9186b2b0123d3088b69eb1ee541567654953e..6f71b111bd18ec053180beecf83dd4549e83c2b9
 100755
--- a/configure
+++ b/configure
@@ -7270,7 +7270,7 @@ fi
 # or bootstrap-ubsan, bootstrap it.
 if echo " ${target_configdirs} " | grep " libsanitizer " > /dev/null 2>&1; then
   case "$BUILD_CONFIG" in
-*bootstrap-asan* | *bootstrap-ubsan* )
+*bootstrap-hwasan* | *bootstrap-asan* | *bootstrap-ubsan* )
   bootstrap_target_libs=${bootstrap_target_libs}target-libsanitizer,
   bootstrap_fixincludes=yes
   ;;
diff --git a/configure.ac b/configure.ac
index 
b8ce2ad20b9d03e42731252a9ec2a8417c13e566..16bfdf164555dad94c789f17b6a63ba1a2e3e9f4
 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2775,7 +2775,7 @@ fi
 # or bootstrap-ubsan, bootstrap it.
 if echo " ${target_configdirs} " | grep " libsanitizer " > /dev/null 2>&1; then
   case "$BUILD_CONFIG" in
-*bootstrap-asan* | *bootstrap-ubsan* )
+*bootstrap-hwasan* | *bootstrap-asan* | *bootstrap-ubsan* )
   bootstrap_target_libs=${bootstrap_target_libs}target-libsanitizer,
   bootstrap_fixincludes=yes
   ;;
diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi
index 
6c9579bfaff955eb43875b404fb7db1a667bf522..427a2f4e56b37e165b72cc166e1acb0732449a8b
 100644
--- a/gcc/doc/install.texi
+++ b/gcc/doc/install.texi
@@ -2645,6 +2645,11 @@ Some examples of build configurations designed for 
developers of GCC are:
 Compiles GCC itself using Address Sanitization in order to catch invalid memory
 accesses within the GCC code.
 
+@item @samp{bootstrap-hwasan}
+Compiles GCC itself using HWAddress Sanitization in order to catch invalid
+memory accesses within the GCC code.  This option is only available on AArch64
+targets with a very recent linux kernel (5.4 or later).
+
 @section Building a cross compiler
 
 When building a cross compiler, it is not generally possible to do a
diff --git a/libiberty/configure b/libiberty/configure
index 
7a34dabec32b0b383bd33f07811757335f4dd39c..cb2dd4ff5295598343cc18b3a79a86a778f2261d
 100755
--- a/libiberty/configure
+++ b/libiberty/configure
@@ -5261,6 +5261,7 @@ fi
 NOASANFLAG=
 case " ${CFLAGS} " in
   *\ -fsanitize=address\ *) NOASANFLAG=-fno-sanitize=address ;;
+  *\ -fsanitize=hwaddress\ *) NOASANFLAG=-fno-sanitize=hwaddress ;;
 esac
 
 
diff --git a/libiberty/configure.ac b/libiberty/configure.ac
index 
f1ce76010c9acde79c5dc46686a78b2e2f19244e..043237628b79cbf37d07359b59c5ffe17a7a22ef
 100644
--- a/libiberty/configure.ac
+++ b/libiberty/configure.ac
@@ -240,6 +240,7 @@ AC_SUBST(PICFLAG)
 NOASANFLAG=
 case " ${CFLAGS} " in
   *\ -fsanitize=address\ *) NOASANFLAG=-fno-sanitize=address ;;
+  *\ -fsanitize=hwaddress\ *) NOASANFLAG=-fno-sanitize=hwaddress ;;
 esac
 AC_SUBST(NOASANFLAG)
 
diff --git a/lto-plugin/Makefile.am b/lto-plugin/Makefile.am
index 
28dc21014b2e86988fa88adabd63ce6092e18e02..34aa397d785e3cc9b6975de460d065900364c3ff
 100644
--- a/lto-plugin/Makefile.am
+++ b/lto-plugin/Makefile.am
@@ -11,8 +11,8 @@ AM_CPPFLAGS = -I$(top_srcdir)/../include $(DEFS)
 AM_CFLAGS = @ac_lto_plugin_warn_cflags@
 AM_LDFLAGS = @ac_lto_plugin_ldflags@
 AM_LIBTOOLFLAGS = --tag=disable-static
-override CFLAGS := $(filter-out -fsanitize=address,$(CFLAGS))
-override LDFLAGS := $(filter-out -fsanitize=address,$(LDFLAGS))
+override CFLAGS := $(filter-

[PATCH 1/X] [libsanitizer] Tie the hwasan library into our build system

2019-11-07 Thread Matthew Malcomson
This patch does tries to tie libhwasan into the GCC build system in the
same way that the other sanitizer runtime libraries are handled.

libsanitizer/ChangeLog:

2019-11-07  Matthew Malcomson  

* Makefile.am:  Build libhwasan.
* Makefile.in:  Build libhwasan.
* asan/Makefile.in:  Build libhwasan.
* configure:  Build libhwasan.
* configure.ac:  Build libhwasan.
* hwasan/Makefile.am: New file.
* hwasan/Makefile.in: New file.
* hwasan/libtool-version: New file.
* interception/Makefile.in: Build libhwasan.
* libbacktrace/Makefile.in: Build libhwasan.
* libsanitizer.spec.in: Build libhwasan.
* lsan/Makefile.in: Build libhwasan.
* merge.sh: Build libhwasan.
* sanitizer_common/Makefile.in: Build libhwasan.
* tsan/Makefile.in: Build libhwasan.
* ubsan/Makefile.in: Build libhwasan.



### Attachment also inlined for ease of reply###


diff --git a/libsanitizer/Makefile.am b/libsanitizer/Makefile.am
index 
65ed1e712378ef453f820f86c4d3221f9dee5f2c..2a7e8e1debe838719db0f0fad218b2543cc3111b
 100644
--- a/libsanitizer/Makefile.am
+++ b/libsanitizer/Makefile.am
@@ -14,11 +14,12 @@ endif
 if LIBBACKTRACE_SUPPORTED
 SUBDIRS += libbacktrace
 endif
-SUBDIRS += lsan asan ubsan
+SUBDIRS += lsan asan ubsan hwasan
 nodist_saninclude_HEADERS += \
   include/sanitizer/lsan_interface.h \
   include/sanitizer/asan_interface.h \
-  include/sanitizer/tsan_interface.h
+  include/sanitizer/tsan_interface.h \
+  include/sanitizer/hwasan_interface.h
 if TSAN_SUPPORTED
 SUBDIRS += tsan
 endif
diff --git a/libsanitizer/Makefile.in b/libsanitizer/Makefile.in
index 
0d789b3a59d21ea2e5a23057ca3afe15425feec4..36aa952af7e04bc0e4fb94cdcd584d539193d781
 100644
--- a/libsanitizer/Makefile.in
+++ b/libsanitizer/Makefile.in
@@ -92,7 +92,8 @@ target_triplet = @target@
 @SANITIZER_SUPPORTED_TRUE@am__append_1 = 
include/sanitizer/common_interface_defs.h \
 @SANITIZER_SUPPORTED_TRUE@ include/sanitizer/lsan_interface.h \
 @SANITIZER_SUPPORTED_TRUE@ include/sanitizer/asan_interface.h \
-@SANITIZER_SUPPORTED_TRUE@ include/sanitizer/tsan_interface.h
+@SANITIZER_SUPPORTED_TRUE@ include/sanitizer/tsan_interface.h \
+@SANITIZER_SUPPORTED_TRUE@ include/sanitizer/hwasan_interface.h
 @SANITIZER_SUPPORTED_TRUE@@USING_MAC_INTERPOSE_FALSE@am__append_2 = 
interception
 @LIBBACKTRACE_SUPPORTED_TRUE@@SANITIZER_SUPPORTED_TRUE@am__append_3 = 
libbacktrace
 @SANITIZER_SUPPORTED_TRUE@@TSAN_SUPPORTED_TRUE@am__append_4 = tsan
@@ -206,7 +207,7 @@ ETAGS = etags
 CTAGS = ctags
 CSCOPE = cscope
 DIST_SUBDIRS = sanitizer_common interception libbacktrace lsan asan \
-   ubsan tsan
+   ubsan hwasan tsan
 ACLOCAL = @ACLOCAL@
 ALLOC_FILE = @ALLOC_FILE@
 AMTAR = @AMTAR@
@@ -328,6 +329,7 @@ install_sh = @install_sh@
 libdir = @libdir@
 libexecdir = @libexecdir@
 link_libasan = @link_libasan@
+link_libhwasan = @link_libhwasan@
 link_liblsan = @link_liblsan@
 link_libtsan = @link_libtsan@
 link_libubsan = @link_libubsan@
@@ -361,7 +363,7 @@ sanincludedir = 
$(libdir)/gcc/$(target_alias)/$(gcc_version)/include/sanitizer
 nodist_saninclude_HEADERS = $(am__append_1)
 @SANITIZER_SUPPORTED_TRUE@SUBDIRS = sanitizer_common $(am__append_2) \
 @SANITIZER_SUPPORTED_TRUE@ $(am__append_3) lsan asan ubsan \
-@SANITIZER_SUPPORTED_TRUE@ $(am__append_4)
+@SANITIZER_SUPPORTED_TRUE@ hwasan $(am__append_4)
 gcc_version := $(shell @get_gcc_base_ver@ $(top_srcdir)/../gcc/BASE-VER)
 
 # Work around what appears to be a GNU make bug handling MAKEFLAGS
diff --git a/libsanitizer/asan/Makefile.in b/libsanitizer/asan/Makefile.in
index 
00b6082da5372efd679ddc230f588bbc58161ef6..76689c3b224b1fb04895ae48829eac4b6784cd84
 100644
--- a/libsanitizer/asan/Makefile.in
+++ b/libsanitizer/asan/Makefile.in
@@ -382,6 +382,7 @@ install_sh = @install_sh@
 libdir = @libdir@
 libexecdir = @libexecdir@
 link_libasan = @link_libasan@
+link_libhwasan = @link_libhwasan@
 link_liblsan = @link_liblsan@
 link_libtsan = @link_libtsan@
 link_libubsan = @link_libubsan@
diff --git a/libsanitizer/configure b/libsanitizer/configure
index 
79b5c1eadb59018bca13a33f19f3494c170365ee..ff72af73e6f77aaf93bf39e6799f896851a377dd
 100755
--- a/libsanitizer/configure
+++ b/libsanitizer/configure
@@ -657,6 +657,7 @@ USING_MAC_INTERPOSE_TRUE
 link_liblsan
 link_libubsan
 link_libtsan
+link_libhwasan
 link_libasan
 LSAN_SUPPORTED_FALSE
 LSAN_SUPPORTED_TRUE
@@ -12334,7 +12335,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 12337 "configure"
+#line 12338 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -12440,7 +12441,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 12443 "configure"
+#line 12444 "configure"
 #

[PATCH 4/X] [libsanitizer][options] Add hwasan flags and argument parsing

2019-11-07 Thread Matthew Malcomson
These flags can't be used at the same time as any of the other
sanitizers.
We add an equivalent flag to -static-libasan in -static-libhwasan to
ensure static linking.

The -fsanitize=kernel-hwaddress option is for compiling targeting the
kernel.  This flag has defaults that allow compiling KASAN with tags as
it is currently implemented.
These defaults are that we do not sanitize variables on the stack and
always recover from a detected bug.
Stack tagging in the kernel is a future aim, stack instrumentation has
not yet been enabled for the kernel for clang either
(https://lists.infradead.org/pipermail/linux-arm-kernel/2019-October/687121.html).

We introduce a backend hook `targetm.memtag.can_tag_addresses` that
indicates to the mid-end whether a target has a feature like AArch64 TBI
where the top byte of an address is ignored.
Without this feature hwasan sanitization is not done.

gcc/ChangeLog:

2019-11-07  Matthew Malcomson  

* asan.c (memory_tagging_p): New.
* asan.h (memory_tagging_p): New.
* common.opt (flag_sanitize_recover): Default for kernel
hwaddress.
(static-libhwasan): New cli option.
* config/aarch64/aarch64.c (aarch64_can_tag_addresses): New.
(TARGET_MEMTAG_CAN_TAG_ADDRESSES): New.
* config/gnu-user.h (LIBHWASAN_EARLY_SPEC): hwasan equivalent of
asan command line flags.
* cppbuiltin.c (define_builtin_macros_for_compilation_flags):
Add hwasan equivalent of __SANITIZE_ADDRESS__.
* doc/tm.texi: Document new hook.
* doc/tm.texi.in: Document new hook.
* flag-types.h (enum sanitize_code): New sanitizer values.
* gcc.c (STATIC_LIBHWASAN_LIBS): New macro.
(LIBHWASAN_SPEC): New macro.
(LIBHWASAN_EARLY_SPEC): New macro.
(SANITIZER_EARLY_SPEC): Update to include hwasan.
(SANITIZER_SPEC): Update to include hwasan.
(sanitize_spec_function): Use hwasan options.
* opts.c (finish_options): Describe conflicts between address
sanitizers.
(sanitizer_opts): Introduce new sanitizer flags.
(common_handle_option): Add defaults for kernel sanitizer.
* params.def (PARAM_HWASAN_RANDOM_FRAME_TAG): New.
(PARAM_HWASAN_STACK): New.
* params.h (HWASAN_STACK): New.
(HWASAN_RANDOM_FRAME_TAG): New.
* target.def (HOOK_PREFIX): Add new hook.
* targhooks.c (default_memtag_can_tag_addresses): New.
* toplev.c (process_options): Ensure hwasan only on TBI
architectures.

gcc/c-family/ChangeLog:

2019-11-07  Matthew Malcomson  

* c-attribs.c (handle_no_sanitize_hwaddress_attribute): New
attribute.



### Attachment also inlined for ease of reply###


diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c
index 
1c9f28587fbb2348cc30e302e889a5a22906901a..a5e68061ff956018957b6be137a7b2f2b7353647
 100644
--- a/gcc/c-family/c-attribs.c
+++ b/gcc/c-family/c-attribs.c
@@ -54,6 +54,8 @@ static tree handle_cold_attribute (tree *, tree, tree, int, 
bool *);
 static tree handle_no_sanitize_attribute (tree *, tree, tree, int, bool *);
 static tree handle_no_sanitize_address_attribute (tree *, tree, tree,
  int, bool *);
+static tree handle_no_sanitize_hwaddress_attribute (tree *, tree, tree,
+   int, bool *);
 static tree handle_no_sanitize_thread_attribute (tree *, tree, tree,
 int, bool *);
 static tree handle_no_address_safety_analysis_attribute (tree *, tree, tree,
@@ -412,6 +414,8 @@ const struct attribute_spec c_common_attribute_table[] =
  handle_no_sanitize_attribute, NULL },
   { "no_sanitize_address",0, 0, true, false, false, false,
  handle_no_sanitize_address_attribute, NULL },
+  { "no_sanitize_hwaddress",0, 0, true, false, false, false,
+ handle_no_sanitize_hwaddress_attribute, NULL },
   { "no_sanitize_thread", 0, 0, true, false, false, false,
  handle_no_sanitize_thread_attribute, NULL },
   { "no_sanitize_undefined",  0, 0, true, false, false, false,
@@ -941,6 +945,22 @@ handle_no_sanitize_address_attribute (tree *node, tree 
name, tree, int,
   return NULL_TREE;
 }
 
+/* Handle a "no_sanitize_hwaddress" attribute; arguments as in
+   struct attribute_spec.handler.  */
+
+static tree
+handle_no_sanitize_hwaddress_attribute (tree *node, tree name, tree, int,
+ bool *no_add_attrs)
+{
+  *no_add_attrs = true;
+  if (TREE_CODE (*node) != FUNCTION_DECL)
+warning (OPT_Wattributes, "%qE attribute ignored", name);
+  else
+add_no_sanitize_value (*node, SANITIZE_HWADDRESS);
+
+  return NULL_TREE;
+}
+
 /* Handle a "no_sanitize_thread" attribute

[PATCH 6/X] [libsanitizer] Add hwasan pass and associated gimple changes

2019-11-07 Thread Matthew Malcomson
There are four main features to this change:

1) Check pointer tags match address tags.

In the new `hwasan` pass we put HWASAN_CHECK internal functions around
all memory accesses, to check that tags in the pointer being used match
the tag stored in shadow memory for the memory region being used.

These internal functions are expanded into actual checks in the sanopt
pass that happens just before expansion into RTL.

We use the same mechanism that currently inserts ASAN_CHECK internal
functions to insert the new HWASAN_CHECK functions.

2) Instrument known builtin function calls.

Handle all builtin functions that we know use memory accesses.
This commit uses the machinery added for ASAN to identify builtin
functions that access memory.

The main differences between the approaches for HWASAN and ASAN are:
 - libhwasan intercepts much less builtin functions.
 - Alloca needs to be transformed differently (instead of adding
   redzones it needs to tag shadow memory and return a tagged pointer).
 - stack_restore needs to untag the shadow stack between the current
   position and where it's going.
 - `noreturn` functions can not be handled by simply unpoisoning the
   entire shadow stack -- there is no "always valid" tag.
   (exceptions and things such as longjmp need to be handled in a
   different way).

For hardware implemented checking (such as AArch64's memory tagging
extension) alloca and stack_restore will need to be handled by hooks in
the backend rather than transformation at the gimple level.  This will
allow architecture specific handling of such stack modifications.

3) Introduce HWASAN block-scope poisoning

Here we use exactly the same mechanism as ASAN_MARK to poison/unpoison
variables on entry/exit of a block.

In order to simply use the exact same machinery we're using the same
internal functions until the SANOPT pass.  This means that all handling
of ASAN_MARK is the same.
This has the negative that the naming may be a little confusing, but a
positive that handling of the internal function doesn't have to be
duplicated for a function that behaves exactly the same but has a
different name.

gcc/ChangeLog:

2019-11-07  Matthew Malcomson  

* asan.c (handle_builtin_stack_restore): Account for HWASAN.
(handle_builtin_alloca): Account for HWASAN.
(get_mem_refs_of_builtin_call): Special case strlen for HWASAN.
(report_error_func): Assert not HWASAN.
(build_check_stmt): Make HWASAN_CHECK instead of ASAN_CHECK.
(instrument_derefs): HWASAN does not tag globals.
(maybe_instrument_call): Don't instrument `noreturn` functions.
(initialize_sanitizer_builtins): Add new type.
(asan_expand_mark_ifn): Account for HWASAN.
(asan_expand_check_ifn): Assert never called by HWASAN.
(asan_expand_poison_ifn): Account for HWASAN.
(hwasan_instrument): New.
(hwasan_base): New.
(hwasan_emit_untag_frame): Free block-scope-var hash map.
(hwasan_check_func): New.
(hwasan_expand_check_ifn): New.
(hwasan_expand_mark_ifn): New.
(gate_hwasan): New.
(class pass_hwasan): New.
(make_pass_hwasan): New.
(class pass_hwasan_O0): New.
(make_pass_hwasan_O0): New.
* asan.h (hwasan_base): New decl.
(hwasan_expand_check_ifn): New decl.
(hwasan_expand_mark_ifn): New decl.
(gate_hwasan): New decl.
(enum hwasan_mark_flags): New.
(asan_intercepted_p): Always false for hwasan.
(asan_sanitize_use_after_scope): Account for HWASAN.
* builtin-types.def (BT_FN_PTR_CONST_PTR_UINT8): New.
* gimple-pretty-print.c (dump_gimple_call_args): Account for
HWASAN.
* gimplify.c (asan_poison_variable): Account for HWASAN.
(gimplify_function_tree): Remove requirement of
SANITIZE_ADDRESS, requiring asan or hwasan is accounted for in
`asan_sanitize_use_after_scope`.
* internal-fn.c (expand_HWASAN_CHECK): New.
(expand_HWASAN_CHOOSE_TAG): New.
(expand_HWASAN_MARK): New.
* internal-fn.def (HWASAN_CHOOSE_TAG): New.
(HWASAN_CHECK): New.
(HWASAN_MARK): New.
* passes.def: Add hwasan and hwasan_O0 passes.
* sanitizer.def (BUILT_IN_HWASAN_LOAD1): New.
(BUILT_IN_HWASAN_LOAD2): New.
(BUILT_IN_HWASAN_LOAD4): New.
(BUILT_IN_HWASAN_LOAD8): New.
(BUILT_IN_HWASAN_LOAD16): New.
(BUILT_IN_HWASAN_LOADN): New.
(BUILT_IN_HWASAN_STORE1): New.
(BUILT_IN_HWASAN_STORE2): New.
(BUILT_IN_HWASAN_STORE4): New.
(BUILT_IN_HWASAN_STORE8): New.
(BUILT_IN_HWASAN_STORE16): New.
(BUILT_IN_HWASAN_STOREN): New.
(BUILT_IN_HWASAN_LOAD1_NOABORT): New.
(BUILT_IN_HWASAN_LOAD2_NOABORT): New.
(BUILT_IN_HWASAN_LOAD4_NOABORT): New.
(BUILT_IN_HWASAN_LOAD8_NOABORT): New.
(B

[PATCH 5/X] [libsanitizer][mid-end] Introduce stack variable handling for HWASAN

2019-11-07 Thread Matthew Malcomson
Handling stack variables has three features.

1) Ensure HWASAN required alignment for stack variables

When tagging shadow memory, we need to ensure that each tag granule is
only used by one variable at a time.

This is done by ensuring that each tagged variable is aligned to the tag
granule representation size and also ensure that the end of each
variable as an alignment boundary between the end and the start of any
other data stored on the stack.

This patch ensures that by adding alignment requirements in
`align_local_variable` and forcing all stack variable allocation to be
deferred so that `expand_stack_vars` can ensure the stack pointer is
aligned before allocating any variable for the current frame.

2) Put tags into each stack variable pointer

Make sure that every pointer to a stack variable includes a tag of some
sort on it.

The way tagging works is:
  1) For every new stack frame, a random tag is generated.
  2) A base register is formed from the stack pointer value and this
 random tag.
  3) References to stack variables are now formed with RTL describing an
 offset from this base in both tag and value.

The random tag generation is handled by a backend hook.  This hook
decides whether to introduce a random tag or use the stack background
based on the parameter hwasan-random-frame-tag.  Using the stack
background is necessary for testing and bootstrap.  It is necessary
during bootstrap to avoid breaking the `configure` test program for
determining stack direction.

Using the stack background means that every stack frame has the initial
tag of zero and variables are tagged with incrementing tags from 1,
which also makes debugging a bit easier.

The tag&value offsets are also handled by a backend hook.

This patch also adds some macros defining how the HWASAN shadow memory
is stored and how a tag is stored in a pointer.

3) For each stack variable, tag and untag the shadow stack on function
   prologue and epilogue.

On entry to each function we tag the relevant shadow stack region for
each stack variable the tag to match the tag added to each pointer for
that variable.

This is the first patch where we use the HWASAN shadow space, so we need
to add in the libhwasan initialisation code that creates this shadow
memory region into the binary we produce.  This instrumentation is done
in `compile_file`.

When exiting a function we need to ensure the shadow stack for this
function has no remaining tag.  Without clearing the shadow stack area
for this stack frame, later function calls could get false positives
when those later function calls check untagged areas (such as parameters
passed on the stack) against a shadow stack area with left-over tag.

Hence we ensure that the entire stack frame is cleared on function exit.

gcc/ChangeLog:

2019-11-07  Matthew Malcomson  

* asan.c (hwasan_record_base): New function.
(hwasan_emit_untag_frame): New.
(hwasan_increment_tag): New function.
(hwasan_with_tag): New function.
(hwasan_tag_init): New function.
(initialize_sanitizer_builtins): Define new builtins.
(ATTR_NOTHROW_LIST): New macro.
(hwasan_current_tag): New.
(hwasan_emit_prologue): New.
(hwasan_create_untagged_base): New.
(hwasan_finish_file): New.
(hwasan_sanitize_stack_p): New.
(memory_tagging_p): New.
* asan.h (hwasan_record_base): New declaration.
(hwasan_emit_untag_frame): New.
(hwasan_increment_tag): New declaration.
(hwasan_with_tag): New declaration.
(hwasan_sanitize_stack_p): New declaration.
(hwasan_tag_init): New declaration.
(memory_tagging_p): New declaration.
(HWASAN_TAG_SIZE): New macro.
(HWASAN_TAG_GRANULE_SIZE):New macro.
(HWASAN_SHIFT):New macro.
(HWASAN_SHIFT_RTX):New macro.
(HWASAN_STACK_BACKGROUND):New macro.
(hwasan_finish_file): New.
(hwasan_current_tag): New.
(hwasan_create_untagged_base): New.
(hwasan_emit_prologue): New.
* cfgexpand.c (struct stack_vars_data): Add information to
record hwasan variable stack offsets.
(expand_stack_vars): Ensure variables are offset from a tagged
base. Record offsets for hwasan. Ensure alignment.
(expand_used_vars): Call function to emit prologue, and get
untagging instructions for function exit.
(align_local_variable): Ensure alignment.
(defer_stack_allocation): Ensure all variables are deferred so
they can be handled by `expand_stack_vars`.
(expand_one_stack_var_at): Account for tags in
variables when using HWASAN.
(expand_one_stack_var_1): Pass new argument to
expand_one_stack_var_at.
(init_vars_expansion): Initialise hwasan internal variables when
starting variable expansion.
* doc/tm.texi (TARGET_MEMTAG_GENTAG): Document.
* doc/tm.texi.in (TARGET_MEMTAG_GE

[PATCH 7/X] [libsanitizer] Add tests

2019-11-07 Thread Matthew Malcomson
Adding hwasan tests.

Frankly, these could be tidied up a little.
I will be tidying them up while getting feedback on the hwasan introduction.


gcc/testsuite/ChangeLog:

2019-11-07  Matthew Malcomson  

* c-c++-common/hwasan/arguments.c: New test.
* c-c++-common/hwasan/halt_on_error-1.c: New test.
* g++.dg/hwasan/rvo-handled.c: New test.
* g++.dg/hwasan/try-catch-0.cpp: New test.
* g++.dg/hwasan/try-catch-1.cpp: New test.
* gcc.dg/hwasan/aligned-alloc.c: New test.
* gcc.dg/hwasan/alloca-array-accessible.c: New test.
* gcc.dg/hwasan/alloca-gets-different-tag.c: New test.
* gcc.dg/hwasan/alloca-outside-caught.c: New test.
* gcc.dg/hwasan/bitfield-1.c: New test.
* gcc.dg/hwasan/bitfield-2.c: New test.
* gcc.dg/hwasan/builtin-special-handling.c: New test.
* gcc.dg/hwasan/check-interface.c: New test.
* gcc.dg/hwasan/hwasan-poison-optimisation.c: New test.
* gcc.dg/hwasan/hwasan-thread-access-parent.c: New test.
* gcc.dg/hwasan/hwasan-thread-basic-failure.c: New test.
* gcc.dg/hwasan/hwasan-thread-clears-stack.c: New test.
* gcc.dg/hwasan/hwasan-thread-success.c: New test.
* gcc.dg/hwasan/hwasan.exp: New file.
* gcc.dg/hwasan/kernel-defaults.c: New test.
* gcc.dg/hwasan/large-aligned-0.c: New test.
* gcc.dg/hwasan/large-aligned-1.c: New test.
* gcc.dg/hwasan/macro-definition.c: New test.
* gcc.dg/hwasan/nested-functions-0.c: New test.
* gcc.dg/hwasan/nested-functions-1.c: New test.
* gcc.dg/hwasan/nested-functions-2.c: New test.
* gcc.dg/hwasan/no-sanitize-attribute.c: New test.
* gcc.dg/hwasan/random-frame-tag.c: New test.
* gcc.dg/hwasan/setjmp-longjmp-0.c: New test.
* gcc.dg/hwasan/setjmp-longjmp-1.c: New test.
* gcc.dg/hwasan/stack-tagging-basic-0.c: New test.
* gcc.dg/hwasan/stack-tagging-basic-1.c: New test.
* gcc.dg/hwasan/stack-tagging-disable.c: New test.
* gcc.dg/hwasan/vararray-outside-caught.c: New test.
* gcc.dg/hwasan/very-large-objects.c: New test.
* lib/hwasan-dg.exp: New file.



### Attachment also inlined for ease of reply###


diff --git a/gcc/testsuite/c-c++-common/hwasan/arguments.c 
b/gcc/testsuite/c-c++-common/hwasan/arguments.c
new file mode 100644
index 
..2d563eb8541694d501b021babd9452fd7fd502a3
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/hwasan/arguments.c
@@ -0,0 +1,7 @@
+/*
+   TODO
+   Somehow test the conflict of arguments
+   -fsanitize=hwaddress -fsanitize=kernel-address
+   -fsanitize=hwaddress -fsanitize=address
+   -fsanitize=hwaddress -fsanitize=thread
+ */
diff --git a/gcc/testsuite/c-c++-common/hwasan/halt_on_error-1.c 
b/gcc/testsuite/c-c++-common/hwasan/halt_on_error-1.c
new file mode 100644
index 
..118191e2e00bd07bd4839888d2fb29baec926c60
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/hwasan/halt_on_error-1.c
@@ -0,0 +1,25 @@
+/* Test recovery mode.  */
+/* { dg-do run } */
+/* { dg-options "-fsanitize-recover=hwaddress" } */
+/* { dg-set-target-env-var HWASAN_OPTIONS "halt_on_error=false" } */
+/* { dg-shouldfail "hwasan" } */
+
+#include 
+
+volatile int ten = 16;
+
+int main() {
+  char x[10];
+  __builtin_memset(x, 0, ten + 1);
+  asm volatile ("" : : : "memory");
+  volatile int res = x[ten];
+  x[ten] = res + 3;
+  res = x[ten];
+  return 0;
+}
+
+/* { dg-output "WRITE of size 17 at 0x\[0-9a-f\]+.*" } */
+/* { dg-output "READ of size 1 at 0x\[0-9a-f\]+.*" } */
+/* { dg-output "WRITE of size 1 at 0x\[0-9a-f\]+.*" } */
+/* { dg-output "READ of size 1 at 0x\[0-9a-f\]+.*" } */
+
diff --git a/gcc/testsuite/g++.dg/hwasan/rvo-handled.c 
b/gcc/testsuite/g++.dg/hwasan/rvo-handled.c
new file mode 100644
index 
..6e6934a0be1b0ce14c459555168f6a2590a8ec7f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/hwasan/rvo-handled.c
@@ -0,0 +1,56 @@
+/* { dg-do run } */
+/* TODO Ensure this test has enough optimisation to get RVO. */
+
+#define assert(x) if (!(x)) __builtin_abort ()
+
+struct big_struct {
+int left;
+int right;
+void *ptr;
+int big_array[100];
+};
+
+/*
+   Tests for RVO (basically, checking -fsanitize=hwaddress has not broken RVO
+   in any way).
+
+   0) The value is accessible in both functions without a hwasan complaint.
+   1) RVO does happen.
+ */
+
+struct big_struct __attribute__ ((noinline))
+return_on_stack()
+{
+  struct big_struct x;
+  x.left = 100;
+  x.right = 20;
+  x.big_array[10] = 30;
+  x.ptr = &x;
+  return x;
+}
+
+struct big_struct __attribute__ ((noinline))
+unnamed_return_on_stack()
+{
+  return (struct big_struct){
+  .left = 100,
+  .right = 20,
+  .ptr = __builtin_frame_address (0),
+ 

Re: [PATCH 3/X] [libsanitizer] Add option to bootstrap using HWASAN

2019-11-11 Thread Matthew Malcomson
On 11/11/2019 14:30, Martin Liška wrote:
> On 11/7/19 7:37 PM, Matthew Malcomson wrote:
>> +@item @samp{bootstrap-hwasan}
>> +Compiles GCC itself using HWAddress Sanitization in order to catch 
>> invalid
>> +memory accesses within the GCC code.  This option is only available 
>> on AArch64
>> +targets with a very recent linux kernel (5.4 or later).
>> +
> 
> Apparently, I see this hunk being applied:
> 
> diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi
> index 2cb8a342a2c..ed47796e052 100644
> --- a/gcc/doc/install.texi
> +++ b/gcc/doc/install.texi
> @@ -2671,6 +2671,11 @@ the build tree.
> 
>   @end table
> 
> +@item @samp{bootstrap-hwasan}
> +Compiles GCC itself using HWAddress Sanitization in order to catch invalid
> +memory accesses within the GCC code.  This option is only available on 
> AArch64
> +targets with a very recent linux kernel (5.4 or later).
> +
>   @section Building a cross compiler
> 
>   When building a cross compiler, it is not generally possible to do a
> 
> and then I see:
> 
> make[2]: Entering directory '/dev/shm/objdir/gcc'
> if [ xinfo = xinfo ]; then \
>  makeinfo --split-size=500 --split-size=500 --no-split -I 
> /home/marxin/Programming/gcc/gcc/doc \
>      -I /home/marxin/Programming/gcc/gcc/doc/include -o 
> doc/gccinstall.info /home/marxin/Programming/gcc/gcc/doc/install.texi; \
> fi
> /home/marxin/Programming/gcc/gcc/doc/install.texi:2674: @item outside of 
> table or list
> make[2]: *** [Makefile:3279: doc/gccinstall.info] Error 1
> make[2]: Leaving directory '/dev/shm/objdir/gcc'
> 
> Can you please check it?
> Thanks,
> Martin

Ah!
My apologies -- I sent up a series with a few documentation mistakes.
(the others were wording problems so less noticeable)

I'm attaching the entire updated patch series (with the other 
documentation fixes in it too) and the fixed patch for just this part in 
case you just want to compile and test right now.

Regards,
Matthew


all-patches.tar.gz
Description: all-patches.tar.gz
diff --git a/config/bootstrap-hwasan.mk b/config/bootstrap-hwasan.mk
new file mode 100644
index ..4f60bed3fd6e98b47a3a38aea6eba2a7c320da25
--- /dev/null
+++ b/config/bootstrap-hwasan.mk
@@ -0,0 +1,8 @@
+# This option enables -fsanitize=hwaddress for stage2 and stage3.
+
+STAGE2_CFLAGS += -fsanitize=hwaddress
+STAGE3_CFLAGS += -fsanitize=hwaddress
+POSTSTAGE1_LDFLAGS += -fsanitize=hwaddress -static-libhwasan \
+		  -B$$r/prev-$(TARGET_SUBDIR)/libsanitizer/ \
+		  -B$$r/prev-$(TARGET_SUBDIR)/libsanitizer/hwasan/ \
+		  -B$$r/prev-$(TARGET_SUBDIR)/libsanitizer/hwasan/.libs
diff --git a/configure b/configure
index aec9186b2b0123d3088b69eb1ee541567654953e..6f71b111bd18ec053180beecf83dd4549e83c2b9 100755
--- a/configure
+++ b/configure
@@ -7270,7 +7270,7 @@ fi
 # or bootstrap-ubsan, bootstrap it.
 if echo " ${target_configdirs} " | grep " libsanitizer " > /dev/null 2>&1; then
   case "$BUILD_CONFIG" in
-*bootstrap-asan* | *bootstrap-ubsan* )
+*bootstrap-hwasan* | *bootstrap-asan* | *bootstrap-ubsan* )
   bootstrap_target_libs=${bootstrap_target_libs}target-libsanitizer,
   bootstrap_fixincludes=yes
   ;;
diff --git a/configure.ac b/configure.ac
index b8ce2ad20b9d03e42731252a9ec2a8417c13e566..16bfdf164555dad94c789f17b6a63ba1a2e3e9f4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2775,7 +2775,7 @@ fi
 # or bootstrap-ubsan, bootstrap it.
 if echo " ${target_configdirs} " | grep " libsanitizer " > /dev/null 2>&1; then
   case "$BUILD_CONFIG" in
-*bootstrap-asan* | *bootstrap-ubsan* )
+*bootstrap-hwasan* | *bootstrap-asan* | *bootstrap-ubsan* )
   bootstrap_target_libs=${bootstrap_target_libs}target-libsanitizer,
   bootstrap_fixincludes=yes
   ;;
diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi
index 6c9579bfaff955eb43875b404fb7db1a667bf522..da9a8809c3440827ac22ef6936e080820197f4e7 100644
--- a/gcc/doc/install.texi
+++ b/gcc/doc/install.texi
@@ -2645,6 +2645,13 @@ Some examples of build configurations designed for developers of GCC are:
 Compiles GCC itself using Address Sanitization in order to catch invalid memory
 accesses within the GCC code.
 
+@item @samp{bootstrap-hwasan}
+Compiles GCC itself using HWAddress Sanitization in order to catch invalid
+memory accesses within the GCC code.  This option is only available on AArch64
+targets with a very recent linux kernel (5.4 or later).
+
+@end table
+
 @section Building a cross compiler
 
 When building a cross compiler, it is not generally possible to do a
diff --git a/libiberty/configure b/libiberty/configure
index 7a34dabec32b0b383bd33f07811757335f4dd39c..cb2dd4ff5295598343cc18b3a79a86a778f2261d 100755
--- a/libiberty/configure
+++ 

Re: v2 [PATCH 0/X] Introduce HWASAN sanitizer to GCC

2019-11-11 Thread Matthew Malcomson
On 07/11/2019 18:37, Matthew Malcomson wrote:
> I have rebased this series onto Martin Liska's patches that take the most
> recent libhwasan from upstream LLVM.
> https://gcc.gnu.org/ml/gcc-patches/2019-11/msg00340.html
> 
> I've also cleared up some nomenclature (I had previously used the word 
> 'colour'
> a few times instead of the word 'tag' and that clashes with other 
> descriptions)
> and based the patch series off a more recent GCC revision (r277678).
> 
> There's an ongoing discussion on whether to have __SANITIZER_ADDRESS__, or
> __SANITIZER_HWADDRESS__, but I'm keeping that discussion to the existing
> thread.
> 
> Similarly there's still the question around C++ exceptions that I'm keeping to
> the existing thread (on the first patch series).
> 
> 
> NOTE:
>Unfortunately, there's a bug in the more recent version of GCC I rebased
>onto.
>Hwasan catches this when bootstrapping, which means bootstrapping with 
> hwasan
>fails.
>I'm working on tracking the bug down now, but sending this series upstream
>for visibility while that happens.
> 
>Bugzilla link:
>https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92410
> 
> Entire patch series attached to cover letter.
> 

It seems that PR 92410 is a little more extensive than it originally 
looked (in fixing it I saw instances of the same basic problem elsewhere 
too).

Just in case anyone wants to take a look at this HWASAN series in the 
meantime there are two ways:

1) Bootstrap with hwasan not crashing on error.

2) Apply the last patch I posted on 
http://pdtlreviewboard.cambridge.arm.com/r/12149/


Number 1 requires the patch below and to run make with HWASAN_OPTIONS 
set to "halt_on_error=0 exitcode=0".

diff --git a/config/bootstrap-hwasan.mk b/config/bootstrap-hwasan.mk
index 91989f4..3672b91 100644
--- a/config/bootstrap-hwasan.mk
+++ b/config/bootstrap-hwasan.mk
@@ -4,8 +4,8 @@
  # breaks.  Running with a random frame tag gives approx. 50% chance of
  # bootstrap comparison diff in libiberty/alloca.c.

-STAGE2_CFLAGS += -fsanitize=hwaddress --param hwasan-random-frame-tag=0
-STAGE3_CFLAGS += -fsanitize=hwaddress --param hwasan-random-frame-tag=0
+STAGE2_CFLAGS += -fsanitize-recover=hwaddress -fsanitize=hwaddress 
--param hwasan-random-frame-tag=0
+STAGE3_CFLAGS += -fsanitize-recover=hwaddress -fsanitize=hwaddress 
--param hwasan-random-frame-tag=0
  POSTSTAGE1_LDFLAGS += -fsanitize=hwaddress -static-libhwasan \
   -B$$r/prev-$(TARGET_SUBDIR)/libsanitizer/ \
   -B$$r/prev-$(TARGET_SUBDIR)/libsanitizer/hwasan/ \




Number 2 option avoids the current problem, but causes two extra 
testsuite failures (unrelated to hwasan) in gcc.dg/fold-eqandshift-1.c 
and gcc.c-torture/compile/pr32482.c.
These are existing bugs that a new `assert` catches.



Re: v2 [PATCH 0/X] Introduce HWASAN sanitizer to GCC

2019-11-11 Thread Matthew Malcomson
On 11/11/2019 16:13, Matthew Malcomson wrote:
> On 07/11/2019 18:37, Matthew Malcomson wrote:
>> I have rebased this series onto Martin Liska's patches that take the most
>> recent libhwasan from upstream LLVM.
>> https://gcc.gnu.org/ml/gcc-patches/2019-11/msg00340.html
>>
>> I've also cleared up some nomenclature (I had previously used the word 
>> 'colour'
>> a few times instead of the word 'tag' and that clashes with other 
>> descriptions)
>> and based the patch series off a more recent GCC revision (r277678).
>>
>> There's an ongoing discussion on whether to have __SANITIZER_ADDRESS__, or
>> __SANITIZER_HWADDRESS__, but I'm keeping that discussion to the existing
>> thread.
>>
>> Similarly there's still the question around C++ exceptions that I'm keeping 
>> to
>> the existing thread (on the first patch series).
>>
>>
>> NOTE:
>> Unfortunately, there's a bug in the more recent version of GCC I rebased
>> onto.
>> Hwasan catches this when bootstrapping, which means bootstrapping with 
>> hwasan
>> fails.
>> I'm working on tracking the bug down now, but sending this series 
>> upstream
>> for visibility while that happens.
>>
>> Bugzilla link:
>> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92410
>>
>> Entire patch series attached to cover letter.
>>
> 
> It seems that PR 92410 is a little more extensive than it originally
> looked (in fixing it I saw instances of the same basic problem elsewhere
> too).
> 
> Just in case anyone wants to take a look at this HWASAN series in the
> meantime there are two ways:
> 
> 1) Bootstrap with hwasan not crashing on error.
> 
> 2) Apply the last patch I posted on
> http://pdtlreviewboard.cambridge.arm.com/r/12149/

Oops -- clipboard didn't have what I thought it did.
I meant https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92410 here.

> 
> 
> Number 1 requires the patch below and to run make with HWASAN_OPTIONS
> set to "halt_on_error=0 exitcode=0".
> 
> diff --git a/config/bootstrap-hwasan.mk b/config/bootstrap-hwasan.mk
> index 91989f4..3672b91 100644
> --- a/config/bootstrap-hwasan.mk
> +++ b/config/bootstrap-hwasan.mk
> @@ -4,8 +4,8 @@
># breaks.  Running with a random frame tag gives approx. 50% chance of
># bootstrap comparison diff in libiberty/alloca.c.
> 
> -STAGE2_CFLAGS += -fsanitize=hwaddress --param hwasan-random-frame-tag=0
> -STAGE3_CFLAGS += -fsanitize=hwaddress --param hwasan-random-frame-tag=0
> +STAGE2_CFLAGS += -fsanitize-recover=hwaddress -fsanitize=hwaddress
> --param hwasan-random-frame-tag=0
> +STAGE3_CFLAGS += -fsanitize-recover=hwaddress -fsanitize=hwaddress
> --param hwasan-random-frame-tag=0
>POSTSTAGE1_LDFLAGS += -fsanitize=hwaddress -static-libhwasan \
> -B$$r/prev-$(TARGET_SUBDIR)/libsanitizer/ \
> -B$$r/prev-$(TARGET_SUBDIR)/libsanitizer/hwasan/ \
> 
> 
> 
> 
> Number 2 option avoids the current problem, but causes two extra
> testsuite failures (unrelated to hwasan) in gcc.dg/fold-eqandshift-1.c
> and gcc.c-torture/compile/pr32482.c.
> These are existing bugs that a new `assert` catches.
> 



[mid-end] Add notes to dataflow insn info when re-emitting (PR92410)

2019-11-12 Thread Matthew Malcomson
In scheduling passes, notes are removed with `remove_notes` before the
scheduling is done, and added back in with `reemit_notes` once the
scheduling has been decided.

This process leaves the notes in the RTL chain with different insn uid's
than were there before.  Having different UID's (larger than the
previous ones) means that DF_INSN_INFO_GET(insn) will access outside of
the allocated array.

This has been seen in the `regstat_bb_compute_calls_crossed` function.
This patch adds an assert to the `regstat_bb_compute_calls_crossed`
function so that bad accesses here are caught instead of going
unnoticed, and then avoids the problem.

We avoid the problem by ensuring that new notes added by `reemit_notes` have an
insn record given to them.  This is done by adding a call to
`df_insn_create_insn_record` on each note added in `reemit_notes`.
`df_insn_create_insn_record` leaves this new record zeroed out, which appears
to be fine for notes (e.g. `df_bb_refs_record` already does not set
anything except the luid for notes, and notes have no dataflow information to
record).

We add the testcase that Martin found here
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92410#c2 .
This testcase fails with the "regstat.c" change, and then succeeds with the
"haifa-sched.c" change.

There is a similar problem with labels, that the `gcc_assert` catches
when running regression tests in gcc.dg/fold-eqandshift-1.c and
gcc.c-torture/compile/pr32482.c.
This is due to the `cfg_layout_finalize` call in `bb-reorder.c` emitting
new labels for the start of the newly created basic blocks. These labels are
not given a dataflow df_insn_info member.

We solve this by manually calling `df_recompute_luids` on each basic
block once this pass has finished.

Testing done:
  Bootstrapped and regression test on aarch64-none-linux-gnu native.

gcc/ChangeLog:

2019-11-12  Matthew Malcomson  

PR middle-end/92410
* bb-reorder.c (pass_reorder_blocks::execute): Recompute
dataflow luids once basic blocks have been reordered.
* haifa-sched.c (reemit_notes): Create df insn record for each
new note.
* regstat.c (regstat_bb_compute_calls_crossed): Assert every
insn has an insn record before trying to use it.

gcc/testsuite/ChangeLog:

2019-11-12  Matthew Malcomson  

PR middle-end/92410
* gcc.dg/torture/pr92410.c: New test.



### Attachment also inlined for ease of reply###


diff --git a/gcc/bb-reorder.c b/gcc/bb-reorder.c
index 
0ac39140c6ce3db8499f99cd8f48321de61b..4943f97a2cfccc7ab7c4834fff2c81f62fc5b738
 100644
--- a/gcc/bb-reorder.c
+++ b/gcc/bb-reorder.c
@@ -2662,6 +2662,8 @@ pass_reorder_blocks::execute (function *fun)
   bb->aux = bb->next_bb;
   cfg_layout_finalize ();
 
+  FOR_EACH_BB_FN (bb, fun)
+df_recompute_luids (bb);
   return 0;
 }
 
diff --git a/gcc/haifa-sched.c b/gcc/haifa-sched.c
index 
41cf1f362e8c34d009b0a310ff5b9a9ffb613631..2e1a84f1325d54ece1cf3c6f0bab607099c71d27
 100644
--- a/gcc/haifa-sched.c
+++ b/gcc/haifa-sched.c
@@ -5433,6 +5433,7 @@ reemit_notes (rtx_insn *insn)
 
  last = emit_note_before (note_type, last);
  remove_note (insn, note);
+ df_insn_create_insn_record (last);
}
 }
 }
diff --git a/gcc/regstat.c b/gcc/regstat.c
index 
4da9b7cc523cde113df931226ea56310b659e619..c6cefb117d7330cc1b9787c37083e05e2acda2d2
 100644
--- a/gcc/regstat.c
+++ b/gcc/regstat.c
@@ -324,6 +324,7 @@ regstat_bb_compute_calls_crossed (unsigned int bb_index, 
bitmap live)
 
   FOR_BB_INSNS_REVERSE (bb, insn)
 {
+  gcc_assert (INSN_UID (insn) < DF_INSN_SIZE ());
   struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
   unsigned int regno;
 
diff --git a/gcc/testsuite/gcc.dg/torture/pr92410.c 
b/gcc/testsuite/gcc.dg/torture/pr92410.c
new file mode 100644
index 
..628e329782260ef36f26506bfbc0d36a93b33f41
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr92410.c
@@ -0,0 +1,8 @@
+/* PR middle-end/92410  */
+/* { dg-do compile } */
+int v;
+
+int a() {
+  ;
+  return v;
+}

diff --git a/gcc/bb-reorder.c b/gcc/bb-reorder.c
index 
0ac39140c6ce3db8499f99cd8f48321de61b..4943f97a2cfccc7ab7c4834fff2c81f62fc5b738
 100644
--- a/gcc/bb-reorder.c
+++ b/gcc/bb-reorder.c
@@ -2662,6 +2662,8 @@ pass_reorder_blocks::execute (function *fun)
   bb->aux = bb->next_bb;
   cfg_layout_finalize ();
 
+  FOR_EACH_BB_FN (bb, fun)
+df_recompute_luids (bb);
   return 0;
 }
 
diff --git a/gcc/haifa-sched.c b/gcc/haifa-sched.c
index 
41cf1f362e8c34d009b0a310ff5b9a9ffb613631..2e1a84f1325d54ece1cf3c6f0bab607099c71d27
 100644
--- a/gcc/haifa-sched.c
+++ b/gcc/haifa-sched.c
@@ -5433,6 +5433,7 @@ reemit_notes (rtx_insn *insn)
 
  last = emit_note_before (note_type, last);
  remove_note (insn, note);
+ df_insn_create_insn_record (last);
}
 }
 }
dif

Re: [PATCH 3/X] [libsanitizer] Add option to bootstrap using HWASAN

2019-11-13 Thread Matthew Malcomson
On 12/11/2019 12:08, Martin Liška wrote:
> On 11/11/19 5:03 PM, Matthew Malcomson wrote:
>> Ah!
>> My apologies -- I sent up a series with a few documentation mistakes.
>> (the others were wording problems so less noticeable)
> 
> That's fine, I fixed that very easily.
> 
> Right now, I can confirm using a aarch64 KVM with the following linux 
> kernel:
> 5.4.0-rc6-3.g7068448-default works. I haven't tried HWASAN bootstrap, 
> but I can
> run almost all hwasan.exp tests.
> 
> There are 2 exceptions:
> 
> FAIL: gcc.dg/hwasan/stack-tagging-basic-1.c   -O2 -flto 
> -fuse-linker-plugin -fno-fat-lto-objects  execution test
> FAIL: gcc.dg/hwasan/large-aligned-1.c   -O2 -flto -fuse-linker-plugin 
> -fno-fat-lto-objects  execution test

Wow, I have no idea how I missed that but thanks for the catch!

> 
> These fail due to unused value of a function that returns int. The 
> attached patch fixes that.
> I'm planning to make a proper comments about the series starting next week.
> 
> For the meantime, I have some libsanitizer upstream suggestions
> that you can may be discuss. It's mostly about
> shadow memory dump differences in between ASAN and HWASAN:
> 

> 
> Improvements I see:
> a) HWASAN uses less compact dump (2 spaces compared to one)
> b) HWASAN is not using colors and it would be handy to know which color 
> is used for "uninitialized" tags
>     and I would mark the 2 compares tags in dumps (ptr/mem)
> c) "Tags for short granules around the buggy address" dump is using a 
> dot notation which seems a bit misleading
> d) For HWASAN address offset is missing for each line in both shadow 
> memory and the pointer

To mention my thoughts in turn:
a) The dump of HWASAN takes more space, but represents more application
bytes for a given space on the console.
Each byte of HWASAN shadow space represents 16 application bytes
while each byte in ASAN shadow space represents 8 application bytes.
I personally appreciate the extra spacing, and figure that the 8|16
byte difference allows for this.

b) Marking 'ptr' and 'mem' in the dump sounds like a good idea to me.
Exactly how I'm not sure -- maybe with a colourscheme?  Do you have a
marking in mind?

Uninitialised shadow space has the zero tag, however, there are a few
extra details that help understanding these traces:

On the stack, zero is both uninitialized and "the background" (i.e.
the tag for anything not specially instrumented, like register spills
and parameters passed on the stack).
However, accessible tagged objects can be given a zero tag.
We allow this to avoid runtime checks when incrementing the random
frame tag to get the tag for a new local variable.
We can easily avoid the zero tag at compile-time if we don't use a
random tag for each frame.  I had this in development at one point
and found it quite useful for verification.  I already have an option
to disable random tags for each frame that this ability could go
under.
I don't believe (but am not 100% certain) this option is in LLVM.

On the heap uninitialised is tag zero, but memory that has been
`free`d is given a random tag, so non-zero in a dump does not mean a
valid object.

c) Is there an alternate notation you have in mind?
I would guess the "dots" are there to say "this granule has no
short-tag information", and I'm not sure what would be a better
way to demonstrate that.

d) I agree, an address offset annotation on each line of the shadow
memory sounds useful.

Cheers,
MM

> 
> Thanks,
> Martin
> 
>>
>> I'm attaching the entire updated patch series (with the other
>> documentation fixes in it too) and the fixed patch for just this part in
>> case you just want to compile and test right now.
> 



[Patch] [AArch64] [SVE] Implement svld1ro intrinsic.

2020-01-09 Thread Matthew Malcomson
We take no action to ensure the SVE vector size is large enough.  It is
left to the user to check that before compiling this intrinsic or before
running such a program on a machine.

The main difference between ld1ro and ld1rq is in the allowed offsets,
the implementation difference is that ld1ro is implemented using integer
modes since there are no pre-existing vector modes of the relevant size.
Adding new vector modes simply for this intrinsic seems to make the code
less tidy.

Specifications can be found under the "Arm C Language Extensions for
Scalable Vector Extension" title at
https://developer.arm.com/architectures/system-architectures/software-standards/acle

gcc/ChangeLog:

2020-01-09  Matthew Malcomson  

* config/aarch64/aarch64-protos.h
(aarch64_sve_ld1ro_operand_p): New.
* config/aarch64/aarch64-sve-builtins-base.cc
(class load_replicate): New.
(class svld1ro_impl): New.
(class svld1rq_impl): Change to inherit from load_replicate.
(svld1ro): New sve intrinsic function base.
* config/aarch64/aarch64-sve-builtins-base.def (svld1ro):
New DEF_SVE_FUNCTION.
* config/aarch64/aarch64-sve-builtins-base.h
(svld1ro): New decl.
* config/aarch64/aarch64-sve-builtins.cc
(function_expander::add_mem_operand): Modify assert to allow
OImode.
* config/aarch64/aarch64-sve.md (@aarch64_sve_ld1ro): New
pattern.
* config/aarch64/aarch64.c
(aarch64_sve_ld1rq_operand_p): Implement in terms of ...
(aarch64_sve_ld1rq_ld1ro_operand_p): This.
(aarch64_sve_ld1ro_operand_p): New.
* config/aarch64/aarch64.md (UNSPEC_LD1RO): New unspec.
* config/aarch64/constraints.md (UOb,UOh,UOw,UOd): New.
* config/aarch64/predicates.md
(aarch64_sve_ld1ro_operand_{b,h,w,d}): New.

gcc/testsuite/ChangeLog:

2020-01-09  Matthew Malcomson  

* gcc.target/aarch64/sve/acle/asm/ld1ro_f16.c: New test.
* gcc.target/aarch64/sve/acle/asm/ld1ro_f32.c: New test.
* gcc.target/aarch64/sve/acle/asm/ld1ro_f64.c: New test.
* gcc.target/aarch64/sve/acle/asm/ld1ro_s16.c: New test.
* gcc.target/aarch64/sve/acle/asm/ld1ro_s32.c: New test.
* gcc.target/aarch64/sve/acle/asm/ld1ro_s64.c: New test.
* gcc.target/aarch64/sve/acle/asm/ld1ro_s8.c: New test.
* gcc.target/aarch64/sve/acle/asm/ld1ro_u16.c: New test.
* gcc.target/aarch64/sve/acle/asm/ld1ro_u32.c: New test.
* gcc.target/aarch64/sve/acle/asm/ld1ro_u64.c: New test.
* gcc.target/aarch64/sve/acle/asm/ld1ro_u8.c: New test.



### Attachment also inlined for ease of reply###


diff --git a/gcc/config/aarch64/aarch64-protos.h 
b/gcc/config/aarch64/aarch64-protos.h
index 
c16b9362ea986ff221755bfc4d10bae674a67ed4..6d2162b93932e433677dae48e5c58975be2902d2
 100644
--- a/gcc/config/aarch64/aarch64-protos.h
+++ b/gcc/config/aarch64/aarch64-protos.h
@@ -582,6 +582,7 @@ rtx aarch64_simd_gen_const_vector_dup (machine_mode, 
HOST_WIDE_INT);
 bool aarch64_simd_mem_operand_p (rtx);
 bool aarch64_sve_ld1r_operand_p (rtx);
 bool aarch64_sve_ld1rq_operand_p (rtx);
+bool aarch64_sve_ld1ro_operand_p (rtx, scalar_mode);
 bool aarch64_sve_ldff1_operand_p (rtx);
 bool aarch64_sve_ldnf1_operand_p (rtx);
 bool aarch64_sve_ldr_operand_p (rtx);
diff --git a/gcc/config/aarch64/aarch64-sve-builtins-base.cc 
b/gcc/config/aarch64/aarch64-sve-builtins-base.cc
index 
38bd3adce1ebbde4c58531ffd26eedd4ae4938b0..e52a6012565fadd84cdd77a613f887e5ae53a576
 100644
--- a/gcc/config/aarch64/aarch64-sve-builtins-base.cc
+++ b/gcc/config/aarch64/aarch64-sve-builtins-base.cc
@@ -1139,7 +1139,7 @@ public:
   }
 };
 
-class svld1rq_impl : public function_base
+class load_replicate : public function_base
 {
 public:
   unsigned int
@@ -1153,7 +1153,11 @@ public:
   {
 return fi.scalar_type (0);
   }
+};
 
+class svld1rq_impl : public load_replicate
+{
+public:
   machine_mode
   memory_vector_mode (const function_instance &fi) const OVERRIDE
   {
@@ -1168,6 +1172,23 @@ public:
   }
 };
 
+class svld1ro_impl : public load_replicate
+{
+public:
+  machine_mode
+  memory_vector_mode (const function_instance &fi) const OVERRIDE
+  {
+return OImode;
+  }
+
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+insn_code icode = code_for_aarch64_sve_ld1ro (e.vector_mode (0));
+return e.use_contiguous_load_insn (icode);
+  }
+};
+
 /* Implements svld2, svld3 and svld4.  */
 class svld234_impl : public full_width_access
 {
@@ -2571,6 +2592,7 @@ FUNCTION (svlasta, svlast_impl, (UNSPEC_LASTA))
 FUNCTION (svlastb, svlast_impl, (UNSPEC_LASTB))
 FUNCTION (svld1, svld1_impl,)
 FUNCTION (svld1_gather, svld1_gather_impl,)
+FUNCTION (svld1ro, svld1ro_impl,)
 FUNCTION (svld1rq, svld1rq_impl,)
 FUNCTION (svld1sb, svld1_extend_impl, (TYPE_SUFFIX_s8))
 FUNCTION (svld1sb_gather, svld1_gather_extend_impl, (TYPE_SUFFIX_s8))
d

Re: Document --with-build-config=bootstrap-asan option.

2020-01-13 Thread Matthew Malcomson
On 11/01/2020 07:19, Gerald Pfeifer wrote:
> On Thu, 12 Dec 2019, Matthew Malcomson wrote:
>> gcc/ChangeLog:
>>
>> 2019-12-12  Matthew Malcomson  
>>
>>  * doc/install.texi: Document bootstrap-asan configuration option.
> 
> I see this introduces a new table.
> 
>> +Some examples of build configurations designed for developers of GCC are:
> 
> @samp{bootstrap-time}, @samp{bootstrap-debug-ckovw} and others appear
> to fall into the same camp, essentially expected to be used by maintainers
> only.
> 
> Would it make sense to add your new option to the existing table, or
> perhaps see which other options from the existing table to move into
> your new one?  Thoughts?

Sounds good me.


> 
> 
> The patch is okay modulo the question above.
> 
> Thanks,
> Gerald
> 

Patch with above suggestion.

#

diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi
index 
80b47812fe66a8ef50edf3aad9708ab3409ba7dc..0705759c69f64c6d06e91f7ae83bb8c1ad210f34
 
100644
--- a/gcc/doc/install.texi
+++ b/gcc/doc/install.texi
@@ -2668,6 +2668,10 @@ Arranges for the run time of each program started 
by the GCC driver,
  built in any stage, to be logged to @file{time.log}, in the top level of
  the build tree.

+@item @samp{bootstrap-asan}
+Compiles GCC itself using Address Sanitization in order to catch 
invalid memory
+accesses within the GCC code.
+
  @end table

  @section Building a cross compiler



Re: [PATCH 6/X] [libsanitizer] Add hwasan pass and associated gimple changes

2020-01-13 Thread Matthew Malcomson
> On 12/12/19 4:19 PM, Matthew Malcomson wrote:
>> - if (is_store && !param_asan_instrument_writes)
>> + if (is_store
>> + && (!param_asan_instrument_writes || !param_hwasan_instrument_writes))
>> return;
>> - if (!is_store && !param_asan_instrument_reads)
>> + if (!is_store
>> + && (!param_asan_instrument_reads || !param_hwasan_instrument_reads))
>> return;
> 
> I know it's very unlikely, but one can use -fsanitize=address and
> --param hwasan-instrument-reads=0 which will drop instrumentation of reads
> for ASAN.

Ah! Thanks for the catch.
Updated patch is attached and has been tested.

I've also attached the patch including the new `Optimization` keyword to the
hwasan parameters to this email -- (putting both on this email to avoid a bit of
email spam).

> 
> Similarly for other parameters.
> 
> Martin


Inlining the new bit that avoids the problem you pointed out above, since
the implementation of that is the only new part someone might object to.


###

diff --git a/gcc/asan.c b/gcc/asan.c
index 
fe6841b4f084f75be534cc9653079ca0a5bdc94e..55723bf4d5d2a4111eb574d169f21332f6eb33ff
 100644
--- a/gcc/asan.c
+++ b/gcc/asan.c
@@ -326,6 +326,25 @@ asan_sanitize_allocas_p (void)
   return (asan_sanitize_stack_p () && param_asan_protect_allocas);
 }
 
+bool
+asan_instrument_reads (void)
+{
+  return (sanitize_flags_p (SANITIZE_ADDRESS) && param_asan_instrument_reads);
+}
+
+bool
+asan_instrument_writes (void)
+{
+  return (sanitize_flags_p (SANITIZE_ADDRESS) && param_asan_instrument_writes);
+}
+
+bool
+asan_memintrin (void)
+{
+  return (sanitize_flags_p (SANITIZE_ADDRESS) && param_asan_memintrin);
+}
+
+
 /* Checks whether section SEC should be sanitized.  */
 
 static bool
@@ -1382,6 +1673,28 @@ hwasan_sanitize_allocas_p (void)
   return (hwasan_sanitize_stack_p () && param_hwasan_protect_allocas);
 }
 
+/* Should we instrument reads?  */
+bool
+hwasan_instrument_reads (void)
+{
+  return (hwasan_sanitize_p () && param_hwasan_instrument_reads);
+}
+
+/* Should we instrument writes?  */
+bool
+hwasan_instrument_writes (void)
+{
+  return (hwasan_sanitize_p () && param_hwasan_instrument_writes);
+}
+
+/* Should we instrument builtin calls?  */
+bool
+hwasan_memintrin (void)
+{
+  return (hwasan_sanitize_p () && param_hwasan_memintrin);
+}
+
+
 /* Insert code to protect stack vars.  The prologue sequence should be emitted
directly, epilogue sequence returned.  BASE is the register holding the
stack base, against which OFFSETS array offsets are relative to, OFFSETS
@@ -2220,9 +2539,9 @@ static void
 instrument_derefs (gimple_stmt_iterator *iter, tree t,
   location_t location, bool is_store)
 {
-  if (is_store && !param_asan_instrument_writes)
+  if (is_store && !(asan_instrument_writes () || hwasan_instrument_writes ()))
 return;
-  if (!is_store && !param_asan_instrument_reads)
+  if (!is_store && !(asan_instrument_reads () || hwasan_instrument_reads ()))
 return;
 
   tree type, base;
@@ -2376,7 +2696,7 @@ instrument_mem_region_access (tree base, tree len,
 static bool
 instrument_builtin_call (gimple_stmt_iterator *iter)
 {
-  if (!param_asan_memintrin)
+  if (!(asan_memintrin () || hwasan_memintrin ()))
 return false;
 
   bool iter_advanced_p = false;

diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c
index 
77649e839c968c38485ea30d332576b9b089effe..c5746e3c89283ef0652de85cf6b94e76263aba38
 100644
--- a/gcc/c-family/c-attribs.c
+++ b/gcc/c-family/c-attribs.c
@@ -54,6 +54,8 @@ static tree handle_cold_attribute (tree *, tree, tree, int, 
bool *);
 static tree handle_no_sanitize_attribute (tree *, tree, tree, int, bool *);
 static tree handle_no_sanitize_address_attribute (tree *, tree, tree,
  int, bool *);
+static tree handle_no_sanitize_hwaddress_attribute (tree *, tree, tree,
+   int, bool *);
 static tree handle_no_sanitize_thread_attribute (tree *, tree, tree,
 int, bool *);
 static tree handle_no_address_safety_analysis_attribute (tree *, tree, tree,
@@ -412,6 +414,8 @@ const struct attribute_spec c_common_attribute_table[] =
  handle_no_sanitize_attribute, NULL },
   { "no_sanitize_address",0, 0, true, false, false, false,
  handle_no_sanitize_address_attribute, NULL },
+  { "no_sanitize_hwaddress",0, 0, true, false, false, false,
+ handle_no_sanitize_hwaddress_attribute, NULL },
   { "no_sanitize_thread", 0, 0, true, false, false, false,
  handle_no_sanitize_thread_attrib

[PATCH][AArch64] Enable CLI for Armv8.6-A f64mm

2020-01-13 Thread Matthew Malcomson
This patch is necessary for sve-ld1ro intrinsic I posted in
https://gcc.gnu.org/ml/gcc-patches/2020-01/msg00466.html .

I had mistakenly thought this option was already enabled upstream.

This provides the option +f64mm, that turns on the 64 bit floating point
matrix multiply extension.  This extension is only available for
AArch64.  Turning on this extension also turns on the SVE extension.

This extension is optional and only available at Armv8.2-A and onward.

We also add the ACLE defined macro for this extension.

Tested on aarch64 cross compiler from x86.

gcc/ChangeLog:

2020-01-13  Matthew Malcomson  

* config/aarch64/aarch64-c.c (_ARM_FEATURE_MATMUL_FLOAT64):
Introduce this ACLE specified predefined macro.
* config/aarch64/aarch64-option-extensions.def (f64mm): New.
(fp): Disabling this disables f64mm.
(simd): Disabling this disables f64mm.
(fp16): Disabling this disables f64mm.
(sve): Disabling this disables f64mm.
* config/aarch64/aarch64.h (AARCH64_FL_F64MM): New.
(AARCH64_ISA_F64MM): New.
(TARGET_F64MM): New.
* doc/invoke.texi (f64mm): Document new option.

gcc/testsuite/ChangeLog:

2020-01-13  Matthew Malcomson  

* gcc.target/aarch64/pragma_cpp_predefs_2.c: Check for f64mm
predef.



### Attachment also inlined for ease of reply###


diff --git a/gcc/config/aarch64/aarch64-c.c b/gcc/config/aarch64/aarch64-c.c
index 
9ccca422b045fcd6875f192680220b2af9d59d31..22fc4a5e337acb4cdd96618b57736f55892bd0e7
 100644
--- a/gcc/config/aarch64/aarch64-c.c
+++ b/gcc/config/aarch64/aarch64-c.c
@@ -166,6 +166,7 @@ aarch64_update_cpp_builtins (cpp_reader *pfile)
   aarch64_def_or_undef (TARGET_MEMTAG, "__ARM_FEATURE_MEMORY_TAGGING", pfile);
 
   aarch64_def_or_undef (TARGET_I8MM, "__ARM_FEATURE_MATMUL_INT8", pfile);
+  aarch64_def_or_undef (TARGET_F64MM, "__ARM_FEATURE_MATMUL_FP64", pfile);
   aarch64_def_or_undef (TARGET_BF16_SIMD,
"__ARM_FEATURE_BF16_VECTOR_ARITHMETIC", pfile);
   aarch64_def_or_undef (TARGET_BF16_FP,
diff --git a/gcc/config/aarch64/aarch64-option-extensions.def 
b/gcc/config/aarch64/aarch64-option-extensions.def
index 
5022a1b3552f35364e35b3955bf2c39a33ab0752..6057b33033a0f3a8be7d656dc1e459d4d93b2842
 100644
--- a/gcc/config/aarch64/aarch64-option-extensions.def
+++ b/gcc/config/aarch64/aarch64-option-extensions.def
@@ -53,26 +53,26 @@
 /* Enabling "fp" just enables "fp".
Disabling "fp" also disables "simd", "crypto", "fp16", "aes", "sha2",
"sha3", sm3/sm4, "sve", "sve2", "sve2-aes", "sve2-sha3", "sve2-sm4",
-   "sve2-bitperm", "i8mm" and "bf16".  */
+   "sve2-bitperm", "i8mm", "f64mm", and "bf16".  */
 AARCH64_OPT_EXTENSION("fp", AARCH64_FL_FP, 0, AARCH64_FL_SIMD | \
  AARCH64_FL_CRYPTO | AARCH64_FL_F16 | AARCH64_FL_AES | \
  AARCH64_FL_SHA2 | AARCH64_FL_SHA3 | AARCH64_FL_SM4 | \
  AARCH64_FL_SVE | AARCH64_FL_SVE2 | AARCH64_FL_SVE2_AES | \
  AARCH64_FL_SVE2_SHA3 | AARCH64_FL_SVE2_SM4 | \
  AARCH64_FL_SVE2_BITPERM | AARCH64_FL_I8MM | \
- AARCH64_FL_BF16, false, "fp")
+ AARCH64_FL_F64MM | AARCH64_FL_BF16, false, "fp")
 
 /* Enabling "simd" also enables "fp".
Disabling "simd" also disables "crypto", "dotprod", "aes", "sha2", "sha3",
"sm3/sm4", "sve", "sve2", "sve2-aes", "sve2-sha3", "sve2-sm4",
-   "sve2-bitperm", and "i8mm".  */
+   "sve2-bitperm", "i8mm", and "f64mm".  */
 AARCH64_OPT_EXTENSION("simd", AARCH64_FL_SIMD, AARCH64_FL_FP, \
  AARCH64_FL_CRYPTO | AARCH64_FL_DOTPROD | \
  AARCH64_FL_AES | AARCH64_FL_SHA2 | AARCH64_FL_SHA3 | \
  AARCH64_FL_SM4 | AARCH64_FL_SVE | AARCH64_FL_SVE2 | \
  AARCH64_FL_SVE2_AES | AARCH64_FL_SVE2_SHA3 | \
  AARCH64_FL_SVE2_SM4 | AARCH64_FL_SVE2_BITPERM | \
- AARCH64_FL_I8MM, false, \
+ AARCH64_FL_I8MM | AARCH64_FL_F64MM, false, \
  "asimd")
 
 /* Enabling "crypto" also enables "fp", "simd", "aes" and "sha2".
@@ -92,12 +92,13 @@ AARCH64_OPT_EXTENSION("crc", AARCH64_FL_CRC, 0, 0, false, 
"crc32")
 AARCH64_OPT_EXTENSION("lse", AARCH64_FL_LSE, 0, 0, false, "atomics")
 
 /* Enabling "fp16" also enables &q

Re: [Patch] [AArch64] [SVE] Implement svld1ro intrinsic.

2020-01-20 Thread Matthew Malcomson
On 20/01/2020 14:53, Christophe Lyon wrote:
> On Thu, 9 Jan 2020 at 16:53, Matthew Malcomson
>  wrote:
>>
>> +   (match_test "aarch64_sve_ld1ro_operand_p (op, DImode)")))
>> +
> 
> 
>>   (define_predicate "aarch64_sve_ldff1_operand"
>> (and (match_code "mem")
> 
>>  (match_test "aarch64_sve_ldff1_operand_p (op)")))
> 
> 
> Hi,
> 
>> diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_f16.c 
>> b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_f16.c
>> new file mode 100644
>> index 
>> ..7badc75a43ab2009e9406afc04c980fc01834716
>> --- /dev/null
>> +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_f16.c
>> @@ -0,0 +1,119 @@
>> +/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
>> +/* { dg-additional-options "-march=armv8.6-a+sve+f64mm" } */
> 
> What is the binutils version requirement for this?
> Some validations using binutils-2.33.1 exhibit failures like:
> /xgcc 
> -B/aci-gcc-fsf/builds/gcc-fsf-gccsrc/obj-aarch64-none-linux-gnu/gcc3/gcc/
> -fno-diagnostics-show-caret -fno-diagnostics-show-line-numbers
> -fdiagnostics-color=never -fdiagnostics-urls=never -std=c90 -O0 -g
> -DTEST_FULL -march=armv8.2-a+sve -fno-ipa-icf
> -march=armv8.6-a+sve+f64mm -c -o ld1ro_s16.o
> /gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_s16.c
> Assembler messages:
> Error: unknown architecture `armv8.6-a+sve+f64mm'
> 
> Error: unrecognized option -march=armv8.6-a+sve+f64mm
> compiler exited with status 1
> FAIL: gcc.target/aarch64/sve/acle/asm/ld1ro_s16.c  -std=c90 -O0 -g
> -DTEST_FULL  1 blank line(s) in output
> FAIL: gcc.target/aarch64/sve/acle/asm/ld1ro_s16.c  -std=c90 -O0 -g
> -DTEST_FULL (test for excess errors)
> Excess errors:
> Assembler messages:
> Error: unknown architecture `armv8.6-a+sve+f64mm'
> Error: unrecognized option -march=armv8.6-a+sve+f64mm
> 
> 
> while other configurations using 2.32 binutils seem to pass this test:
> /xgcc 
> -B/home/tcwg-buildslave/workspace/tcwg-buildfarm__0/_build/builds/aarch64-unknown-linux-gnu/aarch64-unknown-linux-gnu/gcc.git~master_rev_3684bbb022cd75da55e1457673f269980aa12cdf-stage2/gcc/
> /home/tcwg-buildslave/workspace/tcwg-buildfarm__0/snapshots/gcc.git~master_rev_3684bbb022cd75da55e1457673f269980aa12cdf/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_f16.c
> -fno-diagnostics-show-caret -fno-diagnostics-show-line-numbers
> -fdiagnostics-color=never -fdiagnostics-urls=never -std=c90 -O0 -g
> -DTEST_FULL -march=armv8.2-a+sve -fno-ipa-icf
> -march=armv8.6-a+sve+f64mm -S -o ld1ro_f16.s
> PASS: gcc.target/aarch64/sve/acle/asm/ld1ro_f16.c  -std=c90 -O0 -g
> -DTEST_FULL (test for excess errors)
> 
> Ha... took me a while to realize that in the latter case we stop after
> generating the .s file and do not call the assembler...
> 
> 
> So... do we want/need additional consistency checks between gcc and
> gas versions?
> 

Ah! Yes, that should certainly be done.
I'll start that now.

Thanks for pointing it out -- it seems I really did not take enough care 
with this patch...

MM

> 
> Thanks,
> 
> Christophe
> 
> 
>> +



[AArch64] effective_target for aarch64 f64mm asm

2020-01-21 Thread Matthew Malcomson
Commit 9ceec73 introduced intrinsics for the AArch64 FP64 matrix
multiply instructions.  These require binutils support for the same
instructions.
( See https://gcc.gnu.org/ml/gcc-patches/2020-01/msg01234.html for the
testsuite failures this introduced. )

This patch adds a DejaGNU test to ensure this binutils support is there
and uses it in the files that need this test.

NOTE:
I tried to find some way to run the assembly tests if the given version
of binutils is available, but run the compile tests if not.  This is
pretty awkward -- It seems I either have to duplicate all the DejaGNU
comments between two files, or write filename exceptions into the
list of files that aarch64-sve-acle-asm.exp runs tests for.

I decided to not do either, since I figure not running the tests on
older binutils isn't too bad compared to having a bunch more DejaGNU
stuff making the tests harder to read.

Testing Done:
Checked on a cross-compiler that:
Tests running for binutils commit e264b5b7a are listed as UNSUPPORTED.
Tests running for binutils commit 26916852e all pass.

gcc/testsuite/ChangeLog:

2020-01-21  Matthew Malcomson  

* gcc.target/aarch64/sve/acle/asm/ld1ro_f16.c: Use require
directive.
* gcc.target/aarch64/sve/acle/asm/ld1ro_f32.c: Likewise.
* gcc.target/aarch64/sve/acle/asm/ld1ro_f64.c: Likewise.
* gcc.target/aarch64/sve/acle/asm/ld1ro_s16.c: Likewise.
* gcc.target/aarch64/sve/acle/asm/ld1ro_s32.c: Likewise.
* gcc.target/aarch64/sve/acle/asm/ld1ro_s64.c: Likewise.
* gcc.target/aarch64/sve/acle/asm/ld1ro_s8.c: Likewise.
* gcc.target/aarch64/sve/acle/asm/ld1ro_u16.c: Likewise.
* gcc.target/aarch64/sve/acle/asm/ld1ro_u32.c: Likewise.
* gcc.target/aarch64/sve/acle/asm/ld1ro_u64.c: Likewise.
* gcc.target/aarch64/sve/acle/asm/ld1ro_u8.c: Likewise.
* lib/target-supports.exp: Add assembly requirement directive.



### Attachment also inlined for ease of reply###


diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_f16.c 
b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_f16.c
index 
7badc75a43ab2009e9406afc04c980fc01834716..6eb94f1ca5fda961bb23f5c4cf66bc5694d26f36
 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_f16.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_f16.c
@@ -1,5 +1,6 @@
 /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
 /* { dg-additional-options "-march=armv8.6-a+sve+f64mm" } */
+/* { dg-require-effective-target aarch64_asm_f64mm_ok }  */
 
 #include "test_sve_acle.h"
 
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_f32.c 
b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_f32.c
index 
dd8a1c53cd0fb7b7acd0b92394f3977382ac26e0..0a77c37ddd5978db765b4bad23f24da82a0aed11
 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_f32.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_f32.c
@@ -1,5 +1,6 @@
 /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
 /* { dg-additional-options "-march=armv8.6-a+sve+f64mm" } */
+/* { dg-require-effective-target aarch64_asm_f64mm_ok }  */
 
 #include "test_sve_acle.h"
 
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_f64.c 
b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_f64.c
index 
30563698310f65060d34be4bef4c57a74ef9d734..65c6d9b02b804a1480cd5014c8f0ca5f534bacbe
 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_f64.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_f64.c
@@ -1,5 +1,6 @@
 /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
 /* { dg-additional-options "-march=armv8.6-a+sve+f64mm" } */
+/* { dg-require-effective-target aarch64_asm_f64mm_ok }  */
 
 #include "test_sve_acle.h"
 
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_s16.c 
b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_s16.c
index 
d4702fa6cc15e9f93751d8579cfecfd37759306e..e3dc9bd51cf93c2f97e4277181e686d0bf53a1ea
 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_s16.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_s16.c
@@ -1,5 +1,6 @@
 /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
 /* { dg-additional-options "-march=armv8.6-a+sve+f64mm" } */
+/* { dg-require-effective-target aarch64_asm_f64mm_ok }  */
 
 #include "test_sve_acle.h"
 
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_s32.c 
b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_s32.c
index 
4604b0b5fbfb716ae814bf88f7acfe8bf0eaa9f5..f3af8e5cc25791a56930618abf5c092d51e94e9b
 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_s32.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_s32.c
@@ -1,5 +1,6 

Re: [mid-end] Add notes to dataflow insn info when re-emitting (PR92410)

2019-12-09 Thread Matthew Malcomson
Ah,  apologies -- you're right.
I'd already committed the patch this morning, so I'll update it with the 
obvious fix.

Thanks for the catch,
Matthew

On 09/12/2019 12:48, Martin Liška wrote:
> Hello.
> 
> The patch triggers the following warning:
> 
> In file included from /home/marxin/Programming/gcc/gcc/regstat.c:23:
> /home/marxin/Programming/gcc/gcc/regstat.c: In function ‘void 
> regstat_bb_compute_calls_crossed(unsigned int, bitmap)’:
> /home/marxin/Programming/gcc/gcc/regstat.c:327:35: warning: comparison 
> of integer expressions of different signedness: ‘int’ and ‘unsigned int’ 
> [-Wsign-compare]
>    327 |   gcc_assert (INSN_UID (insn) < DF_INSN_SIZE ());
> /home/marxin/Programming/gcc/gcc/system.h:748:14: note: in definition of 
> macro ‘gcc_assert’
>    748 |    ((void)(!(EXPR) ? fancy_abort (__FILE__, __LINE__, 
> __FUNCTION__), 0 : 0))
>    |  ^~~~
> 
> What about something like:
> 
>   gcc/regstat.c | 2 +-
>   1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/gcc/regstat.c b/gcc/regstat.c
> index c6cefb117d7..035d48c28ab 100644
> --- a/gcc/regstat.c
> +++ b/gcc/regstat.c
> @@ -324,7 +324,7 @@ regstat_bb_compute_calls_crossed (unsigned int 
> bb_index, bitmap live)
> 
>     FOR_BB_INSNS_REVERSE (bb, insn)
>   {
> -  gcc_assert (INSN_UID (insn) < DF_INSN_SIZE ());
> +  gcc_assert (INSN_UID (insn) < (int)DF_INSN_SIZE ());
>     struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
>     unsigned int regno;
> 
> Martin



Re: [mid-end] Add notes to dataflow insn info when re-emitting (PR92410)

2019-12-09 Thread Matthew Malcomson
Ah,  apologies -- you're right.
I'd already committed the patch this morning, so I'll update it with the 
obvious fix.

Thanks for the catch,
Matthew

On 09/12/2019 12:48, Martin Liška wrote:
> Hello.
> 
> The patch triggers the following warning:
> 
> In file included from /home/marxin/Programming/gcc/gcc/regstat.c:23:
> /home/marxin/Programming/gcc/gcc/regstat.c: In function ‘void 
> regstat_bb_compute_calls_crossed(unsigned int, bitmap)’:
> /home/marxin/Programming/gcc/gcc/regstat.c:327:35: warning: comparison 
> of integer expressions of different signedness: ‘int’ and ‘unsigned int’ 
> [-Wsign-compare]
>    327 |   gcc_assert (INSN_UID (insn) < DF_INSN_SIZE ());
> /home/marxin/Programming/gcc/gcc/system.h:748:14: note: in definition of 
> macro ‘gcc_assert’
>    748 |    ((void)(!(EXPR) ? fancy_abort (__FILE__, __LINE__, 
> __FUNCTION__), 0 : 0))
>    |  ^~~~
> 
> What about something like:
> 
>   gcc/regstat.c | 2 +-
>   1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/gcc/regstat.c b/gcc/regstat.c
> index c6cefb117d7..035d48c28ab 100644
> --- a/gcc/regstat.c
> +++ b/gcc/regstat.c
> @@ -324,7 +324,7 @@ regstat_bb_compute_calls_crossed (unsigned int 
> bb_index, bitmap live)
> 
>     FOR_BB_INSNS_REVERSE (bb, insn)
>   {
> -  gcc_assert (INSN_UID (insn) < DF_INSN_SIZE ());
> +  gcc_assert (INSN_UID (insn) < (int)DF_INSN_SIZE ());
>     struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
>     unsigned int regno;
> 
> Martin



Re: [PATCH] bring -Warray-bounds closer to -Wstringop-overflow (PR91647, 91463, 91679)

2019-12-09 Thread Matthew Malcomson
On 01/11/2019 21:09, Martin Sebor wrote:
> diff --git a/gcc/gimple-match-head.c b/gcc/gimple-match-head.c
> index 53278168a59..d7c74a1865a 100644
> --- a/gcc/gimple-match-head.c
> +++ b/gcc/gimple-match-head.c
> @@ -837,8 +837,8 @@ try_conditional_simplification (internal_fn ifn, 
> gimple_match_op *res_op,
> gimple_match_op cond_op (gimple_match_cond (res_op->ops[0],
> res_op->ops[num_ops - 1]),
>  op, res_op->type, num_ops - 2);
> -  for (unsigned int i = 1; i < num_ops - 1; ++i)
> -cond_op.ops[i - 1] = res_op->ops[i];
> +
> +  memcpy (cond_op.ops, res_op->ops + 1, (num_ops - 1) * sizeof *cond_op.ops);
> switch (num_ops - 2)
>   {
>   case 2:

I think this copies one extra element than the original code.

(copying `num_ops - 1` elements, while the previous loop only copied 
`num_ops - 2` elements since the counter started at 1).


[PATCH 2/X] [libsanitizer] Only build libhwasan when targeting AArch64

2019-12-12 Thread Matthew Malcomson
Though the library has limited support for x86, we don't have any
support for generating code targeting x86 so there is no point building
for that target.

libsanitizer/ChangeLog:

2019-12-12  Matthew Malcomson  

* Makefile.am: Condition building hwasan directory.
* Makefile.in: Regenerate.
* configure: Regenerate.
* configure.ac: Set HWASAN_SUPPORTED based on target
architecture.
* configure.tgt: Likewise.



### Attachment also inlined for ease of reply###


diff --git a/libsanitizer/Makefile.am b/libsanitizer/Makefile.am
index 
2a7e8e1debe838719db0f0fad218b2543cc3111b..065a65e78d49f7689a01ecb64db1f07ca83aa987
 100644
--- a/libsanitizer/Makefile.am
+++ b/libsanitizer/Makefile.am
@@ -14,7 +14,7 @@ endif
 if LIBBACKTRACE_SUPPORTED
 SUBDIRS += libbacktrace
 endif
-SUBDIRS += lsan asan ubsan hwasan
+SUBDIRS += lsan asan ubsan
 nodist_saninclude_HEADERS += \
   include/sanitizer/lsan_interface.h \
   include/sanitizer/asan_interface.h \
@@ -23,6 +23,9 @@ nodist_saninclude_HEADERS += \
 if TSAN_SUPPORTED
 SUBDIRS += tsan
 endif
+if HWASAN_SUPPORTED
+SUBDIRS += hwasan
+endif
 endif
 
 ## May be used by toolexeclibdir.
diff --git a/libsanitizer/Makefile.in b/libsanitizer/Makefile.in
index 
36aa952af7e04bc0e4fb94cdcd584d539193d781..75a99491cb1d4422fd5e2d93cae93eb883ae0963
 100644
--- a/libsanitizer/Makefile.in
+++ b/libsanitizer/Makefile.in
@@ -97,6 +97,7 @@ target_triplet = @target@
 @SANITIZER_SUPPORTED_TRUE@@USING_MAC_INTERPOSE_FALSE@am__append_2 = 
interception
 @LIBBACKTRACE_SUPPORTED_TRUE@@SANITIZER_SUPPORTED_TRUE@am__append_3 = 
libbacktrace
 @SANITIZER_SUPPORTED_TRUE@@TSAN_SUPPORTED_TRUE@am__append_4 = tsan
+@HWASAN_SUPPORTED_TRUE@@SANITIZER_SUPPORTED_TRUE@am__append_5 = hwasan
 subdir = .
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
 am__aclocal_m4_deps = $(top_srcdir)/../config/acx.m4 \
@@ -207,7 +208,7 @@ ETAGS = etags
 CTAGS = ctags
 CSCOPE = cscope
 DIST_SUBDIRS = sanitizer_common interception libbacktrace lsan asan \
-   ubsan hwasan tsan
+   ubsan tsan hwasan
 ACLOCAL = @ACLOCAL@
 ALLOC_FILE = @ALLOC_FILE@
 AMTAR = @AMTAR@
@@ -363,7 +364,7 @@ sanincludedir = 
$(libdir)/gcc/$(target_alias)/$(gcc_version)/include/sanitizer
 nodist_saninclude_HEADERS = $(am__append_1)
 @SANITIZER_SUPPORTED_TRUE@SUBDIRS = sanitizer_common $(am__append_2) \
 @SANITIZER_SUPPORTED_TRUE@ $(am__append_3) lsan asan ubsan \
-@SANITIZER_SUPPORTED_TRUE@ hwasan $(am__append_4)
+@SANITIZER_SUPPORTED_TRUE@ $(am__append_4) $(am__append_5)
 gcc_version := $(shell @get_gcc_base_ver@ $(top_srcdir)/../gcc/BASE-VER)
 
 # Work around what appears to be a GNU make bug handling MAKEFLAGS
diff --git a/libsanitizer/configure b/libsanitizer/configure
index 
ff72af73e6f77aaf93bf39e6799f896851a377dd..4e95194fe3567b1227c4036c2f5bf6540f735975
 100755
--- a/libsanitizer/configure
+++ b/libsanitizer/configure
@@ -659,6 +659,8 @@ link_libubsan
 link_libtsan
 link_libhwasan
 link_libasan
+HWASAN_SUPPORTED_FALSE
+HWASAN_SUPPORTED_TRUE
 LSAN_SUPPORTED_FALSE
 LSAN_SUPPORTED_TRUE
 TSAN_SUPPORTED_FALSE
@@ -12335,7 +12337,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 12338 "configure"
+#line 12340 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -12441,7 +12443,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 12444 "configure"
+#line 12446 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -15792,6 +15794,7 @@ fi
 # Get target configury.
 unset TSAN_SUPPORTED
 unset LSAN_SUPPORTED
+unset HWASAN_SUPPORTED
 . ${srcdir}/configure.tgt
  if test "x$TSAN_SUPPORTED" = "xyes"; then
   TSAN_SUPPORTED_TRUE=
@@ -15809,6 +15812,14 @@ else
   LSAN_SUPPORTED_FALSE=
 fi
 
+ if test "x$HWASAN_SUPPORTED" = "xyes"; then
+  HWASAN_SUPPORTED_TRUE=
+  HWASAN_SUPPORTED_FALSE='#'
+else
+  HWASAN_SUPPORTED_TRUE='#'
+  HWASAN_SUPPORTED_FALSE=
+fi
+
 
 # Check for functions needed.
 for ac_func in clock_getres clock_gettime clock_settime lstat readlink
@@ -16791,7 +16802,7 @@ ac_config_files="$ac_config_files Makefile 
libsanitizer.spec libbacktrace/backtr
 ac_config_headers="$ac_config_headers config.h"
 
 
-ac_config_files="$ac_config_files interception/Makefile 
sanitizer_common/Makefile libbacktrace/Makefile lsan/Makefile asan/Makefile 
hwasan/Makefile ubsan/Makefile"
+ac_config_files="$ac_config_files interception/Makefile 
sanitizer_common/Makefile libbacktrace/Makefile lsan/Makefile asan/Makefile 
ubsan/Makefile"
 
 
 if test "x$TSAN_SUPPORTED" = "xyes"; then
@@ -16799,6 +16810,11 @@ if test "x$TSAN_SUPPORTED" = "xyes"; then
 
 fi
 
+if test "x$HWASAN_SUPPOR

[PATCH 4/X] [libsanitizer][options] Add hwasan flags and argument parsing

2019-12-12 Thread Matthew Malcomson
These flags can't be used at the same time as any of the other
sanitizers.
We add an equivalent flag to -static-libasan in -static-libhwasan to
ensure static linking.

The -fsanitize=kernel-hwaddress option is for compiling targeting the
kernel.  This flag has defaults that allow compiling KASAN with tags as
it is currently implemented.
These defaults are that we do not sanitize variables on the stack and
always recover from a detected bug.
Stack tagging in the kernel is a future aim, stack instrumentation has
not yet been enabled for the kernel for clang either
(https://lists.infradead.org/pipermail/linux-arm-kernel/2019-October/687121.html).

We introduce a backend hook `targetm.memtag.can_tag_addresses` that
indicates to the mid-end whether a target has a feature like AArch64 TBI
where the top byte of an address is ignored.
Without this feature hwasan sanitization is not done.

gcc/ChangeLog:

2019-12-12  Matthew Malcomson  

* common.opt (flag_sanitize_recover): Default for kernel
hwaddress.
(static-libhwasan): New cli option.
* config/aarch64/aarch64.c (aarch64_can_tag_addresses): New.
(TARGET_MEMTAG_CAN_TAG_ADDRESSES): New.
* config/gnu-user.h (LIBHWASAN_EARLY_SPEC): hwasan equivalent of
asan command line flags.
* cppbuiltin.c (define_builtin_macros_for_compilation_flags):
Add hwasan equivalent of __SANITIZE_ADDRESS__.
* doc/tm.texi: Document new hook.
* doc/tm.texi.in: Document new hook.
* flag-types.h (enum sanitize_code): New sanitizer values.
* gcc.c (STATIC_LIBHWASAN_LIBS): New macro.
(LIBHWASAN_SPEC): New macro.
(LIBHWASAN_EARLY_SPEC): New macro.
(SANITIZER_EARLY_SPEC): Update to include hwasan.
(SANITIZER_SPEC): Update to include hwasan.
(sanitize_spec_function): Use hwasan options.
* opts.c (finish_options): Describe conflicts between address
sanitizers.
(sanitizer_opts): Introduce new sanitizer flags.
(common_handle_option): Add defaults for kernel sanitizer.
* params.opt (hwasan-stack): New
(hwasan-random-frame-tag): New
(hwasan-instrument-allocas): New
(hwasan-instrument-reads): New
(hwasan-instrument-writes): New
(hwasan-memintrin): New
* target.def (HOOK_PREFIX): Add new hook.
* targhooks.c (default_memtag_can_tag_addresses): New.
* toplev.c (process_options): Ensure hwasan only on TBI
architectures.

gcc/c-family/ChangeLog:

2019-12-12  Matthew Malcomson  

* c-attribs.c (handle_no_sanitize_hwaddress_attribute): New
attribute.



### Attachment also inlined for ease of reply###


diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c
index 
dc56e2ec62ffc7f494cc59ddf02452ac0cb406de..81f8dfc6dd3f54067d7cc0def3c0babc03bcd9c4
 100644
--- a/gcc/c-family/c-attribs.c
+++ b/gcc/c-family/c-attribs.c
@@ -54,6 +54,8 @@ static tree handle_cold_attribute (tree *, tree, tree, int, 
bool *);
 static tree handle_no_sanitize_attribute (tree *, tree, tree, int, bool *);
 static tree handle_no_sanitize_address_attribute (tree *, tree, tree,
  int, bool *);
+static tree handle_no_sanitize_hwaddress_attribute (tree *, tree, tree,
+   int, bool *);
 static tree handle_no_sanitize_thread_attribute (tree *, tree, tree,
 int, bool *);
 static tree handle_no_address_safety_analysis_attribute (tree *, tree, tree,
@@ -412,6 +414,8 @@ const struct attribute_spec c_common_attribute_table[] =
  handle_no_sanitize_attribute, NULL },
   { "no_sanitize_address",0, 0, true, false, false, false,
  handle_no_sanitize_address_attribute, NULL },
+  { "no_sanitize_hwaddress",0, 0, true, false, false, false,
+ handle_no_sanitize_hwaddress_attribute, NULL },
   { "no_sanitize_thread", 0, 0, true, false, false, false,
  handle_no_sanitize_thread_attribute, NULL },
   { "no_sanitize_undefined",  0, 0, true, false, false, false,
@@ -946,6 +950,22 @@ handle_no_sanitize_address_attribute (tree *node, tree 
name, tree, int,
   return NULL_TREE;
 }
 
+/* Handle a "no_sanitize_hwaddress" attribute; arguments as in
+   struct attribute_spec.handler.  */
+
+static tree
+handle_no_sanitize_hwaddress_attribute (tree *node, tree name, tree, int,
+ bool *no_add_attrs)
+{
+  *no_add_attrs = true;
+  if (TREE_CODE (*node) != FUNCTION_DECL)
+warning (OPT_Wattributes, "%qE attribute ignored", name);
+  else
+add_no_sanitize_value (*node, SANITIZE_HWADDRESS);
+
+  return NULL_TREE;
+}
+
 /* Handle a "no_sanitize_thread" attribute; arguments as in
struct

[Patch 0/X] HWASAN v3

2019-12-12 Thread Matthew Malcomson
Hello,

I've gone through the suggestions Martin made and implemented  the ones I think
I can implement for GCC10.

The two functionality changes in this version are:
Added the --param's hwasan-instrument-reads, hwasan-instrument-writes,
hwasan-instrument-allocas, hwasan-memintrin, options.  I.e. Those that asan has
and that make sense for hwasan.

Avoided HWASAN_STACK_BACKGROUND in hwasan_increment_tag when using a
deterministic tagging approach.


There are a lot of extra comments and tests.


Bootstrapped and regtested on x86_64 and AArch64.
Bootstrapped with `--with-build-config=bootstrap-hwasan` on AArch64 and hwasan
features tested there.
Built the linux kernel using this feature and ran the test_kasan.ko testing to
check the this works for the kernel.
(NOTE: I actually did all the above testing before a search and replace of
`memory_tagging_p` for `hwasan_sanitize_p` and fixing a typo in the
`hwasan-instrument-allocas` parameter name, I will run all the tests again
before committing but figure I'll send this out now since I fully expect the
tests to still pass).


I noticed one extra testsuite failure from those mentioned in the previous
version emails: g++.dg/cpp2a/ucn2.C.
I believe this is HWASAN correctly catching a problem in the compiler.
I've logged the issue here https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92919 .


I haven't gotten ASAN_MARK to print as HWASAN_MARK when using memory tagging,
since I'm not sure the way I found to implement this would be acceptable.  The
inlined patch below works but it requires a special declaration instead of just
an ~#include~.


diff --git a/gcc/internal-fn.h b/gcc/internal-fn.h
index a1bc081..d81eb12 100644
--- a/gcc/internal-fn.h
+++ b/gcc/internal-fn.h
@@ -101,10 +101,16 @@ extern void init_internal_fns ();
 
 extern const char *const internal_fn_name_array[];
 
+
+extern bool hwasan_sanitize_p (void);
 static inline const char *
 internal_fn_name (enum internal_fn fn)
 {
-  return internal_fn_name_array[(int) fn];
+  const char *ret = internal_fn_name_array[(int) fn];
+  if (! strcmp (ret, "ASAN_MARK")
+  && hwasan_sanitize_p ())
+return "HWASAN_MARK";
+  return ret;
 }
 
 extern internal_fn lookup_internal_fn (const char *);


Entire patch series attached to cover letter.

all-patches.tar.gz
Description: all-patches.tar.gz


[PATCH 3/X] [libsanitizer] Add option to bootstrap using HWASAN

2019-12-12 Thread Matthew Malcomson
This is an analogous option to --bootstrap-asan to configure.  It allows
bootstrapping GCC using HWASAN.

For the same reasons as for ASAN we have to avoid using the HWASAN
sanitizer when compiling libiberty and the lto-plugin.

Also add a function to query whether -fsanitize=hwaddress has been
passed.

ChangeLog:

2019-08-29  Matthew Malcomson  

* configure: Regenerate.
* configure.ac: Add --bootstrap-hwasan option.

config/ChangeLog:

2019-12-12  Matthew Malcomson  

* bootstrap-hwasan.mk: New file.

libiberty/ChangeLog:

2019-12-12  Matthew Malcomson  

* configure: Regenerate.
* configure.ac: Avoid using sanitizer.

lto-plugin/ChangeLog:

2019-12-12  Matthew Malcomson  

* Makefile.am: Avoid using sanitizer.
* Makefile.in: Regenerate.



### Attachment also inlined for ease of reply###


diff --git a/config/bootstrap-hwasan.mk b/config/bootstrap-hwasan.mk
new file mode 100644
index 
..4f60bed3fd6e98b47a3a38aea6eba2a7c320da25
--- /dev/null
+++ b/config/bootstrap-hwasan.mk
@@ -0,0 +1,8 @@
+# This option enables -fsanitize=hwaddress for stage2 and stage3.
+
+STAGE2_CFLAGS += -fsanitize=hwaddress
+STAGE3_CFLAGS += -fsanitize=hwaddress
+POSTSTAGE1_LDFLAGS += -fsanitize=hwaddress -static-libhwasan \
+ -B$$r/prev-$(TARGET_SUBDIR)/libsanitizer/ \
+ -B$$r/prev-$(TARGET_SUBDIR)/libsanitizer/hwasan/ \
+ -B$$r/prev-$(TARGET_SUBDIR)/libsanitizer/hwasan/.libs
diff --git a/configure b/configure
index 
aec9186b2b0123d3088b69eb1ee541567654953e..6f71b111bd18ec053180beecf83dd4549e83c2b9
 100755
--- a/configure
+++ b/configure
@@ -7270,7 +7270,7 @@ fi
 # or bootstrap-ubsan, bootstrap it.
 if echo " ${target_configdirs} " | grep " libsanitizer " > /dev/null 2>&1; then
   case "$BUILD_CONFIG" in
-*bootstrap-asan* | *bootstrap-ubsan* )
+*bootstrap-hwasan* | *bootstrap-asan* | *bootstrap-ubsan* )
   bootstrap_target_libs=${bootstrap_target_libs}target-libsanitizer,
   bootstrap_fixincludes=yes
   ;;
diff --git a/configure.ac b/configure.ac
index 
b8ce2ad20b9d03e42731252a9ec2a8417c13e566..16bfdf164555dad94c789f17b6a63ba1a2e3e9f4
 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2775,7 +2775,7 @@ fi
 # or bootstrap-ubsan, bootstrap it.
 if echo " ${target_configdirs} " | grep " libsanitizer " > /dev/null 2>&1; then
   case "$BUILD_CONFIG" in
-*bootstrap-asan* | *bootstrap-ubsan* )
+*bootstrap-hwasan* | *bootstrap-asan* | *bootstrap-ubsan* )
   bootstrap_target_libs=${bootstrap_target_libs}target-libsanitizer,
   bootstrap_fixincludes=yes
   ;;
diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi
index 
6c9579bfaff955eb43875b404fb7db1a667bf522..da9a8809c3440827ac22ef6936e080820197f4e7
 100644
--- a/gcc/doc/install.texi
+++ b/gcc/doc/install.texi
@@ -2645,6 +2645,13 @@ Some examples of build configurations designed for 
developers of GCC are:
 Compiles GCC itself using Address Sanitization in order to catch invalid memory
 accesses within the GCC code.
 
+@item @samp{bootstrap-hwasan}
+Compiles GCC itself using HWAddress Sanitization in order to catch invalid
+memory accesses within the GCC code.  This option is only available on AArch64
+targets with a very recent linux kernel (5.4 or later).
+
+@end table
+
 @section Building a cross compiler
 
 When building a cross compiler, it is not generally possible to do a
diff --git a/libiberty/configure b/libiberty/configure
index 
7a34dabec32b0b383bd33f07811757335f4dd39c..cb2dd4ff5295598343cc18b3a79a86a778f2261d
 100755
--- a/libiberty/configure
+++ b/libiberty/configure
@@ -5261,6 +5261,7 @@ fi
 NOASANFLAG=
 case " ${CFLAGS} " in
   *\ -fsanitize=address\ *) NOASANFLAG=-fno-sanitize=address ;;
+  *\ -fsanitize=hwaddress\ *) NOASANFLAG=-fno-sanitize=hwaddress ;;
 esac
 
 
diff --git a/libiberty/configure.ac b/libiberty/configure.ac
index 
f1ce76010c9acde79c5dc46686a78b2e2f19244e..043237628b79cbf37d07359b59c5ffe17a7a22ef
 100644
--- a/libiberty/configure.ac
+++ b/libiberty/configure.ac
@@ -240,6 +240,7 @@ AC_SUBST(PICFLAG)
 NOASANFLAG=
 case " ${CFLAGS} " in
   *\ -fsanitize=address\ *) NOASANFLAG=-fno-sanitize=address ;;
+  *\ -fsanitize=hwaddress\ *) NOASANFLAG=-fno-sanitize=hwaddress ;;
 esac
 AC_SUBST(NOASANFLAG)
 
diff --git a/lto-plugin/Makefile.am b/lto-plugin/Makefile.am
index 
28dc21014b2e86988fa88adabd63ce6092e18e02..34aa397d785e3cc9b6975de460d065900364c3ff
 100644
--- a/lto-plugin/Makefile.am
+++ b/lto-plugin/Makefile.am
@@ -11,8 +11,8 @@ AM_CPPFLAGS = -I$(top_srcdir)/../include $(DEFS)
 AM_CFLAGS = @ac_lto_plugin_warn_cflags@
 AM_LDFLAGS = @ac_lto_plugin_ldflags@
 AM_LIBTOOLFLAGS = --tag=disable-static
-override CFLAGS := $(filter-out -fsanitize=address,$(CFLAGS))
-override LDFLAGS := $(filter-out -fsanitize=address,$(LDFLAGS))
+override CFLAGS :

[PATCH 1/X] [libsanitizer] Tie the hwasan library into our build system

2019-12-12 Thread Matthew Malcomson
This patch tries to tie libhwasan into the GCC build system in the same way
that the other sanitizer runtime libraries are handled.

libsanitizer/ChangeLog:

2019-12-12  Matthew Malcomson  

* Makefile.am:  Build libhwasan.
* Makefile.in:  Build libhwasan.
* asan/Makefile.in:  Build libhwasan.
* configure:  Build libhwasan.
* configure.ac:  Build libhwasan.
* hwasan/Makefile.am: New file.
* hwasan/Makefile.in: New file.
* hwasan/libtool-version: New file.
* interception/Makefile.in: Build libhwasan.
* libbacktrace/Makefile.in: Build libhwasan.
* libsanitizer.spec.in: Build libhwasan.
* lsan/Makefile.in: Build libhwasan.
* merge.sh: Build libhwasan.
* sanitizer_common/Makefile.in: Build libhwasan.
* tsan/Makefile.in: Build libhwasan.
* ubsan/Makefile.in: Build libhwasan.



### Attachment also inlined for ease of reply###


diff --git a/libsanitizer/Makefile.am b/libsanitizer/Makefile.am
index 
65ed1e712378ef453f820f86c4d3221f9dee5f2c..2a7e8e1debe838719db0f0fad218b2543cc3111b
 100644
--- a/libsanitizer/Makefile.am
+++ b/libsanitizer/Makefile.am
@@ -14,11 +14,12 @@ endif
 if LIBBACKTRACE_SUPPORTED
 SUBDIRS += libbacktrace
 endif
-SUBDIRS += lsan asan ubsan
+SUBDIRS += lsan asan ubsan hwasan
 nodist_saninclude_HEADERS += \
   include/sanitizer/lsan_interface.h \
   include/sanitizer/asan_interface.h \
-  include/sanitizer/tsan_interface.h
+  include/sanitizer/tsan_interface.h \
+  include/sanitizer/hwasan_interface.h
 if TSAN_SUPPORTED
 SUBDIRS += tsan
 endif
diff --git a/libsanitizer/Makefile.in b/libsanitizer/Makefile.in
index 
0d789b3a59d21ea2e5a23057ca3afe15425feec4..36aa952af7e04bc0e4fb94cdcd584d539193d781
 100644
--- a/libsanitizer/Makefile.in
+++ b/libsanitizer/Makefile.in
@@ -92,7 +92,8 @@ target_triplet = @target@
 @SANITIZER_SUPPORTED_TRUE@am__append_1 = 
include/sanitizer/common_interface_defs.h \
 @SANITIZER_SUPPORTED_TRUE@ include/sanitizer/lsan_interface.h \
 @SANITIZER_SUPPORTED_TRUE@ include/sanitizer/asan_interface.h \
-@SANITIZER_SUPPORTED_TRUE@ include/sanitizer/tsan_interface.h
+@SANITIZER_SUPPORTED_TRUE@ include/sanitizer/tsan_interface.h \
+@SANITIZER_SUPPORTED_TRUE@ include/sanitizer/hwasan_interface.h
 @SANITIZER_SUPPORTED_TRUE@@USING_MAC_INTERPOSE_FALSE@am__append_2 = 
interception
 @LIBBACKTRACE_SUPPORTED_TRUE@@SANITIZER_SUPPORTED_TRUE@am__append_3 = 
libbacktrace
 @SANITIZER_SUPPORTED_TRUE@@TSAN_SUPPORTED_TRUE@am__append_4 = tsan
@@ -206,7 +207,7 @@ ETAGS = etags
 CTAGS = ctags
 CSCOPE = cscope
 DIST_SUBDIRS = sanitizer_common interception libbacktrace lsan asan \
-   ubsan tsan
+   ubsan hwasan tsan
 ACLOCAL = @ACLOCAL@
 ALLOC_FILE = @ALLOC_FILE@
 AMTAR = @AMTAR@
@@ -328,6 +329,7 @@ install_sh = @install_sh@
 libdir = @libdir@
 libexecdir = @libexecdir@
 link_libasan = @link_libasan@
+link_libhwasan = @link_libhwasan@
 link_liblsan = @link_liblsan@
 link_libtsan = @link_libtsan@
 link_libubsan = @link_libubsan@
@@ -361,7 +363,7 @@ sanincludedir = 
$(libdir)/gcc/$(target_alias)/$(gcc_version)/include/sanitizer
 nodist_saninclude_HEADERS = $(am__append_1)
 @SANITIZER_SUPPORTED_TRUE@SUBDIRS = sanitizer_common $(am__append_2) \
 @SANITIZER_SUPPORTED_TRUE@ $(am__append_3) lsan asan ubsan \
-@SANITIZER_SUPPORTED_TRUE@ $(am__append_4)
+@SANITIZER_SUPPORTED_TRUE@ hwasan $(am__append_4)
 gcc_version := $(shell @get_gcc_base_ver@ $(top_srcdir)/../gcc/BASE-VER)
 
 # Work around what appears to be a GNU make bug handling MAKEFLAGS
diff --git a/libsanitizer/asan/Makefile.in b/libsanitizer/asan/Makefile.in
index 
00b6082da5372efd679ddc230f588bbc58161ef6..76689c3b224b1fb04895ae48829eac4b6784cd84
 100644
--- a/libsanitizer/asan/Makefile.in
+++ b/libsanitizer/asan/Makefile.in
@@ -382,6 +382,7 @@ install_sh = @install_sh@
 libdir = @libdir@
 libexecdir = @libexecdir@
 link_libasan = @link_libasan@
+link_libhwasan = @link_libhwasan@
 link_liblsan = @link_liblsan@
 link_libtsan = @link_libtsan@
 link_libubsan = @link_libubsan@
diff --git a/libsanitizer/configure b/libsanitizer/configure
index 
79b5c1eadb59018bca13a33f19f3494c170365ee..ff72af73e6f77aaf93bf39e6799f896851a377dd
 100755
--- a/libsanitizer/configure
+++ b/libsanitizer/configure
@@ -657,6 +657,7 @@ USING_MAC_INTERPOSE_TRUE
 link_liblsan
 link_libubsan
 link_libtsan
+link_libhwasan
 link_libasan
 LSAN_SUPPORTED_FALSE
 LSAN_SUPPORTED_TRUE
@@ -12334,7 +12335,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 12337 "configure"
+#line 12338 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -12440,7 +12441,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 12443 "configure"
+#line 12444 "configure"
 #

[PATCH 5/X] [libsanitizer][mid-end] Introduce stack variable handling for HWASAN

2019-12-12 Thread Matthew Malcomson
Handling stack variables has three features.

1) Ensure HWASAN required alignment for stack variables

When tagging shadow memory, we need to ensure that each tag granule is
only used by one variable at a time.

This is done by ensuring that each tagged variable is aligned to the tag
granule representation size and also ensure that the end of each
variable as an alignment boundary between the end and the start of any
other data stored on the stack.

This patch ensures that by adding alignment requirements in
`align_local_variable` and forcing all stack variable allocation to be
deferred so that `expand_stack_vars` can ensure the stack pointer is
aligned before allocating any variable for the current frame.

2) Put tags into each stack variable pointer

Make sure that every pointer to a stack variable includes a tag of some
sort on it.

The way tagging works is:
  1) For every new stack frame, a random tag is generated.
  2) A base register is formed from the stack pointer value and this
 random tag.
  3) References to stack variables are now formed with RTL describing an
 offset from this base in both tag and value.

The random tag generation is handled by a backend hook.  This hook
decides whether to introduce a random tag or use the stack background
based on the parameter hwasan-random-frame-tag.  Using the stack
background is necessary for testing and bootstrap.  It is necessary
during bootstrap to avoid breaking the `configure` test program for
determining stack direction.

Using the stack background means that every stack frame has the initial
tag of zero and variables are tagged with incrementing tags from 1,
which also makes debugging a bit easier.

The tag&value offsets are also handled by a backend hook.

This patch also adds some macros defining how the HWASAN shadow memory
is stored and how a tag is stored in a pointer.

3) For each stack variable, tag and untag the shadow stack on function
   prologue and epilogue.

On entry to each function we tag the relevant shadow stack region for
each stack variable the tag to match the tag added to each pointer for
that variable.

This is the first patch where we use the HWASAN shadow space, so we need
to add in the libhwasan initialisation code that creates this shadow
memory region into the binary we produce.  This instrumentation is done
in `compile_file`.

When exiting a function we need to ensure the shadow stack for this
function has no remaining tag.  Without clearing the shadow stack area
for this stack frame, later function calls could get false positives
when those later function calls check untagged areas (such as parameters
passed on the stack) against a shadow stack area with left-over tag.

Hence we ensure that the entire stack frame is cleared on function exit.

gcc/ChangeLog:

2019-12-12  Matthew Malcomson  

* asan.c (hwasan_record_base): New function.
(hwasan_emit_untag_frame): New.
(hwasan_increment_tag): New function.
(hwasan_with_tag): New function.
(hwasan_tag_init): New function.
(initialize_sanitizer_builtins): Define new builtins.
(ATTR_NOTHROW_LIST): New macro.
(hwasan_current_tag): New.
(hwasan_emit_prologue): New.
(hwasan_create_untagged_base): New.
(hwasan_finish_file): New.
(hwasan_sanitize_stack_p): New.
(hwasan_sanitize_p): New.
* asan.h (hwasan_record_base): New declaration.
(hwasan_emit_untag_frame): New.
(hwasan_increment_tag): New declaration.
(hwasan_with_tag): New declaration.
(hwasan_sanitize_stack_p): New declaration.
(hwasan_tag_init): New declaration.
(hwasan_sanitize_p): New declaration.
(HWASAN_TAG_SIZE): New macro.
(HWASAN_TAG_GRANULE_SIZE):New macro.
(HWASAN_SHIFT):New macro.
(HWASAN_SHIFT_RTX):New macro.
(HWASAN_STACK_BACKGROUND):New macro.
(hwasan_finish_file): New.
(hwasan_current_tag): New.
(hwasan_create_untagged_base): New.
(hwasan_emit_prologue): New.
* cfgexpand.c (struct stack_vars_data): Add information to
record hwasan variable stack offsets.
(expand_stack_vars): Ensure variables are offset from a tagged
base. Record offsets for hwasan. Ensure alignment.
(expand_used_vars): Call function to emit prologue, and get
untagging instructions for function exit.
(align_local_variable): Ensure alignment.
(defer_stack_allocation): Ensure all variables are deferred so
they can be handled by `expand_stack_vars`.
(expand_one_stack_var_at): Account for tags in
variables when using HWASAN.
(expand_one_stack_var_1): Pass new argument to
expand_one_stack_var_at.
(init_vars_expansion): Initialise hwasan internal variables when
starting variable expansion.
* doc/tm.texi (TARGET_MEMTAG_GENTAG): Document.
* doc/tm.texi.in (TARGET_MEMTAG_GE

[PATCH 6/X] [libsanitizer] Add hwasan pass and associated gimple changes

2019-12-12 Thread Matthew Malcomson
There are four main features to this change:

1) Check pointer tags match address tags.

In the new `hwasan` pass we put HWASAN_CHECK internal functions around
all memory accesses, to check that tags in the pointer being used match
the tag stored in shadow memory for the memory region being used.

These internal functions are expanded into actual checks in the sanopt
pass that happens just before expansion into RTL.

We use the same mechanism that currently inserts ASAN_CHECK internal
functions to insert the new HWASAN_CHECK functions.

2) Instrument known builtin function calls.

Handle all builtin functions that we know use memory accesses.
This commit uses the machinery added for ASAN to identify builtin
functions that access memory.

The main differences between the approaches for HWASAN and ASAN are:
 - libhwasan intercepts much less builtin functions.
 - Alloca needs to be transformed differently (instead of adding
   redzones it needs to tag shadow memory and return a tagged pointer).
 - stack_restore needs to untag the shadow stack between the current
   position and where it's going.
 - `noreturn` functions can not be handled by simply unpoisoning the
   entire shadow stack -- there is no "always valid" tag.
   (exceptions and things such as longjmp need to be handled in a
   different way).

For hardware implemented checking (such as AArch64's memory tagging
extension) alloca and stack_restore will need to be handled by hooks in
the backend rather than transformation at the gimple level.  This will
allow architecture specific handling of such stack modifications.

3) Introduce HWASAN block-scope poisoning

Here we use exactly the same mechanism as ASAN_MARK to poison/unpoison
variables on entry/exit of a block.

In order to simply use the exact same machinery we're using the same
internal functions until the SANOPT pass.  This means that all handling
of ASAN_MARK is the same.
This has the negative that the naming may be a little confusing, but a
positive that handling of the internal function doesn't have to be
duplicated for a function that behaves exactly the same but has a
different name.

gcc/ChangeLog:

2019-12-12  Matthew Malcomson  

* asan.c (handle_builtin_stack_restore): Account for HWASAN.
(handle_builtin_alloca): Account for HWASAN.
(get_mem_refs_of_builtin_call): Special case strlen for HWASAN.
(report_error_func): Assert not HWASAN.
(build_check_stmt): Make HWASAN_CHECK instead of ASAN_CHECK.
(instrument_derefs): HWASAN does not tag globals.
(maybe_instrument_call): Don't instrument `noreturn` functions.
(initialize_sanitizer_builtins): Add new type.
(asan_expand_mark_ifn): Account for HWASAN.
(asan_expand_check_ifn): Assert never called by HWASAN.
(asan_expand_poison_ifn): Account for HWASAN.
(hwasan_instrument): New.
(hwasan_base): New.
(hwasan_emit_untag_frame): Free block-scope-var hash map.
(hwasan_check_func): New.
(hwasan_expand_check_ifn): New.
(hwasan_expand_mark_ifn): New.
(gate_hwasan): New.
(class pass_hwasan): New.
(make_pass_hwasan): New.
(class pass_hwasan_O0): New.
(make_pass_hwasan_O0): New.
* asan.h (hwasan_base): New decl.
(hwasan_expand_check_ifn): New decl.
(hwasan_expand_mark_ifn): New decl.
(gate_hwasan): New decl.
(enum hwasan_mark_flags): New.
(asan_intercepted_p): Always false for hwasan.
(asan_sanitize_use_after_scope): Account for HWASAN.
* builtin-types.def (BT_FN_PTR_CONST_PTR_UINT8): New.
* gimple-pretty-print.c (dump_gimple_call_args): Account for
HWASAN.
* gimplify.c (asan_poison_variable): Account for HWASAN.
(gimplify_function_tree): Remove requirement of
SANITIZE_ADDRESS, requiring asan or hwasan is accounted for in
`asan_sanitize_use_after_scope`.
* internal-fn.c (expand_HWASAN_CHECK): New.
(expand_HWASAN_CHOOSE_TAG): New.
(expand_HWASAN_MARK): New.
(expand_HWASAN_ALLOCA_UNPOISON): New.
* internal-fn.def (HWASAN_CHOOSE_TAG): New.
(HWASAN_CHECK): New.
(HWASAN_MARK): New.
(HWASAN_ALLOCA_UNPOISON): New.
* passes.def: Add hwasan and hwasan_O0 passes.
* sanitizer.def (BUILT_IN_HWASAN_LOAD1): New.
(BUILT_IN_HWASAN_LOAD2): New.
(BUILT_IN_HWASAN_LOAD4): New.
(BUILT_IN_HWASAN_LOAD8): New.
(BUILT_IN_HWASAN_LOAD16): New.
(BUILT_IN_HWASAN_LOADN): New.
(BUILT_IN_HWASAN_STORE1): New.
(BUILT_IN_HWASAN_STORE2): New.
(BUILT_IN_HWASAN_STORE4): New.
(BUILT_IN_HWASAN_STORE8): New.
(BUILT_IN_HWASAN_STORE16): New.
(BUILT_IN_HWASAN_STOREN): New.
(BUILT_IN_HWASAN_LOAD1_NOABORT): New.
(BUILT_IN_HWASAN_LOAD2_NOABORT): New.
(BUILT_IN_HWASAN_LOAD4_NOABORT): New.
   

[PATCH 7/X] [libsanitizer] Add tests

2019-12-12 Thread Matthew Malcomson
Adding hwasan tests.

Only interesting thing here is that we have to make sure the tagging mechanism
is deterministic to avoid flaky tests.

gcc/testsuite/ChangeLog:

2019-12-12  Matthew Malcomson  

* c-c++-common/hwasan/aligned-alloc.c: New test.
* c-c++-common/hwasan/alloca-array-accessible.c: New test.
* c-c++-common/hwasan/alloca-gets-different-tag.c: New test.
* c-c++-common/hwasan/alloca-outside-caught.c: New test.
* c-c++-common/hwasan/arguments.c: New test.
* c-c++-common/hwasan/arguments-1.c: New test.
* c-c++-common/hwasan/arguments-2.c: New test.
* c-c++-common/hwasan/arguments-3.c: New test.
* c-c++-common/hwasan/asan-pr63316.c: New test.
* c-c++-common/hwasan/asan-pr70541.c: New test.
* c-c++-common/hwasan/asan-pr78106.c: New test.
* c-c++-common/hwasan/asan-pr79944.c: New test.
* c-c++-common/hwasan/asan-rlimit-mmap-test-1.c: New test.
* c-c++-common/hwasan/bitfield-1.c: New test.
* c-c++-common/hwasan/bitfield-2.c: New test.
* c-c++-common/hwasan/builtin-special-handling.c: New test.
* c-c++-common/hwasan/check-interface.c: New test.
* c-c++-common/hwasan/halt_on_error-1.c: New test.
* c-c++-common/hwasan/heap-overflow.c: New test.
* c-c++-common/hwasan/hwasan-poison-optimisation.c: New test.
* c-c++-common/hwasan/hwasan-thread-access-parent.c: New test.
* c-c++-common/hwasan/hwasan-thread-basic-failure.c: New test.
* c-c++-common/hwasan/hwasan-thread-clears-stack.c: New test.
* c-c++-common/hwasan/hwasan-thread-success.c: New test.
* c-c++-common/hwasan/kernel-defaults.c: New test.
* c-c++-common/hwasan/large-aligned-0.c: New test.
* c-c++-common/hwasan/large-aligned-1.c: New test.
* c-c++-common/hwasan/large-aligned-untagging-0.c: New test.
* c-c++-common/hwasan/large-aligned-untagging-1.c: New test.
* c-c++-common/hwasan/macro-definition.c: New test.
* c-c++-common/hwasan/no-sanitize-attribute.c: New test.
* c-c++-common/hwasan/param-instrument-reads-and-writes.c: New test.
* c-c++-common/hwasan/param-instrument-reads.c: New test.
* c-c++-common/hwasan/param-instrument-writes.c: New test.
* c-c++-common/hwasan/param-memintrin.c: New test.
* c-c++-common/hwasan/random-frame-tag.c: New test.
* c-c++-common/hwasan/sanity-check-pure-c.c: New test.
* c-c++-common/hwasan/setjmp-longjmp-0.c: New test.
* c-c++-common/hwasan/setjmp-longjmp-1.c: New test.
* c-c++-common/hwasan/stack-tagging-basic-0.c: New test.
* c-c++-common/hwasan/stack-tagging-basic-1.c: New test.
* c-c++-common/hwasan/stack-tagging-disable.c: New test.
* c-c++-common/hwasan/unprotected-allocas-0.c: New test.
* c-c++-common/hwasan/unprotected-allocas-1.c: New test.
* c-c++-common/hwasan/use-after-free.c: New test.
* c-c++-common/hwasan/vararray-outside-caught.c: New test.
* c-c++-common/hwasan/vararray-stack-restore-correct.c: New test.
* c-c++-common/hwasan/very-large-objects.c: New test.
* g++.dg/hwasan/hwasan.exp: New file.
* g++.dg/hwasan/rvo-handled.C: New test.
* g++.dg/hwasan/try-catch-0.cpp: New test.
* g++.dg/hwasan/try-catch-1.cpp: New test.
* gcc.dg/hwasan/hwasan.exp: New file.
* gcc.dg/hwasan/nested-functions-0.c: New test.
* gcc.dg/hwasan/nested-functions-1.c: New test.
* gcc.dg/hwasan/nested-functions-2.c: New test.
* lib/hwasan-dg.exp: New file.



### Attachment also inlined for ease of reply###


diff --git a/gcc/testsuite/c-c++-common/hwasan/aligned-alloc.c 
b/gcc/testsuite/c-c++-common/hwasan/aligned-alloc.c
new file mode 100644
index 
..e5837a9f0766fc4d91fabc1a3c2e0017f845dc46
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/hwasan/aligned-alloc.c
@@ -0,0 +1,15 @@
+/* { dg-do run } */
+/* { dg-shouldfail "hwasan" } */
+/* This program fails at runtime in the libhwasan library.
+   The allocator can't handle the requested invalid alignment.  */
+
+int
+main ()
+{
+  void *p = __builtin_aligned_alloc (17, 100);
+  if (((unsigned long long)p & 0x10) == 0)
+return 0;
+  return 1;
+}
+
+/* { dg-output "HWAddressSanitizer: invalid alignment requested in 
aligned_alloc: 17" } */
diff --git a/gcc/testsuite/c-c++-common/hwasan/alloca-array-accessible.c 
b/gcc/testsuite/c-c++-common/hwasan/alloca-array-accessible.c
new file mode 100644
index 
..c6b4d264b8c477b52b859a0411aabb0fc8dde352
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/hwasan/alloca-array-accessible.c
@@ -0,0 +1,32 @@
+/* { dg-do run } */
+
+#define alloca __builtin_alloca
+
+int __attribute__ ((noinline))
+using_alloca (int num)
+{
+  int retval = 0;
+  int *

Document --with-build-config=bootstrap-asan option.

2019-12-12 Thread Matthew Malcomson
Document how to configure using asan (bootstrap-asan option).

Since I'm adding a bootstrap-hwasan option and documenting that, 
bootstrap-asan should also be documented.

(As Martin pointed out in the hwasan reviews).



(FYI I now notice that my hwasan patch 3/X needs this to apply cleanly).



gcc/ChangeLog:

2019-12-12  Matthew Malcomson  

* doc/install.texi: Document bootstrap-asan configuration option.





###


commit 6e0bbe33120ad3f92e4266ecfe4ecb8ce8958865
Author: Matthew Malcomson 
Date:   Wed Nov 6 12:48:08 2019 +

 Document bootstrap-asan compilation option

diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi
index 80b4781..c5937c9 100644
--- a/gcc/doc/install.texi
+++ b/gcc/doc/install.texi
@@ -2670,6 +2670,14 @@ the build tree.

  @end table

+Some examples of build configurations designed for developers of GCC are:
+
+@table @asis
+@item @samp{bootstrap-asan}
+Compiles GCC itself using Address Sanitization in order to catch 
invalid memory
+accesses within the GCC code.
+@end table
+
  @section Building a cross compiler

  When building a cross compiler, it is not generally possible to do a



[PATCH 3/X] [libsanitizer] Add option to bootstrap using HWASAN

2019-12-12 Thread Matthew Malcomson
Updated to include documentation ChangeLog and apply cleanly on the
bootstrap-asan documentation I mentioned in a different email.



This is an analogous option to --bootstrap-asan to configure.  It allows
bootstrapping GCC using HWASAN.

For the same reasons as for ASAN we have to avoid using the HWASAN
sanitizer when compiling libiberty and the lto-plugin.

Also add a function to query whether -fsanitize=hwaddress has been
passed.

ChangeLog:

2019-08-29  Matthew Malcomson  

* configure: Regenerate.
* configure.ac: Add --bootstrap-hwasan option.

config/ChangeLog:

2019-12-12  Matthew Malcomson  

* bootstrap-hwasan.mk: New file.

gcc/ChangeLog:

2019-12-12  Matthew Malcomson  

* doc/install.texi: Document new option.

libiberty/ChangeLog:

2019-12-12  Matthew Malcomson  

* configure: Regenerate.
* configure.ac: Avoid using sanitizer.

lto-plugin/ChangeLog:

2019-12-12  Matthew Malcomson  

* Makefile.am: Avoid using sanitizer.
* Makefile.in: Regenerate.



### Attachment also inlined for ease of reply###


diff --git a/config/bootstrap-hwasan.mk b/config/bootstrap-hwasan.mk
new file mode 100644
index 
..4f60bed3fd6e98b47a3a38aea6eba2a7c320da25
--- /dev/null
+++ b/config/bootstrap-hwasan.mk
@@ -0,0 +1,8 @@
+# This option enables -fsanitize=hwaddress for stage2 and stage3.
+
+STAGE2_CFLAGS += -fsanitize=hwaddress
+STAGE3_CFLAGS += -fsanitize=hwaddress
+POSTSTAGE1_LDFLAGS += -fsanitize=hwaddress -static-libhwasan \
+ -B$$r/prev-$(TARGET_SUBDIR)/libsanitizer/ \
+ -B$$r/prev-$(TARGET_SUBDIR)/libsanitizer/hwasan/ \
+ -B$$r/prev-$(TARGET_SUBDIR)/libsanitizer/hwasan/.libs
diff --git a/configure b/configure
index 
f6027397cedd5c28cd821a0bc7629d6537393ecf..0b502f2784927d72eab248741633305296bf09e7
 100755
--- a/configure
+++ b/configure
@@ -7270,7 +7270,7 @@ fi
 # or bootstrap-ubsan, bootstrap it.
 if echo " ${target_configdirs} " | grep " libsanitizer " > /dev/null 2>&1; then
   case "$BUILD_CONFIG" in
-*bootstrap-asan* | *bootstrap-ubsan* )
+*bootstrap-hwasan* | *bootstrap-asan* | *bootstrap-ubsan* )
   bootstrap_target_libs=${bootstrap_target_libs}target-libsanitizer,
   bootstrap_fixincludes=yes
   ;;
diff --git a/configure.ac b/configure.ac
index 
50e2fa135b10486170f68ffa162dcbeee2adff90..f793e14e0316e26d05ba72696e8c7c10641c7c96
 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2775,7 +2775,7 @@ fi
 # or bootstrap-ubsan, bootstrap it.
 if echo " ${target_configdirs} " | grep " libsanitizer " > /dev/null 2>&1; then
   case "$BUILD_CONFIG" in
-*bootstrap-asan* | *bootstrap-ubsan* )
+*bootstrap-hwasan* | *bootstrap-asan* | *bootstrap-ubsan* )
   bootstrap_target_libs=${bootstrap_target_libs}target-libsanitizer,
   bootstrap_fixincludes=yes
   ;;
diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi
index 
c5937c94b7cebd3d0f1d7d551a7b593c128e7673..37cb8ed15671205567ee20286e21fb904b3e3c9f
 100644
--- a/gcc/doc/install.texi
+++ b/gcc/doc/install.texi
@@ -2676,6 +2676,12 @@ Some examples of build configurations designed for 
developers of GCC are:
 @item @samp{bootstrap-asan}
 Compiles GCC itself using Address Sanitization in order to catch invalid memory
 accesses within the GCC code.
+
+@item @samp{bootstrap-hwasan}
+Compiles GCC itself using HWAddress Sanitization in order to catch invalid
+memory accesses within the GCC code.  This option is only available on AArch64
+targets with a very recent linux kernel (5.4 or later).
+
 @end table
 
 @section Building a cross compiler
diff --git a/libiberty/configure b/libiberty/configure
index 
7a34dabec32b0b383bd33f07811757335f4dd39c..cb2dd4ff5295598343cc18b3a79a86a778f2261d
 100755
--- a/libiberty/configure
+++ b/libiberty/configure
@@ -5261,6 +5261,7 @@ fi
 NOASANFLAG=
 case " ${CFLAGS} " in
   *\ -fsanitize=address\ *) NOASANFLAG=-fno-sanitize=address ;;
+  *\ -fsanitize=hwaddress\ *) NOASANFLAG=-fno-sanitize=hwaddress ;;
 esac
 
 
diff --git a/libiberty/configure.ac b/libiberty/configure.ac
index 
f1ce76010c9acde79c5dc46686a78b2e2f19244e..043237628b79cbf37d07359b59c5ffe17a7a22ef
 100644
--- a/libiberty/configure.ac
+++ b/libiberty/configure.ac
@@ -240,6 +240,7 @@ AC_SUBST(PICFLAG)
 NOASANFLAG=
 case " ${CFLAGS} " in
   *\ -fsanitize=address\ *) NOASANFLAG=-fno-sanitize=address ;;
+  *\ -fsanitize=hwaddress\ *) NOASANFLAG=-fno-sanitize=hwaddress ;;
 esac
 AC_SUBST(NOASANFLAG)
 
diff --git a/lto-plugin/Makefile.am b/lto-plugin/Makefile.am
index 
28dc21014b2e86988fa88adabd63ce6092e18e02..34aa397d785e3cc9b6975de460d065900364c3ff
 100644
--- a/lto-plugin/Makefile.am
+++ b/lto-plugin/Makefile.am
@@ -11,8 +11,8 @@ AM_CPPFLAGS = -I$(top_srcdir)/../include $(DEFS)
 AM_CFLAGS = @ac_lto_plugin_warn_cflags@
 AM_LDFLAGS = @ac_lto_plugin_

Re: [PATCH 7/X] [libsanitizer] Add tests

2019-12-16 Thread Matthew Malcomson
I just remembered that the run tests all fail on cross builds.
This patch includes the effective target check to determine whether a hwasan
binary can be run on a given target.

We then add that target requirement to all tests which need to run.



Adding hwasan tests.

Only interesting thing here is that we have to make sure the tagging mechanism
is deterministic to avoid flaky tests.

gcc/testsuite/ChangeLog:

2019-12-16  Matthew Malcomson  

* c-c++-common/hwasan/aligned-alloc.c: New test.
* c-c++-common/hwasan/alloca-array-accessible.c: New test.
* c-c++-common/hwasan/alloca-gets-different-tag.c: New test.
* c-c++-common/hwasan/alloca-outside-caught.c: New test.
* c-c++-common/hwasan/arguments.c: New test.
* c-c++-common/hwasan/arguments-1.c: New test.
* c-c++-common/hwasan/arguments-2.c: New test.
* c-c++-common/hwasan/arguments-3.c: New test.
* c-c++-common/hwasan/asan-pr63316.c: New test.
* c-c++-common/hwasan/asan-pr70541.c: New test.
* c-c++-common/hwasan/asan-pr78106.c: New test.
* c-c++-common/hwasan/asan-pr79944.c: New test.
* c-c++-common/hwasan/asan-rlimit-mmap-test-1.c: New test.
* c-c++-common/hwasan/bitfield-1.c: New test.
* c-c++-common/hwasan/bitfield-2.c: New test.
* c-c++-common/hwasan/builtin-special-handling.c: New test.
* c-c++-common/hwasan/check-interface.c: New test.
* c-c++-common/hwasan/halt_on_error-1.c: New test.
* c-c++-common/hwasan/heap-overflow.c: New test.
* c-c++-common/hwasan/hwasan-poison-optimisation.c: New test.
* c-c++-common/hwasan/hwasan-thread-access-parent.c: New test.
* c-c++-common/hwasan/hwasan-thread-basic-failure.c: New test.
* c-c++-common/hwasan/hwasan-thread-clears-stack.c: New test.
* c-c++-common/hwasan/hwasan-thread-success.c: New test.
* c-c++-common/hwasan/kernel-defaults.c: New test.
* c-c++-common/hwasan/large-aligned-0.c: New test.
* c-c++-common/hwasan/large-aligned-1.c: New test.
* c-c++-common/hwasan/large-aligned-untagging-0.c: New test.
* c-c++-common/hwasan/large-aligned-untagging-1.c: New test.
* c-c++-common/hwasan/macro-definition.c: New test.
* c-c++-common/hwasan/no-sanitize-attribute.c: New test.
* c-c++-common/hwasan/param-instrument-reads-and-writes.c: New test.
* c-c++-common/hwasan/param-instrument-reads.c: New test.
* c-c++-common/hwasan/param-instrument-writes.c: New test.
* c-c++-common/hwasan/param-memintrin.c: New test.
* c-c++-common/hwasan/random-frame-tag.c: New test.
* c-c++-common/hwasan/sanity-check-pure-c.c: New test.
* c-c++-common/hwasan/setjmp-longjmp-0.c: New test.
* c-c++-common/hwasan/setjmp-longjmp-1.c: New test.
* c-c++-common/hwasan/stack-tagging-basic-0.c: New test.
* c-c++-common/hwasan/stack-tagging-basic-1.c: New test.
* c-c++-common/hwasan/stack-tagging-disable.c: New test.
* c-c++-common/hwasan/unprotected-allocas-0.c: New test.
* c-c++-common/hwasan/unprotected-allocas-1.c: New test.
* c-c++-common/hwasan/use-after-free.c: New test.
* c-c++-common/hwasan/vararray-outside-caught.c: New test.
* c-c++-common/hwasan/vararray-stack-restore-correct.c: New test.
* c-c++-common/hwasan/very-large-objects.c: New test.
* g++.dg/hwasan/hwasan.exp: New file.
* g++.dg/hwasan/rvo-handled.C: New test.
* gcc.dg/hwasan/hwasan.exp: New file.
* gcc.dg/hwasan/nested-functions-0.c: New test.
* gcc.dg/hwasan/nested-functions-1.c: New test.
* gcc.dg/hwasan/nested-functions-2.c: New test.
* lib/hwasan-dg.exp: New file.



### Attachment also inlined for ease of reply###


diff --git a/gcc/testsuite/c-c++-common/hwasan/aligned-alloc.c 
b/gcc/testsuite/c-c++-common/hwasan/aligned-alloc.c
new file mode 100644
index 
..d38b1f3f62d97dc3f5c3882137c370700fd4f9a0
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/hwasan/aligned-alloc.c
@@ -0,0 +1,16 @@
+/* { dg-do run } */
+/* { dg-require-effective-target hwaddress_exec } */
+/* { dg-shouldfail "hwasan" } */
+/* This program fails at runtime in the libhwasan library.
+   The allocator can't handle the requested invalid alignment.  */
+
+int
+main ()
+{
+  void *p = __builtin_aligned_alloc (17, 100);
+  if (((unsigned long long)p & 0x10) == 0)
+return 0;
+  return 1;
+}
+
+/* { dg-output "HWAddressSanitizer: invalid alignment requested in 
aligned_alloc: 17" } */
diff --git a/gcc/testsuite/c-c++-common/hwasan/alloca-array-accessible.c 
b/gcc/testsuite/c-c++-common/hwasan/alloca-array-accessible.c
new file mode 100644
index 
..5e4c168f77efac5c9335768fb5b76fb3752783e9
--- /dev/null
+++ b/gcc/testsuite/c-c

Re: [Patch 0/X] HWASAN v3

2019-12-17 Thread Matthew Malcomson
I've noticed a few minor problems with this patch series after I sent it 
out (mostly testcase stuff, one documentation tidy-up, but also that one 
patch didn't bootstrap due to something fixed in a later patch).

I also rely on a documentation change that isn't part of the series.

I figure I should make this easy on anyone that wants to try the patch 
series out, so I'm attaching a compressed tarfile containing the entire 
patch series plus the additional documentation patch so it can all be 
applied at once with `git apply *`.

It's attached.

Matthew.



On 12/12/2019 15:18, Matthew Malcomson wrote:
> Hello,
> 
> I've gone through the suggestions Martin made and implemented  the ones I 
> think
> I can implement for GCC10.
> 
> The two functionality changes in this version are:
> Added the --param's hwasan-instrument-reads, hwasan-instrument-writes,
> hwasan-instrument-allocas, hwasan-memintrin, options.  I.e. Those that asan 
> has
> and that make sense for hwasan.
> 
> Avoided HWASAN_STACK_BACKGROUND in hwasan_increment_tag when using a
> deterministic tagging approach.
> 
> 
> There are a lot of extra comments and tests.
> 
> 
> Bootstrapped and regtested on x86_64 and AArch64.
> Bootstrapped with `--with-build-config=bootstrap-hwasan` on AArch64 and hwasan
> features tested there.
> Built the linux kernel using this feature and ran the test_kasan.ko testing to
> check the this works for the kernel.
> (NOTE: I actually did all the above testing before a search and replace of
> `memory_tagging_p` for `hwasan_sanitize_p` and fixing a typo in the
> `hwasan-instrument-allocas` parameter name, I will run all the tests again
> before committing but figure I'll send this out now since I fully expect the
> tests to still pass).
> 
> 
> I noticed one extra testsuite failure from those mentioned in the previous
> version emails: g++.dg/cpp2a/ucn2.C.
> I believe this is HWASAN correctly catching a problem in the compiler.
> I've logged the issue here https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92919 
> .
> 
> 
> I haven't gotten ASAN_MARK to print as HWASAN_MARK when using memory tagging,
> since I'm not sure the way I found to implement this would be acceptable.  The
> inlined patch below works but it requires a special declaration instead of 
> just
> an ~#include~.
> 
> 
> diff --git a/gcc/internal-fn.h b/gcc/internal-fn.h
> index a1bc081..d81eb12 100644
> --- a/gcc/internal-fn.h
> +++ b/gcc/internal-fn.h
> @@ -101,10 +101,16 @@ extern void init_internal_fns ();
>   
>   extern const char *const internal_fn_name_array[];
>   
> +
> +extern bool hwasan_sanitize_p (void);
>   static inline const char *
>   internal_fn_name (enum internal_fn fn)
>   {
> -  return internal_fn_name_array[(int) fn];
> +  const char *ret = internal_fn_name_array[(int) fn];
> +  if (! strcmp (ret, "ASAN_MARK")
> +  && hwasan_sanitize_p ())
> +return "HWASAN_MARK";
> +  return ret;
>   }
>   
>   extern internal_fn lookup_internal_fn (const char *);
> 
> 
> Entire patch series attached to cover letter.
> 



all-patches.tar.gz
Description: all-patches.tar.gz


[PING] Re: [Patch 0/X] HWASAN v3

2020-01-06 Thread Matthew Malcomson
Ping


On 17/12/2019 14:11, Matthew Malcomson wrote:
> I've noticed a few minor problems with this patch series after I sent it
> out (mostly testcase stuff, one documentation tidy-up, but also that one
> patch didn't bootstrap due to something fixed in a later patch).
> 
> I also rely on a documentation change that isn't part of the series.
> 
> I figure I should make this easy on anyone that wants to try the patch
> series out, so I'm attaching a compressed tarfile containing the entire
> patch series plus the additional documentation patch so it can all be
> applied at once with `git apply *`.
> 
> It's attached.
> 
> Matthew.
> 
> 
> 
> On 12/12/2019 15:18, Matthew Malcomson wrote:
>> Hello,
>>
>> I've gone through the suggestions Martin made and implemented  the ones I 
>> think
>> I can implement for GCC10.
>>
>> The two functionality changes in this version are:
>> Added the --param's hwasan-instrument-reads, hwasan-instrument-writes,
>> hwasan-instrument-allocas, hwasan-memintrin, options.  I.e. Those that asan 
>> has
>> and that make sense for hwasan.
>>
>> Avoided HWASAN_STACK_BACKGROUND in hwasan_increment_tag when using a
>> deterministic tagging approach.
>>
>>
>> There are a lot of extra comments and tests.
>>
>>
>> Bootstrapped and regtested on x86_64 and AArch64.
>> Bootstrapped with `--with-build-config=bootstrap-hwasan` on AArch64 and 
>> hwasan
>> features tested there.
>> Built the linux kernel using this feature and ran the test_kasan.ko testing 
>> to
>> check the this works for the kernel.
>> (NOTE: I actually did all the above testing before a search and replace of
>> `memory_tagging_p` for `hwasan_sanitize_p` and fixing a typo in the
>> `hwasan-instrument-allocas` parameter name, I will run all the tests again
>> before committing but figure I'll send this out now since I fully expect the
>> tests to still pass).
>>
>>
>> I noticed one extra testsuite failure from those mentioned in the previous
>> version emails: g++.dg/cpp2a/ucn2.C.
>> I believe this is HWASAN correctly catching a problem in the compiler.
>> I've logged the issue here 
>> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92919 .
>>
>>
>> I haven't gotten ASAN_MARK to print as HWASAN_MARK when using memory tagging,
>> since I'm not sure the way I found to implement this would be acceptable.  
>> The
>> inlined patch below works but it requires a special declaration instead of 
>> just
>> an ~#include~.
>>
>>
>> diff --git a/gcc/internal-fn.h b/gcc/internal-fn.h
>> index a1bc081..d81eb12 100644
>> --- a/gcc/internal-fn.h
>> +++ b/gcc/internal-fn.h
>> @@ -101,10 +101,16 @@ extern void init_internal_fns ();
>>
>>extern const char *const internal_fn_name_array[];
>>
>> +
>> +extern bool hwasan_sanitize_p (void);
>>static inline const char *
>>internal_fn_name (enum internal_fn fn)
>>{
>> -  return internal_fn_name_array[(int) fn];
>> +  const char *ret = internal_fn_name_array[(int) fn];
>> +  if (! strcmp (ret, "ASAN_MARK")
>> +  && hwasan_sanitize_p ())
>> +return "HWASAN_MARK";
>> +  return ret;
>>}
>>
>>extern internal_fn lookup_internal_fn (const char *);
>>
>>
>> Entire patch series attached to cover letter.
>>



Re: [Patch 0/X] HWASAN v3

2020-01-08 Thread Matthew Malcomson
Hi everyone,

I'm writing this email to summarise & publicise the state of this patch 
series, especially the difficulties around approval for GCC 10 mentioned 
on IRC.


The main obstacle seems to be that no maintainer feels they have enough 
knowledge about hwasan and justification that it's worthwhile to approve 
the patch series.

Similarly, Martin has given a review of the parts of the code he can 
(thanks!), but doesn't feel he can do a deep review of the code related 
to the RTL hooks and stack expansion -- hence that part is as yet not 
reviewed in-depth.



The questions around justification raised on IRC are mainly that it 
seems like a proof-of-concept for MTE rather than a stand-alone useable 
sanitizer.  Especially since in the GNU world hwasan instrumented code 
is not really ready for production since we can only use the 
less-"interceptor ABI" rather than the "platform ABI".  This restriction 
is because there is no version of glibc with the required modifications 
to provide the "platform ABI".

(n.b. that since https://reviews.llvm.org/D69574 the code-generation for 
these ABI's is the same).


 From my perspective the reasons that make HWASAN useful in itself are:

1) Much less memory usage.

 From a back-of-the-envelope calculation based on the hwasan paper's 
table of memory overhead from over-alignment 
https://arxiv.org/pdf/1802.09517.pdf  I guess hwasan instrumented code 
has an overhead of about 1.1x (~4% from overalignment and ~6.25% from 
shadow memory), while asan seems to have an overhead somewhere in the 
range 1.5x - 3x.

Maybe there's some data out there comparing total overheads that I 
haven't found? (I'd appreciate a reference if anyone has that info).



2) Available on more architectures that MTE.

HWASAN only requires TBI, which is a feature of all AArch64 machines, 
while MTE will be an optional extension and only available on certain 
architectures.


3) This enables using hwasan in the kernel.

While instrumented user-space applications will be using the 
"interceptor ABI" and hence are likely not production-quality, the 
biggest aim of implementing hwasan in GCC is to allow building the Linux 
kernel with tag-based sanitization using GCC.

Instrumented kernel code uses hooks in the kernel itself, so this ABI 
distinction is no longer relevant, and this sanitizer should produce a 
production-quality kernel binary.




I'm hoping I can find a maintainer willing to review and ACK this patch 
series -- especially with stage3 coming to a close soon.  If there's 
anything else I could do to help get someone willing up-to-speed then 
please just ask.


Cheers,
Matthew



On 07/01/2020 15:14, Martin Liška wrote:
> On 12/12/19 4:18 PM, Matthew Malcomson wrote:
> 
> Hello.
> 
> I've just sent few comments that are related to the v3 of the patch set.
> Based on the HWASAN (limited) knowledge the patch seems reasonable to me.
> I haven't looked much at the newly introduced RTL-hooks.
> But these seems to me isolated to the aarch64 port.
> 
> I can also verify that the patchset works on my aarch64 linux machine and
> hwasan.exp and asan.exp tests succeed.
> 
>> I haven't gotten ASAN_MARK to print as HWASAN_MARK when using memory 
>> tagging,
>> since I'm not sure the way I found to implement this would be 
>> acceptable.  The
>> inlined patch below works but it requires a special declaration 
>> instead of just
>> an ~#include~.
> 
> Knowing that, I would not bother with the printing of HWASAN_MARK.
> 
> Thanks for the series,
> Martin



gcc: docs: Fix documentation of two hooks

2024-04-08 Thread Matthew Malcomson
The `function_attribute_inlinable_p` hook documentation described it
returning the value if it is OK to inline the provided fndecl into "the
current function".  AFAICS This hook is only called when
`current_function_decl` is the same as the `fndecl` argument that the
hook is given, hence asking whether `fndecl` can be inlined into "the
current function" doesn't make sense.
Update the documentation to match this understanding.

The `unspec_may_trap_p` documentation mentioned applying to either
`unspec` or `unspec_volatile`.  AFAICS this hook is only used for
`unspec` codes since c84a808e493a, so I removed the mention of
`unspec_volatile`.

gcc/ChangeLog:

* doc/tm.texi (function_attribute_inlinable_p,
unspec_may_trap_p): Update documentation.
* target.def (function_attribute_inlinable_p,
unspec_may_trap_p): Update documentation.

--
N.b. not entirely sure who to ask for review, went with docs maintainers, but
if that's incorrect please do redirect me.

### Attachment also inlined for ease of reply###


diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 
c8b8b126b2424b6552f824ba42ac329cfaf84d84..f0051f0ae1e9444d5d585135c90a68ca760c2fbd
 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -10752,10 +10752,10 @@ attribute handlers.  So far this only affects the 
@var{noinit} and
 
 @deftypefn {Target Hook} bool TARGET_FUNCTION_ATTRIBUTE_INLINABLE_P 
(const_tree @var{fndecl})
 @cindex inlining
-This target hook returns @code{true} if it is OK to inline @var{fndecl}
-into the current function, despite its having target-specific
-attributes, @code{false} otherwise.  By default, if a function has a
-target specific attribute attached to it, it will not be inlined.
+This target hook returns @code{false} if the target-specific attributes on
+@var{fndecl} always block it getting inlined, @code{true} otherwise.  By
+default, if a function has a target specific attribute attached to it, it
+will not be inlined.
 @end deftypefn
 
 @deftypefn {Target Hook} bool TARGET_OPTION_VALID_ATTRIBUTE_P (tree 
@var{fndecl}, tree @var{name}, tree @var{args}, int @var{flags})
@@ -12245,12 +12245,10 @@ allocation.
 @end deftypefn
 
 @deftypefn {Target Hook} int TARGET_UNSPEC_MAY_TRAP_P (const_rtx @var{x}, 
unsigned @var{flags})
-This target hook returns nonzero if @var{x}, an @code{unspec} or
-@code{unspec_volatile} operation, might cause a trap.  Targets can use
-this hook to enhance precision of analysis for @code{unspec} and
-@code{unspec_volatile} operations.  You may call @code{may_trap_p_1}
-to analyze inner elements of @var{x} in which case @var{flags} should be
-passed along.
+This target hook returns nonzero if @var{x}, an @code{unspec} might cause
+a trap.  Targets can use this hook to enhance precision of analysis for
+@code{unspec} operations.  You may call @code{may_trap_p_1} to analyze inner
+elements of @var{x} in which case @var{flags} should be passed along.
 @end deftypefn
 
 @deftypefn {Target Hook} void TARGET_SET_CURRENT_FUNCTION (tree @var{decl})
diff --git a/gcc/target.def b/gcc/target.def
index 
fdad7bbc93e2ad8aea30336d5cd4af67801e9c74..2b2a6c11807eff228788fae1cd1370e8971fbf3e
 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -2314,10 +2314,10 @@ attribute handlers.  So far this only affects the 
@var{noinit} and\n\
 DEFHOOK
 (function_attribute_inlinable_p,
  "@cindex inlining\n\
-This target hook returns @code{true} if it is OK to inline @var{fndecl}\n\
-into the current function, despite its having target-specific\n\
-attributes, @code{false} otherwise.  By default, if a function has a\n\
-target specific attribute attached to it, it will not be inlined.",
+This target hook returns @code{false} if the target-specific attributes on\n\
+@var{fndecl} always block it getting inlined, @code{true} otherwise.  By\n\
+default, if a function has a target specific attribute attached to it, it\n\
+will not be inlined.",
  bool, (const_tree fndecl),
  hook_bool_const_tree_false)
 
@@ -4057,12 +4057,10 @@ allocation.",
FLAGS has the same meaning as in rtlanal.cc: may_trap_p_1.  */
 DEFHOOK
 (unspec_may_trap_p,
- "This target hook returns nonzero if @var{x}, an @code{unspec} or\n\
-@code{unspec_volatile} operation, might cause a trap.  Targets can use\n\
-this hook to enhance precision of analysis for @code{unspec} and\n\
-@code{unspec_volatile} operations.  You may call @code{may_trap_p_1}\n\
-to analyze inner elements of @var{x} in which case @var{flags} should be\n\
-passed along.",
+ "This target hook returns nonzero if @var{x}, an @code{unspec} might cause\n\
+a trap.  Targets can use this hook to enhance precision of analysis for\n\
+@code{unspec} operations.  You may call @code{may_trap_p_1} to analyze inner\n\
+elements of @var{x} in which case @var{flags} should be passed along.",
  int, (const_rtx x, unsigned flags),
  default_unspec_may_trap_p)
 



diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 
c8b8b12

Re: [PATCH] arm: fix c23 0-named-args caller-side stdarg

2024-02-26 Thread Matthew Malcomson

Hi Alexandre,

I don't have the ability to OK the patch, but I'm attempting to do a 
review in

order to reduce the workload for any maintainer.  (Apologies for the slow
response).

I think you're right that the AAPCS32 requires all arguments to be passed in
registers for this testcase.
(Nit on the commit-message: It says that your reading of the AAPCS32 
suggests
that the *caller* is correct -- I believe based on the change you 
suggested you

meant *callee* is correct in expecting arguments in registers.)

The approach you suggest looks OK to me -- I do notice that it doesn't 
fix the

legacy ABI's of `atpcs` and `apcs` and guess it would be nicer to have them
working at the same time though would defer to maintainers on how 
important that

is.
(For the benefit of others reading) I don't believe there is any ABI concern
with this since it's fixing something that is currently not working at 
all and

only applies to c23 (so a change shouldn't have too much of an impact).

You mention you chose to make the change in the arm backend rather than 
general

code due to hesitancy to change the generic ABI-affecting code. That makes
sense to me, certainly at this late stage in the development cycle.

That said, I do expect the more robust solution would be to change a part of
the generic ABI code and would like to check that this makes sense to 
you and

anyone else upstream in the discussion (justification below).
So would suggest to the maintainers that maybe this goes in with a note to
remember to look at a possible generic code change later on.

Does that sound reasonable to you?

--
Justification for why a change to the generic ABI code would be better 
in the

end:

IIUC (from the documentation of the hooks) `pretend_outgoing_varargs_named`
really should mean that `n_named_args = num_actuals`.  That seems to be 
what the

documentation for `strict_argument_naming` indicates should happen.

``` (Documentation for TARGET_STRICT_ARGUMENT_NAMING):
If it returns 'false', but 'TARGET_PRETEND_OUTGOING_VARARGS_NAMED' returns
'true', then all arguments are treated as named.
```

Because of this I guess that if `pretend_outgoing_varargs_named` only 
means to
pretend the above *except* in the c23 0-named-args case that seems like 
it would

be a bit awkward to account for in backends.

From a quick check on c23-stdarg-4.c it does look like the below change 
ends up
with the same codegen as your patch (except in the case of those legacy 
ABI's,

where the below does make the caller and callee ABI match AFAICT):

```
  diff --git a/gcc/calls.cc b/gcc/calls.cc
  index 01f44734743..0b302f633ed 100644
  --- a/gcc/calls.cc
  +++ b/gcc/calls.cc
  @@ -2970,14 +2970,15 @@ expand_call (tree exp, rtx target, int ignore)
    we do not have any reliable way to pass unnamed args in
    registers, so we must force them into memory.  */

  -  if (type_arg_types != 0
  +  if ((type_arg_types != 0 || TYPE_NO_NAMED_ARGS_STDARG_P (funtype))
 && targetm.calls.strict_argument_naming (args_so_far))
   ;
 else if (type_arg_types != 0
 && ! targetm.calls.pretend_outgoing_varargs_named 
(args_so_far))

   /* Don't include the last named arg.  */
   --n_named_args;
  -  else if (TYPE_NO_NAMED_ARGS_STDARG_P (funtype))
  +  else if (TYPE_NO_NAMED_ARGS_STDARG_P (funtype)
  +    && ! targetm.calls.pretend_outgoing_varargs_named (args_so_far))
   n_named_args = 0;
 else
   /* Treat all args as named.  */
```

Do you agree that this makes sense (i.e. is there something I'm 
completely missing)?


FWIW I attempted to try and find other targets which have
`strict_argument_naming` returning `false`, `pretend_outgoing_varargs_named`
returning true, and some use of the `.named` member of function 
arguments.  I

got the below list.  I recognise it doesn't mean there's a bug in these
backends, but thought it might help the discussion.
(lm32 mcore msp430 gcn cris fr30 frv h8300 arm v850 rx pru)



On 1/23/24 08:26, Alexandre Oliva wrote:

On Dec  5, 2023, Alexandre Oliva  wrote:


arm: fix c23 0-named-args caller-side stdarg

Ping?
https://gcc.gnu.org/pipermail/gcc-patches/2023-December/639472.html


The commit message doesn't name explicitly the fixed testsuite
failures.  Here they are:
FAIL: gcc.dg/c23-stdarg-4.c execution test
FAIL: gcc.dg/torture/c23-stdarg-split-1a.c   -O0  execution test
FAIL: gcc.dg/torture/c23-stdarg-split-1a.c   -O1  execution test
FAIL: gcc.dg/torture/c23-stdarg-split-1a.c   -O2  execution test
FAIL: gcc.dg/torture/c23-stdarg-split-1a.c   -O2 -flto -fno-use-linker-plugin 
-flto-partition=none  execution test
FAIL: gcc.dg/torture/c23-stdarg-split-1a.c   -O2 -flto -fuse-linker-plugin 
-fno-fat-lto-objects  execution test
FAIL: gcc.dg/torture/c23-stdarg-split-1a.c   -O3 -g  execution test
FAIL: gcc.dg/torture/c23-stdarg-split-1a.c   -Os  execution test
Tested on arm-eabi.  Ok to install?




Re: gcc: docs: Fix documentation of two hooks

2024-07-01 Thread Matthew Malcomson

Ping plus some extra people on Cc since I wasn't sure who to ask for review.
(Adding maintainers for `middle-end` plus Richard S).

N.b. I'd update the cover-letter to also mention that no existing 
implementation of `function_attribute_inlinable_p` uses "the current 
function" in any way.



On 4/8/24 11:34, Matthew Malcomson wrote:

The `function_attribute_inlinable_p` hook documentation described it
returning the value if it is OK to inline the provided fndecl into "the
current function".  AFAICS This hook is only called when
`current_function_decl` is the same as the `fndecl` argument that the
hook is given, hence asking whether `fndecl` can be inlined into "the
current function" doesn't make sense.
Update the documentation to match this understanding.

The `unspec_may_trap_p` documentation mentioned applying to either
`unspec` or `unspec_volatile`.  AFAICS this hook is only used for
`unspec` codes since c84a808e493a, so I removed the mention of
`unspec_volatile`.

gcc/ChangeLog:

* doc/tm.texi (function_attribute_inlinable_p,
unspec_may_trap_p): Update documentation.
* target.def (function_attribute_inlinable_p,
unspec_may_trap_p): Update documentation.

--
N.b. not entirely sure who to ask for review, went with docs maintainers, but
if that's incorrect please do redirect me.

### Attachment also inlined for ease of reply###


diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 
c8b8b126b2424b6552f824ba42ac329cfaf84d84..f0051f0ae1e9444d5d585135c90a68ca760c2fbd
 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -10752,10 +10752,10 @@ attribute handlers.  So far this only affects the 
@var{noinit} and
  
  @deftypefn {Target Hook} bool TARGET_FUNCTION_ATTRIBUTE_INLINABLE_P (const_tree @var{fndecl})

  @cindex inlining
-This target hook returns @code{true} if it is OK to inline @var{fndecl}
-into the current function, despite its having target-specific
-attributes, @code{false} otherwise.  By default, if a function has a
-target specific attribute attached to it, it will not be inlined.
+This target hook returns @code{false} if the target-specific attributes on
+@var{fndecl} always block it getting inlined, @code{true} otherwise.  By
+default, if a function has a target specific attribute attached to it, it
+will not be inlined.
  @end deftypefn
  
  @deftypefn {Target Hook} bool TARGET_OPTION_VALID_ATTRIBUTE_P (tree @var{fndecl}, tree @var{name}, tree @var{args}, int @var{flags})

@@ -12245,12 +12245,10 @@ allocation.
  @end deftypefn
  
  @deftypefn {Target Hook} int TARGET_UNSPEC_MAY_TRAP_P (const_rtx @var{x}, unsigned @var{flags})

-This target hook returns nonzero if @var{x}, an @code{unspec} or
-@code{unspec_volatile} operation, might cause a trap.  Targets can use
-this hook to enhance precision of analysis for @code{unspec} and
-@code{unspec_volatile} operations.  You may call @code{may_trap_p_1}
-to analyze inner elements of @var{x} in which case @var{flags} should be
-passed along.
+This target hook returns nonzero if @var{x}, an @code{unspec} might cause
+a trap.  Targets can use this hook to enhance precision of analysis for
+@code{unspec} operations.  You may call @code{may_trap_p_1} to analyze inner
+elements of @var{x} in which case @var{flags} should be passed along.
  @end deftypefn
  
  @deftypefn {Target Hook} void TARGET_SET_CURRENT_FUNCTION (tree @var{decl})

diff --git a/gcc/target.def b/gcc/target.def
index 
fdad7bbc93e2ad8aea30336d5cd4af67801e9c74..2b2a6c11807eff228788fae1cd1370e8971fbf3e
 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -2314,10 +2314,10 @@ attribute handlers.  So far this only affects the 
@var{noinit} and\n\
  DEFHOOK
  (function_attribute_inlinable_p,
   "@cindex inlining\n\
-This target hook returns @code{true} if it is OK to inline @var{fndecl}\n\
-into the current function, despite its having target-specific\n\
-attributes, @code{false} otherwise.  By default, if a function has a\n\
-target specific attribute attached to it, it will not be inlined.",
+This target hook returns @code{false} if the target-specific attributes on\n\
+@var{fndecl} always block it getting inlined, @code{true} otherwise.  By\n\
+default, if a function has a target specific attribute attached to it, it\n\
+will not be inlined.",
   bool, (const_tree fndecl),
   hook_bool_const_tree_false)
  
@@ -4057,12 +4057,10 @@ allocation.",

 FLAGS has the same meaning as in rtlanal.cc: may_trap_p_1.  */
  DEFHOOK
  (unspec_may_trap_p,
- "This target hook returns nonzero if @var{x}, an @code{unspec} or\n\
-@code{unspec_volatile} operation, might cause a trap.  Targets can use\n\
-this hook to enhance precision of analysis for @code{unspec} and\n\
-@code{unspec_volatile} operations.  You may call @code{may_trap_p_1}\n\
-to analyze inner elements of @var{x} in which case @var{flags} should be\n\
-passed along."

testsuite: Remove no_fsanitize_address install directory dependency

2024-07-10 Thread Matthew Malcomson
The current no_fsanitize_address effective target check (implemented in
target-supports.exp rather than in asan.exp) has some problems with the
link path.

Because it is not called from in between asan_init and asan_finish the
link paths of the compiler are not changed to point at the build
directories.

That means that they point at the install directory that the current
build is configured for.  Hence this test passes if the current compiler
has ASAN support *and* if there are ASAN libraries in the directory that
this build is configured to install into.

That is an unnecessary requirement.  On looking through each of the
tests that currently use no_fsanitize_address it seems all are `compile`
tests.  Hence we can change the logical test of the effective target
from "can we link an ASAN executable" to "can we compile for ASAN" and
avoid the need to set up link paths correctly for this test.

N.b. one alternative would be to remove this effective target and try to
move all tests which currently use this into directories which run their
tests between calls to `asan_finish` and `asan_init`.  This seems like
it might ensure a clearer division of "asan tests must be run in X
directories" and avoid problems similar to the one here in the future.
I'm suggesting this change as it appears the easiest to make and I
didn't think the above too bad a risk to take -- especially if the name
of the test is clear.

In doing this I also inverted the meaning of this check.  Rather than
the function indicating whether we *do not* support something and
tests using `dg-skip-if` to avoid running a test if this returns true,
this function indicates whether we *do* support something and tests
use `dg-require-effective-target` to run a test if it returns true.

Testing done by checking that each of the affected testcases changes
from UNSUPPORTED to PASS when run individually without any install
directory available.

gcc/testsuite/ChangeLog:

* g++.dg/warn/uninit-pr93100.C: Convert no_fsanitize_address use
to fsanitize_address_compilation.
* gcc.dg/pr91441.c: Likewise.
* gcc.dg/pr96260.c: Likewise.
* gcc.dg/pr96307.c: Likewise.
* gcc.dg/uninit-pr93100.c: Likewise.
* gnat.dg/asan1.adb: Likewise.
* gcc.target/aarch64/sve/pr97696.c: Likewise.
* lib/target-supports.exp (no_fsanitize_address): Rename to ...
(fsanitize_address_compilation): Make this a compile-only test
and avoid the need to set linker paths and invert semantics.



### Attachment also inlined for ease of reply###


diff --git a/gcc/testsuite/g++.dg/warn/uninit-pr93100.C 
b/gcc/testsuite/g++.dg/warn/uninit-pr93100.C
index 
e08a36d68a91ba9620ab44d5772017d598f50826..2f6056cc3c3e8fd4aa8e88236a31b8f4344b89ca
 100644
--- a/gcc/testsuite/g++.dg/warn/uninit-pr93100.C
+++ b/gcc/testsuite/g++.dg/warn/uninit-pr93100.C
@@ -1,7 +1,7 @@
 /* PR tree-optimization/98508 - Sanitizer disable -Wall and -Wextra
{ dg-do compile }
{ dg-options "-O0 -Wall -fsanitize=address" }
-   { dg-skip-if "no address sanitizer" { no_fsanitize_address } } */
+   { dg-require-effective-target fsanitize_address_compilation } */
 
 struct S
 {
diff --git a/gcc/testsuite/gcc.dg/pr91441.c b/gcc/testsuite/gcc.dg/pr91441.c
index 
4c785f61e597533202f9d3a42ce5a94aa3fd758f..4bd4c295913262463e2029f4a0466719474cc77a
 100644
--- a/gcc/testsuite/gcc.dg/pr91441.c
+++ b/gcc/testsuite/gcc.dg/pr91441.c
@@ -1,7 +1,7 @@
 /* PR target/91441 */
 /* { dg-do compile  } */
 /* { dg-options "--param asan-stack=1 -fsanitize=kernel-address" } */
-/* { dg-skip-if "no address sanitizer" { no_fsanitize_address } } */
+/* { dg-require-effective-target fsanitize_address_compilation } */
 
 int *bar(int *);
 int *f( int a)
diff --git a/gcc/testsuite/gcc.dg/pr96260.c b/gcc/testsuite/gcc.dg/pr96260.c
index 
587afb76116c5759751d5d6a2ceb1b4a392bc38a..a2b326c8e567972494e6e64d33a3e7f6c514f91d
 100644
--- a/gcc/testsuite/gcc.dg/pr96260.c
+++ b/gcc/testsuite/gcc.dg/pr96260.c
@@ -1,7 +1,7 @@
 /* PR target/96260 */
 /* { dg-do compile } */
 /* { dg-options "--param asan-stack=1 -fsanitize=kernel-address 
-fasan-shadow-offset=0x10" } */
-/* { dg-skip-if "no address sanitizer" { no_fsanitize_address } } */
+/* { dg-require-effective-target fsanitize_address_compilation } */
 
 int *bar(int *);
 int *f( int a)
diff --git a/gcc/testsuite/gcc.dg/pr96307.c b/gcc/testsuite/gcc.dg/pr96307.c
index 
89002b85c8ea6829e6b78679eedde653bb16753e..f49a9f642d35ffdfb16ac4f715dd8a25793a4817
 100644
--- a/gcc/testsuite/gcc.dg/pr96307.c
+++ b/gcc/testsuite/gcc.dg/pr96307.c
@@ -1,7 +1,7 @@
 /* PR target/96307 */
 /* { dg-do compile } */
 /* { dg-additional-options "-fsanitize=kernel-address 
--param=asan-instrumentation-with-call-threshold=8" } */
-/* { dg-skip-if "no address sanitizer" { no_fsanitize_address } } */
+/* { dg-require-effective-target fsanitize_address_compilation } */
 
 #include 
 enum a {test1, test2, test3=INT_MAX};
diff -

Re: testsuite: Remove no_fsanitize_address install directory dependency

2024-07-10 Thread Matthew Malcomson

... Oops, just after sending I noticed that
`check_effective_target_fsanitize_address_compilation` is caching its 
result under the same name as the original 
`check_effective_target_fsanitize_address` in `asan-dg.exp`.


Attaching an updated patch (with updated cover letter) that adjusts the 
property that uses a different name to cache under, given that this is

testing something different than the original function.
Have again tested that the problematic tests run without an install 
directory.



On 7/10/24 13:19, Matthew Malcomson wrote:

The current no_fsanitize_address effective target check (implemented in
target-supports.exp rather than in asan.exp) has some problems with the
link path.

Because it is not called from in between asan_init and asan_finish the
link paths of the compiler are not changed to point at the build
directories.

That means that they point at the install directory that the current
build is configured for.  Hence this test passes if the current compiler
has ASAN support *and* if there are ASAN libraries in the directory that
this build is configured to install into.

That is an unnecessary requirement.  On looking through each of the
tests that currently use no_fsanitize_address it seems all are `compile`
tests.  Hence we can change the logical test of the effective target
from "can we link an ASAN executable" to "can we compile for ASAN" and
avoid the need to set up link paths correctly for this test.

N.b. one alternative would be to remove this effective target and try to
move all tests which currently use this into directories which run their
tests between calls to `asan_finish` and `asan_init`.  This seems like
it might ensure a clearer division of "asan tests must be run in X
directories" and avoid problems similar to the one here in the future.
I'm suggesting this change as it appears the easiest to make and I
didn't think the above too bad a risk to take -- especially if the name
of the test is clear.

In doing this I also inverted the meaning of this check.  Rather than
the function indicating whether we *do not* support something and
tests using `dg-skip-if` to avoid running a test if this returns true,
this function indicates whether we *do* support something and tests
use `dg-require-effective-target` to run a test if it returns true.

Testing done by checking that each of the affected testcases changes
from UNSUPPORTED to PASS when run individually without any install
directory available.

gcc/testsuite/ChangeLog:

* g++.dg/warn/uninit-pr93100.C: Convert no_fsanitize_address use
to fsanitize_address_compilation.
* gcc.dg/pr91441.c: Likewise.
* gcc.dg/pr96260.c: Likewise.
* gcc.dg/pr96307.c: Likewise.
* gcc.dg/uninit-pr93100.c: Likewise.
* gnat.dg/asan1.adb: Likewise.
* gcc.target/aarch64/sve/pr97696.c: Likewise.
* lib/target-supports.exp (no_fsanitize_address): Rename to ...
(fsanitize_address_compilation): Make this a compile-only test
and avoid the need to set linker paths and invert semantics.



### Attachment also inlined for ease of reply###


diff --git a/gcc/testsuite/g++.dg/warn/uninit-pr93100.C 
b/gcc/testsuite/g++.dg/warn/uninit-pr93100.C
index 
e08a36d68a91ba9620ab44d5772017d598f50826..2f6056cc3c3e8fd4aa8e88236a31b8f4344b89ca
 100644
--- a/gcc/testsuite/g++.dg/warn/uninit-pr93100.C
+++ b/gcc/testsuite/g++.dg/warn/uninit-pr93100.C
@@ -1,7 +1,7 @@
  /* PR tree-optimization/98508 - Sanitizer disable -Wall and -Wextra
 { dg-do compile }
 { dg-options "-O0 -Wall -fsanitize=address" }
-   { dg-skip-if "no address sanitizer" { no_fsanitize_address } } */
+   { dg-require-effective-target fsanitize_address_compilation } */
  
  struct S

  {
diff --git a/gcc/testsuite/gcc.dg/pr91441.c b/gcc/testsuite/gcc.dg/pr91441.c
index 
4c785f61e597533202f9d3a42ce5a94aa3fd758f..4bd4c295913262463e2029f4a0466719474cc77a
 100644
--- a/gcc/testsuite/gcc.dg/pr91441.c
+++ b/gcc/testsuite/gcc.dg/pr91441.c
@@ -1,7 +1,7 @@
  /* PR target/91441 */
  /* { dg-do compile  } */
  /* { dg-options "--param asan-stack=1 -fsanitize=kernel-address" } */
-/* { dg-skip-if "no address sanitizer" { no_fsanitize_address } } */
+/* { dg-require-effective-target fsanitize_address_compilation } */
  
  int *bar(int *);

  int *f( int a)
diff --git a/gcc/testsuite/gcc.dg/pr96260.c b/gcc/testsuite/gcc.dg/pr96260.c
index 
587afb76116c5759751d5d6a2ceb1b4a392bc38a..a2b326c8e567972494e6e64d33a3e7f6c514f91d
 100644
--- a/gcc/testsuite/gcc.dg/pr96260.c
+++ b/gcc/testsuite/gcc.dg/pr96260.c
@@ -1,7 +1,7 @@
  /* PR target/96260 */
  /* { dg-do compile } */
  /* { dg-options "--param asan-stack=1 -fsanitize=kernel-address 
-fasan-shadow-offset=0x10" } */
-/* { dg-skip-if "no address sanitizer" { no_fsanitize_address } } */
+/* { dg-require-effective-target fsanitize_address_compil

Re: testsuite: Remove no_fsanitize_address install directory dependency

2024-07-10 Thread Matthew Malcomson

On 7/10/24 13:42, Rainer Orth wrote:

N.b. one alternative would be to remove this effective target and try to
move all tests which currently use this into directories which run their
tests between calls to `asan_finish` and `asan_init`.  This seems like
it might ensure a clearer division of "asan tests must be run in X
directories" and avoid problems similar to the one here in the future.
I'm suggesting this change as it appears the easiest to make and I
didn't think the above too bad a risk to take -- especially if the name
of the test is clear.


moving the tests would be clearer IMO, otherwise we have two separate
mechanisms for the same issue.  Especially since we're talking about 7
tests only.  The only complication would be the aarch64 test where
there's currently no asan subdir.


I'm in the middle of doing this.

Just wanted to mention the other complications (in case that changes 
what looks like the best option) -- the compilation options that tests 
get run under change (because they're being run by a different test 
runner), and also there's no `asan` subdir for gnat.dg (the ada test).


I'm thinking that the change in options is not that bad (will eventually 
filter out the options that are not valid for the test, will likely run 
with slightly less variations than before), but still worth mentioning.





In doing this I also inverted the meaning of this check.  Rather than
the function indicating whether we *do not* support something and
tests using `dg-skip-if` to avoid running a test if this returns true,
this function indicates whether we *do* support something and tests
use `dg-require-effective-target` to run a test if it returns true.

Testing done by checking that each of the affected testcases changes
from UNSUPPORTED to PASS when run individually without any install
directory available.


Please remember to state on which target you've run the tests.


Good point ;-)
I ran the SVE test on AArch64, the ada test on x86 (because that's where 
I could install a host gnat compiler easily to build ada), and all the 
others on both these targets.


[PATCH 2/X] libsanitizer: Only build libhwasan when targeting AArch64

2020-08-17 Thread Matthew Malcomson
Though the library has limited support for x86, we don't have any
support for generating code targeting x86 so there is no point building
for that target.

libsanitizer/ChangeLog:

* Makefile.am: Condition building hwasan directory.
* Makefile.in: Regenerate.
* configure: Regenerate.
* configure.ac: Set HWASAN_SUPPORTED based on target
architecture.
* configure.tgt: Likewise.



### Attachment also inlined for ease of reply###


diff --git a/libsanitizer/Makefile.am b/libsanitizer/Makefile.am
index 
2a7e8e1debe838719db0f0fad218b2543cc3111b..065a65e78d49f7689a01ecb64db1f07ca83aa987
 100644
--- a/libsanitizer/Makefile.am
+++ b/libsanitizer/Makefile.am
@@ -14,7 +14,7 @@ endif
 if LIBBACKTRACE_SUPPORTED
 SUBDIRS += libbacktrace
 endif
-SUBDIRS += lsan asan ubsan hwasan
+SUBDIRS += lsan asan ubsan
 nodist_saninclude_HEADERS += \
   include/sanitizer/lsan_interface.h \
   include/sanitizer/asan_interface.h \
@@ -23,6 +23,9 @@ nodist_saninclude_HEADERS += \
 if TSAN_SUPPORTED
 SUBDIRS += tsan
 endif
+if HWASAN_SUPPORTED
+SUBDIRS += hwasan
+endif
 endif
 
 ## May be used by toolexeclibdir.
diff --git a/libsanitizer/Makefile.in b/libsanitizer/Makefile.in
index 
2c57d49cbffdb486645aeb5f2c0f85d6e0fad124..3873ea4d7050f04a3f7bbd0dd3f2a71e9b65d287
 100644
--- a/libsanitizer/Makefile.in
+++ b/libsanitizer/Makefile.in
@@ -97,6 +97,7 @@ target_triplet = @target@
 @SANITIZER_SUPPORTED_TRUE@@USING_MAC_INTERPOSE_FALSE@am__append_2 = 
interception
 @LIBBACKTRACE_SUPPORTED_TRUE@@SANITIZER_SUPPORTED_TRUE@am__append_3 = 
libbacktrace
 @SANITIZER_SUPPORTED_TRUE@@TSAN_SUPPORTED_TRUE@am__append_4 = tsan
+@HWASAN_SUPPORTED_TRUE@@SANITIZER_SUPPORTED_TRUE@am__append_5 = hwasan
 subdir = .
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
 am__aclocal_m4_deps = $(top_srcdir)/../config/acx.m4 \
@@ -208,7 +209,7 @@ ETAGS = etags
 CTAGS = ctags
 CSCOPE = cscope
 DIST_SUBDIRS = sanitizer_common interception libbacktrace lsan asan \
-   ubsan hwasan tsan
+   ubsan tsan hwasan
 ACLOCAL = @ACLOCAL@
 ALLOC_FILE = @ALLOC_FILE@
 AMTAR = @AMTAR@
@@ -364,7 +365,7 @@ sanincludedir = 
$(libdir)/gcc/$(target_alias)/$(gcc_version)/include/sanitizer
 nodist_saninclude_HEADERS = $(am__append_1)
 @SANITIZER_SUPPORTED_TRUE@SUBDIRS = sanitizer_common $(am__append_2) \
 @SANITIZER_SUPPORTED_TRUE@ $(am__append_3) lsan asan ubsan \
-@SANITIZER_SUPPORTED_TRUE@ hwasan $(am__append_4)
+@SANITIZER_SUPPORTED_TRUE@ $(am__append_4) $(am__append_5)
 gcc_version := $(shell @get_gcc_base_ver@ $(top_srcdir)/../gcc/BASE-VER)
 
 # Work around what appears to be a GNU make bug handling MAKEFLAGS
diff --git a/libsanitizer/configure b/libsanitizer/configure
index 
9ed9669a85d3cfc2f2f623e796e61a5f8f7e4ded..cc5c229f4aebcdd454e9e2e415a8e16046dc1b1a
 100755
--- a/libsanitizer/configure
+++ b/libsanitizer/configure
@@ -659,6 +659,8 @@ link_libubsan
 link_libtsan
 link_libhwasan
 link_libasan
+HWASAN_SUPPORTED_FALSE
+HWASAN_SUPPORTED_TRUE
 LSAN_SUPPORTED_FALSE
 LSAN_SUPPORTED_TRUE
 TSAN_SUPPORTED_FALSE
@@ -12362,7 +12364,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 12365 "configure"
+#line 12367 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -12468,7 +12470,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 12471 "configure"
+#line 12473 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -15819,6 +15821,7 @@ fi
 # Get target configury.
 unset TSAN_SUPPORTED
 unset LSAN_SUPPORTED
+unset HWASAN_SUPPORTED
 . ${srcdir}/configure.tgt
  if test "x$TSAN_SUPPORTED" = "xyes"; then
   TSAN_SUPPORTED_TRUE=
@@ -15836,6 +15839,14 @@ else
   LSAN_SUPPORTED_FALSE=
 fi
 
+ if test "x$HWASAN_SUPPORTED" = "xyes"; then
+  HWASAN_SUPPORTED_TRUE=
+  HWASAN_SUPPORTED_FALSE='#'
+else
+  HWASAN_SUPPORTED_TRUE='#'
+  HWASAN_SUPPORTED_FALSE=
+fi
+
 
 # Check for functions needed.
 for ac_func in clock_getres clock_gettime clock_settime lstat readlink
@@ -16818,7 +16829,7 @@ ac_config_files="$ac_config_files Makefile 
libsanitizer.spec libbacktrace/backtr
 ac_config_headers="$ac_config_headers config.h"
 
 
-ac_config_files="$ac_config_files interception/Makefile 
sanitizer_common/Makefile libbacktrace/Makefile lsan/Makefile asan/Makefile 
hwasan/Makefile ubsan/Makefile"
+ac_config_files="$ac_config_files interception/Makefile 
sanitizer_common/Makefile libbacktrace/Makefile lsan/Makefile asan/Makefile 
ubsan/Makefile"
 
 
 if test "x$TSAN_SUPPORTED" = "xyes"; then
@@ -16826,6 +16837,11 @@ if test "x$TSAN_SUPPORTED" = "xyes"; then
 
 fi
 
+if test "x$HWASAN_SUPPORTED" = "xyes"; then
+  ac_config_files="$ac_config_files hwasan/Makefile"
+
+fi
+
 
 
 
@@ -17090,6 +17106,10 @@ if test -z "${LSAN_SUPPORTED_TRUE}" && test -z 
"${LSAN_SUPPORTED_FALSE}"; then
   as_fn_error $? "conditional \"LSAN_SUPPORTED\" was never defined.
 Usually t

[PATCH 1/X] libsanitizer: Tie the hwasan library into our build system

2020-08-17 Thread Matthew Malcomson
This patch tries to tie libhwasan into the GCC build system in the same way
that the other sanitizer runtime libraries are handled.

libsanitizer/ChangeLog:

* Makefile.am:  Build libhwasan.
* Makefile.in:  Build libhwasan.
* asan/Makefile.in:  Build libhwasan.
* configure:  Build libhwasan.
* configure.ac:  Build libhwasan.
* hwasan/Makefile.am: New file.
* hwasan/Makefile.in: New file.
* hwasan/libtool-version: New file.
* interception/Makefile.in: Build libhwasan.
* libbacktrace/Makefile.in: Build libhwasan.
* libsanitizer.spec.in: Build libhwasan.
* lsan/Makefile.in: Build libhwasan.
* sanitizer_common/Makefile.in: Build libhwasan.
* tsan/Makefile.in: Build libhwasan.
* ubsan/Makefile.in: Build libhwasan.



### Attachment also inlined for ease of reply###


diff --git a/libsanitizer/Makefile.am b/libsanitizer/Makefile.am
index 
65ed1e712378ef453f820f86c4d3221f9dee5f2c..2a7e8e1debe838719db0f0fad218b2543cc3111b
 100644
--- a/libsanitizer/Makefile.am
+++ b/libsanitizer/Makefile.am
@@ -14,11 +14,12 @@ endif
 if LIBBACKTRACE_SUPPORTED
 SUBDIRS += libbacktrace
 endif
-SUBDIRS += lsan asan ubsan
+SUBDIRS += lsan asan ubsan hwasan
 nodist_saninclude_HEADERS += \
   include/sanitizer/lsan_interface.h \
   include/sanitizer/asan_interface.h \
-  include/sanitizer/tsan_interface.h
+  include/sanitizer/tsan_interface.h \
+  include/sanitizer/hwasan_interface.h
 if TSAN_SUPPORTED
 SUBDIRS += tsan
 endif
diff --git a/libsanitizer/Makefile.in b/libsanitizer/Makefile.in
index 
02c7f70ac6578a3e93a490ce8bd2c54fc0693c50..2c57d49cbffdb486645aeb5f2c0f85d6e0fad124
 100644
--- a/libsanitizer/Makefile.in
+++ b/libsanitizer/Makefile.in
@@ -92,7 +92,8 @@ target_triplet = @target@
 @SANITIZER_SUPPORTED_TRUE@am__append_1 = 
include/sanitizer/common_interface_defs.h \
 @SANITIZER_SUPPORTED_TRUE@ include/sanitizer/lsan_interface.h \
 @SANITIZER_SUPPORTED_TRUE@ include/sanitizer/asan_interface.h \
-@SANITIZER_SUPPORTED_TRUE@ include/sanitizer/tsan_interface.h
+@SANITIZER_SUPPORTED_TRUE@ include/sanitizer/tsan_interface.h \
+@SANITIZER_SUPPORTED_TRUE@ include/sanitizer/hwasan_interface.h
 @SANITIZER_SUPPORTED_TRUE@@USING_MAC_INTERPOSE_FALSE@am__append_2 = 
interception
 @LIBBACKTRACE_SUPPORTED_TRUE@@SANITIZER_SUPPORTED_TRUE@am__append_3 = 
libbacktrace
 @SANITIZER_SUPPORTED_TRUE@@TSAN_SUPPORTED_TRUE@am__append_4 = tsan
@@ -207,7 +208,7 @@ ETAGS = etags
 CTAGS = ctags
 CSCOPE = cscope
 DIST_SUBDIRS = sanitizer_common interception libbacktrace lsan asan \
-   ubsan tsan
+   ubsan hwasan tsan
 ACLOCAL = @ACLOCAL@
 ALLOC_FILE = @ALLOC_FILE@
 AMTAR = @AMTAR@
@@ -329,6 +330,7 @@ install_sh = @install_sh@
 libdir = @libdir@
 libexecdir = @libexecdir@
 link_libasan = @link_libasan@
+link_libhwasan = @link_libhwasan@
 link_liblsan = @link_liblsan@
 link_libtsan = @link_libtsan@
 link_libubsan = @link_libubsan@
@@ -362,7 +364,7 @@ sanincludedir = 
$(libdir)/gcc/$(target_alias)/$(gcc_version)/include/sanitizer
 nodist_saninclude_HEADERS = $(am__append_1)
 @SANITIZER_SUPPORTED_TRUE@SUBDIRS = sanitizer_common $(am__append_2) \
 @SANITIZER_SUPPORTED_TRUE@ $(am__append_3) lsan asan ubsan \
-@SANITIZER_SUPPORTED_TRUE@ $(am__append_4)
+@SANITIZER_SUPPORTED_TRUE@ hwasan $(am__append_4)
 gcc_version := $(shell @get_gcc_base_ver@ $(top_srcdir)/../gcc/BASE-VER)
 
 # Work around what appears to be a GNU make bug handling MAKEFLAGS
diff --git a/libsanitizer/asan/Makefile.in b/libsanitizer/asan/Makefile.in
index 
29622bf466a37f819c9fade30e31195adda51190..25c7fd7b7597d6e243005a1bb7de5b6243d2cfcf
 100644
--- a/libsanitizer/asan/Makefile.in
+++ b/libsanitizer/asan/Makefile.in
@@ -383,6 +383,7 @@ install_sh = @install_sh@
 libdir = @libdir@
 libexecdir = @libexecdir@
 link_libasan = @link_libasan@
+link_libhwasan = @link_libhwasan@
 link_liblsan = @link_liblsan@
 link_libtsan = @link_libtsan@
 link_libubsan = @link_libubsan@
diff --git a/libsanitizer/configure b/libsanitizer/configure
index 
04eca04fbe5e59bae1ba00597de0cf1b7cf1b5fa..9ed9669a85d3cfc2f2f623e796e61a5f8f7e4ded
 100755
--- a/libsanitizer/configure
+++ b/libsanitizer/configure
@@ -657,6 +657,7 @@ USING_MAC_INTERPOSE_TRUE
 link_liblsan
 link_libubsan
 link_libtsan
+link_libhwasan
 link_libasan
 LSAN_SUPPORTED_FALSE
 LSAN_SUPPORTED_TRUE
@@ -12361,7 +12362,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 12364 "configure"
+#line 12365 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -12467,7 +12468,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 12470 "configure"
+#line 12471 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -15943,6 +15944,10 @@ fi
 link_libasan=$link_sanitizer_common
 
 
+# Set up the set of additional libr

[PATCH 3/X] libsanitizer: Add option to bootstrap using HWASAN

2020-08-17 Thread Matthew Malcomson
This is an analogous option to --bootstrap-asan to configure.  It allows
bootstrapping GCC using HWASAN.

For the same reasons as for ASAN we have to avoid using the HWASAN
sanitizer when compiling libiberty and the lto-plugin.

Also add a function to query whether -fsanitize=hwaddress has been
passed.

ChangeLog:

* configure: Regenerate.
* configure.ac: Add --bootstrap-hwasan option.

config/ChangeLog:

* bootstrap-hwasan.mk: New file.

gcc/ChangeLog:

* doc/install.texi: Document new option.

libiberty/ChangeLog:

* configure: Regenerate.
* configure.ac: Avoid using sanitizer.

lto-plugin/ChangeLog:

* Makefile.am: Avoid using sanitizer.
* Makefile.in: Regenerate.



### Attachment also inlined for ease of reply###


diff --git a/config/bootstrap-hwasan.mk b/config/bootstrap-hwasan.mk
new file mode 100644
index 
..4f60bed3fd6e98b47a3a38aea6eba2a7c320da25
--- /dev/null
+++ b/config/bootstrap-hwasan.mk
@@ -0,0 +1,8 @@
+# This option enables -fsanitize=hwaddress for stage2 and stage3.
+
+STAGE2_CFLAGS += -fsanitize=hwaddress
+STAGE3_CFLAGS += -fsanitize=hwaddress
+POSTSTAGE1_LDFLAGS += -fsanitize=hwaddress -static-libhwasan \
+ -B$$r/prev-$(TARGET_SUBDIR)/libsanitizer/ \
+ -B$$r/prev-$(TARGET_SUBDIR)/libsanitizer/hwasan/ \
+ -B$$r/prev-$(TARGET_SUBDIR)/libsanitizer/hwasan/.libs
diff --git a/configure b/configure
index 
a0c5aca9e8d5cae2782c8fe4625a501853dc226a..203319e3f899e8d24429950c3a5d22927fb5150f
 100755
--- a/configure
+++ b/configure
@@ -8297,7 +8297,7 @@ fi
 # or bootstrap-ubsan, bootstrap it.
 if echo " ${target_configdirs} " | grep " libsanitizer " > /dev/null 2>&1; then
   case "$BUILD_CONFIG" in
-*bootstrap-asan* | *bootstrap-ubsan* )
+*bootstrap-hwasan* | *bootstrap-asan* | *bootstrap-ubsan* )
   bootstrap_target_libs=${bootstrap_target_libs}target-libsanitizer,
   bootstrap_fixincludes=yes
   ;;
diff --git a/configure.ac b/configure.ac
index 
1a53ed418e4d97606356b14a17b50186c79adcd3..9d5c187c31bfc01003e75058896b686807e47643
 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2809,7 +2809,7 @@ fi
 # or bootstrap-ubsan, bootstrap it.
 if echo " ${target_configdirs} " | grep " libsanitizer " > /dev/null 2>&1; then
   case "$BUILD_CONFIG" in
-*bootstrap-asan* | *bootstrap-ubsan* )
+*bootstrap-hwasan* | *bootstrap-asan* | *bootstrap-ubsan* )
   bootstrap_target_libs=${bootstrap_target_libs}target-libsanitizer,
   bootstrap_fixincludes=yes
   ;;
diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi
index 
d581a34653f61a440b3c3b832836fe109e2fbd08..25d041fcbb1f7c16f7ac47b7b5d4ea8308c6f69c
 100644
--- a/gcc/doc/install.texi
+++ b/gcc/doc/install.texi
@@ -2767,6 +2767,11 @@ the build tree.
 Compiles GCC itself using Address Sanitization in order to catch invalid memory
 accesses within the GCC code.
 
+@item @samp{bootstrap-hwasan}
+Compiles GCC itself using HWAddress Sanitization in order to catch invalid
+memory accesses within the GCC code.  This option is only available on AArch64
+targets running a Linux kernel that supports the required ABI (5.4 or later).
+
 @end table
 
 @section Building a cross compiler
diff --git a/libiberty/configure b/libiberty/configure
index 
1f8e23f0d235a6a5d5158bf6705023db95ac7023..59e0b73d5838bbd42a5548759084471e97ec254f
 100755
--- a/libiberty/configure
+++ b/libiberty/configure
@@ -5264,6 +5264,7 @@ fi
 NOASANFLAG=
 case " ${CFLAGS} " in
   *\ -fsanitize=address\ *) NOASANFLAG=-fno-sanitize=address ;;
+  *\ -fsanitize=hwaddress\ *) NOASANFLAG=-fno-sanitize=hwaddress ;;
 esac
 
 
diff --git a/libiberty/configure.ac b/libiberty/configure.ac
index 
4e2599c14a89bafcb8c7e523b9ce5b3d60b8c0f6..ad952963971a31968b5d109661b9cab0aa4b95fc
 100644
--- a/libiberty/configure.ac
+++ b/libiberty/configure.ac
@@ -240,6 +240,7 @@ AC_SUBST(PICFLAG)
 NOASANFLAG=
 case " ${CFLAGS} " in
   *\ -fsanitize=address\ *) NOASANFLAG=-fno-sanitize=address ;;
+  *\ -fsanitize=hwaddress\ *) NOASANFLAG=-fno-sanitize=hwaddress ;;
 esac
 AC_SUBST(NOASANFLAG)
 
diff --git a/lto-plugin/Makefile.am b/lto-plugin/Makefile.am
index 
ba5882df7a7272f65219191c82ecd78ab4d3725e..50d6e09dac881d28d4ff70def47b09ed8c0ea66c
 100644
--- a/lto-plugin/Makefile.am
+++ b/lto-plugin/Makefile.am
@@ -11,8 +11,8 @@ AM_CPPFLAGS = -I$(top_srcdir)/../include $(DEFS)
 AM_CFLAGS = @ac_lto_plugin_warn_cflags@ $(CET_HOST_FLAGS)
 AM_LDFLAGS = @ac_lto_plugin_ldflags@
 AM_LIBTOOLFLAGS = --tag=disable-static
-override CFLAGS := $(filter-out -fsanitize=address,$(CFLAGS))
-override LDFLAGS := $(filter-out -fsanitize=address,$(LDFLAGS))
+override CFLAGS := $(filter-out -fsanitize=address 
-fsanitize=hwaddress,$(CFLAGS))
+override LDFLAGS := $(filter-out -fsanitize=address 
-fsanitize=hwaddress,$(LDFLAGS))
 
 libexecsub_LTLIBRARIES = liblto_plugin.la
 gcc_build_dir = @gcc_build_dir@
diff --git a/lto-plugin/Ma

[PATCH 7/X] libsanitizer: Add tests

2020-08-17 Thread Matthew Malcomson
Adding hwasan tests.

Only interesting thing here is that we have to make sure the tagging mechanism
is deterministic to avoid flaky tests.

gcc/testsuite/ChangeLog:

* c-c++-common/hwasan/aligned-alloc.c: New test.
* c-c++-common/hwasan/alloca-array-accessible.c: New test.
* c-c++-common/hwasan/alloca-gets-different-tag.c: New test.
* c-c++-common/hwasan/alloca-outside-caught.c: New test.
* c-c++-common/hwasan/arguments.c: New test.
* c-c++-common/hwasan/arguments-1.c: New test.
* c-c++-common/hwasan/arguments-2.c: New test.
* c-c++-common/hwasan/arguments-3.c: New test.
* c-c++-common/hwasan/asan-pr63316.c: New test.
* c-c++-common/hwasan/asan-pr70541.c: New test.
* c-c++-common/hwasan/asan-pr78106.c: New test.
* c-c++-common/hwasan/asan-pr79944.c: New test.
* c-c++-common/hwasan/asan-rlimit-mmap-test-1.c: New test.
* c-c++-common/hwasan/bitfield-1.c: New test.
* c-c++-common/hwasan/bitfield-2.c: New test.
* c-c++-common/hwasan/builtin-special-handling.c: New test.
* c-c++-common/hwasan/check-interface.c: New test.
* c-c++-common/hwasan/halt_on_error-1.c: New test.
* c-c++-common/hwasan/heap-overflow.c: New test.
* c-c++-common/hwasan/hwasan-poison-optimisation.c: New test.
* c-c++-common/hwasan/hwasan-thread-access-parent.c: New test.
* c-c++-common/hwasan/hwasan-thread-basic-failure.c: New test.
* c-c++-common/hwasan/hwasan-thread-clears-stack.c: New test.
* c-c++-common/hwasan/hwasan-thread-success.c: New test.
* c-c++-common/hwasan/kernel-defaults.c: New test.
* c-c++-common/hwasan/large-aligned-0.c: New test.
* c-c++-common/hwasan/large-aligned-1.c: New test.
* c-c++-common/hwasan/large-aligned-untagging-0.c: New test.
* c-c++-common/hwasan/large-aligned-untagging-1.c: New test.
* c-c++-common/hwasan/large-aligned-untagging-2.c: New test.
* c-c++-common/hwasan/large-aligned-untagging-3.c: New test.
* c-c++-common/hwasan/large-aligned-untagging-4.c: New test.
* c-c++-common/hwasan/large-aligned-untagging-5.c: New test.
* c-c++-common/hwasan/large-aligned-untagging-6.c: New test.
* c-c++-common/hwasan/large-aligned-untagging-7.c: New test.
* c-c++-common/hwasan/macro-definition.c: New test.
* c-c++-common/hwasan/no-sanitize-attribute.c: New test.
* c-c++-common/hwasan/param-instrument-reads-and-writes.c: New test.
* c-c++-common/hwasan/param-instrument-reads.c: New test.
* c-c++-common/hwasan/param-instrument-writes.c: New test.
* c-c++-common/hwasan/param-instrument-mem-intrinsics.c: New test.
* c-c++-common/hwasan/random-frame-tag.c: New test.
* c-c++-common/hwasan/sanity-check-pure-c.c: New test.
* c-c++-common/hwasan/setjmp-longjmp-0.c: New test.
* c-c++-common/hwasan/setjmp-longjmp-1.c: New test.
* c-c++-common/hwasan/stack-tagging-basic-0.c: New test.
* c-c++-common/hwasan/stack-tagging-basic-1.c: New test.
* c-c++-common/hwasan/stack-tagging-disable.c: New test.
* c-c++-common/hwasan/unprotected-allocas-0.c: New test.
* c-c++-common/hwasan/unprotected-allocas-1.c: New test.
* c-c++-common/hwasan/use-after-free.c: New test.
* c-c++-common/hwasan/vararray-outside-caught.c: New test.
* c-c++-common/hwasan/vararray-stack-restore-correct.c: New test.
* c-c++-common/hwasan/very-large-objects.c: New test.
* g++.dg/hwasan/hwasan.exp: New file.
* g++.dg/hwasan/rvo-handled.C: New test.
* gcc.dg/hwasan/hwasan.exp: New file.
* gcc.dg/hwasan/nested-functions-0.c: New test.
* gcc.dg/hwasan/nested-functions-1.c: New test.
* gcc.dg/hwasan/nested-functions-2.c: New test.
* lib/hwasan-dg.exp: New file.


hwasan-diff6.patch.gz
Description: application/gzip


[PATCH 5/X] libsanitizer: mid-end: Introduce stack variable handling for HWASAN

2020-08-17 Thread Matthew Malcomson
Handling stack variables has three features.

1) Ensure HWASAN required alignment for stack variables

When tagging shadow memory, we need to ensure that each tag granule is
only used by one variable at a time.

This is done by ensuring that each tagged variable is aligned to the tag
granule representation size and also ensure that the end of each
object is aligned to ensure the start of any other data stored on the
stack is in a different granule.

This patch ensures the above by adding alignment requirements in
`align_local_variable` and forcing all stack variable allocation to be
deferred so that `expand_stack_vars` can ensure the stack pointer is
aligned before allocating any variable for the current frame.

2) Put tags into each stack variable pointer

Make sure that every pointer to a stack variable includes a tag of some
sort on it.

The way tagging works is:
  1) For every new stack frame, a random tag is generated.
  2) A base register is formed from the stack pointer value and this
 random tag.
  3) References to stack variables are now formed with RTL describing an
 offset from this base in both tag and value.

The random tag generation is handled by a backend hook.  This hook
decides whether to introduce a random tag or use the stack background
based on the parameter hwasan-random-frame-tag.  Using the stack
background is necessary for testing and bootstrap.  It is necessary
during bootstrap to avoid breaking the `configure` test program for
determining stack direction.

Using the stack background means that every stack frame has the initial
tag of zero and variables are tagged with incrementing tags from 1,
which also makes debugging a bit easier.

The tag&value offsets are also handled by a backend hook.

This patch also adds some macros defining how the HWASAN shadow memory
is stored and how a tag is stored in a pointer.

3) For each stack variable, tag and untag the shadow stack on function
   prologue and epilogue.

On entry to each function we tag the relevant shadow stack region for
each stack variable the tag to match the tag added to each pointer for
that variable.

This is the first patch where we use the HWASAN shadow space, so we need
to add in the libhwasan initialisation code that creates this shadow
memory region into the binary we produce.  This instrumentation is done
in `compile_file`.

When exiting a function we need to ensure the shadow stack for this
function has no remaining tag.  Without clearing the shadow stack area
for this stack frame, later function calls could get false positives
when those later function calls check untagged areas (such as parameters
passed on the stack) against a shadow stack area with left-over tag.

Hence we ensure that the entire stack frame is cleared on function exit.

config/ChangeLog:

* bootstrap-hwasan.mk: Disable random frame tags for
stack-tagging during bootstrap.

gcc/ChangeLog:

* asan.c (hwasan_record_base): New function.
(hwasan_emit_untag_frame): New.
(hwasan_increment_tag): New function.
(hwasan_with_tag): New function.
(hwasan_tag_init): New function.
(initialize_sanitizer_builtins): Define new builtins.
(ATTR_NOTHROW_LIST): New macro.
(hwasan_current_tag): New.
(hwasan_extract_tag): New.
(hwasan_emit_prologue): New.
(hwasan_create_untagged_base): New.
(hwasan_finish_file): New.
(hwasan_ctor_statements): New variable.
(hwasan_sanitize_stack_p): New.
(hwasan_sanitize_p): New.
(hwasan_sanitize_allocas_p): New.
* asan.h (hwasan_record_base): New declaration.
(hwasan_emit_untag_frame): New.
(hwasan_increment_tag): New declaration.
(hwasan_with_tag): New declaration.
(hwasan_sanitize_stack_p): New declaration.
(hwasan_sanitize_allocas_p): New declaration.
(hwasan_tag_init): New declaration.
(hwasan_sanitize_p): New declaration.
(HWASAN_TAG_SIZE): New macro.
(HWASAN_TAG_GRANULE_SIZE): New macro.
(HWASAN_TAG_SHIFT_SIZE): New macro.
(HWASAN_SHIFT): New macro.
(HWASAN_SHIFT_RTX): New macro.
(HWASAN_STACK_BACKGROUND): New macro.
(hwasan_finish_file): New declaration.
(hwasan_current_tag): New declaration.
(hwasan_create_untagged_base): New declaration.
(hwasan_extract_tag): New declaration.
(hwasan_emit_prologue): New declaration.
* cfgexpand.c (struct stack_vars_data): Add information to
record hwasan variable stack offsets.
(expand_stack_vars): Ensure variables are offset from a tagged
base. Record offsets for hwasan. Ensure alignment.
(expand_used_vars): Call function to emit prologue, and get
untagging instructions for function exit.
(align_local_variable): Ensure alignment.
(defer_stack_allocation): Ensure all variables are deferred so
they can be handled by `expan

[PATCH 6/X] libsanitizer: Add hwasan pass and associated gimple changes

2020-08-17 Thread Matthew Malcomson
There are four main features to this change:

1) Check pointer tags match address tags.

In the new `hwasan` pass we put HWASAN_CHECK internal functions before
all memory accesses to check that tags in the pointer being used match
the tag stored in shadow memory for the memory region being used.

These internal functions are expanded into actual checks in the sanopt
pass that happens just before expansion into RTL.

We use the same mechanism that currently inserts ASAN_CHECK internal
functions to insert the new HWASAN_CHECK functions.

2) Instrument known builtin function calls.

Handle all builtin functions that we know use memory accesses.
This commit uses the machinery added for ASAN to identify builtin
functions that access memory.

The main differences between the approaches for HWASAN and ASAN are:
 - libhwasan intercepts much less builtin functions.
 - Alloca needs to be transformed differently (instead of adding
   redzones it needs to tag shadow memory and return a tagged pointer).
 - stack_restore needs to untag the shadow stack between the current
   position and where it's going.
 - `noreturn` functions can not be handled by simply unpoisoning the
   entire shadow stack -- there is no "always valid" tag.
   (exceptions and things such as longjmp need to be handled in a
   different way).

For hardware implemented checking (such as AArch64's memory tagging
extension) alloca and stack_restore will need to be handled by hooks in
the backend rather than transformation at the gimple level.  This will
allow architecture specific handling of such stack modifications.

3) Introduce HWASAN block-scope poisoning

Here we use exactly the same mechanism as ASAN_MARK to poison/unpoison
variables on entry/exit of a block.

In order to simply use the exact same machinery we're using the same
internal functions until the SANOPT pass.  This means that all handling
of ASAN_MARK is the same.
This has the negative that the naming may be a little confusing, but a
positive that handling of the internal function doesn't have to be
duplicated for a function that behaves exactly the same but has a
different name.

gcc/ChangeLog:

* asan.c (asan_instrument_reads): New.
(asan_instrument_writes): New.
(asan_memintrin): New.
(handle_builtin_stack_restore): Account for HWASAN.
(handle_builtin_alloca): Account for HWASAN.
(get_mem_refs_of_builtin_call): Special case strlen for HWASAN.
(report_error_func): Assert not HWASAN.
(build_check_stmt): Make HWASAN_CHECK instead of ASAN_CHECK.
(instrument_derefs): HWASAN does not tag globals.
(instrument_builtin_call): Use new helper functions.
(maybe_instrument_call): Don't instrument `noreturn` functions.
(initialize_sanitizer_builtins): Add new type.
(asan_expand_mark_ifn): Account for HWASAN.
(asan_expand_check_ifn): Assert never called by HWASAN.
(asan_expand_poison_ifn): Account for HWASAN.
(hwasan_instrument_reads): New.
(hwasan_instrument_writes): New.
(hwasan_memintrin): New.
(hwasan_instrument): New.
(hwasan_base): New.
(hwasan_check_func): New.
(hwasan_expand_check_ifn): New.
(hwasan_expand_mark_ifn): New.
(gate_hwasan): New.
(class pass_hwasan): New.
(make_pass_hwasan): New.
(class pass_hwasan_O0): New.
(make_pass_hwasan_O0): New.
* asan.h (hwasan_base): New decl.
(hwasan_expand_check_ifn): New decl.
(hwasan_expand_mark_ifn): New decl.
(gate_hwasan): New decl.
(enum hwasan_mark_flags): New.
(asan_intercepted_p): Always false for hwasan.
(asan_sanitize_use_after_scope): Account for HWASAN.
* builtin-types.def (BT_FN_PTR_CONST_PTR_UINT8): New.
* gimple-pretty-print.c (dump_gimple_call_args): Account for
HWASAN.
* gimplify.c (asan_poison_variable): Account for HWASAN.
(gimplify_function_tree): Remove requirement of
SANITIZE_ADDRESS, requiring asan or hwasan is accounted for in
`asan_sanitize_use_after_scope`.
* internal-fn.c (expand_HWASAN_CHECK): New.
(expand_HWASAN_CHOOSE_TAG): New.
(expand_HWASAN_MARK): New.
(expand_HWASAN_ALLOCA_UNPOISON): New.
* internal-fn.def (HWASAN_CHOOSE_TAG): New.
(HWASAN_CHECK): New.
(HWASAN_MARK): New.
(HWASAN_ALLOCA_UNPOISON): New.
* passes.def: Add hwasan and hwasan_O0 passes.
* sanitizer.def (BUILT_IN_HWASAN_LOAD1): New.
(BUILT_IN_HWASAN_LOAD2): New.
(BUILT_IN_HWASAN_LOAD4): New.
(BUILT_IN_HWASAN_LOAD8): New.
(BUILT_IN_HWASAN_LOAD16): New.
(BUILT_IN_HWASAN_LOADN): New.
(BUILT_IN_HWASAN_STORE1): New.
(BUILT_IN_HWASAN_STORE2): New.
(BUILT_IN_HWASAN_STORE4): New.
(BUILT_IN_HWASAN_STORE8): New.
(BUILT_IN_HWASAN_STORE16): New.
(BUILT_IN_HWASAN_STOREN): N

[PATCH 4/X] libsanitizer: options: Add hwasan flags and argument parsing

2020-08-17 Thread Matthew Malcomson
These flags can't be used at the same time as any of the other
sanitizers.
We add an equivalent flag to -static-libasan in -static-libhwasan to
ensure static linking.

The -fsanitize=kernel-hwaddress option is for compiling targeting the
kernel.  This flag has defaults that allow compiling KASAN with tags as
it is currently implemented.
These defaults are that we do not sanitize variables on the stack and
always recover from a detected bug.
Stack tagging in the kernel is a future aim, I don't know of any reason
it would not work, but this has not yet been tested.

We introduce a backend hook `targetm.memtag.can_tag_addresses` that
indicates to the mid-end whether a target has a feature like AArch64 TBI
where the top byte of an address is ignored.
Without this feature hwasan sanitization is not done.

gcc/ChangeLog:

* common.opt (flag_sanitize_recover): Default for kernel
hwaddress.
(static-libhwasan): New cli option.
* config/aarch64/aarch64.c (aarch64_can_tag_addresses): New.
(TARGET_MEMTAG_CAN_TAG_ADDRESSES): New.
* config/gnu-user.h (LIBHWASAN_EARLY_SPEC): hwasan equivalent of
asan command line flags.
* cppbuiltin.c (define_builtin_macros_for_compilation_flags):
Add hwasan equivalent of __SANITIZE_ADDRESS__.
* doc/invoke.texi: Document hwasan command line flags.
* doc/tm.texi: Document new hook.
* doc/tm.texi.in: Document new hook.
* flag-types.h (enum sanitize_code): New sanitizer values.
* gcc.c (STATIC_LIBHWASAN_LIBS): New macro.
(LIBHWASAN_SPEC): New macro.
(LIBHWASAN_EARLY_SPEC): New macro.
(SANITIZER_EARLY_SPEC): Update to include hwasan.
(SANITIZER_SPEC): Update to include hwasan.
(sanitize_spec_function): Use hwasan options.
* opts.c (finish_options): Describe conflicts between address
sanitizers.
(sanitizer_opts): Introduce new sanitizer flags.
(common_handle_option): Add defaults for kernel sanitizer.
* params.opt (hwasan--instrument-stack): New
(hwasan-random-frame-tag): New
(hwasan-instrument-allocas): New
(hwasan-instrument-reads): New
(hwasan-instrument-writes): New
(hwasan-instrument-mem-intrinsics): New
* target.def (HOOK_PREFIX): Add new hook.
(can_tag_addresses): Add new hook under memtag prefix.
* targhooks.c (default_memtag_can_tag_addresses): New.
* targhooks.h (default_memtag_can_tag_addresses): New decl.
* toplev.c (process_options): Ensure hwasan only on TBI
architectures.

gcc/c-family/ChangeLog:

* c-attribs.c (handle_no_sanitize_hwaddress_attribute): New
attribute.



### Attachment also inlined for ease of reply###


diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c
index 
372148315389db6671dfd943fd1a68670fcb1cbc..f8bf165aa48b5709c26f4e8245e5ab929b44fca6
 100644
--- a/gcc/c-family/c-attribs.c
+++ b/gcc/c-family/c-attribs.c
@@ -54,6 +54,8 @@ static tree handle_cold_attribute (tree *, tree, tree, int, 
bool *);
 static tree handle_no_sanitize_attribute (tree *, tree, tree, int, bool *);
 static tree handle_no_sanitize_address_attribute (tree *, tree, tree,
  int, bool *);
+static tree handle_no_sanitize_hwaddress_attribute (tree *, tree, tree,
+   int, bool *);
 static tree handle_no_sanitize_thread_attribute (tree *, tree, tree,
 int, bool *);
 static tree handle_no_address_safety_analysis_attribute (tree *, tree, tree,
@@ -412,6 +414,8 @@ const struct attribute_spec c_common_attribute_table[] =
  handle_no_sanitize_attribute, NULL },
   { "no_sanitize_address",0, 0, true, false, false, false,
  handle_no_sanitize_address_attribute, NULL },
+  { "no_sanitize_hwaddress",0, 0, true, false, false, false,
+ handle_no_sanitize_hwaddress_attribute, NULL },
   { "no_sanitize_thread", 0, 0, true, false, false, false,
  handle_no_sanitize_thread_attribute, NULL },
   { "no_sanitize_undefined",  0, 0, true, false, false, false,
@@ -946,6 +950,22 @@ handle_no_sanitize_address_attribute (tree *node, tree 
name, tree, int,
   return NULL_TREE;
 }
 
+/* Handle a "no_sanitize_hwaddress" attribute; arguments as in
+   struct attribute_spec.handler.  */
+
+static tree
+handle_no_sanitize_hwaddress_attribute (tree *node, tree name, tree, int,
+ bool *no_add_attrs)
+{
+  *no_add_attrs = true;
+  if (TREE_CODE (*node) != FUNCTION_DECL)
+warning (OPT_Wattributes, "%qE attribute ignored", name);
+  else
+add_no_sanitize_value (*node, SANITIZE_HWADDRESS);
+
+  return NULL_TREE;
+}
+
 /* Handle a "no_sanitize_thread" attribute; arguments as in
struct at

[testsuite] Add @ lines to check-function-bodies fluff

2020-03-10 Thread Matthew Malcomson
When using `check-function-bodies`, the subroutine `parse_function_bodies` uses
the `fluff` regexp to remove uninteresting assembly lines.

Arm targets generate assembly with some lines prefixed by `@`, these lines are
left by this process.

As an example of some lines prefixed by `@': the assembly output from the
`stacktest1` function in "bfloat16_simd_3_1.c" is:

.align  2
.global stacktest1
.arch armv8.2-a
.syntax unified
.arm
.fpu neon-fp-armv8
.type   stacktest1, %function
stacktest1:
@ args = 0, pretend = 0, frame = 8
@ frame_needed = 0, uses_anonymous_args = 0
@ link register save eliminated.
sub sp, sp, #8
add r3, sp, #6
vst1.16 {d0[0]}, [r3]
vld1.16 {d0[0]}, [r3]
add sp, sp, #8
@ sp needed
bx  lr
.size   stacktest1, .-stacktest1



It seems that previous uses of `check-function-bodies` in the arm backend have
avoided problems with such lines since they use the `...` regexp in each place
such fluff occurs.

I'm currently writing a patch that I'd like to match the entire function body,
so I'd like to remove such `@` lines automatically.

gcc/testsuite/ChangeLog:

2020-03-10  Matthew Malcomson  

* lib/scanasm.exp (parse_function_bodies): Lines starting with '@' also
counted as fluff.



### Attachment also inlined for ease of reply###


diff --git a/gcc/testsuite/lib/scanasm.exp b/gcc/testsuite/lib/scanasm.exp
index 
5ca58d4042027683da12bc2a1d161195cd6439e7..f7d27735112f8edd8a39a326020c3d08dd36e765
 100644
--- a/gcc/testsuite/lib/scanasm.exp
+++ b/gcc/testsuite/lib/scanasm.exp
@@ -569,7 +569,7 @@ proc parse_function_bodies { filename result } {
 set terminator {^\s*\.size}
 
 # Regexp for lines that aren't interesting.
-set fluff {^\s*(?:\.|//)}
+set fluff {^\s*(?:\.|//|@)}
 
 set fd [open $filename r]
 set in_function 0

diff --git a/gcc/testsuite/lib/scanasm.exp b/gcc/testsuite/lib/scanasm.exp
index 
5ca58d4042027683da12bc2a1d161195cd6439e7..f7d27735112f8edd8a39a326020c3d08dd36e765
 100644
--- a/gcc/testsuite/lib/scanasm.exp
+++ b/gcc/testsuite/lib/scanasm.exp
@@ -569,7 +569,7 @@ proc parse_function_bodies { filename result } {
 set terminator {^\s*\.size}
 
 # Regexp for lines that aren't interesting.
-set fluff {^\s*(?:\.|//)}
+set fluff {^\s*(?:\.|//|@)}
 
 set fd [open $filename r]
 set in_function 0



Fwd: [testsuite] Add @ lines to check-function-bodies fluff

2020-03-10 Thread Matthew Malcomson

Cc'ing maintainers and original author of `check-function-bodies`.

It looks like I missed that the first time around.


 Forwarded Message 
Subject: [testsuite] Add @ lines to check-function-bodies fluff
Date: Tue, 10 Mar 2020 17:22:52 +
From: Matthew Malcomson 
To: gcc-patches@gcc.gnu.org
CC: n...@arm.com

When using `check-function-bodies`, the subroutine 
`parse_function_bodies` uses

the `fluff` regexp to remove uninteresting assembly lines.

Arm targets generate assembly with some lines prefixed by `@`, these 
lines are

left by this process.

As an example of some lines prefixed by `@': the assembly output from the
`stacktest1` function in "bfloat16_simd_3_1.c" is:

.align  2
.global stacktest1
.arch armv8.2-a
.syntax unified
.arm
.fpu neon-fp-armv8
.type   stacktest1, %function
stacktest1:
@ args = 0, pretend = 0, frame = 8
@ frame_needed = 0, uses_anonymous_args = 0
@ link register save eliminated.
sub sp, sp, #8
add r3, sp, #6
vst1.16 {d0[0]}, [r3]
vld1.16 {d0[0]}, [r3]
add sp, sp, #8
@ sp needed
bx  lr
.size   stacktest1, .-stacktest1



It seems that previous uses of `check-function-bodies` in the arm 
backend have
avoided problems with such lines since they use the `...` regexp in each 
place

such fluff occurs.

I'm currently writing a patch that I'd like to match the entire function 
body,

so I'd like to remove such `@` lines automatically.

gcc/testsuite/ChangeLog:

2020-03-10  Matthew Malcomson  

* lib/scanasm.exp (parse_function_bodies): Lines starting with '@' also
counted as fluff.



### Attachment also inlined for ease of reply 
###



diff --git a/gcc/testsuite/lib/scanasm.exp b/gcc/testsuite/lib/scanasm.exp
index 
5ca58d4042027683da12bc2a1d161195cd6439e7..f7d27735112f8edd8a39a326020c3d08dd36e765 
100644

--- a/gcc/testsuite/lib/scanasm.exp
+++ b/gcc/testsuite/lib/scanasm.exp
@@ -569,7 +569,7 @@ proc parse_function_bodies { filename result } {
 set terminator {^\s*\.size}
  # Regexp for lines that aren't interesting.
-set fluff {^\s*(?:\.|//)}
+set fluff {^\s*(?:\.|//|@)}
  set fd [open $filename r]
 set in_function 0


diff --git a/gcc/testsuite/lib/scanasm.exp b/gcc/testsuite/lib/scanasm.exp
index 
5ca58d4042027683da12bc2a1d161195cd6439e7..f7d27735112f8edd8a39a326020c3d08dd36e765
 100644
--- a/gcc/testsuite/lib/scanasm.exp
+++ b/gcc/testsuite/lib/scanasm.exp
@@ -569,7 +569,7 @@ proc parse_function_bodies { filename result } {
 set terminator {^\s*\.size}
 
 # Regexp for lines that aren't interesting.
-set fluff {^\s*(?:\.|//)}
+set fluff {^\s*(?:\.|//|@)}
 
 set fd [open $filename r]
 set in_function 0



SLS Mitigation patches backported for GCC9

2020-07-21 Thread Matthew Malcomson
Hello,

Eventually we will want to backport the SLS patches to older branches.

When the GCC10 release is unfrozen we will work on getting the same patches
already posted backported to that branch.  The patches already posted on the
mailing list apply cleanly to the current releases/gcc-10 branch.

I've heard interest in having the GCC 9 patches, so I'm posting the modified
versions upstream sooner than otherwise.

Cheers,
Matthew

Entire patch series attached to cover letter.

all-patches.tar.gz
Description: application/gzip


aarch64: (GCC-9 Backport) Introduce SLS mitigation for RET and BR instructions

2020-07-21 Thread Matthew Malcomson
Instructions following RET or BR are not necessarily executed.  In order
to avoid speculation past RET and BR we can simply append a speculation
barrier.

Since these speculation barriers will not be architecturally executed,
they are not expected to add a high performance penalty.

The speculation barrier is to be SB when targeting architectures which
have this enabled, and DSB SY + ISB otherwise.

We add tests for each of the cases where such an instruction was seen.

This is implemented by modifying each machine description pattern that
emits either a RET or a BR instruction.  We choose not to use something
like `TARGET_ASM_FUNCTION_EPILOGUE` since it does not affect the
`indirect_jump`, `jump`, `sibcall_insn` and `sibcall_value_insn`
patterns and we find it preferable to implement the functionality in the
same way for every pattern.

There is one particular case which is slightly tricky.  The
implementation of TARGET_ASM_TRAMPOLINE_TEMPLATE uses a BR which needs
to be mitigated against.  The trampoline template is used *once* per
compilation unit, and the TRAMPOLINE_SIZE is exposed to the user via the
builtin macro __LIBGCC_TRAMPOLINE_SIZE__.
In the future we may implement function specific attributes to turn on
and off hardening on a per-function basis.
The fixed nature of the trampoline described above implies it will be
safer to ensure this speculation barrier is always used.

Testing:
  Bootstrap and regtest done on aarch64-none-linux
  Used a temporary hack(1) to use these options on every test in the
  testsuite and a script to check that the output never emitted an
  unmitigated RET or BR.

1) Temporary hack was a change to the testsuite to always use
`-save-temps` and run a script on the assembly output of those
compilations which produced one to ensure every RET or BR is immediately
followed by a speculation barrier.

gcc/ChangeLog:

* config/aarch64/aarch64-protos.h (aarch64_sls_barrier): New.
* config/aarch64/aarch64.c (aarch64_output_casesi): Emit
speculation barrier after BR instruction if needs be.
(aarch64_trampoline_init): Handle ptr_mode value & adjust size
of code copied.
(aarch64_sls_barrier): New.
(aarch64_asm_trampoline_template): Add needed barriers.
* config/aarch64/aarch64.h (AARCH64_ISA_SB): New.
(TARGET_SB): New.
(TRAMPOLINE_SIZE): Account for barrier.
* config/aarch64/aarch64.md (indirect_jump, *casesi_dispatch,
simple_return, *do_return, *sibcall_insn, *sibcall_value_insn):
Emit barrier if needs be, also account for possible barrier using
"sls_length" attribute.
(sls_length): New attribute.
(length): Determine default using any non-default sls_length
value.

gcc/testsuite/ChangeLog:

* gcc.target/aarch64/sls-mitigation/sls-miti-retbr.c: New test.
* gcc.target/aarch64/sls-mitigation/sls-miti-retbr-pacret.c:
New test.
* gcc.target/aarch64/sls-mitigation/sls-mitigation.exp: New file.
* lib/target-supports.exp (check_effective_target_aarch64_asm_sb_ok):
New proc.

(cherry picked from be178ecd5ac1fe1510d960ff95c66d0ff831afe1)


### Attachment also inlined for ease of reply###


diff --git a/gcc/config/aarch64/aarch64-protos.h 
b/gcc/config/aarch64/aarch64-protos.h
index 
db5a6a3a1813abbbeeaaa7009466ac58595e12bc..46196fe648e06f6b7543d8656cd6be6b39f8f774
 100644
--- a/gcc/config/aarch64/aarch64-protos.h
+++ b/gcc/config/aarch64/aarch64-protos.h
@@ -658,6 +658,7 @@ extern const atomic_ool_names aarch64_ool_ldset_names;
 extern const atomic_ool_names aarch64_ool_ldclr_names;
 extern const atomic_ool_names aarch64_ool_ldeor_names;
 
+const char *aarch64_sls_barrier (int);
 extern bool aarch64_harden_sls_retbr_p (void);
 extern bool aarch64_harden_sls_blr_p (void);
 
diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
index 
0e9b79e23f05f34cfee5fdccf5792af077a95798..8dcc9b1cec347104ca3bbcc34a45b30fcf35a886
 100644
--- a/gcc/config/aarch64/aarch64.h
+++ b/gcc/config/aarch64/aarch64.h
@@ -235,6 +235,7 @@ extern unsigned aarch64_architecture_version;
 #define AARCH64_ISA_F16FML(aarch64_isa_flags & AARCH64_FL_F16FML)
 #define AARCH64_ISA_RCPC8_4   (aarch64_isa_flags & AARCH64_FL_RCPC8_4)
 #define AARCH64_ISA_V8_5  (aarch64_isa_flags & AARCH64_FL_V8_5)
+#define AARCH64_ISA_SB(aarch64_isa_flags & AARCH64_FL_SB)
 
 /* Crypto is an optional extension to AdvSIMD.  */
 #define TARGET_CRYPTO (TARGET_SIMD && AARCH64_ISA_CRYPTO)
@@ -285,6 +286,9 @@ extern unsigned aarch64_architecture_version;
 #define TARGET_FIX_ERR_A53_835769_DEFAULT 1
 #endif
 
+/* SB instruction is enabled through +sb.  */
+#define TARGET_SB (AARCH64_ISA_SB)
+
 /* Apply the workaround for Cortex-A53 erratum 835769.  */
 #define TARGET_FIX_ERR_A53_835769  \
   ((aarch64_fix_a53_err835769 == 2)\
@@ -931,8 +935,10 @@ typedef struct
 
 #define RETURN_ADDR_RTX 

aarch64: (GCC-9 Backport) Mitigate SLS for BLR instruction

2020-07-21 Thread Matthew Malcomson
This patch introduces the mitigation for Straight Line Speculation past
the BLR instruction.

This mitigation replaces BLR instructions with a BL to a stub which uses
a BR to jump to the original value.  These function stubs are then
appended with a speculation barrier to ensure no straight line
speculation happens after these jumps.

When optimising for speed we use a set of stubs for each function since
this should help the branch predictor make more accurate predictions
about where a stub should branch.

When optimising for size we use one set of stubs for all functions.
This set of stubs can have human readable names, and we are using
`__call_indirect_x` for register x.

When BTI branch protection is enabled the BLR instruction can jump to a
`BTI c` instruction using any register, while the BR instruction can
only jump to a `BTI c` instruction using the x16 or x17 registers.
Hence, in order to ensure this transformation is safe we mov the value
of the original register into x16 and use x16 for the BR.

As an example when optimising for size:
a
BLR x0
instruction would get transformed to something like
BL __call_indirect_x0
where __call_indirect_x0 labels a thunk that contains
__call_indirect_x0:
MOV X16, X0
BR X16


The first version of this patch used local symbols specific to a
compilation unit to try and avoid relocations.
This was mistaken since functions coming from the same compilation unit
can still be in different sections, and the assembler will insert
relocations at jumps between sections.

On any relocation the linker is permitted to emit a veneer to handle
jumps between symbols that are very far apart.  The registers x16 and
x17 may be clobbered by these veneers.
Hence the function stubs cannot rely on the values of x16 and x17 being
the same as just before the function stub is called.

Similar can be said for the hot/cold partitioning of single functions,
so function-local stubs have the same restriction.

This updated version of the patch never emits function stubs for x16 and
x17, and instead forces other registers to be used.

Given the above, there is now no benefit to local symbols (since they
are not enough to avoid dealing with linker intricacies).  This patch
now uses global symbols with hidden visibility each stored in their own
COMDAT section.  This means stubs can be shared between compilation
units while still avoiding the PLT indirection.

This patch also removes the `__call_indirect_x30` stub (and
function-local equivalent) which would simply jump back to the original
location.

The function-local stubs are emitted to the assembly output file in one
chunk, which means we need not add the speculation barrier directly
after each one.
This is because we know for certain that the instructions directly after
the BR in all but the last function stub will be from another one of
these stubs and hence will not contain a speculation gadget.
Instead we add a speculation barrier at the end of the sequence of
stubs.

The global stubs are emitted in COMDAT/.linkonce sections by
themselves so that the linker can remove duplicates from multiple object
files.  This means they are not emitted in one chunk, and each one must
include the speculation barrier.

Another difference is that since the global stubs are shared across
compilation units we do not know that all functions will be targeting an
architecture supporting the SB instruction.
Rather than provide multiple stubs for each architecture, we provide a
stub that will work for all architectures -- using the DSB+ISB barrier.

This mitigation does not apply for BLR instructions in the following
places:
- Some accesses to thread-local variables use a code sequence with a BLR
  instruction.  This code sequence is part of the binary interface between
  compiler and linker. If this BLR instruction needs to be mitigated, it'd
  probably be best to do so in the linker. It seems that the code sequence
  for thread-local variable access is unlikely to lead to a Spectre Revalation
  Gadget.
- PLT stubs are produced by the linker and each contain a BLR instruction.
  It seems that at most only after the last PLT stub a Spectre Revalation
  Gadget might appear.

Testing:
  Bootstrap and regtest on AArch64
(with BOOT_CFLAGS="-mharden-sls=retbr,blr")
  Used a temporary hack(1) in gcc-dg.exp to use these options on every
  test in the testsuite, a slight modification to emit the speculation
  barrier after every function stub, and a script to check that the
  output never emitted a BLR, or unmitigated BR or RET instruction.
  Similar on an aarch64-none-elf cross-compiler.

1) Temporary hack emitted a speculation barrier at the end of every stub
function, and used a script to ensure that:
  a) Every RET or BR is immediately followed by a speculation barrier.
  b) No BLR instruction is emitted by compiler.

gcc/ChangeLog:

* config/aarch64/aarch64-protos.h (aarch64_indirect_call_asm):
New declaration.
* confi

aarch64: (GCC-9 Backport) New Straight Line Speculation (SLS) mitigation flags

2020-07-21 Thread Matthew Malcomson
Here we introduce the flags that will be used for straight line speculation.

The new flag introduced is `-mharden-sls=`.
This flag can take arguments of `none`, `all`, or a comma seperated list
of one or more of `retbr` or `blr`.
`none` indicates no special mitigation of the straight line speculation
vulnerability.
`all` requests all mitigations currently implemented.
`retbr` requests that the RET and BR instructions have a speculation
barrier inserted after them.
`blr` requests that BLR instructions are replaced by a BL to a function
stub using a BR with a speculation barrier after it.

Setting this on a per-function basis using attributes or the like is not
enabled, but may be in the future.

gcc/ChangeLog:

* config/aarch64/aarch64-protos.h (aarch64_harden_sls_retbr_p):
New.
(aarch64_harden_sls_blr_p): New.
* config/aarch64/aarch64.c (enum aarch64_sls_hardening_type):
New.
(aarch64_harden_sls_retbr_p): New.
(aarch64_harden_sls_blr_p): New.
(aarch64_validate_sls_mitigation): New.
(aarch64_override_options): Parse options for SLS mitigation.
* config/aarch64/aarch64.opt (-mharden-sls): New option.
* doc/invoke.texi: Document new option.

(cherry picked from commit a9ba2a9b77bec7eacaf066801f22d1c366a2bc86)


### Attachment also inlined for ease of reply###


diff --git a/gcc/config/aarch64/aarch64-protos.h 
b/gcc/config/aarch64/aarch64-protos.h
index 
af2a17f0bf3b50a306b14d8c0aa431269f54ef2e..db5a6a3a1813abbbeeaaa7009466ac58595e12bc
 100644
--- a/gcc/config/aarch64/aarch64-protos.h
+++ b/gcc/config/aarch64/aarch64-protos.h
@@ -658,4 +658,7 @@ extern const atomic_ool_names aarch64_ool_ldset_names;
 extern const atomic_ool_names aarch64_ool_ldclr_names;
 extern const atomic_ool_names aarch64_ool_ldeor_names;
 
+extern bool aarch64_harden_sls_retbr_p (void);
+extern bool aarch64_harden_sls_blr_p (void);
+
 #endif /* GCC_AARCH64_PROTOS_H */
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 
1b6e67ccd53da05c88b13cac8b524ba2b8cfe43f..0903370b6128e19016f97cb6b0fd44e6b51e569e
 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -11791,6 +11791,79 @@ aarch64_validate_mcpu (const char *str, const struct 
processor **res,
   return false;
 }
 
+/* Straight line speculation indicators.  */
+enum aarch64_sls_hardening_type
+{
+  SLS_NONE = 0,
+  SLS_RETBR = 1,
+  SLS_BLR = 2,
+  SLS_ALL = 3,
+};
+static enum aarch64_sls_hardening_type aarch64_sls_hardening;
+
+/* Return whether we should mitigatate Straight Line Speculation for the RET
+   and BR instructions.  */
+bool
+aarch64_harden_sls_retbr_p (void)
+{
+  return aarch64_sls_hardening & SLS_RETBR;
+}
+
+/* Return whether we should mitigatate Straight Line Speculation for the BLR
+   instruction.  */
+bool
+aarch64_harden_sls_blr_p (void)
+{
+  return aarch64_sls_hardening & SLS_BLR;
+}
+
+/* As of yet we only allow setting these options globally, in the future we may
+   allow setting them per function.  */
+static void
+aarch64_validate_sls_mitigation (const char *const_str)
+{
+  char *token_save = NULL;
+  char *str = NULL;
+
+  if (strcmp (const_str, "none") == 0)
+{
+  aarch64_sls_hardening = SLS_NONE;
+  return;
+}
+  if (strcmp (const_str, "all") == 0)
+{
+  aarch64_sls_hardening = SLS_ALL;
+  return;
+}
+
+  char *str_root = xstrdup (const_str);
+  str = strtok_r (str_root, ",", &token_save);
+  if (!str)
+error ("invalid argument given to %<-mharden-sls=%>");
+
+  int temp = SLS_NONE;
+  while (str)
+{
+  if (strcmp (str, "blr") == 0)
+   temp |= SLS_BLR;
+  else if (strcmp (str, "retbr") == 0)
+   temp |= SLS_RETBR;
+  else if (strcmp (str, "none") == 0 || strcmp (str, "all") == 0)
+   {
+ error ("%<%s%> must be by itself for %<-mharden-sls=%>", str);
+ break;
+   }
+  else
+   {
+ error ("invalid argument %<%s%> for %<-mharden-sls=%>", str);
+ break;
+   }
+  str = strtok_r (NULL, ",", &token_save);
+}
+  aarch64_sls_hardening = (aarch64_sls_hardening_type) temp;
+  free (str_root);
+}
+
 /* Parses CONST_STR for branch protection features specified in
aarch64_branch_protect_types, and set any global variables required.  
Returns
the parsing result and assigns LAST_STR to the last processed token from
@@ -12029,6 +12102,9 @@ aarch64_override_options (void)
   selected_arch = NULL;
   selected_tune = NULL;
 
+  if (aarch64_harden_sls_string)
+aarch64_validate_sls_mitigation (aarch64_harden_sls_string);
+
   if (aarch64_branch_protection_string)
 aarch64_validate_mbranch_protection (aarch64_branch_protection_string);
 
diff --git a/gcc/config/aarch64/aarch64.opt b/gcc/config/aarch64/aarch64.opt
index 
f474a28eb9234cf87b22492c4396d5a31857cd39..4beb2d3d243c4ca36e7604c02ab5d9e80955f55a
 100644
--- a/gcc/config/aarch64/aarch64.opt
+++ b/gcc/config/aarch

Re: SLS Mitigation patches backported for GCC9

2020-07-24 Thread Matthew Malcomson

On 24/07/2020 12:01, Kyrylo Tkachov wrote:

Hi Matthew,


-Original Message-
From: Matthew Malcomson 
Sent: 21 July 2020 16:16
To: gcc-patches@gcc.gnu.org
Cc: Richard Earnshaw ; Kyrylo Tkachov
; Ross Burton 
Subject: SLS Mitigation patches backported for GCC9

Hello,

Eventually we will want to backport the SLS patches to older branches.

When the GCC10 release is unfrozen we will work on getting the same
patches
already posted backported to that branch.  The patches already posted on
the
mailing list apply cleanly to the current releases/gcc-10 branch.

I've heard interest in having the GCC 9 patches, so I'm posting the modified
versions upstream sooner than otherwise.


I'd say let's go ahead with the GCC 10 patches (assuming testing works out well 
on there).
For the GCC 9 patches it would be useful if you included a bit of text of how 
they differ from the GCC 10/11 patches.
This would speed up the technical review.
Thanks,
Kyrill



Cheers,
Matthew

Entire patch series attached to cover letter.


Below were the only two "interesting" hunks that failed to apply after 
`patch -p1`.


The differences causing these were:
- in GCC-9 the `retab` instruction wasn't in the "do_return" pattern.
- `simple_return` had "aarch64_use_simple_return_insn_p ()" as a
   condition.




--- gcc/config/aarch64/aarch64.md
+++ gcc/config/aarch64/aarch64.md
@@ -863,18 +882,23 @@
   [(return)]
   ""
   {
+const char *ret = NULL;
 if (aarch64_return_address_signing_enabled ()
&& TARGET_ARMV8_3
&& !crtl->calls_eh_return)
   {
if (aarch64_ra_sign_key == AARCH64_KEY_B)
- return "retab";
+ ret = "retab";
else
- return "retaa";
+ ret = "retaa";
   }
-return "ret";
+else
+  ret = "ret";
+output_asm_insn (ret, operands);
+return aarch64_sls_barrier (aarch64_harden_sls_retbr_p ());
   }
-  [(set_attr "type" "branch")]
+  [(set_attr "type" "branch")
+   (set_attr "sls_length" "retbr")]
 )

 (define_expand "return"
@@ -886,8 +910,12 @@
 (define_insn "simple_return"
   [(simple_return)]
   ""
-  "ret"
-  [(set_attr "type" "branch")]
+  {
+output_asm_insn ("ret", operands);
+return aarch64_sls_barrier (aarch64_harden_sls_retbr_p ());
+  }
+  [(set_attr "type" "branch")
+   (set_attr "sls_length" "retbr")]
 )

 (define_insn "*cb1"


[Arm] Implement CDE intrinsics for MVE registers.

2020-03-26 Thread Matthew Malcomson
[Arm] Implement CDE intrinsics for MVE registers.

Implement CDE intrinsics on MVE registers.

Other than the basics required for adding intrinsics this patch consists
of three changes.

** We separate out the MVE types and casts from the arm_mve.h header.

This is so that the types can be used in arm_cde.h without the need to include
the entire arm_mve.h header.
The only type that arm_cde.h needs is `uint8x16_t`, so this separation could be
avoided by using a `typedef` in this file.
Since the introduced intrinsics are all defined to act on the full range of MVE
types, declaring all such types seems intuitive since it will provide their
declaration to the user too.

This arm_mve_types.h header not only includes the MVE types, but also
the conversion intrinsics between them.
Some of the conversion intrinsics are needed for arm_cde.h, but most are
not.  We include all conversion intrinsics to keep the definition of
such conversion functions all in one place, on the understanding that
extra conversion functions being defined when including `arm_cde.h` is
not a problem.

** We define the TARGET_RESOLVE_OVERLOADED_BUILTIN hook for the Arm backend.

This is needed to implement the polymorphism for the required intrinsics.
The intrinsics have no specialised version, and the resulting assembly
instruction for all different types should be exactly the same.
Due to this we have implemented these intrinsics via one builtin on one type.
All other calls to the intrinsic with different types are implicitly cast to
the one type that is defined, and hence are all expanded to the same RTL
pattern that is only defined for one machine mode.

** We seperate the initialisation of the CDE intrinsics from others.

This allows us to ensure that the CDE intrinsics acting on MVE registers
are only created when both CDE and MVE are available.
Only initialising these builtins when both features are available is
especially important since they require a type that is only initialised
when the target supports hard float.  Hence trying to initialise these
builtins on a soft float target would cause an ICE.

Testing done:
  Full bootstrap and regtest on arm-none-linux-gnueabihf
  Regression test on arm-none-eabi

NOTE: These tests ICE on arm-none-eabi.
This is due to bugzilla bug 94341, and not due to a problem in this patch.

NOTE2: This patch depends on the CDE intrinsic framework patch by
Dennis.
https://gcc.gnu.org/pipermail/gcc-patches/2020-March/542008.html


Ok for trunk?

gcc/ChangeLog:

2020-03-26  Matthew Malcomson  

* config.gcc (arm_mve_types.h): New extra_header for arm.
* config/arm/arm-builtins.c (arm_resolve_overloaded_builtin): New.
(arm_init_cde_builtins): New.
(arm_init_acle_builtins): Remove initialisation of CDE builtins.
(arm_init_builtins): Call arm_init_cde_builtins when target
supports CDE.
* config/arm/arm-c.c (arm_resolve_overloaded_builtin): New declaration.
(arm_register_target_pragmas): Initialise resolve_overloaded_builtin
hook to the implementation for the arm backend.
* config/arm/arm.h (ARM_MVE_CDE_CONST_1): New.
(ARM_MVE_CDE_CONST_2): New.
(ARM_MVE_CDE_CONST_3): New.
* config/arm/arm_cde.h (__arm_vcx1q_u8): New.
(__arm_vcx1qa): New.
(__arm_vcx2q): New.
(__arm_vcx2q_u8): New.
(__arm_vcx2qa): New.
(__arm_vcx3q): New.
(__arm_vcx3q_u8): New.
(__arm_vcx3qa): New.
* config/arm/arm_cde_builtins.def (vcx1q, vcx1qa, vcx2q, vcx2qa, vcx3q,
vcx3qa): New builtins defined.
* config/arm/arm_mve.h: Move typedefs and conversion intrinsics
to arm_mve_types.h header.
* config/arm/arm_mve_types.h: New file.
* config/arm/mve.md (arm_vcx1qv16qi, arm_vcx1qav16qi, arm_vcx2qv16qi,
arm_vcx2qav16qi, arm_vcx3qv16qi, arm_vcx3qav16qi): New patterns.
* config/arm/predicates.md (const_int_mve_cde1_operand,
const_int_mve_cde2_operand, const_int_mve_cde3_operand): New.

gcc/testsuite/ChangeLog:

2020-03-26  Matthew Malcomson  
Dennis Zhang  

* gcc.target/arm/acle/cde-mve-error-1.c: New test.
* gcc.target/arm/acle/cde-mve-error-2.c: New test.
* gcc.target/arm/acle/cde-mve-error-3.c: New test.
* gcc.target/arm/acle/cde-mve-full-assembly.c: New test.
* gcc.target/arm/acle/cde-mve-tests.c: New test.
* lib/target-supports.exp (arm_v8_1m_main_cde_mve_fp): New check
effective.


cde_mve_regs.patch.gz
Description: application/gzip


[Arm] Implement CDE predicated intrinsics for MVE registers

2020-04-07 Thread Matthew Malcomson
These intrinsics are the predicated version of the intrinsics inroduced
in https://gcc.gnu.org/pipermail/gcc-patches/2020-March/542725.html.

These are not yet public on developer.arm.com but we have reached
internal consensus on them.

The approach follows the same method as for the CDE intrinsics for MVE
registers, most notably using the same arm_resolve_overloaded_builtin
function with minor modifications.

The resolver hook has been moved from arm-builtins.c to arm-c.c so it
can access the c-common function build_function_call_vec.  This function
is needed to perform the same checks on arguments as a normal C or C++
function would perform.
It is fine to put this resolver in arm-c.c since it's only use is for
the ACLE functions, and these are only available in C/C++.
So that the resolver function has access to information it needs from
the builtins, we put two query functions into arm-builtins.c and use
them from arm-c.c.

We rely on the order that the builtins are defined in
gcc/config/arm/arm_cde_builtins.def, knowing that the predicated
versions come after the non-predicated versions.

The machine description patterns for these builtins are simpler than
those for the non-predicated versions, since the accumulator versions
*and* non-accumulator versions both need an input vector now.
The input vector is needed for the non-accumulator version to describe
the original values for those lanes that are not updated during the
merge operation.

We additionally need to introduce qualifiers for these new builtins,
which follow the same pattern as the non-predicated versions but with an
extra argument to describe the predicate.

Error message changes:
- We directly mention the builtin argument when complaining that an
  argument is not in the correct range.
  This more closely matches the C error messages.
- We ensure the resolver complains about *all* invalid arguments to a
  function instead of just the first one.
- The resolver error messages index arguments from 1 instead of 0 to
  match the arguments coming from the C/C++ frontend.

In order to allow the user to give an argument for the merging predicate
when they don't care what data is stored in the 'false' lanes, we also
move the __arm_vuninitializedq* intrinsics from arm_mve.h to
arm_mve_types.h which is shared with arm_cde.h.

We only move the fully type-specified `__arm_vuninitializedq*`
intrinsics and not the polymorphic versions, since moving the
polymorphic versions requires moving the _Generic framework as well as
just the intrinsics we're interested in.  This matches the approach taken
for the `__arm_vreinterpret*` functions in this include file.

This patch also contains a slight change in spacing of an existing
assembly instruction to be emitted.
This is just to help writing tests -- vmsr usually has a tab and a space
between the mnemonic and the first argument, but in one case it just has
a tab -- making all the same helps make test regexps simpler.

Testing Done:
Bootstrap and full regtest on arm-none-linux-gnueabihf
Full regtest on arm-none-eabi

All testing done with a local fix for the bugzilla PR below.
That bugzilla currently causes multiple ICE's on the tests added in
this patch.
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94341

gcc/ChangeLog:

2020-04-07  Matthew Malcomson  

* config/arm/arm-builtins.c (CX_UNARY_UNONE_QUALIFIERS): New.
(CX_BINARY_UNONE_QUALIFIERS): New.
(CX_TERNARY_UNONE_QUALIFIERS): New.
(arm_resolve_overloaded_builtin): Move to arm-c.c.
(arm_expand_builtin_args): Update error message.
(enum resolver_ident): New.
(arm_describe_resolver): New.
(arm_cde_end_args): New.
* config/arm/arm-builtins.h: New file.
* config/arm/arm-c.c (arm_resolve_overloaded_builtin): New.
(arm_resolve_cde_builtin): Moved from arm-builtins.c.
* config/arm/arm_cde.h (__arm_vcx1q_m, __arm_vcx1qa_m,
__arm_vcx2q_m, __arm_vcx2qa_m, __arm_vcx3q_m, __arm_vcx3qa_m):
New.
* config/arm/arm_cde_builtins.def (vcx1q_p_, vcx1qa_p_,
vcx2q_p_, vcx2qa_p_, vcx3q_p_, vcx3qa_p_): New builtin defs.
* config/arm/iterators.md (CDE_VCX): New int iterator.
(a) New int attribute.
* config/arm/mve.md (arm_vcx1q_p_v16qi, arm_vcx2q_p_v16qi,
arm_vcx3q_p_v16qi): New patterns.
* config/arm/vfp.md (thumb2_movhi_fp16): Extra space in assembly.

gcc/testsuite/ChangeLog:

2020-04-07  Matthew Malcomson  

* gcc.target/arm/acle/cde-errors.c: Add predicated forms.
* gcc.target/arm/acle/cde-mve-error-1.c: Add predicated forms.
* gcc.target/arm/acle/cde-mve-error-2.c: Add predicated forms.
* gcc.target/arm/acle/cde-mve-error-3.c: Add predicated forms.
* gcc.target/arm/acle/cde-mve-full-assembly.c: Add predicated
forms.
* gcc.target/arm/acle/cde-mve-tests.c: Add predicated forms.
* gcc

[Arm] Implement CDE intrinsics for MVE registers.

2020-04-08 Thread Matthew Malcomson

This patch updates the previous one by rebasing onto the recent MVE patches on
trunk.

Implement CDE intrinsics on MVE registers.

Other than the basics required for adding intrinsics this patch consists
of three changes.

** We separate out the MVE types and casts from the arm_mve.h header.

This is so that the types can be used in arm_cde.h without the need to include
the entire arm_mve.h header.
The only type that arm_cde.h needs is `uint8x16_t`, so this separation could be
avoided by using a `typedef` in this file.
Since the introduced intrinsics are all defined to act on the full range of MVE
types, declaring all such types seems intuitive since it will provide their
declaration to the user too.

This arm_mve_types.h header not only includes the MVE types, but also
the conversion intrinsics between them.
Some of the conversion intrinsics are needed for arm_cde.h, but most are
not.  We include all conversion intrinsics to keep the definition of
such conversion functions all in one place, on the understanding that
extra conversion functions being defined when including `arm_cde.h` is
not a problem.

** We define the TARGET_RESOLVE_OVERLOADED_BUILTIN hook for the Arm backend.

This is needed to implement the polymorphism for the required intrinsics.
The intrinsics have no specialised version, and the resulting assembly
instruction for all different types should be exactly the same.
Due to this we have implemented these intrinsics via one builtin on one type.
All other calls to the intrinsic with different types are implicitly cast to
the one type that is defined, and hence are all expanded to the same RTL
pattern that is only defined for one machine mode.

** We seperate the initialisation of the CDE intrinsics from others.

This allows us to ensure that the CDE intrinsics acting on MVE registers
are only created when both CDE and MVE are available.
Only initialising these builtins when both features are available is
especially important since they require a type that is only initialised
when the target supports hard float.  Hence trying to initialise these
builtins on a soft float target would cause an ICE.

Testing done:
  Full bootstrap and regtest on arm-none-linux-gnueabihf
  Regression test on arm-none-eabi


NOTE: This patch depends on the CDE intrinsic framework patch by Dennis.
https://gcc.gnu.org/pipermail/gcc-patches/2020-March/542008.html


Ok for trunk?

gcc/ChangeLog:

2020-04-08  Matthew Malcomson  

* config.gcc (arm_mve_types.h): New extra_header for arm.
* config/arm/arm-builtins.c (arm_resolve_overloaded_builtin): New.
(arm_init_cde_builtins): New.
(arm_init_acle_builtins): Remove initialisation of CDE builtins.
(arm_init_builtins): Call arm_init_cde_builtins when target
supports CDE.
* config/arm/arm-c.c (arm_resolve_overloaded_builtin): New declaration.
(arm_register_target_pragmas): Initialise resolve_overloaded_builtin
hook to the implementation for the arm backend.
* config/arm/arm.h (ARM_MVE_CDE_CONST_1): New.
(ARM_MVE_CDE_CONST_2): New.
(ARM_MVE_CDE_CONST_3): New.
* config/arm/arm_cde.h (__arm_vcx1q_u8): New.
(__arm_vcx1qa): New.
(__arm_vcx2q): New.
(__arm_vcx2q_u8): New.
(__arm_vcx2qa): New.
(__arm_vcx3q): New.
(__arm_vcx3q_u8): New.
(__arm_vcx3qa): New.
* config/arm/arm_cde_builtins.def (vcx1q, vcx1qa, vcx2q, vcx2qa, vcx3q,
vcx3qa): New builtins defined.
* config/arm/arm_mve.h: Move typedefs and conversion intrinsics
to arm_mve_types.h header.
* config/arm/arm_mve_types.h: New file.
* config/arm/mve.md (arm_vcx1qv16qi, arm_vcx1qav16qi, arm_vcx2qv16qi,
arm_vcx2qav16qi, arm_vcx3qv16qi, arm_vcx3qav16qi): New patterns.
* config/arm/predicates.md (const_int_mve_cde1_operand,
const_int_mve_cde2_operand, const_int_mve_cde3_operand): New.

gcc/testsuite/ChangeLog:

2020-04-08  Matthew Malcomson  
Dennis Zhang  

* gcc.target/arm/acle/cde-mve-error-1.c: New test.
* gcc.target/arm/acle/cde-mve-error-2.c: New test.
* gcc.target/arm/acle/cde-mve-error-3.c: New test.
* gcc.target/arm/acle/cde-mve-full-assembly.c: New test.
* gcc.target/arm/acle/cde-mve-tests.c: New test.
* lib/target-supports.exp (arm_v8_1m_main_cde_mve_fp): New check
effective.


cde-mve-intrinsics.patch.gz
Description: application/gzip


[Arm] Implement CDE predicated intrinsics for MVE registers

2020-04-08 Thread Matthew Malcomson
This is an update of the previous patch but rebased onto recent MVE patches.
https://gcc.gnu.org/pipermail/gcc-patches/2020-April/543414.html

These intrinsics are the predicated version of the intrinsics inroduced
in https://gcc.gnu.org/pipermail/gcc-patches/2020-April/543527.html.

These are not yet public on developer.arm.com but we have reached
internal consensus on them.

The approach follows the same method as for the CDE intrinsics for MVE
registers, most notably using the same arm_resolve_overloaded_builtin
function with minor modifications.

The resolver hook has been moved from arm-builtins.c to arm-c.c so it
can access the c-common function build_function_call_vec.  This function
is needed to perform the same checks on arguments as a normal C or C++
function would perform.
It is fine to put this resolver in arm-c.c since it's only use is for
the ACLE functions, and these are only available in C/C++.
So that the resolver function has access to information it needs from
the builtins, we put two query functions into arm-builtins.c and use
them from arm-c.c.

We rely on the order that the builtins are defined in
gcc/config/arm/arm_cde_builtins.def, knowing that the predicated
versions come after the non-predicated versions.

The machine description patterns for these builtins are simpler than
those for the non-predicated versions, since the accumulator versions
*and* non-accumulator versions both need an input vector now.
The input vector is needed for the non-accumulator version to describe
the original values for those lanes that are not updated during the
merge operation.

We additionally need to introduce qualifiers for these new builtins,
which follow the same pattern as the non-predicated versions but with an
extra argument to describe the predicate.

Error message changes:
- We directly mention the builtin argument when complaining that an
  argument is not in the correct range.
  This more closely matches the C error messages.
- We ensure the resolver complains about *all* invalid arguments to a
  function instead of just the first one.
- The resolver error messages index arguments from 1 instead of 0 to
  match the arguments coming from the C/C++ frontend.

In order to allow the user to give an argument for the merging predicate
when they don't care what data is stored in the 'false' lanes, we also
move the __arm_vuninitializedq* intrinsics from arm_mve.h to
arm_mve_types.h which is shared with arm_cde.h.

We only move the fully type-specified `__arm_vuninitializedq*`
intrinsics and not the polymorphic versions, since moving the
polymorphic versions requires moving the _Generic framework as well as
just the intrinsics we're interested in.  This matches the approach taken
for the `__arm_vreinterpret*` functions in this include file.

This patch also contains a slight change in spacing of an existing
assembly instruction to be emitted.
This is just to help writing tests -- vmsr usually has a tab and a space
between the mnemonic and the first argument, but in one case it just has
a tab -- making all the same helps make test regexps simpler.

Testing Done:
Bootstrap and full regtest on arm-none-linux-gnueabihf
Full regtest on arm-none-eabi

gcc/ChangeLog:

2020-04-08  Matthew Malcomson  

* config/arm/arm-builtins.c (CX_UNARY_UNONE_QUALIFIERS): New.
(CX_BINARY_UNONE_QUALIFIERS): New.
(CX_TERNARY_UNONE_QUALIFIERS): New.
(arm_resolve_overloaded_builtin): Move to arm-c.c.
(arm_expand_builtin_args): Update error message.
(enum resolver_ident): New.
(arm_describe_resolver): New.
(arm_cde_end_args): New.
* config/arm/arm-builtins.h: New file.
* config/arm/arm-c.c (arm_resolve_overloaded_builtin): New.
(arm_resolve_cde_builtin): Moved from arm-builtins.c.
* config/arm/arm_cde.h (__arm_vcx1q_m, __arm_vcx1qa_m,
__arm_vcx2q_m, __arm_vcx2qa_m, __arm_vcx3q_m, __arm_vcx3qa_m):
New.
* config/arm/arm_cde_builtins.def (vcx1q_p_, vcx1qa_p_,
vcx2q_p_, vcx2qa_p_, vcx3q_p_, vcx3qa_p_): New builtin defs.
* config/arm/iterators.md (CDE_VCX): New int iterator.
(a) New int attribute.
* config/arm/mve.md (arm_vcx1q_p_v16qi, arm_vcx2q_p_v16qi,
arm_vcx3q_p_v16qi): New patterns.
* config/arm/vfp.md (thumb2_movhi_fp16): Extra space in assembly.

gcc/testsuite/ChangeLog:

2020-04-08  Matthew Malcomson  

* gcc.target/arm/acle/cde-errors.c: Add predicated forms.
* gcc.target/arm/acle/cde-mve-error-1.c: Add predicated forms.
* gcc.target/arm/acle/cde-mve-error-2.c: Add predicated forms.
* gcc.target/arm/acle/cde-mve-error-3.c: Add predicated forms.
* gcc.target/arm/acle/cde-mve-full-assembly.c: Add predicated
forms.
* gcc.target/arm/acle/cde-mve-tests.c: Add predicated forms.
* gcc.target/arm/acle/cde_v_1_err.c (test_imm_range): Update for
er

[PATCH] [Arm] Implement scalar Custom Datapath Extension intrinsics

2020-04-08 Thread Matthew Malcomson
Patch rebased onto recent trunk.


This patch introduces the scalar CDE (Custom Datapath Extension)
intrinsics for the arm backend.

There is nothing beyond the standard in this patch.  We simply build upon what
has been done by Dennis for the vector intrinsics.

We do add `+cdecp6` to the default arguments for `target-supports.exp`, this
allows for using coprocessor 6 in tests. This patch uses an alternate
coprocessor to ease assembler scanning by looking for a use of coprocessor 6.

We also ensure that any DImode registers are put in an even-odd register pair
when compiling for a target with CDE -- this avoids faulty code generation for 
-Os
when producing the cx*d instructions.

Testing done:
Bootstrapped and regtested for arm-none-linux-gnueabihf.

gcc/ChangeLog:

2020-04-08  Matthew Malcomson  

* config/arm/arm.c (arm_hard_regno_mode_ok): DImode registers forced 
into
even-odd register pairs for TARGET_CDE.
* config/arm/arm.h (ARM_CCDE_CONST_1): New.
(ARM_CCDE_CONST_2): New.
(ARM_CCDE_CONST_3): New.
* config/arm/arm.md (arm_cx1si, arm_cx1di arm_cx1asi, arm_cx1adi 
arm_cx2si,
arm_cx2di arm_cx2asi, arm_cx2adi arm_cx3si, arm_cx3di arm_cx3asi,
arm_cx3adi): New patterns.
* config/arm/arm_cde.h (__arm_cx1, __arm_cx1a, __arm_cx2, __arm_cx2a,
__arm_cx3, __arm_cx3a, __arm_cx1d, __arm_cx1da, __arm_cx2d, __arm_cx2da,
__arm_cx3d, __arm_cx3da): New ACLE function macros.
* config/arm/arm_cde_builtins.def (cx1, cx1a, cx2, cx2a, cx3, cx3a): 
Define
intrinsics.
* config/arm/iterators.md (cde_suffix, cde_dest): New mode attributes.
* config/arm/predicates.md (const_int_ccde1_operand,
const_int_ccde2_operand, const_int_ccde3_operand): New.
* config/arm/unspecs.md (UNSPEC_CDE, UNSPEC_CDEA): New.

gcc/testsuite/ChangeLog:

2020-04-08  Matthew Malcomson  

* gcc.target/arm/acle/cde-errors.c: New test.
* gcc.target/arm/acle/cde.c: New test.
* lib/target-supports.exp: Update CDE flags to enable coprocessor 6.



### Attachment also inlined for ease of reply###


diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
index 
ca36a74cd1fa161c388961588fa0f96030b7888e..83886a2fcb3844f6a5060e451125a6cd2d505c5c
 100644
--- a/gcc/config/arm/arm.h
+++ b/gcc/config/arm/arm.h
@@ -576,6 +576,9 @@ extern int arm_arch_cde;
 extern int arm_arch_cde_coproc;
 extern const int arm_arch_cde_coproc_bits[];
 #define ARM_CDE_CONST_COPROC   7
+#define ARM_CCDE_CONST_1   ((1 << 13) - 1)
+#define ARM_CCDE_CONST_2   ((1 << 9 ) - 1)
+#define ARM_CCDE_CONST_3   ((1 << 6 ) - 1)
 #define ARM_VCDE_CONST_1   ((1 << 11) - 1)
 #define ARM_VCDE_CONST_2   ((1 << 6 ) - 1)
 #define ARM_VCDE_CONST_3   ((1 << 3 ) - 1)
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 
da0bfbc35501ba40324a38ee9ebc194f43196837..be076e4ac59be7f224b769bbca4013a554b50c07
 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -25057,10 +25057,11 @@ arm_hard_regno_mode_ok (unsigned int regno, 
machine_mode mode)
   if (ARM_NUM_REGS (mode) > 4)
return false;
 
-  if (TARGET_THUMB2 && !TARGET_HAVE_MVE)
+  if (TARGET_THUMB2 && !(TARGET_HAVE_MVE || TARGET_CDE))
return true;
 
-  return !(TARGET_LDRD && GET_MODE_SIZE (mode) > 4 && (regno & 1) != 0);
+  return !((TARGET_LDRD || TARGET_CDE)
+  && GET_MODE_SIZE (mode) > 4 && (regno & 1) != 0);
 }
 
   if (regno == FRAME_POINTER_REGNUM
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 
6d5560398dae3d0ace0342b4907542d2a6865f70..9c4d66f4efe70d9ab8896865cbf45285e5cfbaf9
 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -4408,6 +4408,70 @@
(set_attr "shift" "3")
(set_attr "type" "logic_shift_reg")])
 


+;; Custom Datapath Extension insns.
+(define_insn "arm_cx1"
+   [(set (match_operand:SIDI 0 "s_register_operand" "=r")
+(unspec:SIDI [(match_operand:SI 1 "const_int_coproc_operand" "i")
+  (match_operand:SI 2 "const_int_ccde1_operand" "i")]
+   UNSPEC_CDE))]
+   "TARGET_CDE"
+   "cx1\\tp%c1, , %2"
+)
+
+(define_insn "arm_cx1a"
+   [(set (match_operand:SIDI 0 "s_register_operand" "=r")
+(unspec:SIDI [(match_operand:SI 1 "const_int_coproc_operand" "i")
+  (match_operand:SIDI 2 "s_register_operand" "0")
+  (match_operand:SI 3 "const_int_ccde1_operand" "i")]
+   UNSPEC_CDEA))]
+   "TARGET_CDE"
+   "cx1a\\tp%c1, , %3"
+)
+
+(define_insn "arm_cx2"
+   [(set (match_operand:SIDI 0 &quo

[PATCH] [Arm] Implement scalar Custom Datapath Extension intrinsics

2020-04-08 Thread Matthew Malcomson
Suggestions applied.  I didn't update the indentation since it seems good to me
(with the `(unspec:SIDI ...)` indented one more level than the SET as
suggested).  I'm guessing it looked strange since that line is indented with a
tab and that can look different in different text editors.


This patch introduces the scalar CDE (Custom Datapath Extension)
intrinsics for the arm backend.

There is nothing beyond the standard in this patch.  We simply build upon what
has been done by Dennis for the vector intrinsics.

We do add `+cdecp6` to the default arguments for `target-supports.exp`, this
allows for using coprocessor 6 in tests. This patch uses an alternate
coprocessor to ease assembler scanning by looking for a use of coprocessor 6.

We also ensure that any DImode registers are put in an even-odd register pair
when compiling for a target with CDE -- this avoids faulty code generation for
-Os when producing the cx*d instructions.

Testing done:
Bootstrapped and regtested for arm-none-linux-gnueabihf.

gcc/ChangeLog:

2020-04-08  Matthew Malcomson  

* config/arm/arm.c (arm_hard_regno_mode_ok): DImode registers forced
into even-odd register pairs for TARGET_CDE.
* config/arm/arm.h (ARM_CCDE_CONST_1): New.
(ARM_CCDE_CONST_2): New.
(ARM_CCDE_CONST_3): New.
* config/arm/arm.md (arm_cx1si, arm_cx1di arm_cx1asi, arm_cx1adi
arm_cx2si, arm_cx2di arm_cx2asi, arm_cx2adi arm_cx3si, arm_cx3di
arm_cx3asi, arm_cx3adi): New patterns.
* config/arm/arm_cde.h (__arm_cx1, __arm_cx1a, __arm_cx2, __arm_cx2a,
__arm_cx3, __arm_cx3a, __arm_cx1d, __arm_cx1da, __arm_cx2d, __arm_cx2da,
__arm_cx3d, __arm_cx3da): New ACLE function macros.
* config/arm/arm_cde_builtins.def (cx1, cx1a, cx2, cx2a, cx3, cx3a):
Define intrinsics.
* config/arm/iterators.md (cde_suffix, cde_dest): New mode attributes.
* config/arm/predicates.md (const_int_ccde1_operand,
const_int_ccde2_operand, const_int_ccde3_operand): New.
* config/arm/unspecs.md (UNSPEC_CDE, UNSPEC_CDEA): New.

gcc/testsuite/ChangeLog:

2020-04-08  Matthew Malcomson  

* gcc.target/arm/acle/cde-errors.c: New test.
* gcc.target/arm/acle/cde.c: New test.
* lib/target-supports.exp: Update CDE flags to enable coprocessor 6.



### Attachment also inlined for ease of reply###


diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
index 
ca36a74cd1fa161c388961588fa0f96030b7888e..83886a2fcb3844f6a5060e451125a6cd2d505c5c
 100644
--- a/gcc/config/arm/arm.h
+++ b/gcc/config/arm/arm.h
@@ -576,6 +576,9 @@ extern int arm_arch_cde;
 extern int arm_arch_cde_coproc;
 extern const int arm_arch_cde_coproc_bits[];
 #define ARM_CDE_CONST_COPROC   7
+#define ARM_CCDE_CONST_1   ((1 << 13) - 1)
+#define ARM_CCDE_CONST_2   ((1 << 9 ) - 1)
+#define ARM_CCDE_CONST_3   ((1 << 6 ) - 1)
 #define ARM_VCDE_CONST_1   ((1 << 11) - 1)
 #define ARM_VCDE_CONST_2   ((1 << 6 ) - 1)
 #define ARM_VCDE_CONST_3   ((1 << 3 ) - 1)
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 
da0bfbc35501ba40324a38ee9ebc194f43196837..be076e4ac59be7f224b769bbca4013a554b50c07
 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -25057,10 +25057,11 @@ arm_hard_regno_mode_ok (unsigned int regno, 
machine_mode mode)
   if (ARM_NUM_REGS (mode) > 4)
return false;
 
-  if (TARGET_THUMB2 && !TARGET_HAVE_MVE)
+  if (TARGET_THUMB2 && !(TARGET_HAVE_MVE || TARGET_CDE))
return true;
 
-  return !(TARGET_LDRD && GET_MODE_SIZE (mode) > 4 && (regno & 1) != 0);
+  return !((TARGET_LDRD || TARGET_CDE)
+  && GET_MODE_SIZE (mode) > 4 && (regno & 1) != 0);
 }
 
   if (regno == FRAME_POINTER_REGNUM
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 
6d5560398dae3d0ace0342b4907542d2a6865f70..9c4d66f4efe70d9ab8896865cbf45285e5cfbaf9
 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -4408,6 +4408,70 @@
(set_attr "shift" "3")
(set_attr "type" "logic_shift_reg")])
 


+;; Custom Datapath Extension insns.
+(define_insn "arm_cx1"
+   [(set (match_operand:SIDI 0 "s_register_operand" "=r")
+(unspec:SIDI [(match_operand:SI 1 "const_int_coproc_operand" "i")
+  (match_operand:SI 2 "const_int_ccde1_operand" "i")]
+   UNSPEC_CDE))]
+   "TARGET_CDE"
+   "cx1\\tp%c1, , %2"
+)
+
+(define_insn "arm_cx1a"
+   [(set (match_operand:SIDI 0 "s_register_operand" "=r")
+(unspec:SIDI [(match_operand:SI 1 "const_int_coproc_operand" "i")
+  (match_operand:SIDI 2 "s_register_operand" "0

[wwwdocs] [arm] Document CDE intrinsics from ACLE

2020-04-08 Thread Matthew Malcomson
New in GCC 10.


### Attachment also inlined for ease of reply###


diff --git a/htdocs/gcc-10/changes.html b/htdocs/gcc-10/changes.html
index 
3d8e0ba989e860d307310378a2be99b32a27261f..389561d13c69b650528e8ed8859ebbb5760438c6
 100644
--- a/htdocs/gcc-10/changes.html
+++ b/htdocs/gcc-10/changes.html
@@ -624,6 +624,9 @@ a work-in-progress.
   added: this M-profile feature is no longer restricted to targets
   with MOVT. For example, -mcpu=cortex-m0
   now supports this option.
+  Support for the Custom Datapath Extension ACLE
+  https://developer.arm.com/docs/101028/0010/custom-datapath-extension";>
+  intrinsics has been added.
 
 
 AVR

diff --git a/htdocs/gcc-10/changes.html b/htdocs/gcc-10/changes.html
index 
3d8e0ba989e860d307310378a2be99b32a27261f..389561d13c69b650528e8ed8859ebbb5760438c6
 100644
--- a/htdocs/gcc-10/changes.html
+++ b/htdocs/gcc-10/changes.html
@@ -624,6 +624,9 @@ a work-in-progress.
   added: this M-profile feature is no longer restricted to targets
   with MOVT. For example, -mcpu=cortex-m0
   now supports this option.
+  Support for the Custom Datapath Extension ACLE
+  https://developer.arm.com/docs/101028/0010/custom-datapath-extension";>
+  intrinsics has been added.
 
 
 AVR



[Arm] Allow the use of arm_cde.h for C++

2020-04-09 Thread Matthew Malcomson
arm_cde.h includes the arm_mve_types.h header, which declares some C++
overloaded functions.

There is a superfluous `extern "C"` statement in arm_cde.h, which
encompasses these functions.  This means that if compiling for C++, the
overloaded functions are declared, but are declared without name
mangling.  Hence all the function names are the same and we have many
conflicting declarations.

Testing Done:
  Regression tested for arm-none-eabi.

gcc/ChangeLog:

2020-04-09  Matthew Malcomson  

* config/arm/arm_cde.h: Remove `extern "C"` when compiling for
C++.

gcc/testsuite/ChangeLog:

2020-04-09  Matthew Malcomson  

* g++.target/arm/cde_mve.C: New test.



### Attachment also inlined for ease of reply###


diff --git a/gcc/config/arm/arm_cde.h b/gcc/config/arm/arm_cde.h
index 
d8ddda6bd648d8b94e97f7b6403b7708cebc9eb3..0ba3ee02d057dd280c9b3400ef70b46ed472aec3
 100644
--- a/gcc/config/arm/arm_cde.h
+++ b/gcc/config/arm/arm_cde.h
@@ -27,10 +27,6 @@
 #ifndef _GCC_ARM_CDE_H
 #define _GCC_ARM_CDE_H 1
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 #include 
 
 #if defined (__ARM_FEATURE_CDE)
@@ -177,8 +173,4 @@ extern "C" {
 
 #endif
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif
diff --git a/gcc/testsuite/g++.target/arm/cde_mve.C 
b/gcc/testsuite/g++.target/arm/cde_mve.C
new file mode 100644
index 
..897cbd2b8119471385c1c51158b1aa4851acbaf1
--- /dev/null
+++ b/gcc/testsuite/g++.target/arm/cde_mve.C
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_v8_1m_main_cde_mve_fp_ok } */
+/* { dg-add-options arm_v8_1m_main_cde_mve_fp } */
+
+/* Ensure this compiles.  */
+#include "arm_cde.h"
+int foo ()
+{
+  return 1;
+}

diff --git a/gcc/config/arm/arm_cde.h b/gcc/config/arm/arm_cde.h
index 
d8ddda6bd648d8b94e97f7b6403b7708cebc9eb3..0ba3ee02d057dd280c9b3400ef70b46ed472aec3
 100644
--- a/gcc/config/arm/arm_cde.h
+++ b/gcc/config/arm/arm_cde.h
@@ -27,10 +27,6 @@
 #ifndef _GCC_ARM_CDE_H
 #define _GCC_ARM_CDE_H 1
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 #include 
 
 #if defined (__ARM_FEATURE_CDE)
@@ -177,8 +173,4 @@ extern "C" {
 
 #endif
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif
diff --git a/gcc/testsuite/g++.target/arm/cde_mve.C 
b/gcc/testsuite/g++.target/arm/cde_mve.C
new file mode 100644
index 
..897cbd2b8119471385c1c51158b1aa4851acbaf1
--- /dev/null
+++ b/gcc/testsuite/g++.target/arm/cde_mve.C
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_v8_1m_main_cde_mve_fp_ok } */
+/* { dg-add-options arm_v8_1m_main_cde_mve_fp } */
+
+/* Ensure this compiles.  */
+#include "arm_cde.h"
+int foo ()
+{
+  return 1;
+}



[Arm] Disallow arm_movdi when targetting MVE

2020-04-15 Thread Matthew Malcomson
Without disabling this, the pattern can try and move DImode values
between floating point registers and general registers.
The constraints on this pattern can't handle that, and reload goes into
an infinite loop.

This was the cause of a testsuite failure in cde_v_1_mve.c, which is now
gone.

A DImode move for MVE now uses the `movdi_vfp` pattern, which is the same
pattern used for such a move when MVE is not available but the target has
TARGET_HARD_FLOAT.

Testing done:
Bootstrapped and regtested on arm-none-linux-gnueabihf
regtested on arm-none-eabi

gcc/ChangeLog:

2020-04-15  Matthew Malcomson  

* config/arm/arm.md (arm_movdi): Disallow for MVE.



### Attachment also inlined for ease of reply###


diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 
7bc55cce61b2e45e5875a233dd4546d59399d749..a6a31f8f4ef8d3c8c96c61b450dbd7c28d08b55c
 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -6233,6 +6233,7 @@
(match_operand:DI 1 "di_operand"  "rDa,Db,Dc,mi,r"))]
   "TARGET_32BIT
&& !(TARGET_HARD_FLOAT)
+   && !(TARGET_HAVE_MVE || TARGET_HAVE_MVE_FLOAT)
&& !TARGET_IWMMXT
&& (   register_operand (operands[0], DImode)
|| register_operand (operands[1], DImode))"

diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 
7bc55cce61b2e45e5875a233dd4546d59399d749..a6a31f8f4ef8d3c8c96c61b450dbd7c28d08b55c
 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -6233,6 +6233,7 @@
(match_operand:DI 1 "di_operand"  "rDa,Db,Dc,mi,r"))]
   "TARGET_32BIT
&& !(TARGET_HARD_FLOAT)
+   && !(TARGET_HAVE_MVE || TARGET_HAVE_MVE_FLOAT)
&& !TARGET_IWMMXT
&& (   register_operand (operands[0], DImode)
|| register_operand (operands[1], DImode))"



Re: [PATCH 1/2] testsuite: [arm/cde] Include arm_cde.h and arm_mve.h in arm_v8*m_main_cde*

2020-04-20 Thread Matthew Malcomson

On 20/04/2020 08:47, Christophe Lyon via Gcc-patches wrote:

Since arm_cde.h includes stdint.h, its use requires the presence of
the right gnu/stub-*.h, so make sure to include it when checking the
arm_v8*m_main_cde* effective targets, otherwise we can decide CDE is
supported while it's not really (all tests that use arm_v8m_main_cde*
also include arm_cde.h aynway).

Similarly for the effective targets that also require MVE.

This makes several tests unsupported rather than fail.


Hi Christophe,

This looks like a good idea to me -- though I'm not a maintainer so that 
means little ;-)


I just wanted to ask -- is this needed mainly if testing without a fully 
functional C99 environment?
I would imagine that a fully set up environment would have some sort of 
`stdint.h` available, even if not using the glibc gnu/stub-*.h files 
(e.g. using the newlib headers).


Cheers,
Matthew


---
  gcc/testsuite/lib/target-supports.exp | 10 --
  1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/gcc/testsuite/lib/target-supports.exp 
b/gcc/testsuite/lib/target-supports.exp
index d16498d..23a5abf 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -5140,21 +5140,25 @@ proc add_options_for_arm_v8_2a_bf16_neon { flags } {
  #   /* { dg-add-options arm_v8m_main_cde } */
  # The tests are valid for Arm.
  
-foreach { armfunc armflag armdef } {

+foreach { armfunc armflag armdef arminc } {
arm_v8m_main_cde
"-march=armv8-m.main+cdecp0+cdecp6 -mthumb"
"defined (__ARM_FEATURE_CDE)"
+   ""
arm_v8m_main_cde_fp
"-march=armv8-m.main+fp+cdecp0+cdecp6 -mthumb -mfpu=auto"
"defined (__ARM_FEATURE_CDE) && defined (__ARM_FP)"
+   ""
arm_v8_1m_main_cde_mve
"-march=armv8.1-m.main+mve+cdecp0+cdecp6 -mthumb -mfpu=auto"
"defined (__ARM_FEATURE_CDE) && defined (__ARM_FEATURE_MVE)"
+   "#include "
arm_v8_1m_main_cde_mve_fp
"-march=armv8.1-m.main+mve.fp+cdecp0+cdecp6 -mthumb -mfpu=auto"
"defined (__ARM_FEATURE_CDE) || __ARM_FEATURE_MVE == 3"
+   "#include "
} {
-eval [string map [list FUNC $armfunc FLAG $armflag DEF $armdef ] {
+eval [string map [list FUNC $armfunc FLAG $armflag DEF $armdef INC $arminc 
] {
proc check_effective_target_FUNC_ok_nocache { } {
global et_FUNC_flags
set et_FUNC_flags ""
@@ -5167,6 +5171,8 @@ foreach { armfunc armflag armdef } {
#if !(DEF)
#error "DEF failed"
#endif
+   #include 
+   INC
} "FLAG"] } {
set et_FUNC_flags "FLAG"
return 1





[AArch64] (PR94383) Avoid C++17 empty base field checking for HVA/HFA

2020-04-21 Thread Matthew Malcomson
In C++17, an empty class deriving from an empty base is not an
aggregate, while in C++14 it is.  In order to implement this, GCC adds
an artificial field to such classes.

This artificial field has no mapping to Fundamental Data Types in the
AArch64 PCS ABI and hence should not count towards determining whether an
object can be passed using the vector registers as per section
"6.4.2 Parameter Passing Rules" in the AArch64 PCS.
https://github.com/ARM-software/abi-aa/blob/master/aapcs64/aapcs64.rst#the-base-procedure-call-standard

This patch avoids counting this artificial field in
aapcs_vfp_sub_candidate, and hence calculates whether such objects
should be passed in vector registers in the same manner as C++14 (where
the artificial field does not exist).

Before this change, the test below would pass the arguments to `f` in
general registers.  After this change, the test passes the arguments to
`f` using the vector registers.

The new behaviour matches the behaviour of `armclang`, and also matches
the behaviour when run with `-std=gnu++14`.

> gcc -std=gnu++17 test.cpp

``` test.cpp
struct base {};

struct pair : base
{
  float first;
  float second;
  pair (float f, float s) : first(f), second(s) {}
};

void f (pair);
int main()
{
  f({3.14, 666});
  return 1;
}
```

We add a `-Wpsabi` warning to catch cases where this fix has changed the ABI for
some functions.  Unfortunately this warning is currently emitted multiple times
for each problem, but I feel this is not much of a problem and can be fixed
later if needs be.


Testing:
Bootstrapped on aarch64-linux.
Jakub has provided a testsuite change that catches the original problem.
https://gcc.gnu.org/pipermail/gcc-patches/2020-April/544204.html
This patch makes that testcase pass.

gcc/ChangeLog:

2020-04-21  Matthew Malcomson  
Jakub Jelinek  

PR target/94383
* config/aarch64/aarch64.c (enum cpp17empty_state): New.
(aapcs_vfp_sub_candidate): Account for C++17 empty base class
artificial fields.
(aarch64_vfp_is_call_or_return_candidate): Warn when ABI PCS decision is
different after this fix.



### Attachment also inlined for ease of reply###


diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 
c90de65de127992cc0bd9603a32684ebb5bd4fdf..f9f40d52c846afae0d8d2cd9ed4737cdc4b88896
 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -15909,13 +15909,30 @@ aarch64_conditional_register_usage (void)
 }
 }
 
+enum cpp17empty_state {
+DONT_AVOID = 0,
+AVOID = 1,
+AVOID_DONE = 3
+};
+
 /* Walk down the type tree of TYPE counting consecutive base elements.
If *MODEP is VOIDmode, then set it to the first valid floating point
type.  If a non-floating point type is found, or if a floating point
type that doesn't match a non-VOIDmode *MODEP is found, then return -1,
-   otherwise return the count in the sub-tree.  */
+   otherwise return the count in the sub-tree.
+
+   The AVOID_C17EMPTY_FIELD argument is to allow the caller to check whether
+   this function has changed its behaviour after the fix for PR94384 -- this
+   fix is to avoid artificial fields in empty base classes.
+   When called pointing at a value of DONT_AVOID then this function does not
+   avoid the artificial fields -- this is useful to check whether the function
+   returns something different after the fix.
+   When called pointing at a value which has the AVOID bit set, this function
+   avoids such artificial fields and sets the value to AVOID_DONE when one of
+   these fields has been set.  */
 static int
-aapcs_vfp_sub_candidate (const_tree type, machine_mode *modep)
+aapcs_vfp_sub_candidate (const_tree type, machine_mode *modep,
+enum cpp17empty_state *avoid_c17empty_field)
 {
   machine_mode mode;
   HOST_WIDE_INT size;
@@ -15992,7 +16009,8 @@ aapcs_vfp_sub_candidate (const_tree type, machine_mode 
*modep)
|| TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
  return -1;
 
-   count = aapcs_vfp_sub_candidate (TREE_TYPE (type), modep);
+   count = aapcs_vfp_sub_candidate (TREE_TYPE (type), modep,
+avoid_c17empty_field);
if (count == -1
|| !index
|| !TYPE_MAX_VALUE (index)
@@ -16030,7 +16048,22 @@ aapcs_vfp_sub_candidate (const_tree type, machine_mode 
*modep)
if (TREE_CODE (field) != FIELD_DECL)
  continue;
 
-   sub_count = aapcs_vfp_sub_candidate (TREE_TYPE (field), modep);
+   /* Ignore C++17 empty base fields, while their type indicates
+  they do contain padding, they have zero size and thus don't
+  contain any padding.  */
+   if (DECL_ARTIFICIAL (field)
+   && DECL_NAME (field) == NULL_TREE
+   && RECORD_OR_UNION_TYPE_P (TREE_TYPE (fiel

[AArch64] (PR94383) Avoid C++17 empty base field checking for HVA/HFA

2020-04-23 Thread Matthew Malcomson
In C++17, an empty class deriving from an empty base is not an
aggregate, while in C++14 it is.  In order to implement this, GCC adds
an artificial field to such classes.

This artificial field has no mapping to Fundamental Data Types in the
AArch64 PCS ABI and hence should not count towards determining whether an
object can be passed using the vector registers as per section
"6.4.2 Parameter Passing Rules" in the AArch64 PCS.
https://github.com/ARM-software/abi-aa/blob/master/aapcs64/aapcs64.rst#the-base-procedure-call-standard

This patch avoids counting this artificial field in
aapcs_vfp_sub_candidate, and hence calculates whether such objects
should be passed in vector registers in the same manner as C++14 (where
the artificial field does not exist).

Before this change, the test below would pass the arguments to `f` in
general registers.  After this change, the test passes the arguments to
`f` using the vector registers.

The new behaviour matches the behaviour of `armclang`, and also matches
the behaviour when run with `-std=gnu++14`.

> gcc -std=gnu++17 test.cpp

``` test.cpp
struct base {};

struct pair : base
{
  float first;
  float second;
  pair (float f, float s) : first(f), second(s) {}
};

void f (pair);
int main()
{
  f({3.14, 666});
  return 1;
}
```

We add a `-Wpsabi` warning to catch cases where this fix has changed the ABI for
some functions.  Unfortunately this warning is not emitted twice for multiple
calls to the same function, but I feel this is not much of a problem and can be
fixed later if needs be.

(i.e. if `main` called `f` twice in a row we only emit a diagnostic for the
first).

Testing:
Minimal testing done just to demonstrate new warning message and to check
tests related to this still pass.


gcc/ChangeLog:

2020-04-23  Matthew Malcomson  
Jakub Jelinek  

PR target/94383
* config/aarch64/aarch64.c (aapcs_vfp_sub_candidate): Account for C++17
empty base class artificial fields.
(aarch64_vfp_is_call_or_return_candidate): Warn when ABI PCS decision is
different after this fix.



### Attachment also inlined for ease of reply###


diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 
f728ac530a4ac968de16ea59d2b724ed63b23d6f..25f60ec44ae3a177d0aceb4bae92ea17da91ba05
 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -16442,9 +16442,19 @@ aarch64_member_type_forces_blk (const_tree 
field_or_array, machine_mode mode)
If *MODEP is VOIDmode, then set it to the first valid floating point
type.  If a non-floating point type is found, or if a floating point
type that doesn't match a non-VOIDmode *MODEP is found, then return -1,
-   otherwise return the count in the sub-tree.  */
+   otherwise return the count in the sub-tree.
+
+   The AVOID_CXX17_EMPTY_BASE argument is to allow the caller to check whether
+   this function has changed its behavior after the fix for PR94384 -- this fix
+   is to avoid artificial fields in empty base classes.
+   When called with this argument as a NULL pointer this function does not
+   avoid the artificial fields -- this is useful to check whether the function
+   returns something different after the fix.
+   When called pointing at a value, this function avoids such artificial fields
+   and sets the value to TRUE when one of these fields has been set.  */
 static int
-aapcs_vfp_sub_candidate (const_tree type, machine_mode *modep)
+aapcs_vfp_sub_candidate (const_tree type, machine_mode *modep,
+bool *avoid_cxx17_empty_base)
 {
   machine_mode mode;
   HOST_WIDE_INT size;
@@ -16520,7 +16530,8 @@ aapcs_vfp_sub_candidate (const_tree type, machine_mode 
*modep)
|| TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
  return -1;
 
-   count = aapcs_vfp_sub_candidate (TREE_TYPE (type), modep);
+   count = aapcs_vfp_sub_candidate (TREE_TYPE (type), modep,
+avoid_cxx17_empty_base);
if (count == -1
|| !index
|| !TYPE_MAX_VALUE (index)
@@ -16558,7 +16569,18 @@ aapcs_vfp_sub_candidate (const_tree type, machine_mode 
*modep)
if (TREE_CODE (field) != FIELD_DECL)
  continue;
 
-   sub_count = aapcs_vfp_sub_candidate (TREE_TYPE (field), modep);
+   /* Ignore C++17 empty base fields, while their type indicates
+  they do contain padding, they have zero size and thus don't
+  contain any padding.  */
+   if (cxx17_empty_base_field_p (field)
+   && avoid_cxx17_empty_base)
+ {
+   *avoid_cxx17_empty_base = true;
+   continue;
+ }
+
+   sub_count = aapcs_vfp_sub_candidate (TREE_TYPE (field), modep,
+avoid_cxx17_empty_base);
if (sub_count < 0)

[Arm] Account for C++17 artificial field determining Homogeneous Aggregates

2020-04-27 Thread Matthew Malcomson
NOTE:
  There is another patch in the making to handle the APCS abi (selected with
  `-mabi=apcs-gnu`).  That patch has a very different change in behaviour and
  is in a different part of the code so I'm keeping it in a different patch.

In C++14, an empty class deriving from an empty base is not an
aggregate, while in C++17 it is.  In order to implement this, GCC adds
an artificial field to such classes.

This artificial field has no mapping to Fundamental Data Types in the
Arm PCS ABI and hence should not count towards determining whether an
object can be passed using the vector registers as per section
"7.1.2 Procedure Calling" in the arm PCS
https://developer.arm.com/docs/ihi0042/latest?_ga=2.60211309.1506853196.1533541889-405231439.1528186050

This patch avoids counting this artificial field in
aapcs_vfp_sub_candidate, and hence calculates whether such objects
should be passed in vector registers in the same manner as C++14 (where
the artificial field does not exist).

Before this change, the test below would pass the arguments to `f` in
general registers.  After this change, the test passes the arguments to
`f` using the vector registers.

The new behaviour matches the behaviour of `armclang`, and also matches
the GCC behaviour when run with `-std=gnu++14`.

> gcc -std=gnu++17 -march=armv8-a+simd -mfloat-abi=hard test.cpp

``` test.cpp
struct base {};

struct pair : base
{
  float first;
  float second;
  pair (float f, float s) : first(f), second(s) {}
};

void f (pair);
int main()
{
  f({3.14, 666});
  return 1;
}
```

We add a `-Wpsabi` warning to catch cases where this fix has changed the ABI for
some functions.  Unfortunately this warning is not emitted twice for multiple
calls to the same function, but I feel this is not much of a problem and can be
fixed later if needs be.

(i.e. if `main` called `f` twice in a row we only emit a diagnostic for the
first).

Testing:
Bootstrapped and regression tested on arm-linux.
This change fixes the struct-layout-1 tests Jakub added
https://gcc.gnu.org/pipermail/gcc-patches/2020-April/544204.html
Regression tested on arm-none-eabi.

gcc/ChangeLog:

2020-04-27  Matthew Malcomson  
Jakub Jelinek  

PR target/94383
* config/arm/arm.c (aapcs_vfp_sub_candidate): Account for C++17 empty
base class artificial fields.
(aapcs_vfp_is_call_or_return_candidate): Warn when PCS ABI
decision is different after this fix.



### Attachment also inlined for ease of reply###


diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 
0151bda90d961ae1a001c61cd5e94d6ec67e3aea..0db444c3fdb2ba6fb7ebad410310fb5b1bc0e304
 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -6139,9 +6139,19 @@ aapcs_vfp_cum_init (CUMULATIVE_ARGS *pcum  
ATTRIBUTE_UNUSED,
If *MODEP is VOIDmode, then set it to the first valid floating point
type.  If a non-floating point type is found, or if a floating point
type that doesn't match a non-VOIDmode *MODEP is found, then return -1,
-   otherwise return the count in the sub-tree.  */
+   otherwise return the count in the sub-tree.
+
+   The AVOID_CXX17_EMPTY_BASE argument is to allow the caller to check whether
+   this function has changed its behavior after the fix for PR94384 -- this fix
+   is to avoid artificial fields in empty base classes.
+   When called with this argument as a NULL pointer this function does not
+   avoid the artificial fields -- this is useful to check whether the function
+   returns something different after the fix.
+   When called pointing at a value, this function avoids such artificial fields
+   and sets the value to TRUE when one of these fields has been set.  */
 static int
-aapcs_vfp_sub_candidate (const_tree type, machine_mode *modep)
+aapcs_vfp_sub_candidate (const_tree type, machine_mode *modep,
+bool *avoid_cxx17_empty_base)
 {
   machine_mode mode;
   HOST_WIDE_INT size;
@@ -6213,7 +6223,8 @@ aapcs_vfp_sub_candidate (const_tree type, machine_mode 
*modep)
|| TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
  return -1;
 
-   count = aapcs_vfp_sub_candidate (TREE_TYPE (type), modep);
+   count = aapcs_vfp_sub_candidate (TREE_TYPE (type), modep,
+avoid_cxx17_empty_base);
if (count == -1
|| !index
|| !TYPE_MAX_VALUE (index)
@@ -6251,7 +6262,18 @@ aapcs_vfp_sub_candidate (const_tree type, machine_mode 
*modep)
if (TREE_CODE (field) != FIELD_DECL)
  continue;
 
-   sub_count = aapcs_vfp_sub_candidate (TREE_TYPE (field), modep);
+   /* Ignore C++17 empty base fields, while their type indicates
+  they do contain padding, they have zero size and thus don't
+  contain any padding.  */
+   if (cxx17_empty_base_field_p (field)
+

Straight Line Speculation (SLS) mitigation.

2020-06-08 Thread Matthew Malcomson
Hi,

A new speculative cache side-channel vulnerability has been published at
the link below, named "straight-line speculation" (SLS in this patch series).
https://developer.arm.com/support/arm-security-updates/speculative-processor-vulnerability/downloads/straight-line-speculation
This vulnerability has been given CVE number CVE-2020-13844.

We have prepared some toolchain mitigations for this vulnerability.  These
mitigate against the RET, BR case and the BLR case mentioned in the linked
whitepaper.

The part of vulnerability relevant to these toolchain mitigations is as
follows:
Some processors may speculatively execute the instructions immediately
following what should be a change in control flow.  The examples we mitigate in
this patch series are the instructions RET (return), BR (indirect jump) and BLR
(indirect function call).
Where the speculative path contains a suitable code sequence, often described
by researchers as a "Spectre Revelation Gadget", such straight-line speculation
could lead to changes in the caches and similar structures that are indicative
of secrets, making those secrets vulnerable to revelation through timing
analysis.

The gist of the mitigation posted here is:

Every RET and BR instruction has a speculation barrier placed directly after
it.  These speculation barriers are not to be architecturally executed, so the
performance cost is expected to be low.

Each BLR instruction is replaced by a BL to a function stub consisting of a BR
instruction followed by a speculation barrier.
This alternate approach is used since the instructions directly after a BLR are
usually architecturally executed, and this approach ensures the speculation
barrier is off that architecturally executed path.
Arm has been unable to demonstrate straight line speculation past a BL or B
instruction, and so we believe the BL instruction can be used without a
barrier.

In summary, a
  RET
will be transformed to
  RET
  

While a
  BLR x
will be transformed to a
  BL __call_indirect_x
call, with __call_indirect_x being a thunk that looks like
__call_indirect_x:
  BR x
  


The patch series is structured as follows:
1) Introduce new command line arguments.
2) The RET/BR mitigation.
3) The BLR mitigation.

There are a few known places where this toolchain mitigation does not protect
against speculation places:
- Some accesses to thread-local variables use a code sequence including a BLR
  instruction.   This code sequence is part of the binary interface between
  compiler and linker. If this BLR instruction needs to be mitigated, it'd
  probably be best to do so in the linker.
  It seems that the code sequence for thread-local variable access is unlikely
  to lead to a Spectre Revalation Gadget.
- PLT stubs are produced by the linker, and each contain a BLR instruction.
  It seems that at most this could introduce one spectre relevation gadget
  after the last PLT stub.
- Use of BR, RET, or BLR instructions in assembly are not mitigated.
- Use of BR, RET, or BLR instructions in libraries and run-time library
  routines that are not recompiled with this toolchain mitigation are not
  mitigated.

N.b. patches with similar functionality are being posted to LLVM.

Thanks,
Matthew.


Entire patch series attached to cover letter.

all-patches.tar.gz
Description: application/gzip


[Patch 3/3] aarch64: Mitigate SLS for BLR instruction

2020-06-08 Thread Matthew Malcomson
This patch introduces the mitigation for Straight Line Speculation past
the BLR instruction.

This mitigation replaces BLR instructions with a BL to a stub which
simply consists of a BR to the original register.  These function stubs
are then appended with a speculation barrier to ensure no straight line
speculation happens after these jumps.

When optimising for speed we use a set of stubs for each function since
this should help the branch predictor make more accurate predictions
about where a stub should branch.

When optimising for size we use one set of stubs for the entire
compilation unit.
This set of stubs can have human readable names, and we are currently
using `__call_indirect_x` for register x.

As an example when optimising for size:
a
BLR x0
instruction would get transformed to
BL __call_indirect_x0
with __call_indirect_x0 labelling a thunk that contains
__call_indirect_x0:
BR X0
speculation barrier

Since we add these function stubs to the assembly output all in one
chunk, we need not add the speculation barrier directly after each one.
This is because we know for certain that the instructions directly after
the BR in all but the last function stub will be from another one of
these stubs and hence will not contain a speculation gadget.
Instead we add a speculation barrier at the end of the sequence of
stubs.

Special care needs to be given to this transformation occuring in
a context where BTI is enabled.  A BLR can jump to a `BTI c` target,
while a BR can only jump to a `BTI c` target if it uses the registers
x16 or x17.
Hence we use constraints to limit the registers used when this
transformation is being made in an environment that uses BTI.

This mitigation does not apply for BLR instructions in the following
places:
- Some accesses to thread-local variables use a code sequence with a BLR
  instruction.  This code sequence is part of the binary interface between
  compiler and linker. If this BLR instruction needs to be mitigated, it'd
  probably be best to do so in the linker. It seems that the code sequence
  for thread-local variable access is unlikely to lead to a Spectre Revalation
  Gadget.
- PLT stubs are produced by the linker and each contain a BLR instruction.
  It seems that at most only after the last PLT stub a Spectre Revalation
  Gadget might appear.

Testing:
  Bootstrap and regtest on AArch64
(with BOOT_CFLAGS="-mharden-sls=retbr,blr")
  Used a temporary hack(1) in gcc-dg.exp to use these options on every
  test in the testsuite, a slight modification to emit the speculation
  barrier after every function stub, and a script to check that the
  output never emitted a BLR, or unmitigated BR or RET instruction.
  Similar on an aarch64-none-elf cross-compiler.

1) Temporary hack emitted a speculation barrier at the end of every stub
function, and used a script to ensure that:
  a) Every RET or BR is immediately followed by a speculation barrier.
  b) No BLR instruction is emitted by compiler.


gcc/ChangeLog:

2020-06-08  Matthew Malcomson  

* config/aarch64/aarch64-protos.h (aarch64_indirect_call_asm):
New declaration.
* config/aarch64/aarch64.c (aarch64_use_return_insn_p): Return
false if hardening BLR instructions.
(aarch64_sls_shared_thunks): Global array to store stub labels.
(aarch64_create_blr_label): New.
(print_asm_branch): New macro.
(aarch64_sls_emit_blr_function_thunks): New.
(aarch64_sls_emit_shared_blr_thunks): New.
(aarch64_asm_file_end): New.
(aarch64_indirect_call_asm): New.
(TARGET_ASM_FILE_END): Use aarch64_asm_file_end.
(TARGET_ASM_FUNCTION_EPILOGUE): Use
aarch64_sls_emit_blr_function_thunks.
* config/aarch64/aarch64.h (struct machine_function): Introduce
`call_via` array to store function-local stub labels.
* config/aarch64/aarch64.md (*call_insn, *call_value_insn): Use
aarch64_indirect_call_asm to emit code when hardening BLR
instructions.

gcc/testsuite/ChangeLog:

2020-06-08  Matthew Malcomson  

* gcc.target/aarch64/sls-mitigation/sls-miti-blr-bti.c: New test.
* gcc.target/aarch64/sls-mitigation/sls-miti-blr.c: New test.



### Attachment also inlined for ease of reply###


diff --git a/gcc/config/aarch64/aarch64-protos.h 
b/gcc/config/aarch64/aarch64-protos.h
index 
d2eb739bc89ecd9d0212416b8dc3ee4ba236a271..e79f9cbc783e75132e999395ff975f9768436419
 100644
--- a/gcc/config/aarch64/aarch64-protos.h
+++ b/gcc/config/aarch64/aarch64-protos.h
@@ -781,6 +781,7 @@ extern const atomic_ool_names aarch64_ool_ldeor_names;
 tree aarch64_resolve_overloaded_builtin_general (location_t, tree, void *);
 
 const char * aarch64_sls_barrier (int);
+const char * aarch64_indirect_call_asm (rtx);
 extern bool aarch64_harden_sls_retbr_p (void);
 extern bool aarch64_harden_sls_blr_p (void);
 
diff --git a/gcc/config/aarch64/aarch64.h b/gcc

[Patch 1/3] aarch64: New Straight Line Speculation (SLS) mitigation flags

2020-06-08 Thread Matthew Malcomson
Here we introduce the flags that will be used for straight line speculation.

The new flag introduced is `-mharden-sls=`.
This flag can take arguments of `none`, `all`, or a comma seperated list of one
or more of `retbr` or `blr`.
`none` indicates no special mitigation of the straight line speculation
vulnerability.
`all` requests all mitigations currently implemented.
`retbr` requests that the RET and BR instructions have a speculation barrier
inserted after them.
`blr` requests that BLR instructions are replaced by a BL to a function stub
using a BR with a speculation barrier after it.

Setting this on a per-function basis using attributes or the like is not
enabled, but may be in the future.

gcc/ChangeLog:

2020-06-08  Matthew Malcomson  

* config/aarch64/aarch64-protos.h (aarch64_harden_sls_retbr_p):
New.
(aarch64_harden_sls_blr_p): New.
* config/aarch64/aarch64.c (enum aarch64_sls_hardening_type):
New.
(aarch64_harden_sls_retbr_p): New.
(aarch64_harden_sls_blr_p): New.
(aarch64_validate_sls_mitigation): New.
(aarch64_override_options): Parse options for SLS mitigation.
* config/aarch64/aarch64.opt (-mharden-sls): New option.
* doc/invoke.texi: Document new option.



### Attachment also inlined for ease of reply###


diff --git a/gcc/config/aarch64/aarch64-protos.h 
b/gcc/config/aarch64/aarch64-protos.h
index 
9e43adb7db0373df6cc5ef1d2b22f217aca2aad2..8ca67d7e69edaf73c84f079e7e1c483009ad10c0
 100644
--- a/gcc/config/aarch64/aarch64-protos.h
+++ b/gcc/config/aarch64/aarch64-protos.h
@@ -780,4 +780,7 @@ extern const atomic_ool_names aarch64_ool_ldeor_names;
 
 tree aarch64_resolve_overloaded_builtin_general (location_t, tree, void *);
 
+extern bool aarch64_harden_sls_retbr_p (void);
+extern bool aarch64_harden_sls_blr_p (void);
+
 #endif /* GCC_AARCH64_PROTOS_H */
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 
e92c7e69fcb7a8689a8b7098b86ff050dc9ab78b..775f49991e5f599a843d3ef490b8cd044acfe78f
 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -14466,6 +14466,81 @@ aarch64_validate_mcpu (const char *str, const struct 
processor **res,
   return false;
 }
 
+
+/* Straight line speculation indicators.  */
+enum aarch64_sls_hardening_type
+{
+SLS_NONE = 0,
+SLS_RETBR = 1,
+SLS_BLR = 2,
+SLS_ALL = 3,
+};
+static enum aarch64_sls_hardening_type aarch64_sls_hardening;
+/* Return whether we should mitigatate Straight Line Speculation for the RET
+   and BR instructions.  */
+bool
+aarch64_harden_sls_retbr_p (void)
+{
+  return aarch64_sls_hardening & SLS_RETBR;
+}
+/* Return whether we should mitigatate Straight Line Speculation for the RET
+   and BR instructions.  */
+bool
+aarch64_harden_sls_blr_p (void)
+{
+  return aarch64_sls_hardening & SLS_BLR;
+}
+
+/* As of yet we only allow setting these options globally, in the future we may
+   allow setting them per function.  */
+static void
+aarch64_validate_sls_mitigation (const char *const_str)
+{
+  char *str_root = xstrdup (const_str);
+  char *token_save = NULL;
+  char *str = NULL;
+  int temp = SLS_NONE;
+
+  aarch64_sls_hardening = SLS_NONE;
+  if (strcmp (str_root, "none") == 0)
+goto finish;
+  if (strcmp (str_root, "all") == 0)
+{
+  aarch64_sls_hardening = SLS_ALL;
+  goto finish;
+}
+
+  str = strtok_r (str_root, ",", &token_save);
+  if (!str)
+{
+  error ("invalid argument given to %<-mharden-sls=%>");
+  goto finish;
+}
+
+  while (str)
+{
+  if (strcmp (str, "blr") == 0)
+   temp |= SLS_BLR;
+  else if (strcmp (str, "retbr") == 0)
+   temp |= SLS_RETBR;
+  else if (strcmp (str, "none") == 0 || strcmp (str, "all") == 0)
+   {
+ error ("%<%s%> must be by itself for %<-mharden-sls=%>", str);
+ break;
+   }
+  else
+   {
+ error ("invalid argument %<%s%> for %<-mharden-sls=%>", str);
+ break;
+   }
+  str = strtok_r (NULL, ",", &token_save);
+}
+  aarch64_sls_hardening = (aarch64_sls_hardening_type) temp;
+finish:
+  free (str_root);
+  return;
+}
+
 /* Parses CONST_STR for branch protection features specified in
aarch64_branch_protect_types, and set any global variables required.  
Returns
the parsing result and assigns LAST_STR to the last processed token from
@@ -14710,6 +14785,9 @@ aarch64_override_options (void)
   selected_arch = NULL;
   selected_tune = NULL;
 
+  if (aarch64_harden_sls_string)
+  aarch64_validate_sls_mitigation (aarch64_harden_sls_string);
+
   if (aarch64_branch_protection_string)
 aarch64_validate_mbranch_protection (aarch64_branch_protection_string);
 
diff --git a/gcc/config/aarch64/aarch64.opt b/gcc/config/aarch64/aarch64.opt
ind

[Patch 2/3] aarch64: Introduce SLS mitigation for RET and BR instructions

2020-06-08 Thread Matthew Malcomson
Instructions following RET or BR are not necessarily executed.  In order
to avoid speculation past RET and BR we can simply append a speculation
barrier.

Since these speculation barriers will not be architecturally executed,
they are not expected to add a high performance penalty.

The speculation barrier is to be SB when targeting architectures which
have this enabled, and DSB SY + ISB otherwise.

We add tests for each of the cases where such an instruction was seen.

This is implemented by modifying each machine description pattern that
emits either a RET or a BR instruction.  We choose not to use something
like `TARGET_ASM_FUNCTION_EPILOGUE` since it does not affect the
`indirect_jump`, `jump`, `sibcall_insn` and `sibcall_value_insn`
patterns and we find it preferable to implement the functionality in the
same way for every pattern.

There is one particular case which is slightly tricky.  The
implementation of TARGET_ASM_TRAMPOLINE_TEMPLATE uses a BR which needs
to be mitigated against.  The trampoline template is used *once* per
compilation unit, and the TRAMPOLINE_SIZE is exposed to the user via the
builtin macro __LIBGCC_TRAMPOLINE_SIZE__.
In the future we may implement function specific attributes to turn on
and off hardening on a per-function basis.
The fixed nature of the trampoline described above implies it will be
safer to ensure this speculation barrier is always used.

Testing:
  Bootstrap and regtest done on aarch64-none-linux
  Used a temporary hack(1) to use these options on every test in the
  testsuite and a script to check that the output never emitted an
  unmitigated RET or BR.


1) Temporary hack was a change to the testsuite to always use
`-save-temps` and run a script on the assembly output of those
compilations which produced one to ensure every RET or BR is immediately
followed by a speculation barrier.


gcc/ChangeLog:

2020-06-08  Matthew Malcomson  

* config/aarch64/aarch64-protos.h (aarch64_sls_barrier): New.
* config/aarch64/aarch64.c (aarch64_output_casesi): Emit
speculation barrier after BR instruction if needs be.
(aarch64_sls_barrier): New.
(aarch64_asm_trampoline_template): Add needed barriers.
* config/aarch64/aarch64.h (AARCH64_ISA_SB): New.
(TARGET_SB): New.
(TRAMPOLINE_SIZE): Account for barrier.
* config/aarch64/aarch64.md (indirect_jump, *casesi_dispatch,
*do_return, simple_return, *sibcall_insn, *sibcall_value_insn):
Emit barrier if needs be, also account for possible barrier in
"length" attribute.
* config/aarch64/aarch64.opt (-mharden-sls-retbr): Introduce new
option.

gcc/testsuite/ChangeLog:

2020-06-08  Matthew Malcomson  

* gcc.target/aarch64/sls-mitigation/sls-miti-retbr.c: New test.
* gcc.target/aarch64/sls-mitigation/sls-miti-retbr-pacret.c:
New test.
* gcc.target/aarch64/sls-mitigation/sls-mitigation.exp: New file.
* lib/target-supports.exp (check_effective_target_aarch64_asm_sb_ok):
New proc.



### Attachment also inlined for ease of reply###


diff --git a/gcc/config/aarch64/aarch64-protos.h 
b/gcc/config/aarch64/aarch64-protos.h
index 
8ca67d7e69edaf73c84f079e7e1c483009ad10c0..d2eb739bc89ecd9d0212416b8dc3ee4ba236a271
 100644
--- a/gcc/config/aarch64/aarch64-protos.h
+++ b/gcc/config/aarch64/aarch64-protos.h
@@ -780,6 +780,7 @@ extern const atomic_ool_names aarch64_ool_ldeor_names;
 
 tree aarch64_resolve_overloaded_builtin_general (location_t, tree, void *);
 
+const char * aarch64_sls_barrier (int);
 extern bool aarch64_harden_sls_retbr_p (void);
 extern bool aarch64_harden_sls_blr_p (void);
 
diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
index 
24767c747bab0d711627c5c646937c42f210d70b..5da3d94e335fc315e1d90e6a674f2f09cf1a4529
 100644
--- a/gcc/config/aarch64/aarch64.h
+++ b/gcc/config/aarch64/aarch64.h
@@ -281,6 +281,7 @@ extern unsigned aarch64_architecture_version;
 #define AARCH64_ISA_F32MM (aarch64_isa_flags & AARCH64_FL_F32MM)
 #define AARCH64_ISA_F64MM (aarch64_isa_flags & AARCH64_FL_F64MM)
 #define AARCH64_ISA_BF16  (aarch64_isa_flags & AARCH64_FL_BF16)
+#define AARCH64_ISA_SB(aarch64_isa_flags & AARCH64_FL_SB)
 
 /* Crypto is an optional extension to AdvSIMD.  */
 #define TARGET_CRYPTO (TARGET_SIMD && AARCH64_ISA_CRYPTO)
@@ -378,6 +379,9 @@ extern unsigned aarch64_architecture_version;
 #define TARGET_FIX_ERR_A53_835769_DEFAULT 1
 #endif
 
+/* SB instruction is enabled through +sb.  */
+#define TARGET_SB (AARCH64_ISA_SB)
+
 /* Apply the workaround for Cortex-A53 erratum 835769.  */
 #define TARGET_FIX_ERR_A53_835769  \
   ((aarch64_fix_a53_err835769 == 2)\
@@ -1058,8 +1062,11 @@ typedef struct
 
 #define RETURN_ADDR_RTX aarch64_return_addr
 
-/* BTI c + 3 insns + 2 pointer-sized entries.  */
-#define TRAMPOLINE_SIZE(TARGET_ILP32 ? 24 :

[Patch v2 3/3] aarch64: Mitigate SLS for BLR instruction

2020-06-23 Thread Matthew Malcomson
This patch introduces the mitigation for Straight Line Speculation past
the BLR instruction.

This mitigation replaces BLR instructions with a BL to a stub which uses
a BR to jump to the original value.  These function stubs are then
appended with a speculation barrier to ensure no straight line
speculation happens after these jumps.

When optimising for speed we use a set of stubs for each function since
this should help the branch predictor make more accurate predictions
about where a stub should branch.

When optimising for size we use one set of stubs for all functions.
This set of stubs can have human readable names, and we are using
`__call_indirect_x` for register x.

When BTI branch protection is enabled the BLR instruction can jump to a
`BTI c` instruction using any register, while the BR instruction can
only jump to a `BTI c` instruction using the x16 or x17 registers.
Hence, in order to ensure this transformation is safe we mov the value
of the original register into x16 and use x16 for the BR.

As an example when optimising for size:
a
BLR x0
instruction would get transformed to something like
BL __call_indirect_x0
where __call_indirect_x0 labels a thunk that contains
__call_indirect_x0:
MOV X16, X0
BR X16



The first version of this patch used local symbols specific to a
compilation unit to try and avoid relocations.
This was mistaken since functions coming from the same compilation unit
can still be in different sections, and the assembler will insert
relocations at jumps between sections.

On any relocation the linker is permitted to emit a veneer to handle
jumps between symbols that are very far apart.  The registers x16 and
x17 may be clobbered by these veneers.
Hence the function stubs cannot rely on the values of x16 and x17 being
the same as just before the function stub is called.

Similar can be said for the hot/cold partitioning of single functions,
so function-local stubs have the same restriction.

This updated version of the patch never emits function stubs for x16 and
x17, and instead forces other registers to be used.


Given the above, there is now no benefit to local symbols (since they
are not enough to avoid dealing with linker intricacies).  This patch
now uses global symbols with hidden visibility each stored in their own
COMDAT section.  This means stubs can be shared between compilation
units while still avoiding the PLT indirection.


This patch also removes the `__call_indirect_x30` stub (and
function-local equivalent) which would simply jump back to the original
location.


The function-local stubs are emitted to the assembly output file in one
chunk, which means we need not add the speculation barrier directly
after each one.
This is because we know for certain that the instructions directly after
the BR in all but the last function stub will be from another one of
these stubs and hence will not contain a speculation gadget.
Instead we add a speculation barrier at the end of the sequence of
stubs.

The global stubs are emitted in COMDAT/.linkonce sections by
themselves so that the linker can remove duplicates from multiple object
files.  This means they are not emitted in one chunk, and each one must
include the speculation barrier.

Another difference is that since the global stubs are shared across
compilation units we do not know that all functions will be targeting an
architecture supporting the SB instruction.
Rather than provide multiple stubs for each architecture, we provide a
stub that will work for all architectures -- using the DSB+ISB barrier.


This mitigation does not apply for BLR instructions in the following
places:
- Some accesses to thread-local variables use a code sequence with a BLR
  instruction.  This code sequence is part of the binary interface between
  compiler and linker. If this BLR instruction needs to be mitigated, it'd
  probably be best to do so in the linker. It seems that the code sequence
  for thread-local variable access is unlikely to lead to a Spectre Revalation
  Gadget.
- PLT stubs are produced by the linker and each contain a BLR instruction.
  It seems that at most only after the last PLT stub a Spectre Revalation
  Gadget might appear.

Testing:
  Bootstrap and regtest on AArch64
(with BOOT_CFLAGS="-mharden-sls=retbr,blr")
  Used a temporary hack(1) in gcc-dg.exp to use these options on every
  test in the testsuite, a slight modification to emit the speculation
  barrier after every function stub, and a script to check that the
  output never emitted a BLR, or unmitigated BR or RET instruction.
  Similar on an aarch64-none-elf cross-compiler.

1) Temporary hack emitted a speculation barrier at the end of every stub
function, and used a script to ensure that:
  a) Every RET or BR is immediately followed by a speculation barrier.
  b) No BLR instruction is emitted by compiler.


gcc/ChangeLog:

2020-06-23  Matthew Malcomson  

* config/aarch64/aarch64-protos.h (aarch64_in

  1   2   3   >