summaryrefslogtreecommitdiffstats
path: root/compiler-rt
diff options
context:
space:
mode:
authorKostya Serebryany <kcc@google.com>2014-04-16 13:52:28 +0000
committerKostya Serebryany <kcc@google.com>2014-04-16 13:52:28 +0000
commitae401ca5e7d25ae3057e0c62d752ce7ac9b0ff29 (patch)
treed6c6ff4320e6890737a9f44a3e1b18dd1d8d6a9c /compiler-rt
parented1547040c08cde387574c9b1a97c3404ccfc1b6 (diff)
downloadbcm5719-llvm-ae401ca5e7d25ae3057e0c62d752ce7ac9b0ff29.tar.gz
bcm5719-llvm-ae401ca5e7d25ae3057e0c62d752ce7ac9b0ff29.zip
[asan] add __asan_load1/__asan_store1/... callbacks to asan-rt; together with -mllvm -asan-instrumentation-with-call-threshold=N this will be a workaround for PR17409
llvm-svn: 206387
Diffstat (limited to 'compiler-rt')
-rw-r--r--compiler-rt/lib/asan/asan_interface_internal.h14
-rw-r--r--compiler-rt/lib/asan/asan_rtl.cc31
-rw-r--r--compiler-rt/lib/asan/tests/asan_noinst_test.cc37
3 files changed, 82 insertions, 0 deletions
diff --git a/compiler-rt/lib/asan/asan_interface_internal.h b/compiler-rt/lib/asan/asan_interface_internal.h
index ce71eed8110..6a6ab002e82 100644
--- a/compiler-rt/lib/asan/asan_interface_internal.h
+++ b/compiler-rt/lib/asan/asan_interface_internal.h
@@ -121,6 +121,20 @@ extern "C" {
// Global flag, copy of ASAN_OPTIONS=detect_stack_use_after_return
SANITIZER_INTERFACE_ATTRIBUTE
extern int __asan_option_detect_stack_use_after_return;
+
+ SANITIZER_INTERFACE_ATTRIBUTE
+ extern uptr *__asan_test_only_reported_buggy_pointer;
+
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_load1(uptr p);
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_load2(uptr p);
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_load4(uptr p);
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_load8(uptr p);
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_load16(uptr p);
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_store1(uptr p);
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_store2(uptr p);
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_store4(uptr p);
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_store8(uptr p);
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_store16(uptr p);
} // extern "C"
#endif // ASAN_INTERFACE_INTERNAL_H
diff --git a/compiler-rt/lib/asan/asan_rtl.cc b/compiler-rt/lib/asan/asan_rtl.cc
index 298baadb05f..d0edccc31fc 100644
--- a/compiler-rt/lib/asan/asan_rtl.cc
+++ b/compiler-rt/lib/asan/asan_rtl.cc
@@ -29,6 +29,7 @@
#include "lsan/lsan_common.h"
int __asan_option_detect_stack_use_after_return; // Global interface symbol.
+uptr *__asan_test_only_reported_buggy_pointer; // Used only for testing asan.
namespace __asan {
@@ -374,6 +375,36 @@ void __asan_report_ ## type ## _n(uptr addr, uptr size) { \
ASAN_REPORT_ERROR_N(load, false)
ASAN_REPORT_ERROR_N(store, true)
+#define ASAN_MEMORY_ACCESS_CALLBACK(type, is_write, size) \
+ extern "C" NOINLINE INTERFACE_ATTRIBUTE void __asan_##type##size(uptr addr); \
+ void __asan_##type##size(uptr addr) { \
+ uptr sp = MEM_TO_SHADOW(addr); \
+ uptr s = size <= SHADOW_GRANULARITY ? *reinterpret_cast<u8 *>(sp) \
+ : *reinterpret_cast<u16 *>(sp); \
+ if (s) { \
+ if (size >= SHADOW_GRANULARITY || \
+ (((addr & (SHADOW_GRANULARITY - 1)) + size - 1)) >= s) { \
+ if (__asan_test_only_reported_buggy_pointer) { \
+ *__asan_test_only_reported_buggy_pointer = addr; \
+ } else { \
+ GET_CALLER_PC_BP_SP; \
+ __asan_report_error(pc, bp, sp, addr, is_write, size); \
+ } \
+ } \
+ } \
+ }
+
+ASAN_MEMORY_ACCESS_CALLBACK(load, false, 1)
+ASAN_MEMORY_ACCESS_CALLBACK(load, false, 2)
+ASAN_MEMORY_ACCESS_CALLBACK(load, false, 4)
+ASAN_MEMORY_ACCESS_CALLBACK(load, false, 8)
+ASAN_MEMORY_ACCESS_CALLBACK(load, false, 16)
+ASAN_MEMORY_ACCESS_CALLBACK(store, true, 1)
+ASAN_MEMORY_ACCESS_CALLBACK(store, true, 2)
+ASAN_MEMORY_ACCESS_CALLBACK(store, true, 4)
+ASAN_MEMORY_ACCESS_CALLBACK(store, true, 8)
+ASAN_MEMORY_ACCESS_CALLBACK(store, true, 16)
+
// Force the linker to keep the symbols for various ASan interface functions.
// We want to keep those in the executable in order to let the instrumented
// dynamic libraries access the symbol even if it is not used by the executable
diff --git a/compiler-rt/lib/asan/tests/asan_noinst_test.cc b/compiler-rt/lib/asan/tests/asan_noinst_test.cc
index 0abb398e9b6..fe4112d1392 100644
--- a/compiler-rt/lib/asan/tests/asan_noinst_test.cc
+++ b/compiler-rt/lib/asan/tests/asan_noinst_test.cc
@@ -217,3 +217,40 @@ TEST(AddressSanitizer, ShadowRegionIsPoisonedTest) {
ptr = kHighShadowBeg + 200;
EXPECT_EQ(ptr, __asan_region_is_poisoned(ptr, 100));
}
+
+// 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,
+ }
+ };
+
+ uptr buggy_ptr;
+ __asan_test_only_reported_buggy_pointer = &buggy_ptr;
+ for (uptr len = 16; len <= 32; len++) {
+ char *ptr = new char[len];
+ uptr p = reinterpret_cast<uptr>(ptr);
+ for (uptr is_write = 0; is_write <= 1; is_write++) {
+ for (uptr size_log = 0; size_log <= 4; size_log++) {
+ uptr size = 1 << size_log;
+ CB call = cb[is_write][size_log];
+ // Iterate only size-aligned offsets.
+ for (uptr offset = 0; offset < len; offset += size) {
+ buggy_ptr = 0;
+ call(p + offset);
+ if (offset + size <= len)
+ EXPECT_EQ(buggy_ptr, 0U);
+ else
+ EXPECT_EQ(buggy_ptr, p + offset);
+ }
+ }
+ }
+ delete [] ptr;
+ }
+ __asan_test_only_reported_buggy_pointer = 0;
+}
OpenPOWER on IntegriCloud