diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_allocator.cc b/compiler-rt/lib/sanitizer_common/sanitizer_allocator.cc index b6134c68aad12ce931bbdd3a5f97d2aa7438f1af..be2f94c8dd2fbd08ea7ef7a99b292848abdf1e7a 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_allocator.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_allocator.cc @@ -28,20 +28,27 @@ extern "C" void __libc_free(void *ptr); namespace __sanitizer { -static const u64 kInternalAllocBlockMagic = 0x7A6CB03ABCEBC042ull; +const u64 kBlockMagic = 0x6A6CB03ABCEBC041ull; void *InternalAlloc(uptr size) { void *p = LIBC_MALLOC(size + sizeof(u64)); - ((u64*)p)[0] = kInternalAllocBlockMagic; + ((u64*)p)[0] = kBlockMagic; return (char*)p + sizeof(u64); } void InternalFree(void *addr) { if (!addr) return; addr = (char*)addr - sizeof(u64); - CHECK_EQ(((u64*)addr)[0], kInternalAllocBlockMagic); + CHECK_EQ(((u64*)addr)[0], kBlockMagic); ((u64*)addr)[0] = 0; LIBC_FREE(addr); } +void *InternalAllocBlock(void *p) { + CHECK_NE(p, (void*)0); + u64 *pp = (u64*)((uptr)p & ~0x7); + for (; pp[0] != kBlockMagic; pp--) {} + return pp + 1; +} + } // namespace __sanitizer diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common.h b/compiler-rt/lib/sanitizer_common/sanitizer_common.h index 27e54056d6e9fc7939db976505e44bc26e8399c1..f24539b69b015f39b745131d0af5c8767561d29d 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common.h @@ -48,7 +48,10 @@ bool MemoryRangeIsAvailable(uptr range_start, uptr range_end); // Internal allocator void *InternalAlloc(uptr size); -void InternalFree(void *addr); +void InternalFree(void *p); +// Given the pointer p into a valid allocated block, +// returns a pointer to the beginning of the block. +void *InternalAllocBlock(void *p); // IO void RawWrite(const char *buffer); diff --git a/compiler-rt/lib/sanitizer_common/tests/sanitizer_allocator_test.cc b/compiler-rt/lib/sanitizer_common/tests/sanitizer_allocator_test.cc new file mode 100644 index 0000000000000000000000000000000000000000..2a739471fbd06eb1ebee8e9809616abdeb0766ae --- /dev/null +++ b/compiler-rt/lib/sanitizer_common/tests/sanitizer_allocator_test.cc @@ -0,0 +1,56 @@ +//===-- sanitizer_allocator_test.cc ---------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is a part of ThreadSanitizer (TSan), a race detector. +// +//===----------------------------------------------------------------------===// +#include "sanitizer_common/sanitizer_common.h" +#include "gtest/gtest.h" +#include + +namespace __tsan { + +TEST(Allocator, Basic) { + char *p = (char*)InternalAlloc(10); + EXPECT_NE(p, (char*)0); + char *p2 = (char*)InternalAlloc(20); + EXPECT_NE(p2, (char*)0); + EXPECT_NE(p2, p); + for (int i = 0; i < 10; i++) { + p[i] = 42; + EXPECT_EQ(p, InternalAllocBlock(p + i)); + } + for (int i = 0; i < 20; i++) { + ((char*)p2)[i] = 42; + EXPECT_EQ(p2, InternalAllocBlock(p2 + i)); + } + InternalFree(p); + InternalFree(p2); +} + +TEST(Allocator, Stress) { + const int kCount = 1000; + char *ptrs[kCount]; + unsigned rnd = 42; + for (int i = 0; i < kCount; i++) { + uptr sz = rand_r(&rnd) % 1000; + char *p = (char*)InternalAlloc(sz); + EXPECT_NE(p, (char*)0); + for (uptr j = 0; j < sz; j++) { + p[j] = 42; + EXPECT_EQ(p, InternalAllocBlock(p + j)); + } + ptrs[i] = p; + } + for (int i = 0; i < kCount; i++) { + InternalFree(ptrs[i]); + } +} + +} // namespace __tsan