[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
This commit is contained in:
Kostya Serebryany 2014-04-16 13:52:28 +00:00
parent ed1547040c
commit ae401ca5e7
3 changed files with 82 additions and 0 deletions

View File

@ -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

View File

@ -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

View File

@ -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;
}