[compiler-rt] r321203 - [hwasan] Implement -fsanitize-recover=hwaddress.

Evgeniy Stepanov via llvm-commits llvm-commits at lists.llvm.org
Wed Dec 20 11:05:44 PST 2017


Author: eugenis
Date: Wed Dec 20 11:05:44 2017
New Revision: 321203

URL: http://llvm.org/viewvc/llvm-project?rev=321203&view=rev
Log:
[hwasan] Implement -fsanitize-recover=hwaddress.

Summary: Very similar to AddressSanitizer, with the exception of the error type encoding.

Reviewers: kcc, alekseyshl

Subscribers: cfe-commits, kubamracek, llvm-commits, hiraditya

Differential Revision: https://reviews.llvm.org/D41417

Modified:
    compiler-rt/trunk/lib/hwasan/hwasan.cc
    compiler-rt/trunk/lib/hwasan/hwasan_interface_internal.h
    compiler-rt/trunk/lib/hwasan/hwasan_linux.cc
    compiler-rt/trunk/test/hwasan/TestCases/halt-on-error.cc

Modified: compiler-rt/trunk/lib/hwasan/hwasan.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/hwasan/hwasan.cc?rev=321203&r1=321202&r2=321203&view=diff
==============================================================================
--- compiler-rt/trunk/lib/hwasan/hwasan.cc (original)
+++ compiler-rt/trunk/lib/hwasan/hwasan.cc Wed Dec 20 11:05:44 2017
@@ -252,40 +252,112 @@ static void SigIll() {
   // __builtin_unreachable();
 }
 
-template<bool IsStore, unsigned LogSize>
-__attribute__((always_inline, nodebug))
-static void CheckAddress(uptr p) {
+enum class ErrorAction { Abort, Recover };
+enum class AccessType { Load, Store };
+
+template <ErrorAction EA, AccessType AT, unsigned LogSize>
+__attribute__((always_inline, nodebug)) static void CheckAddress(uptr p) {
   tag_t ptr_tag = GetTagFromPointer(p);
   uptr ptr_raw = p & ~kAddressTagMask;
   tag_t mem_tag = *(tag_t *)MEM_TO_SHADOW(ptr_raw);
-  if (UNLIKELY(ptr_tag != mem_tag)) SigIll<0x100 + 0x10 * IsStore + LogSize>();
+  if (UNLIKELY(ptr_tag != mem_tag)) {
+    SigIll<0x100 + 0x20 * (EA == ErrorAction::Recover) +
+           0x10 * (AT == AccessType::Store) + LogSize>();
+    if (EA == ErrorAction::Abort) __builtin_unreachable();
+  }
 }
 
-template<bool IsStore>
-__attribute__((always_inline, nodebug))
-static void CheckAddressSized(uptr p, uptr sz) {
+template <ErrorAction EA, AccessType AT>
+__attribute__((always_inline, nodebug)) static void CheckAddressSized(uptr p,
+                                                                      uptr sz) {
   CHECK_NE(0, sz);
   tag_t ptr_tag = GetTagFromPointer(p);
   uptr ptr_raw = p & ~kAddressTagMask;
   tag_t *shadow_first = (tag_t *)MEM_TO_SHADOW(ptr_raw);
   tag_t *shadow_last = (tag_t *)MEM_TO_SHADOW(ptr_raw + sz - 1);
   for (tag_t *t = shadow_first; t <= shadow_last; ++t)
-    if (UNLIKELY(ptr_tag != *t)) SigIll<0x100 + 0x10 * IsStore + 0xf>();
+    if (UNLIKELY(ptr_tag != *t)) {
+      SigIll<0x100 + 0x20 * (EA == ErrorAction::Recover) +
+             0x10 * (AT == AccessType::Store) + 0xf>();
+      if (EA == ErrorAction::Abort) __builtin_unreachable();
+    }
+}
+
+void __hwasan_load(uptr p, uptr sz) {
+  CheckAddressSized<ErrorAction::Abort, AccessType::Load>(p, sz);
+}
+void __hwasan_load1(uptr p) {
+  CheckAddress<ErrorAction::Abort, AccessType::Load, 0>(p);
+}
+void __hwasan_load2(uptr p) {
+  CheckAddress<ErrorAction::Abort, AccessType::Load, 1>(p);
+}
+void __hwasan_load4(uptr p) {
+  CheckAddress<ErrorAction::Abort, AccessType::Load, 2>(p);
+}
+void __hwasan_load8(uptr p) {
+  CheckAddress<ErrorAction::Abort, AccessType::Load, 3>(p);
+}
+void __hwasan_load16(uptr p) {
+  CheckAddress<ErrorAction::Abort, AccessType::Load, 4>(p);
+}
+
+void __hwasan_load_noabort(uptr p, uptr sz) {
+  CheckAddressSized<ErrorAction::Recover, AccessType::Load>(p, sz);
+}
+void __hwasan_load1_noabort(uptr p) {
+  CheckAddress<ErrorAction::Recover, AccessType::Load, 0>(p);
+}
+void __hwasan_load2_noabort(uptr p) {
+  CheckAddress<ErrorAction::Recover, AccessType::Load, 1>(p);
+}
+void __hwasan_load4_noabort(uptr p) {
+  CheckAddress<ErrorAction::Recover, AccessType::Load, 2>(p);
+}
+void __hwasan_load8_noabort(uptr p) {
+  CheckAddress<ErrorAction::Recover, AccessType::Load, 3>(p);
+}
+void __hwasan_load16_noabort(uptr p) {
+  CheckAddress<ErrorAction::Recover, AccessType::Load, 4>(p);
+}
+
+void __hwasan_store(uptr p, uptr sz) {
+  CheckAddressSized<ErrorAction::Abort, AccessType::Store>(p, sz);
+}
+void __hwasan_store1(uptr p) {
+  CheckAddress<ErrorAction::Abort, AccessType::Store, 0>(p);
+}
+void __hwasan_store2(uptr p) {
+  CheckAddress<ErrorAction::Abort, AccessType::Store, 1>(p);
+}
+void __hwasan_store4(uptr p) {
+  CheckAddress<ErrorAction::Abort, AccessType::Store, 2>(p);
+}
+void __hwasan_store8(uptr p) {
+  CheckAddress<ErrorAction::Abort, AccessType::Store, 3>(p);
+}
+void __hwasan_store16(uptr p) {
+  CheckAddress<ErrorAction::Abort, AccessType::Store, 4>(p);
 }
 
-void __hwasan_load(uptr p, uptr sz) { CheckAddressSized<false>(p, sz); }
-void __hwasan_load1(uptr p) { CheckAddress<false, 0>(p); }
-void __hwasan_load2(uptr p) { CheckAddress<false, 1>(p); }
-void __hwasan_load4(uptr p) { CheckAddress<false, 2>(p); }
-void __hwasan_load8(uptr p) { CheckAddress<false, 3>(p); }
-void __hwasan_load16(uptr p) { CheckAddress<false, 4>(p); }
-
-void __hwasan_store(uptr p, uptr sz) { CheckAddressSized<true>(p, sz); }
-void __hwasan_store1(uptr p) { CheckAddress<true, 0>(p); }
-void __hwasan_store2(uptr p) { CheckAddress<true, 1>(p); }
-void __hwasan_store4(uptr p) { CheckAddress<true, 2>(p); }
-void __hwasan_store8(uptr p) { CheckAddress<true, 3>(p); }
-void __hwasan_store16(uptr p) { CheckAddress<true, 4>(p); }
+void __hwasan_store_noabort(uptr p, uptr sz) {
+  CheckAddressSized<ErrorAction::Recover, AccessType::Store>(p, sz);
+}
+void __hwasan_store1_noabort(uptr p) {
+  CheckAddress<ErrorAction::Recover, AccessType::Store, 0>(p);
+}
+void __hwasan_store2_noabort(uptr p) {
+  CheckAddress<ErrorAction::Recover, AccessType::Store, 1>(p);
+}
+void __hwasan_store4_noabort(uptr p) {
+  CheckAddress<ErrorAction::Recover, AccessType::Store, 2>(p);
+}
+void __hwasan_store8_noabort(uptr p) {
+  CheckAddress<ErrorAction::Recover, AccessType::Store, 3>(p);
+}
+void __hwasan_store16_noabort(uptr p) {
+  CheckAddress<ErrorAction::Recover, AccessType::Store, 4>(p);
+}
 
 #if !SANITIZER_SUPPORTS_WEAK_HOOKS
 extern "C" {

Modified: compiler-rt/trunk/lib/hwasan/hwasan_interface_internal.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/hwasan/hwasan_interface_internal.h?rev=321203&r1=321202&r2=321203&view=diff
==============================================================================
--- compiler-rt/trunk/lib/hwasan/hwasan_interface_internal.h (original)
+++ compiler-rt/trunk/lib/hwasan/hwasan_interface_internal.h Wed Dec 20 11:05:44 2017
@@ -45,6 +45,19 @@ SANITIZER_INTERFACE_ATTRIBUTE
 void __hwasan_load16(uptr);
 
 SANITIZER_INTERFACE_ATTRIBUTE
+void __hwasan_load_noabort(uptr, uptr);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __hwasan_load1_noabort(uptr);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __hwasan_load2_noabort(uptr);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __hwasan_load4_noabort(uptr);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __hwasan_load8_noabort(uptr);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __hwasan_load16_noabort(uptr);
+
+SANITIZER_INTERFACE_ATTRIBUTE
 void __hwasan_store(uptr, uptr);
 SANITIZER_INTERFACE_ATTRIBUTE
 void __hwasan_store1(uptr);
@@ -57,6 +70,19 @@ void __hwasan_store8(uptr);
 SANITIZER_INTERFACE_ATTRIBUTE
 void __hwasan_store16(uptr);
 
+SANITIZER_INTERFACE_ATTRIBUTE
+void __hwasan_store_noabort(uptr, uptr);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __hwasan_store1_noabort(uptr);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __hwasan_store2_noabort(uptr);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __hwasan_store4_noabort(uptr);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __hwasan_store8_noabort(uptr);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __hwasan_store16_noabort(uptr);
+
 // Returns the offset of the first tag mismatch or -1 if the whole range is
 // good.
 SANITIZER_INTERFACE_ATTRIBUTE

Modified: compiler-rt/trunk/lib/hwasan/hwasan_linux.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/hwasan/hwasan_linux.cc?rev=321203&r1=321202&r2=321203&view=diff
==============================================================================
--- compiler-rt/trunk/lib/hwasan/hwasan_linux.cc (original)
+++ compiler-rt/trunk/lib/hwasan/hwasan_linux.cc Wed Dec 20 11:05:44 2017
@@ -174,12 +174,14 @@ struct AccessInfo {
   uptr size;
   bool is_store;
   bool is_load;
+  bool recover;
 };
 
 #if defined(__aarch64__)
 static AccessInfo GetAccessInfo(siginfo_t *info, ucontext_t *uc) {
   // Access type is encoded in HLT immediate as 0x1XY,
-  // where X is 1 for store, 0 for load.
+  // where X&1 is 1 for store, 0 for load,
+  // and X&2 is 1 if the error is recoverable.
   // Valid values of Y are 0 to 4, which are interpreted as log2(access_size),
   // and 0xF, which means that access size is stored in X1 register.
   // Access address is always in X0 register.
@@ -189,6 +191,7 @@ static AccessInfo GetAccessInfo(siginfo_
   if ((code & 0xff00) != 0x100)
     return AccessInfo{0, 0, false, false}; // Not ours.
   bool is_store = code & 0x10;
+  bool recover = code & 0x20;
   unsigned size_log = code & 0xf;
   if (size_log > 4 && size_log != 0xf)
     return AccessInfo{0, 0, false, false}; // Not ours.
@@ -200,6 +203,7 @@ static AccessInfo GetAccessInfo(siginfo_
     ai.size = uc->uc_mcontext.regs[1];
   else
     ai.size = 1U << size_log;
+  ai.recover = recover;
   return ai;
 }
 #else
@@ -223,7 +227,7 @@ static bool HwasanOnSIGILL(int signo, si
   ReportTagMismatch(stack, ai.addr, ai.size, ai.is_store);
 
   ++hwasan_report_count;
-  if (flags()->halt_on_error)
+  if (flags()->halt_on_error || !ai.recover)
     Die();
 
   uc->uc_mcontext.pc += 4;

Modified: compiler-rt/trunk/test/hwasan/TestCases/halt-on-error.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/hwasan/TestCases/halt-on-error.cc?rev=321203&r1=321202&r2=321203&view=diff
==============================================================================
--- compiler-rt/trunk/test/hwasan/TestCases/halt-on-error.cc (original)
+++ compiler-rt/trunk/test/hwasan/TestCases/halt-on-error.cc Wed Dec 20 11:05:44 2017
@@ -1,4 +1,19 @@
-// RUN: %clangxx_hwasan -O0 %s -o %t && not %env_hwasan_opts=halt_on_error=0 %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_hwasan -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefixes=COMMON
+// RUN: %clangxx_hwasan -O0 %s -o %t && not %env_hwasan_opts=halt_on_error=1 %run %t 2>&1 | FileCheck %s --check-prefix=COMMON
+// RUN: %clangxx_hwasan -O0 %s -o %t && not %env_hwasan_opts=halt_on_error=0 %run %t 2>&1 | FileCheck %s --check-prefix=COMMON
+
+// RUN: %clangxx_hwasan -O0 %s -o %t -fsanitize-recover=hwaddress && not %run %t 2>&1 | FileCheck %s --check-prefix=COMMON
+// RUN: %clangxx_hwasan -O0 %s -o %t -fsanitize-recover=hwaddress && not %env_hwasan_opts=halt_on_error=1 %run %t 2>&1 | FileCheck %s --check-prefix=COMMON
+// RUN: %clangxx_hwasan -O0 %s -o %t -fsanitize-recover=hwaddress && not %env_hwasan_opts=halt_on_error=0 %run %t 2>&1 | FileCheck %s --check-prefixes=COMMON,RECOVER
+
+// RUN: %clangxx_hwasan -mllvm -hwasan-instrument-with-calls=1 -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=COMMON
+// RUN: %clangxx_hwasan -mllvm -hwasan-instrument-with-calls=1 -O0 %s -o %t && not %env_hwasan_opts=halt_on_error=1 %run %t 2>&1 | FileCheck %s --check-prefix=COMMON
+// RUN: %clangxx_hwasan -mllvm -hwasan-instrument-with-calls=1 -O0 %s -o %t && not %env_hwasan_opts=halt_on_error=0 %run %t 2>&1 | FileCheck %s --check-prefix=COMMON
+
+// RUN: %clangxx_hwasan -mllvm -hwasan-instrument-with-calls=1 -O0 %s -o %t -fsanitize-recover=hwaddress && not %run %t 2>&1 | FileCheck %s --check-prefix=COMMON
+// RUN: %clangxx_hwasan -mllvm -hwasan-instrument-with-calls=1 -O0 %s -o %t -fsanitize-recover=hwaddress && not %env_hwasan_opts=halt_on_error=1 %run %t 2>&1 | FileCheck %s --check-prefix=COMMON
+// RUN: %clangxx_hwasan -mllvm -hwasan-instrument-with-calls=1 -O0 %s -o %t -fsanitize-recover=hwaddress && not %env_hwasan_opts=halt_on_error=0 %run %t 2>&1 | FileCheck %s --check-prefixes=COMMON,RECOVER
+
 // REQUIRES: stable-runtime
 
 #include <stdlib.h>
@@ -10,17 +25,18 @@ int main() {
   free(x);
   __hwasan_disable_allocator_tagging();
   return x[2] + ((char *)x)[6] + ((char *)x)[9];
-  // CHECK: READ of size 4 at
-  // CHECK: #0 {{.*}} in main {{.*}}halt-on-error.cc:12
-  // CHECK: SUMMARY: HWAddressSanitizer: tag-mismatch {{.*}} in main
-
-  // CHECK: READ of size 1 at
-  // CHECK: #0 {{.*}} in main {{.*}}halt-on-error.cc:12
-  // CHECK: SUMMARY: HWAddressSanitizer: tag-mismatch {{.*}} in main
-
-  // CHECK: READ of size 1 at
-  // CHECK: #0 {{.*}} in main {{.*}}halt-on-error.cc:12
-  // CHECK: SUMMARY: HWAddressSanitizer: tag-mismatch {{.*}} in main
+  // COMMON: READ of size 4 at
+  // When instrumenting with callbacks, main is actually #1, and #0 is __hwasan_load4.
+  // COMMON: #{{.*}} in main {{.*}}halt-on-error.cc:27
+  // COMMON: SUMMARY: HWAddressSanitizer: tag-mismatch {{.*}} in
+
+  // RECOVER: READ of size 1 at
+  // RECOVER: #{{.*}} in main {{.*}}halt-on-error.cc:27
+  // RECOVER: SUMMARY: HWAddressSanitizer: tag-mismatch {{.*}} in
+
+  // RECOVER: READ of size 1 at
+  // RECOVER: #{{.*}} in main {{.*}}halt-on-error.cc:27
+  // RECOVER: SUMMARY: HWAddressSanitizer: tag-mismatch {{.*}} in
 
-  // CHECK-NOT: tag-mismatch
+  // COMMON-NOT: tag-mismatch
 }




More information about the llvm-commits mailing list