[compiler-rt] c135248 - [ASan] Shared optimized callbacks implementation.

Kirill Stoimenov via llvm-commits llvm-commits at lists.llvm.org
Tue Dec 14 07:55:53 PST 2021


Author: Kirill Stoimenov
Date: 2021-12-14T15:55:14Z
New Revision: c13524856bb304e6b4f80da7f5c5ecdc021920ee

URL: https://github.com/llvm/llvm-project/commit/c13524856bb304e6b4f80da7f5c5ecdc021920ee
DIFF: https://github.com/llvm/llvm-project/commit/c13524856bb304e6b4f80da7f5c5ecdc021920ee.diff

LOG: [ASan] Shared optimized callbacks implementation.

This change moves optimized callbacks from each .o file to compiler-rt. Instead of using code generation it uses direct assembly implementation. Please note that the 'or' version is not implemented and it will produce unresolved external if somehow 'or' version is requested.

Reviewed By: vitalybuka

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

Added: 
    compiler-rt/lib/asan/asan_rtl_x86_64.S

Modified: 
    compiler-rt/lib/asan/CMakeLists.txt
    compiler-rt/lib/asan/asan_interface.inc
    compiler-rt/lib/asan/tests/asan_noinst_test.cpp
    compiler-rt/test/asan/TestCases/Linux/interface_symbols_linux.cpp

Removed: 
    


################################################################################
diff  --git a/compiler-rt/lib/asan/CMakeLists.txt b/compiler-rt/lib/asan/CMakeLists.txt
index 120f9652634c7..2e63c8d051688 100644
--- a/compiler-rt/lib/asan/CMakeLists.txt
+++ b/compiler-rt/lib/asan/CMakeLists.txt
@@ -34,6 +34,7 @@ set(ASAN_SOURCES
 
 if (NOT WIN32 AND NOT APPLE)
   list(APPEND ASAN_SOURCES
+    asan_rtl_x86_64.S
     asan_interceptors_vfork.S
     )
 endif()

diff  --git a/compiler-rt/lib/asan/asan_interface.inc b/compiler-rt/lib/asan/asan_interface.inc
index ea28fc8ae87c5..d8499974e25ec 100644
--- a/compiler-rt/lib/asan/asan_interface.inc
+++ b/compiler-rt/lib/asan/asan_interface.inc
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 // Asan interface list.
 //===----------------------------------------------------------------------===//
+
 INTERFACE_FUNCTION(__asan_addr_is_in_fake_stack)
 INTERFACE_FUNCTION(__asan_address_is_poisoned)
 INTERFACE_FUNCTION(__asan_after_dynamic_init)
@@ -179,3 +180,37 @@ INTERFACE_FUNCTION(__asan_update_allocation_context)
 INTERFACE_WEAK_FUNCTION(__asan_default_options)
 INTERFACE_WEAK_FUNCTION(__asan_default_suppressions)
 INTERFACE_WEAK_FUNCTION(__asan_on_error)
+
+#if defined(__x86_64__) && \
+    !(defined(SANITIZER_MAC) || defined(SANITIZER_WINDOWS))
+
+#  define ASAN_MEMORY_ACCESS_CALLBACK_ADD(s, reg, op) \
+    INTERFACE_FUNCTION(__asan_check_##op##_add_##s##_##reg)
+
+#  define ASAN_MEMORY_ACCESS_CALLBACKS_ADD(reg)    \
+    ASAN_MEMORY_ACCESS_CALLBACK_ADD(1, reg, load)  \
+    ASAN_MEMORY_ACCESS_CALLBACK_ADD(1, reg, store) \
+    ASAN_MEMORY_ACCESS_CALLBACK_ADD(2, reg, load)  \
+    ASAN_MEMORY_ACCESS_CALLBACK_ADD(2, reg, store) \
+    ASAN_MEMORY_ACCESS_CALLBACK_ADD(4, reg, load)  \
+    ASAN_MEMORY_ACCESS_CALLBACK_ADD(4, reg, store) \
+    ASAN_MEMORY_ACCESS_CALLBACK_ADD(8, reg, load)  \
+    ASAN_MEMORY_ACCESS_CALLBACK_ADD(8, reg, store) \
+    ASAN_MEMORY_ACCESS_CALLBACK_ADD(16, reg, load) \
+    ASAN_MEMORY_ACCESS_CALLBACK_ADD(16, reg, store)
+
+ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RAX)
+ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RBX)
+ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RCX)
+ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RDX)
+ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RSI)
+ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RDI)
+ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RBP)
+ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R8)
+ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R9)
+ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R12)
+ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R13)
+ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R14)
+ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R15)
+
+#endif  // defined(__x86_64__)

diff  --git a/compiler-rt/lib/asan/asan_rtl_x86_64.S b/compiler-rt/lib/asan/asan_rtl_x86_64.S
new file mode 100644
index 0000000000000..42e343c825f3f
--- /dev/null
+++ b/compiler-rt/lib/asan/asan_rtl_x86_64.S
@@ -0,0 +1,143 @@
+#include "asan_mapping.h"
+#include "sanitizer_common/sanitizer_asm.h"
+
+#if defined(__x86_64__)
+#include "sanitizer_common/sanitizer_platform.h"
+
+.section .text
+.file "asan_rtl_x86_64.S"
+
+#define NAME(n, reg, op, s, i) n##_##op##_##i##_##s##_##reg
+
+#define FNAME(reg, op, s, i) NAME(__asan_check, reg, op, s, i)
+#define RLABEL(reg, op, s, i) NAME(.return, reg, op, s, i)
+#define CLABEL(reg, op, s, i) NAME(.check, reg, op, s, i)
+#define FLABEL(reg, op, s, i) NAME(.fail, reg, op, s, i)
+
+#define BEGINF(reg, op, s, i) \
+.globl  FNAME(reg, op, s, i) ;\
+ASM_TYPE_FUNCTION(FNAME(reg, op, s, i)) ;\
+.cfi_startproc ;\
+FNAME(reg, op, s, i): ;\
+
+#define ENDF .cfi_endproc ;\
+
+// Access check functions for 1,2 and 4 byte types, which require extra checks.
+#define ASAN_MEMORY_ACCESS_INITIAL_CHECK_ADD(reg, op, s) \
+        mov    %##reg,%r10 ;\
+        shr    $0x3,%r10 ;\
+        movsbl ASAN_SHADOW_OFFSET_CONST(%r10),%r10d ;\
+        test   %r10d,%r10d ;\
+        jne    CLABEL(reg, op, s, add) ;\
+RLABEL(reg, op, s, add): ;\
+        retq  ;\
+
+#define ASAN_MEMORY_ACCESS_EXTRA_CHECK_1(reg, op, i) \
+CLABEL(reg, op, 1, i): ;\
+        push   %rcx ;\
+        mov    %##reg,%rcx ;\
+        and    $0x7,%ecx ;\
+        cmp    %r10d,%ecx ;\
+        pop    %rcx ;\
+        jl     RLABEL(reg, op, 1, i);\
+        mov    %##reg,%rdi ;\
+        jmp    __asan_report_##op##1 at PLT ;\
+
+#define ASAN_MEMORY_ACCESS_EXTRA_CHECK_2(reg, op, i) \
+CLABEL(reg, op, 2, i): ;\
+        push   %rcx ;\
+        mov    %##reg,%rcx ;\
+        and    $0x7,%ecx ;\
+        add    $0x1,%ecx ;\
+        cmp    %r10d,%ecx ;\
+        pop    %rcx ;\
+        jl     RLABEL(reg, op, 2, i);\
+        mov    %##reg,%rdi ;\
+        jmp    __asan_report_##op##2 at PLT ;\
+
+#define ASAN_MEMORY_ACCESS_EXTRA_CHECK_4(reg, op, i) \
+CLABEL(reg, op, 4, i): ;\
+        push   %rcx ;\
+        mov    %##reg,%rcx ;\
+        and    $0x7,%ecx ;\
+        add    $0x3,%ecx ;\
+        cmp    %r10d,%ecx ;\
+        pop    %rcx ;\
+        jl     RLABEL(reg, op, 4, i);\
+        mov    %##reg,%rdi ;\
+        jmp    __asan_report_##op##4 at PLT ;\
+
+#define ASAN_MEMORY_ACCESS_CALLBACK_ADD_1(reg, op) \
+BEGINF(reg, op, 1, add) ;\
+        ASAN_MEMORY_ACCESS_INITIAL_CHECK_ADD(reg, op, 1) ;\
+        ASAN_MEMORY_ACCESS_EXTRA_CHECK_1(reg, op, add) ;\
+ENDF
+
+#define ASAN_MEMORY_ACCESS_CALLBACK_ADD_2(reg, op) \
+BEGINF(reg, op, 2, add) ;\
+        ASAN_MEMORY_ACCESS_INITIAL_CHECK_ADD(reg, op, 2) ;\
+        ASAN_MEMORY_ACCESS_EXTRA_CHECK_2(reg, op, add) ;\
+ENDF
+
+#define ASAN_MEMORY_ACCESS_CALLBACK_ADD_4(reg, op) \
+BEGINF(reg, op, 4, add) ;\
+        ASAN_MEMORY_ACCESS_INITIAL_CHECK_ADD(reg, op, 4) ;\
+        ASAN_MEMORY_ACCESS_EXTRA_CHECK_4(reg, op, add) ;\
+ENDF
+
+// Access check functions for 8 and 16 byte types: no extra checks required.
+#define ASAN_MEMORY_ACCESS_CHECK_ADD(reg, op, s, c) \
+        mov    %##reg,%r10 ;\
+        shr    $0x3,%r10 ;\
+        ##c    $0x0,ASAN_SHADOW_OFFSET_CONST(%r10) ;\
+        jne    FLABEL(reg, op, s, add) ;\
+        retq  ;\
+
+#define ASAN_MEMORY_ACCESS_FAIL(reg, op, s, i) \
+FLABEL(reg, op, s, i): ;\
+        mov    %##reg,%rdi ;\
+        jmp    __asan_report_##op##s at PLT;\
+
+#define ASAN_MEMORY_ACCESS_CALLBACK_ADD_8(reg, op) \
+BEGINF(reg, op, 8, add) ;\
+        ASAN_MEMORY_ACCESS_CHECK_ADD(reg, op, 8, cmpb) ;\
+        ASAN_MEMORY_ACCESS_FAIL(reg, op, 8, add) ;\
+ENDF
+
+#define ASAN_MEMORY_ACCESS_CALLBACK_ADD_16(reg, op) \
+BEGINF(reg, op, 16, add) ;\
+        ASAN_MEMORY_ACCESS_CHECK_ADD(reg, op, 16, cmpw) ;\
+        ASAN_MEMORY_ACCESS_FAIL(reg, op, 16, add) ;\
+ENDF
+
+#define ASAN_MEMORY_ACCESS_CALLBACKS_ADD(reg) \
+ASAN_MEMORY_ACCESS_CALLBACK_ADD_1(reg, load) \
+ASAN_MEMORY_ACCESS_CALLBACK_ADD_1(reg, store) \
+ASAN_MEMORY_ACCESS_CALLBACK_ADD_2(reg, load) \
+ASAN_MEMORY_ACCESS_CALLBACK_ADD_2(reg, store) \
+ASAN_MEMORY_ACCESS_CALLBACK_ADD_4(reg, load) \
+ASAN_MEMORY_ACCESS_CALLBACK_ADD_4(reg, store) \
+ASAN_MEMORY_ACCESS_CALLBACK_ADD_8(reg, load) \
+ASAN_MEMORY_ACCESS_CALLBACK_ADD_8(reg, store) \
+ASAN_MEMORY_ACCESS_CALLBACK_ADD_16(reg, load) \
+ASAN_MEMORY_ACCESS_CALLBACK_ADD_16(reg, store) \
+
+
+// Instantiate all but R10 and R11 callbacks. We are using PLTSafe class with
+// the intrinsic, which guarantees that the code generation will never emit
+// R10 or R11 callback.
+ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RAX)
+ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RBX)
+ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RCX)
+ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RDX)
+ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RSI)
+ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RDI)
+ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RBP)
+ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R8)
+ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R9)
+ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R12)
+ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R13)
+ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R14)
+ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R15)
+
+#endif

diff  --git a/compiler-rt/lib/asan/tests/asan_noinst_test.cpp b/compiler-rt/lib/asan/tests/asan_noinst_test.cpp
index a98e67085b95b..97a60a104cd52 100644
--- a/compiler-rt/lib/asan/tests/asan_noinst_test.cpp
+++ b/compiler-rt/lib/asan/tests/asan_noinst_test.cpp
@@ -231,23 +231,8 @@ TEST(AddressSanitizer, ShadowRegionIsPoisonedTest) {
 }
 
 // Test __asan_load1 & friends.
-TEST(AddressSanitizer, LoadStoreCallbacks) {
-  typedef void (*CB)(uptr p);
-  CB cb[2][5] = {{
-                     __asan_load1,
-                     __asan_load2,
-                     __asan_load4,
-                     __asan_load8,
-                     __asan_load16,
-                 },
-                 {
-                     __asan_store1,
-                     __asan_store2,
-                     __asan_store4,
-                     __asan_store8,
-                     __asan_store16,
-                 }};
-
+typedef void (*CB)(uptr p);
+static void TestLoadStoreCallbacks(CB cb[2][5]) {
   uptr buggy_ptr;
 
   __asan_test_only_reported_buggy_pointer = &buggy_ptr;
@@ -277,3 +262,86 @@ TEST(AddressSanitizer, LoadStoreCallbacks) {
   }
   __asan_test_only_reported_buggy_pointer = 0;
 }
+
+TEST(AddressSanitizer, LoadStoreCallbacks) {
+  CB cb[2][5] = {{
+                     __asan_load1,
+                     __asan_load2,
+                     __asan_load4,
+                     __asan_load8,
+                     __asan_load16,
+                 },
+                 {
+                     __asan_store1,
+                     __asan_store2,
+                     __asan_store4,
+                     __asan_store8,
+                     __asan_store16,
+                 }};
+  TestLoadStoreCallbacks(cb);
+}
+
+#if defined(__x86_64__) && \
+    !(defined(SANITIZER_MAC) || defined(SANITIZER_WINDOWS))
+// clang-format off
+
+#define CALL_ASAN_MEMORY_ACCESS_CALLBACK_ADD(s, reg, op)        \
+  void CallAsanMemoryAccessAdd##reg##op##s(uptr address) {      \
+  asm("push  %%" #reg " \n"                                     \
+  "mov   %[x], %%" #reg " \n"                                   \
+  "call  __asan_check_" #op "_add_" #s "_" #reg "\n"            \
+  "pop   %%" #reg " \n"                                         \
+  :                                                             \
+  : [x] "r"(address)                                            \
+      : "r8", "rdi");                                           \
+  }
+
+#define TEST_ASAN_MEMORY_ACCESS_CALLBACKS_ADD(reg)            \
+  CALL_ASAN_MEMORY_ACCESS_CALLBACK_ADD(1, reg, load)          \
+  CALL_ASAN_MEMORY_ACCESS_CALLBACK_ADD(1, reg, store)         \
+  CALL_ASAN_MEMORY_ACCESS_CALLBACK_ADD(2, reg, load)          \
+  CALL_ASAN_MEMORY_ACCESS_CALLBACK_ADD(2, reg, store)         \
+  CALL_ASAN_MEMORY_ACCESS_CALLBACK_ADD(4, reg, load)          \
+  CALL_ASAN_MEMORY_ACCESS_CALLBACK_ADD(4, reg, store)         \
+  CALL_ASAN_MEMORY_ACCESS_CALLBACK_ADD(8, reg, load)          \
+  CALL_ASAN_MEMORY_ACCESS_CALLBACK_ADD(8, reg, store)         \
+  CALL_ASAN_MEMORY_ACCESS_CALLBACK_ADD(16, reg, load)         \
+  CALL_ASAN_MEMORY_ACCESS_CALLBACK_ADD(16, reg, store)        \
+                                                              \
+  TEST(AddressSanitizer, LoadStoreCallbacksAddX86##reg) {     \
+    CB cb[2][5] = {{                                          \
+                       CallAsanMemoryAccessAdd##reg##load1,   \
+                       CallAsanMemoryAccessAdd##reg##load2,   \
+                       CallAsanMemoryAccessAdd##reg##load4,   \
+                       CallAsanMemoryAccessAdd##reg##load8,   \
+                       CallAsanMemoryAccessAdd##reg##load16,  \
+                   },                                         \
+                   {                                          \
+                       CallAsanMemoryAccessAdd##reg##store1,  \
+                       CallAsanMemoryAccessAdd##reg##store2,  \
+                       CallAsanMemoryAccessAdd##reg##store4,  \
+                       CallAsanMemoryAccessAdd##reg##store8,  \
+                       CallAsanMemoryAccessAdd##reg##store16, \
+                   }};                                        \
+    TestLoadStoreCallbacks(cb);                               \
+  }
+
+// Instantiate all but R10 and R11 callbacks. We are using PLTSafe class with
+// the intrinsic, which guarantees that the code generation will never emit
+// R10 or R11 callbacks.
+TEST_ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RAX)
+TEST_ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RBX)
+TEST_ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RCX)
+TEST_ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RDX)
+TEST_ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RSI)
+TEST_ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RDI)
+TEST_ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RBP)
+TEST_ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R8)
+TEST_ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R9)
+TEST_ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R12)
+TEST_ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R13)
+TEST_ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R14)
+TEST_ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R15)
+
+// clang-format on
+#endif

diff  --git a/compiler-rt/test/asan/TestCases/Linux/interface_symbols_linux.cpp b/compiler-rt/test/asan/TestCases/Linux/interface_symbols_linux.cpp
index 8c22976e71078..37bca5852f49a 100644
--- a/compiler-rt/test/asan/TestCases/Linux/interface_symbols_linux.cpp
+++ b/compiler-rt/test/asan/TestCases/Linux/interface_symbols_linux.cpp
@@ -1,5 +1,7 @@
 // Check the presence of interface symbols in compiled file.
 
+// RUN: %clangxx -x c++-header -o - -E %p/../../../../lib/asan/asan_interface.inc  \
+// RUN:  | sed "s/INTERFACE_FUNCTION/\nINTERFACE_FUNCTION/g" >  %t.asan_interface.inc
 // RUN: %clangxx_asan -O2 %s -o %t.exe
 // RUN: nm -D %t.exe | grep " [TWw] "                                          \
 // RUN:  | grep -o "\(__asan_\|__ubsan_\|__sancov_\|__sanitizer_\)[^ ]*"       \
@@ -10,7 +12,7 @@
 // RUN:  > %t.exports
 //
 // RUN: grep -e "INTERFACE_\(WEAK_\)\?FUNCTION"                                \
-// RUN:  %p/../../../../lib/asan/asan_interface.inc                            \
+// RUN:  %t.asan_interface.inc                                                 \
 // RUN:  %p/../../../../lib/ubsan/ubsan_interface.inc                          \
 // RUN:  %p/../../../../lib/sanitizer_common/sanitizer_common_interface.inc    \
 // RUN:  %p/../../../../lib/sanitizer_common/sanitizer_common_interface_posix.inc \


        


More information about the llvm-commits mailing list