HWASan support in ART.

Two small tweaks:
* The highest 8 bits of a pointer in hwasan contain a random tag which needs to
  be removed before comparing _unrelated_ pointers.
* Annotate DoLongJump. HWASan needs to re-tag the newly unallocated stack space
  to match SP. This is similar to ASan annotation (__asan_handle_noreturn), but
  more precise - HWASan needs to know the destination SP address because it can
  not conservatively "unpoison" the entire stack like ASan does.

Bug: 112438058
Test: mmm SANITIZE_TARGET=hwaddress

Change-Id: I9f9d92495b3a4b2637e48c7af1b614e8d1db8ea0
diff --git a/runtime/arch/arm64/context_arm64.cc b/runtime/arch/arm64/context_arm64.cc
index 0f0814a..16f4792 100644
--- a/runtime/arch/arm64/context_arm64.cc
+++ b/runtime/arch/arm64/context_arm64.cc
@@ -23,6 +23,12 @@
 #include "quick/quick_method_frame_info.h"
 #include "thread-current-inl.h"
 
+#if __has_feature(hwaddress_sanitizer)
+#include <sanitizer/hwasan_interface.h>
+#else
+#define __hwasan_handle_longjmp(sp)
+#endif
+
 namespace art {
 namespace arm64 {
 
@@ -139,6 +145,8 @@
   }
   // Ensure the Thread Register contains the address of the current thread.
   DCHECK_EQ(reinterpret_cast<uintptr_t>(Thread::Current()), gprs[TR]);
+  // Tell HWASan about the new stack top.
+  __hwasan_handle_longjmp(reinterpret_cast<void*>(gprs[SP]));
   // The Marking Register will be updated by art_quick_do_long_jump.
   art_quick_do_long_jump(gprs, fprs);
 }
diff --git a/runtime/thread.cc b/runtime/thread.cc
index df7f19d..abc1bfd 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -25,6 +25,12 @@
 #include <sys/resource.h>
 #include <sys/time.h>
 
+#if __has_feature(hwaddress_sanitizer)
+#include <sanitizer/hwasan_interface.h>
+#else
+#define __hwasan_tag_pointer(p, t) (p)
+#endif
+
 #include <algorithm>
 #include <bitset>
 #include <cerrno>
@@ -623,7 +629,9 @@
 #endif
       volatile char space[kPageSize - (kAsanMultiplier * 256)];
       char sink ATTRIBUTE_UNUSED = space[zero];  // NOLINT
-      if (reinterpret_cast<uintptr_t>(space) >= target + kPageSize) {
+      // Remove tag from the pointer. Nop in non-hwasan builds.
+      uintptr_t addr = reinterpret_cast<uintptr_t>(__hwasan_tag_pointer(space, 0));
+      if (addr >= target + kPageSize) {
         Touch(target);
       }
       zero *= 2;  // Try to avoid tail recursion.