diff options
author | Kostya Serebryany <kcc@google.com> | 2014-04-16 13:52:28 +0000 |
---|---|---|
committer | Kostya Serebryany <kcc@google.com> | 2014-04-16 13:52:28 +0000 |
commit | ae401ca5e7d25ae3057e0c62d752ce7ac9b0ff29 (patch) | |
tree | d6c6ff4320e6890737a9f44a3e1b18dd1d8d6a9c /compiler-rt | |
parent | ed1547040c08cde387574c9b1a97c3404ccfc1b6 (diff) | |
download | bcm5719-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.h | 14 | ||||
-rw-r--r-- | compiler-rt/lib/asan/asan_rtl.cc | 31 | ||||
-rw-r--r-- | compiler-rt/lib/asan/tests/asan_noinst_test.cc | 37 |
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; +} |