Generalize sanitizer allocator public interface.

Introduce new public header <sanitizer/allocator_interface.h> and a set
of functions __sanitizer_get_ownership(), __sanitizer_malloc_hook() etc.
that will eventually replace their tool-specific equivalents
(__asan_get_ownership(), __msan_get_ownership() etc.). Tool-specific
functions are now deprecated and implemented as stubs redirecting
to __sanitizer_ versions (which are implemented differently in each tool).

Replace all uses of __xsan_ versions with __sanitizer_ versions in unit
and lit tests.

llvm-svn: 212469
This commit is contained in:
Alexey Samsonov 2014-07-07 17:39:31 +00:00
parent 761439962b
commit 91bb8e0e3a
29 changed files with 368 additions and 153 deletions

View File

@ -1,4 +1,5 @@
set(SANITIZER_HEADERS
sanitizer/allocator_interface.h
sanitizer/asan_interface.h
sanitizer/common_interface_defs.h
sanitizer/dfsan_interface.h

View File

@ -0,0 +1,66 @@
//===-- allocator_interface.h ---------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Public interface header for allocator used in sanitizers (ASan/TSan/MSan).
//===----------------------------------------------------------------------===//
#ifndef SANITIZER_ALLOCATOR_INTERFACE_H
#define SANITIZER_ALLOCATOR_INTERFACE_H
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
/* Returns the estimated number of bytes that will be reserved by allocator
for request of "size" bytes. If allocator can't allocate that much
memory, returns the maximal possible allocation size, otherwise returns
"size". */
size_t __sanitizer_get_estimated_allocated_size(size_t size);
/* Returns true if p was returned by the allocator and
is not yet freed. */
int __sanitizer_get_ownership(const volatile void *p);
/* Returns the number of bytes reserved for the pointer p.
Requires (get_ownership(p) == true) or (p == 0). */
size_t __sanitizer_get_allocated_size(const volatile void *p);
/* Number of bytes, allocated and not yet freed by the application. */
size_t __sanitizer_get_current_allocated_bytes();
/* Number of bytes, mmaped by the allocator to fulfill allocation requests.
Generally, for request of X bytes, allocator can reserve and add to free
lists a large number of chunks of size X to use them for future requests.
All these chunks count toward the heap size. Currently, allocator never
releases memory to OS (instead, it just puts freed chunks to free
lists). */
size_t __sanitizer_get_heap_size();
/* Number of bytes, mmaped by the allocator, which can be used to fulfill
allocation requests. When a user program frees memory chunk, it can first
fall into quarantine and will count toward __sanitizer_get_free_bytes()
later. */
size_t __sanitizer_get_free_bytes();
/* Number of bytes in unmapped pages, that are released to OS. Currently,
always returns 0. */
size_t __sanitizer_get_unmapped_bytes();
/* Malloc hooks that may be optionally provided by user.
__sanitizer_malloc_hook(ptr, size) is called immediately after
allocation of "size" bytes, which returned "ptr".
__sanitizer_free_hook(ptr) is called immediately before
deallocation of "ptr". */
void __sanitizer_malloc_hook(const volatile void *ptr, size_t size);
void __sanitizer_free_hook(const volatile void *ptr);
#ifdef __cplusplus
} // extern "C"
#endif
#endif

View File

@ -87,28 +87,42 @@ extern "C" {
// for request of "size" bytes. If ASan allocator can't allocate that much
// memory, returns the maximal possible allocation size, otherwise returns
// "size".
/* DEPRECATED: Use __sanitizer_get_estimated_allocated_size instead. */
size_t __asan_get_estimated_allocated_size(size_t size);
// Returns 1 if p was returned by the ASan allocator and is not yet freed.
// Otherwise returns 0.
/* DEPRECATED: Use __sanitizer_get_ownership instead. */
int __asan_get_ownership(const void *p);
// Returns the number of bytes reserved for the pointer p.
// Requires (get_ownership(p) == true) or (p == 0).
/* DEPRECATED: Use __sanitizer_get_allocated_size instead. */
size_t __asan_get_allocated_size(const void *p);
// Number of bytes, allocated and not yet freed by the application.
/* DEPRECATED: Use __sanitizer_get_current_allocated_bytes instead. */
size_t __asan_get_current_allocated_bytes();
// Number of bytes, mmaped by asan allocator to fulfill allocation requests.
// Generally, for request of X bytes, allocator can reserve and add to free
// lists a large number of chunks of size X to use them for future requests.
// All these chunks count toward the heap size. Currently, allocator never
// releases memory to OS (instead, it just puts freed chunks to free lists).
/* DEPRECATED: Use __sanitizer_get_heap_size instead. */
size_t __asan_get_heap_size();
// Number of bytes, mmaped by asan allocator, which can be used to fulfill
// allocation requests. When a user program frees memory chunk, it can first
// fall into quarantine and will count toward __asan_get_free_bytes() later.
/* DEPRECATED: Use __sanitizer_get_free_bytes instead. */
size_t __asan_get_free_bytes();
// Number of bytes in unmapped pages, that are released to OS. Currently,
// always returns 0.
/* DEPRECATED: Use __sanitizer_get_unmapped_bytes instead. */
size_t __asan_get_unmapped_bytes();
// Prints accumulated stats to stderr. Used for debugging.
void __asan_print_accumulated_stats();
@ -121,6 +135,7 @@ extern "C" {
// allocation of "size" bytes, which returned "ptr".
// __asan_free_hook(ptr) is called immediately before
// deallocation of "ptr".
/* DEPRECATED: Use __sanitizer_malloc_hook / __sanitizer_free_hook instead. */
void __asan_malloc_hook(void *ptr, size_t size);
void __asan_free_hook(void *ptr);

View File

@ -89,8 +89,8 @@ extern "C" {
a string containing Msan runtime options. See msan_flags.h for details. */
const char* __msan_default_options();
// Sets the callback to be called right before death on error.
// Passing 0 will unset the callback.
/* Sets the callback to be called right before death on error.
Passing 0 will unset the callback. */
void __msan_set_death_callback(void (*callback)(void));
/***********************************/
@ -100,17 +100,21 @@ extern "C" {
for request of "size" bytes. If Msan allocator can't allocate that much
memory, returns the maximal possible allocation size, otherwise returns
"size". */
/* DEPRECATED: Use __sanitizer_get_estimated_allocated_size instead. */
size_t __msan_get_estimated_allocated_size(size_t size);
/* Returns true if p was returned by the Msan allocator and
is not yet freed. */
/* DEPRECATED: Use __sanitizer_get_ownership instead. */
int __msan_get_ownership(const volatile void *p);
/* Returns the number of bytes reserved for the pointer p.
Requires (get_ownership(p) == true) or (p == 0). */
/* DEPRECATED: Use __sanitizer_get_allocated_size instead. */
size_t __msan_get_allocated_size(const volatile void *p);
/* Number of bytes, allocated and not yet freed by the application. */
/* DEPRECATED: Use __sanitizer_get_current_allocated_bytes instead. */
size_t __msan_get_current_allocated_bytes();
/* Number of bytes, mmaped by msan allocator to fulfill allocation requests.
@ -119,16 +123,19 @@ extern "C" {
All these chunks count toward the heap size. Currently, allocator never
releases memory to OS (instead, it just puts freed chunks to free
lists). */
/* DEPRECATED: Use __sanitizer_get_heap_size instead. */
size_t __msan_get_heap_size();
/* Number of bytes, mmaped by msan allocator, which can be used to fulfill
allocation requests. When a user program frees memory chunk, it can first
fall into quarantine and will count toward __msan_get_free_bytes()
later. */
/* DEPRECATED: Use __sanitizer_get_free_bytes instead. */
size_t __msan_get_free_bytes();
/* Number of bytes in unmapped pages, that are released to OS. Currently,
always returns 0. */
/* DEPRECATED: Use __sanitizer_get_unmapped_bytes instead. */
size_t __msan_get_unmapped_bytes();
/* Malloc hooks that may be optionally provided by user.
@ -136,8 +143,10 @@ extern "C" {
allocation of "size" bytes, which returned "ptr".
__msan_free_hook(ptr) is called immediately before
deallocation of "ptr". */
/* DEPRECATED: Use __sanitizer_malloc_hook / __sanitizer_free_hook instead. */
void __msan_malloc_hook(const volatile void *ptr, size_t size);
void __msan_free_hook(const volatile void *ptr);
#ifdef __cplusplus
} // extern "C"
#endif

View File

@ -21,6 +21,7 @@
#include "asan_report.h"
#include "asan_stack.h"
#include "asan_thread.h"
#include "sanitizer_common/sanitizer_allocator_interface.h"
#include "sanitizer_common/sanitizer_flags.h"
#include "sanitizer_common/sanitizer_internal_defs.h"
#include "sanitizer_common/sanitizer_list.h"
@ -760,26 +761,35 @@ using namespace __asan; // NOLINT
// ASan allocator doesn't reserve extra bytes, so normally we would
// just return "size". We don't want to expose our redzone sizes, etc here.
uptr __asan_get_estimated_allocated_size(uptr size) {
uptr __sanitizer_get_estimated_allocated_size(uptr size) {
return size;
}
uptr __asan_get_estimated_allocated_size(uptr size) {
return __sanitizer_get_estimated_allocated_size(size);
}
int __asan_get_ownership(const void *p) {
int __sanitizer_get_ownership(const void *p) {
uptr ptr = reinterpret_cast<uptr>(p);
return (AllocationSize(ptr) > 0);
}
int __asan_get_ownership(const void *p) {
return __sanitizer_get_ownership(p);
}
uptr __asan_get_allocated_size(const void *p) {
uptr __sanitizer_get_allocated_size(const void *p) {
if (p == 0) return 0;
uptr ptr = reinterpret_cast<uptr>(p);
uptr allocated_size = AllocationSize(ptr);
// Die if p is not malloced or if it is already freed.
if (allocated_size == 0) {
GET_STACK_TRACE_FATAL_HERE;
ReportAsanGetAllocatedSizeNotOwned(ptr, &stack);
ReportSanitizerGetAllocatedSizeNotOwned(ptr, &stack);
}
return allocated_size;
}
uptr __asan_get_allocated_size(const void *p) {
return __sanitizer_get_allocated_size(p);
}
#if !SANITIZER_SUPPORTS_WEAK_HOOKS
// Provide default (no-op) implementation of malloc hooks.
@ -793,5 +803,14 @@ SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
void __asan_free_hook(void *ptr) {
(void)ptr;
}
SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
void __sanitizer_malloc_hook(void *ptr, uptr size) {
(void)ptr;
(void)size;
}
SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
void __sanitizer_free_hook(void *ptr) {
(void)ptr;
}
} // extern "C"
#endif

View File

@ -110,24 +110,26 @@ extern "C" {
SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
/* OPTIONAL */ void __asan_on_error();
// ---------------------------
// FIXME: Replace these functions with __sanitizer equivalent.
SANITIZER_INTERFACE_ATTRIBUTE
uptr __asan_get_estimated_allocated_size(uptr size);
SANITIZER_INTERFACE_ATTRIBUTE int __asan_get_ownership(const void *p);
SANITIZER_INTERFACE_ATTRIBUTE uptr __asan_get_allocated_size(const void *p);
SANITIZER_INTERFACE_ATTRIBUTE uptr __asan_get_current_allocated_bytes();
SANITIZER_INTERFACE_ATTRIBUTE uptr __asan_get_heap_size();
SANITIZER_INTERFACE_ATTRIBUTE uptr __asan_get_free_bytes();
SANITIZER_INTERFACE_ATTRIBUTE uptr __asan_get_unmapped_bytes();
SANITIZER_INTERFACE_ATTRIBUTE void __asan_print_accumulated_stats();
SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
/* OPTIONAL */ const char* __asan_default_options();
SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
/* OPTIONAL */ void __asan_malloc_hook(void *ptr, uptr size);
SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
/* OPTIONAL */ void __asan_free_hook(void *ptr);
// ---------------------------
SANITIZER_INTERFACE_ATTRIBUTE void __asan_print_accumulated_stats();
SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
/* OPTIONAL */ const char* __asan_default_options();
// Global flag, copy of ASAN_OPTIONS=detect_stack_use_after_return
SANITIZER_INTERFACE_ATTRIBUTE

View File

@ -112,9 +112,11 @@ bool PlatformHasDifferentMemcpyAndMemmove();
// Add convenient macro for interface functions that may be represented as
// weak hooks.
#define ASAN_MALLOC_HOOK(ptr, size) \
if (&__asan_malloc_hook) __asan_malloc_hook(ptr, size)
if (&__asan_malloc_hook) __asan_malloc_hook(ptr, size); \
if (&__sanitizer_malloc_hook) __sanitizer_malloc_hook(ptr, size)
#define ASAN_FREE_HOOK(ptr) \
if (&__asan_free_hook) __asan_free_hook(ptr)
if (&__asan_free_hook) __asan_free_hook(ptr); \
if (&__sanitizer_free_hook) __sanitizer_free_hook(ptr)
#define ASAN_ON_ERROR() \
if (&__asan_on_error) __asan_on_error()

View File

@ -698,17 +698,17 @@ void ReportMallocUsableSizeNotOwned(uptr addr, StackTrace *stack) {
ReportErrorSummary("bad-malloc_usable_size", stack);
}
void ReportAsanGetAllocatedSizeNotOwned(uptr addr, StackTrace *stack) {
void ReportSanitizerGetAllocatedSizeNotOwned(uptr addr, StackTrace *stack) {
ScopedInErrorReport in_report;
Decorator d;
Printf("%s", d.Warning());
Report("ERROR: AddressSanitizer: attempting to call "
"__asan_get_allocated_size() for pointer which is "
"__sanitizer_get_allocated_size() for pointer which is "
"not owned: %p\n", addr);
Printf("%s", d.EndWarning());
stack->Print();
DescribeHeapAddress(addr, 1);
ReportErrorSummary("bad-__asan_get_allocated_size", stack);
ReportErrorSummary("bad-__sanitizer_get_allocated_size", stack);
}
void ReportStringFunctionMemoryRangesOverlap(

View File

@ -43,8 +43,8 @@ void NORETURN ReportAllocTypeMismatch(uptr addr, StackTrace *free_stack,
AllocType dealloc_type);
void NORETURN ReportMallocUsableSizeNotOwned(uptr addr,
StackTrace *stack);
void NORETURN ReportAsanGetAllocatedSizeNotOwned(uptr addr,
StackTrace *stack);
void NORETURN
ReportSanitizerGetAllocatedSizeNotOwned(uptr addr, StackTrace *stack);
void NORETURN ReportStringFunctionMemoryRangesOverlap(
const char *function, const char *offset1, uptr length1,
const char *offset2, uptr length2, StackTrace *stack);

View File

@ -15,6 +15,7 @@
#include "asan_internal.h"
#include "asan_stats.h"
#include "asan_thread.h"
#include "sanitizer_common/sanitizer_allocator_interface.h"
#include "sanitizer_common/sanitizer_mutex.h"
#include "sanitizer_common/sanitizer_stackdepot.h"
@ -139,7 +140,7 @@ static void PrintAccumulatedStats() {
// ---------------------- Interface ---------------- {{{1
using namespace __asan; // NOLINT
uptr __asan_get_current_allocated_bytes() {
uptr __sanitizer_get_current_allocated_bytes() {
AsanStats stats;
GetAccumulatedStats(&stats);
uptr malloced = stats.malloced;
@ -148,14 +149,20 @@ uptr __asan_get_current_allocated_bytes() {
// way we update accumulated stats.
return (malloced > freed) ? malloced - freed : 1;
}
uptr __asan_get_current_allocated_bytes() {
return __sanitizer_get_current_allocated_bytes();
}
uptr __asan_get_heap_size() {
uptr __sanitizer_get_heap_size() {
AsanStats stats;
GetAccumulatedStats(&stats);
return stats.mmaped - stats.munmaped;
}
uptr __asan_get_heap_size() {
return __sanitizer_get_heap_size();
}
uptr __asan_get_free_bytes() {
uptr __sanitizer_get_free_bytes() {
AsanStats stats;
GetAccumulatedStats(&stats);
uptr total_free = stats.mmaped
@ -168,10 +175,16 @@ uptr __asan_get_free_bytes() {
// way we update accumulated stats.
return (total_free > total_used) ? total_free - total_used : 1;
}
uptr __asan_get_free_bytes() {
return __sanitizer_get_free_bytes();
}
uptr __asan_get_unmapped_bytes() {
uptr __sanitizer_get_unmapped_bytes() {
return 0;
}
uptr __asan_get_unmapped_bytes() {
return __sanitizer_get_unmapped_bytes();
}
void __asan_print_accumulated_stats() {
PrintAccumulatedStats();

View File

@ -11,18 +11,19 @@
//
//===----------------------------------------------------------------------===//
#include "asan_test_utils.h"
#include "sanitizer/asan_interface.h"
#include <sanitizer/allocator_interface.h>
#include <sanitizer/asan_interface.h>
TEST(AddressSanitizerInterface, GetEstimatedAllocatedSize) {
EXPECT_EQ(0U, __asan_get_estimated_allocated_size(0));
EXPECT_EQ(0U, __sanitizer_get_estimated_allocated_size(0));
const size_t sizes[] = { 1, 30, 1<<30 };
for (size_t i = 0; i < 3; i++) {
EXPECT_EQ(sizes[i], __asan_get_estimated_allocated_size(sizes[i]));
EXPECT_EQ(sizes[i], __sanitizer_get_estimated_allocated_size(sizes[i]));
}
}
static const char* kGetAllocatedSizeErrorMsg =
"attempting to call __asan_get_allocated_size";
"attempting to call __sanitizer_get_allocated_size";
TEST(AddressSanitizerInterface, GetAllocatedSizeAndOwnershipTest) {
const size_t kArraySize = 100;
@ -31,38 +32,41 @@ TEST(AddressSanitizerInterface, GetAllocatedSizeAndOwnershipTest) {
// Allocated memory is owned by allocator. Allocated size should be
// equal to requested size.
EXPECT_EQ(true, __asan_get_ownership(array));
EXPECT_EQ(kArraySize, __asan_get_allocated_size(array));
EXPECT_EQ(true, __asan_get_ownership(int_ptr));
EXPECT_EQ(sizeof(int), __asan_get_allocated_size(int_ptr));
EXPECT_EQ(true, __sanitizer_get_ownership(array));
EXPECT_EQ(kArraySize, __sanitizer_get_allocated_size(array));
EXPECT_EQ(true, __sanitizer_get_ownership(int_ptr));
EXPECT_EQ(sizeof(int), __sanitizer_get_allocated_size(int_ptr));
// We cannot call GetAllocatedSize from the memory we didn't map,
// and from the interior pointers (not returned by previous malloc).
void *wild_addr = (void*)0x1;
EXPECT_FALSE(__asan_get_ownership(wild_addr));
EXPECT_DEATH(__asan_get_allocated_size(wild_addr), kGetAllocatedSizeErrorMsg);
EXPECT_FALSE(__asan_get_ownership(array + kArraySize / 2));
EXPECT_DEATH(__asan_get_allocated_size(array + kArraySize / 2),
EXPECT_FALSE(__sanitizer_get_ownership(wild_addr));
EXPECT_DEATH(__sanitizer_get_allocated_size(wild_addr),
kGetAllocatedSizeErrorMsg);
EXPECT_FALSE(__sanitizer_get_ownership(array + kArraySize / 2));
EXPECT_DEATH(__sanitizer_get_allocated_size(array + kArraySize / 2),
kGetAllocatedSizeErrorMsg);
// NULL is not owned, but is a valid argument for __asan_get_allocated_size().
EXPECT_FALSE(__asan_get_ownership(NULL));
EXPECT_EQ(0U, __asan_get_allocated_size(NULL));
// NULL is not owned, but is a valid argument for
// __sanitizer_get_allocated_size().
EXPECT_FALSE(__sanitizer_get_ownership(NULL));
EXPECT_EQ(0U, __sanitizer_get_allocated_size(NULL));
// When memory is freed, it's not owned, and call to GetAllocatedSize
// is forbidden.
free(array);
EXPECT_FALSE(__asan_get_ownership(array));
EXPECT_DEATH(__asan_get_allocated_size(array), kGetAllocatedSizeErrorMsg);
EXPECT_FALSE(__sanitizer_get_ownership(array));
EXPECT_DEATH(__sanitizer_get_allocated_size(array),
kGetAllocatedSizeErrorMsg);
delete int_ptr;
void *zero_alloc = Ident(malloc(0));
if (zero_alloc != 0) {
// If malloc(0) is not null, this pointer is owned and should have valid
// allocated size.
EXPECT_TRUE(__asan_get_ownership(zero_alloc));
EXPECT_TRUE(__sanitizer_get_ownership(zero_alloc));
// Allocated size is 0 or 1 depending on the allocator used.
EXPECT_LT(__asan_get_allocated_size(zero_alloc), 2U);
EXPECT_LT(__sanitizer_get_allocated_size(zero_alloc), 2U);
}
free(zero_alloc);
}
@ -71,14 +75,14 @@ TEST(AddressSanitizerInterface, GetCurrentAllocatedBytesTest) {
size_t before_malloc, after_malloc, after_free;
char *array;
const size_t kMallocSize = 100;
before_malloc = __asan_get_current_allocated_bytes();
before_malloc = __sanitizer_get_current_allocated_bytes();
array = Ident((char*)malloc(kMallocSize));
after_malloc = __asan_get_current_allocated_bytes();
after_malloc = __sanitizer_get_current_allocated_bytes();
EXPECT_EQ(before_malloc + kMallocSize, after_malloc);
free(array);
after_free = __asan_get_current_allocated_bytes();
after_free = __sanitizer_get_current_allocated_bytes();
EXPECT_EQ(before_malloc, after_free);
}
@ -88,11 +92,11 @@ TEST(AddressSanitizerInterface, GetHeapSizeTest) {
// otherwise it will be stuck in quarantine instead of being unmaped.
static const size_t kLargeMallocSize = (1 << 28) + 1; // 256M
free(Ident(malloc(kLargeMallocSize))); // Drain quarantine.
size_t old_heap_size = __asan_get_heap_size();
size_t old_heap_size = __sanitizer_get_heap_size();
for (int i = 0; i < 3; i++) {
// fprintf(stderr, "allocating %zu bytes:\n", kLargeMallocSize);
free(Ident(malloc(kLargeMallocSize)));
EXPECT_EQ(old_heap_size, __asan_get_heap_size());
EXPECT_EQ(old_heap_size, __sanitizer_get_heap_size());
}
}
@ -116,7 +120,7 @@ static void *ManyThreadsWithStatsWorker(void *arg) {
TEST(AddressSanitizerInterface, ManyThreadsWithStatsStressTest) {
size_t before_test, after_test, i;
pthread_t threads[kManyThreadsNumThreads];
before_test = __asan_get_current_allocated_bytes();
before_test = __sanitizer_get_current_allocated_bytes();
for (i = 0; i < kManyThreadsNumThreads; i++) {
PTHREAD_CREATE(&threads[i], 0,
(void* (*)(void *x))ManyThreadsWithStatsWorker, (void*)i);
@ -124,7 +128,7 @@ TEST(AddressSanitizerInterface, ManyThreadsWithStatsStressTest) {
for (i = 0; i < kManyThreadsNumThreads; i++) {
PTHREAD_JOIN(threads[i], 0);
}
after_test = __asan_get_current_allocated_bytes();
after_test = __sanitizer_get_current_allocated_bytes();
// ASan stats also reflect memory usage of internal ASan RTL structs,
// so we can't check for equality here.
EXPECT_LT(after_test, before_test + (1UL<<20));
@ -417,11 +421,11 @@ TEST(AddressSanitizerInterface, GetOwnershipStressTest) {
sizes.push_back(size);
}
for (size_t i = 0; i < 4000000; i++) {
EXPECT_FALSE(__asan_get_ownership(&pointers));
EXPECT_FALSE(__asan_get_ownership((void*)0x1234));
EXPECT_FALSE(__sanitizer_get_ownership(&pointers));
EXPECT_FALSE(__sanitizer_get_ownership((void*)0x1234));
size_t idx = i % kNumMallocs;
EXPECT_TRUE(__asan_get_ownership(pointers[idx]));
EXPECT_EQ(sizes[idx], __asan_get_allocated_size(pointers[idx]));
EXPECT_TRUE(__sanitizer_get_ownership(pointers[idx]));
EXPECT_EQ(sizes[idx], __sanitizer_get_allocated_size(pointers[idx]));
}
for (size_t i = 0, n = pointers.size(); i < n; i++)
free(pointers[i]);

View File

@ -16,6 +16,7 @@
#include "asan_internal.h"
#include "asan_mapping.h"
#include "asan_test_utils.h"
#include <sanitizer/allocator_interface.h>
#include <assert.h>
#include <stdio.h>
@ -175,12 +176,12 @@ void *ThreadedQuarantineTestWorker(void *unused) {
// destroyed.
TEST(AddressSanitizer, ThreadedQuarantineTest) {
const int n_threads = 3000;
size_t mmaped1 = __asan_get_heap_size();
size_t mmaped1 = __sanitizer_get_heap_size();
for (int i = 0; i < n_threads; i++) {
pthread_t t;
PTHREAD_CREATE(&t, NULL, ThreadedQuarantineTestWorker, 0);
PTHREAD_JOIN(t, 0);
size_t mmaped2 = __asan_get_heap_size();
size_t mmaped2 = __sanitizer_get_heap_size();
EXPECT_LT(mmaped2 - mmaped1, 320U * (1 << 20));
}
}

View File

@ -141,8 +141,10 @@ void MsanTSDDtor(void *tsd);
} // namespace __msan
#define MSAN_MALLOC_HOOK(ptr, size) \
if (&__msan_malloc_hook) __msan_malloc_hook(ptr, size)
if (&__msan_malloc_hook) __msan_malloc_hook(ptr, size); \
if (&__sanitizer_malloc_hook) __sanitizer_malloc_hook(ptr, size)
#define MSAN_FREE_HOOK(ptr) \
if (&__msan_free_hook) __msan_free_hook(ptr)
if (&__msan_free_hook) __msan_free_hook(ptr); \
if (&__sanitizer_free_hook) __sanitizer_free_hook(ptr)
#endif // MSAN_H

View File

@ -13,6 +13,7 @@
//===----------------------------------------------------------------------===//
#include "sanitizer_common/sanitizer_allocator.h"
#include "sanitizer_common/sanitizer_allocator_interface.h"
#include "sanitizer_common/sanitizer_stackdepot.h"
#include "msan.h"
#include "msan_allocator.h"
@ -182,24 +183,45 @@ static uptr AllocationSize(const void *p) {
using namespace __msan;
uptr __msan_get_current_allocated_bytes() {
uptr __sanitizer_get_current_allocated_bytes() {
uptr stats[AllocatorStatCount];
allocator.GetStats(stats);
return stats[AllocatorStatAllocated];
}
uptr __msan_get_current_allocated_bytes() {
return __sanitizer_get_current_allocated_bytes();
}
uptr __msan_get_heap_size() {
uptr __sanitizer_get_heap_size() {
uptr stats[AllocatorStatCount];
allocator.GetStats(stats);
return stats[AllocatorStatMapped];
}
uptr __msan_get_heap_size() {
return __sanitizer_get_heap_size();
}
uptr __msan_get_free_bytes() { return 1; }
uptr __sanitizer_get_free_bytes() { return 1; }
uptr __msan_get_free_bytes() {
return __sanitizer_get_free_bytes();
}
uptr __msan_get_unmapped_bytes() { return 1; }
uptr __sanitizer_get_unmapped_bytes() { return 1; }
uptr __msan_get_unmapped_bytes() {
return __sanitizer_get_unmapped_bytes();
}
uptr __msan_get_estimated_allocated_size(uptr size) { return size; }
uptr __sanitizer_get_estimated_allocated_size(uptr size) { return size; }
uptr __msan_get_estimated_allocated_size(uptr size) {
return __sanitizer_get_estimated_allocated_size(size);
}
int __msan_get_ownership(const void *p) { return AllocationSize(p) != 0; }
int __sanitizer_get_ownership(const void *p) { return AllocationSize(p) != 0; }
int __msan_get_ownership(const void *p) {
return __sanitizer_get_ownership(p);
}
uptr __msan_get_allocated_size(const void *p) { return AllocationSize(p); }
uptr __sanitizer_get_allocated_size(const void *p) { return AllocationSize(p); }
uptr __msan_get_allocated_size(const void *p) {
return __sanitizer_get_allocated_size(p);
}

View File

@ -21,6 +21,7 @@
#include "msan_thread.h"
#include "sanitizer_common/sanitizer_platform_limits_posix.h"
#include "sanitizer_common/sanitizer_allocator.h"
#include "sanitizer_common/sanitizer_allocator_interface.h"
#include "sanitizer_common/sanitizer_allocator_internal.h"
#include "sanitizer_common/sanitizer_atomic.h"
#include "sanitizer_common/sanitizer_common.h"
@ -208,7 +209,7 @@ INTERCEPTOR(void, cfree, void *ptr) {
}
INTERCEPTOR(uptr, malloc_usable_size, void *ptr) {
return __msan_get_allocated_size(ptr);
return __sanitizer_get_allocated_size(ptr);
}
// This function actually returns a struct by value, but we can't unpoison a

View File

@ -161,32 +161,27 @@ void __sanitizer_unaligned_store32(uu32 *p, u32 x);
SANITIZER_INTERFACE_ATTRIBUTE
void __sanitizer_unaligned_store64(uu64 *p, u64 x);
// ---------------------------
// FIXME: Replace these functions with __sanitizer equivalent.
SANITIZER_INTERFACE_ATTRIBUTE
uptr __msan_get_estimated_allocated_size(uptr size);
SANITIZER_INTERFACE_ATTRIBUTE
int __msan_get_ownership(const void *p);
SANITIZER_INTERFACE_ATTRIBUTE
uptr __msan_get_allocated_size(const void *p);
SANITIZER_INTERFACE_ATTRIBUTE
uptr __msan_get_current_allocated_bytes();
SANITIZER_INTERFACE_ATTRIBUTE
uptr __msan_get_heap_size();
SANITIZER_INTERFACE_ATTRIBUTE
uptr __msan_get_free_bytes();
SANITIZER_INTERFACE_ATTRIBUTE
uptr __msan_get_unmapped_bytes();
SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
/* OPTIONAL */ void __msan_malloc_hook(void *ptr, uptr size);
SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
/* OPTIONAL */ void __msan_free_hook(void *ptr);
// ---------------------------
SANITIZER_INTERFACE_ATTRIBUTE
void __msan_dr_is_initialized();

View File

@ -18,6 +18,7 @@
#include "sanitizer_common/tests/sanitizer_test_utils.h"
#include "sanitizer/allocator_interface.h"
#include "sanitizer/msan_interface.h"
#include "msandr_test_so.h"
@ -3022,12 +3023,12 @@ TEST(MemorySanitizer, valloc) {
TEST(MemorySanitizer, pvalloc) {
void *p = pvalloc(kPageSize + 100);
EXPECT_EQ(0U, (uintptr_t)p % kPageSize);
EXPECT_EQ(2 * kPageSize, __msan_get_allocated_size(p));
EXPECT_EQ(2 * kPageSize, __sanitizer_get_allocated_size(p));
free(p);
p = pvalloc(0); // pvalloc(0) should allocate at least one page.
EXPECT_EQ(0U, (uintptr_t)p % kPageSize);
EXPECT_EQ(kPageSize, __msan_get_allocated_size(p));
EXPECT_EQ(kPageSize, __sanitizer_get_allocated_size(p));
free(p);
}
@ -4076,7 +4077,7 @@ TEST(MemorySanitizerStress, DISABLED_MallocStackTrace) {
TEST(MemorySanitizerAllocator, get_estimated_allocated_size) {
size_t sizes[] = {0, 20, 5000, 1<<20};
for (size_t i = 0; i < sizeof(sizes) / sizeof(*sizes); ++i) {
size_t alloc_size = __msan_get_estimated_allocated_size(sizes[i]);
size_t alloc_size = __sanitizer_get_estimated_allocated_size(sizes[i]);
EXPECT_EQ(alloc_size, sizes[i]);
}
}
@ -4085,26 +4086,26 @@ TEST(MemorySanitizerAllocator, get_allocated_size_and_ownership) {
char *array = reinterpret_cast<char*>(malloc(100));
int *int_ptr = new int;
EXPECT_TRUE(__msan_get_ownership(array));
EXPECT_EQ(100U, __msan_get_allocated_size(array));
EXPECT_TRUE(__sanitizer_get_ownership(array));
EXPECT_EQ(100U, __sanitizer_get_allocated_size(array));
EXPECT_TRUE(__msan_get_ownership(int_ptr));
EXPECT_EQ(sizeof(*int_ptr), __msan_get_allocated_size(int_ptr));
EXPECT_TRUE(__sanitizer_get_ownership(int_ptr));
EXPECT_EQ(sizeof(*int_ptr), __sanitizer_get_allocated_size(int_ptr));
void *wild_addr = reinterpret_cast<void*>(0x1);
EXPECT_FALSE(__msan_get_ownership(wild_addr));
EXPECT_EQ(0U, __msan_get_allocated_size(wild_addr));
EXPECT_FALSE(__sanitizer_get_ownership(wild_addr));
EXPECT_EQ(0U, __sanitizer_get_allocated_size(wild_addr));
EXPECT_FALSE(__msan_get_ownership(array + 50));
EXPECT_EQ(0U, __msan_get_allocated_size(array + 50));
EXPECT_FALSE(__sanitizer_get_ownership(array + 50));
EXPECT_EQ(0U, __sanitizer_get_allocated_size(array + 50));
// NULL is a valid argument for GetAllocatedSize but is not owned.
EXPECT_FALSE(__sanitizer_get_ownership(NULL));
EXPECT_EQ(0U, __sanitizer_get_allocated_size(NULL));
// NULL is a valid argument for GetAllocatedSize but is not owned.
EXPECT_FALSE(__msan_get_ownership(NULL));
EXPECT_EQ(0U, __msan_get_allocated_size(NULL));
free(array);
EXPECT_FALSE(__msan_get_ownership(array));
EXPECT_EQ(0U, __msan_get_allocated_size(array));
EXPECT_FALSE(__sanitizer_get_ownership(array));
EXPECT_EQ(0U, __sanitizer_get_allocated_size(array));
delete int_ptr;
}

View File

@ -45,6 +45,7 @@ set(SANITIZER_LIBCDEP_SOURCES
set(SANITIZER_HEADERS
sanitizer_addrhashmap.h
sanitizer_allocator.h
sanitizer_allocator_interface.h
sanitizer_allocator_internal.h
sanitizer_atomic.h
sanitizer_atomic_clang.h

View File

@ -0,0 +1,38 @@
//===-- sanitizer_allocator_interface.h ------------------------- C++ -----===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Re-declaration of functions from public sanitizer allocator interface.
//
//===----------------------------------------------------------------------===//
#ifndef SANITIZER_ALLOCATOR_INTERFACE_H
#define SANITIZER_ALLOCATOR_INTERFACE_H
#include "sanitizer_internal_defs.h"
using __sanitizer::uptr;
extern "C" {
SANITIZER_INTERFACE_ATTRIBUTE
uptr __sanitizer_get_estimated_allocated_size(uptr size);
SANITIZER_INTERFACE_ATTRIBUTE int __sanitizer_get_ownership(const void *p);
SANITIZER_INTERFACE_ATTRIBUTE uptr
__sanitizer_get_allocated_size(const void *p);
SANITIZER_INTERFACE_ATTRIBUTE uptr __sanitizer_get_current_allocated_bytes();
SANITIZER_INTERFACE_ATTRIBUTE uptr __sanitizer_get_heap_size();
SANITIZER_INTERFACE_ATTRIBUTE uptr __sanitizer_get_free_bytes();
SANITIZER_INTERFACE_ATTRIBUTE uptr __sanitizer_get_unmapped_bytes();
SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
/* OPTIONAL */ void __sanitizer_malloc_hook(void *ptr, uptr size);
SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
/* OPTIONAL */ void __sanitizer_free_hook(void *ptr);
} // extern "C"
#endif // SANITIZER_ALLOCATOR_INTERFACE_H

View File

@ -10,6 +10,7 @@
// This file is a part of ThreadSanitizer (TSan), a race detector.
//
//===----------------------------------------------------------------------===//
#include "sanitizer_common/sanitizer_allocator_interface.h"
#include "sanitizer_common/sanitizer_common.h"
#include "sanitizer_common/sanitizer_placement_new.h"
#include "tsan_mman.h"
@ -22,10 +23,17 @@ extern "C" void WEAK __tsan_malloc_hook(void *ptr, uptr size) {
(void)ptr;
(void)size;
}
extern "C" void WEAK __sanitizer_malloc_hook(void *ptr, uptr size) {
(void)ptr;
(void)size;
}
extern "C" void WEAK __tsan_free_hook(void *ptr) {
(void)ptr;
}
extern "C" void WEAK __sanitizer_free_hook(void *ptr) {
(void)ptr;
}
namespace __tsan {
@ -128,7 +136,7 @@ void *user_realloc(ThreadState *thr, uptr pc, void *p, uptr sz) {
return p2;
}
uptr user_alloc_usable_size(void *p) {
uptr user_alloc_usable_size(const void *p) {
if (p == 0)
return 0;
MBlock *b = ctx->metamap.GetBlock((uptr)p);
@ -140,6 +148,7 @@ void invoke_malloc_hook(void *ptr, uptr size) {
if (ctx == 0 || !ctx->initialized || thr->ignore_interceptors)
return;
__tsan_malloc_hook(ptr, size);
__sanitizer_malloc_hook(ptr, size);
}
void invoke_free_hook(void *ptr) {
@ -147,6 +156,7 @@ void invoke_free_hook(void *ptr) {
if (ctx == 0 || !ctx->initialized || thr->ignore_interceptors)
return;
__tsan_free_hook(ptr);
__sanitizer_free_hook(ptr);
}
void *internal_alloc(MBlockType typ, uptr sz) {
@ -173,37 +183,58 @@ void internal_free(void *p) {
using namespace __tsan;
extern "C" {
uptr __tsan_get_current_allocated_bytes() {
uptr __sanitizer_get_current_allocated_bytes() {
uptr stats[AllocatorStatCount];
allocator()->GetStats(stats);
return stats[AllocatorStatAllocated];
}
uptr __tsan_get_current_allocated_bytes() {
return __sanitizer_get_current_allocated_bytes();
}
uptr __tsan_get_heap_size() {
uptr __sanitizer_get_heap_size() {
uptr stats[AllocatorStatCount];
allocator()->GetStats(stats);
return stats[AllocatorStatMapped];
}
uptr __tsan_get_heap_size() {
return __sanitizer_get_heap_size();
}
uptr __sanitizer_get_free_bytes() {
return 1;
}
uptr __tsan_get_free_bytes() {
return 1;
return __sanitizer_get_free_bytes();
}
uptr __sanitizer_get_unmapped_bytes() {
return 1;
}
uptr __tsan_get_unmapped_bytes() {
return 1;
return __sanitizer_get_unmapped_bytes();
}
uptr __tsan_get_estimated_allocated_size(uptr size) {
uptr __sanitizer_get_estimated_allocated_size(uptr size) {
return size;
}
bool __tsan_get_ownership(void *p) {
return allocator()->GetBlockBegin(p) != 0;
uptr __tsan_get_estimated_allocated_size(uptr size) {
return __sanitizer_get_estimated_allocated_size(size);
}
uptr __tsan_get_allocated_size(void *p) {
int __sanitizer_get_ownership(const void *p) {
return allocator()->GetBlockBegin(p) != 0;
}
int __tsan_get_ownership(const void *p) {
return __sanitizer_get_ownership(p);
}
uptr __sanitizer_get_allocated_size(const void *p) {
return user_alloc_usable_size(p);
}
uptr __tsan_get_allocated_size(const void *p) {
return __sanitizer_get_allocated_size(p);
}
void __tsan_on_thread_idle() {
ThreadState *thr = cur_thread();

View File

@ -31,7 +31,7 @@ void *user_alloc(ThreadState *thr, uptr pc, uptr sz,
void user_free(ThreadState *thr, uptr pc, void *p);
void *user_realloc(ThreadState *thr, uptr pc, void *p, uptr sz);
void *user_alloc_aligned(ThreadState *thr, uptr pc, uptr sz, uptr align);
uptr user_alloc_usable_size(void *p);
uptr user_alloc_usable_size(const void *p);
// Invoking malloc/free hooks that may be installed by the user.
void invoke_malloc_hook(void *ptr, uptr size);

View File

@ -11,20 +11,11 @@
//
//===----------------------------------------------------------------------===//
#include <limits>
#include <sanitizer/allocator_interface.h>
#include "tsan_mman.h"
#include "tsan_rtl.h"
#include "gtest/gtest.h"
extern "C" {
uptr __tsan_get_current_allocated_bytes();
uptr __tsan_get_heap_size();
uptr __tsan_get_free_bytes();
uptr __tsan_get_unmapped_bytes();
uptr __tsan_get_estimated_allocated_size(uptr size);
bool __tsan_get_ownership(void *p);
uptr __tsan_get_allocated_size(void *p);
}
namespace __tsan {
TEST(Mman, Internal) {
@ -118,30 +109,30 @@ TEST(Mman, UsableSize) {
TEST(Mman, Stats) {
ThreadState *thr = cur_thread();
uptr alloc0 = __tsan_get_current_allocated_bytes();
uptr heap0 = __tsan_get_heap_size();
uptr free0 = __tsan_get_free_bytes();
uptr unmapped0 = __tsan_get_unmapped_bytes();
uptr alloc0 = __sanitizer_get_current_allocated_bytes();
uptr heap0 = __sanitizer_get_heap_size();
uptr free0 = __sanitizer_get_free_bytes();
uptr unmapped0 = __sanitizer_get_unmapped_bytes();
EXPECT_EQ(__tsan_get_estimated_allocated_size(10), (uptr)10);
EXPECT_EQ(__tsan_get_estimated_allocated_size(20), (uptr)20);
EXPECT_EQ(__tsan_get_estimated_allocated_size(100), (uptr)100);
EXPECT_EQ(10U, __sanitizer_get_estimated_allocated_size(10));
EXPECT_EQ(20U, __sanitizer_get_estimated_allocated_size(20));
EXPECT_EQ(100U, __sanitizer_get_estimated_allocated_size(100));
char *p = (char*)user_alloc(thr, 0, 10);
EXPECT_EQ(__tsan_get_ownership(p), true);
EXPECT_EQ(__tsan_get_allocated_size(p), (uptr)10);
EXPECT_TRUE(__sanitizer_get_ownership(p));
EXPECT_EQ(10U, __sanitizer_get_allocated_size(p));
EXPECT_EQ(__tsan_get_current_allocated_bytes(), alloc0 + 16);
EXPECT_GE(__tsan_get_heap_size(), heap0);
EXPECT_EQ(__tsan_get_free_bytes(), free0);
EXPECT_EQ(__tsan_get_unmapped_bytes(), unmapped0);
EXPECT_EQ(alloc0 + 16, __sanitizer_get_current_allocated_bytes());
EXPECT_GE(__sanitizer_get_heap_size(), heap0);
EXPECT_EQ(free0, __sanitizer_get_free_bytes());
EXPECT_EQ(unmapped0, __sanitizer_get_unmapped_bytes());
user_free(thr, 0, p);
EXPECT_EQ(__tsan_get_current_allocated_bytes(), alloc0);
EXPECT_GE(__tsan_get_heap_size(), heap0);
EXPECT_EQ(__tsan_get_free_bytes(), free0);
EXPECT_EQ(__tsan_get_unmapped_bytes(), unmapped0);
EXPECT_EQ(alloc0, __sanitizer_get_current_allocated_bytes());
EXPECT_GE(__sanitizer_get_heap_size(), heap0);
EXPECT_EQ(free0, __sanitizer_get_free_bytes());
EXPECT_EQ(unmapped0, __sanitizer_get_unmapped_bytes());
}
TEST(Mman, CallocOverflow) {

View File

@ -6,8 +6,8 @@
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <sanitizer/allocator_interface.h>
extern "C" size_t __asan_get_heap_size();
static pthread_key_t tsd_key;
void *Thread(void *) {
@ -30,7 +30,7 @@ int main() {
pthread_t t;
pthread_create(&t, 0, Thread, 0);
pthread_join(t, 0);
size_t new_heap_size = __asan_get_heap_size();
size_t new_heap_size = __sanitizer_get_heap_size();
fprintf(stderr, "heap size: new: %zd old: %zd\n", new_heap_size, old_heap_size);
if (old_heap_size)
assert(old_heap_size == new_heap_size);

View File

@ -4,7 +4,7 @@
#include <assert.h>
#include <pthread.h>
#include <sanitizer/asan_interface.h>
#include <sanitizer/allocator_interface.h>
#include <stdio.h>
#include <stdlib.h>
@ -17,12 +17,12 @@ void* allocate(void *arg) {
}
void* check_stats(void *arg) {
assert(__asan_get_current_allocated_bytes() > 0);
assert(__sanitizer_get_current_allocated_bytes() > 0);
return 0;
}
int main() {
size_t used_mem = __asan_get_current_allocated_bytes();
size_t used_mem = __sanitizer_get_current_allocated_bytes();
printf("Before: %zu\n", used_mem);
const int kNumIterations = 1000;
for (int iter = 0; iter < kNumIterations; iter++) {
@ -33,7 +33,7 @@ int main() {
}
for (int j = 0; j < 4; j++)
assert(0 == pthread_join(thr[j], 0));
used_mem = __asan_get_current_allocated_bytes();
used_mem = __sanitizer_get_current_allocated_bytes();
if (used_mem > kLargeAlloc) {
printf("After iteration %d: %zu\n", iter, used_mem);
return 1;

View File

@ -7,11 +7,12 @@
#include <stdlib.h>
#include <unistd.h>
#include <sanitizer/allocator_interface.h>
static void *glob_ptr;
extern "C" {
void __asan_free_hook(void *ptr) {
void __sanitizer_free_hook(const volatile void *ptr) {
if (ptr == glob_ptr) {
*(int*)ptr = 0;
write(1, "FreeHook\n", sizeof("FreeHook\n"));

View File

@ -6,22 +6,21 @@
#include <stdlib.h>
#include <unistd.h>
#include <sanitizer/allocator_interface.h>
extern "C" {
bool __asan_get_ownership(const void *p);
void *global_ptr;
const volatile void *global_ptr;
// Note: avoid calling functions that allocate memory in malloc/free
// to avoid infinite recursion.
void __asan_malloc_hook(void *ptr, size_t sz) {
if (__asan_get_ownership(ptr)) {
void __sanitizer_malloc_hook(const volatile void *ptr, size_t sz) {
if (__sanitizer_get_ownership(ptr)) {
write(1, "MallocHook\n", sizeof("MallocHook\n"));
global_ptr = ptr;
}
}
void __asan_free_hook(void *ptr) {
if (__asan_get_ownership(ptr) && ptr == global_ptr)
void __sanitizer_free_hook(const volatile void *ptr) {
if (__sanitizer_get_ownership(ptr) && ptr == global_ptr)
write(1, "FreeHook\n", sizeof("FreeHook\n"));
}
} // extern "C"

View File

@ -8,17 +8,17 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <sanitizer/asan_interface.h>
#include <sanitizer/allocator_interface.h>
int main(int argc, char **argv) {
if (argc < 2)
return 1;
bool large_redzone = atoi(argv[1]);
size_t before = __asan_get_heap_size();
size_t before = __sanitizer_get_heap_size();
void *pp[10000];
for (int i = 0; i < 10000; ++i)
pp[i] = malloc(4096 - 64);
size_t after = __asan_get_heap_size();
size_t after = __sanitizer_get_heap_size();
for (int i = 0; i < 10000; ++i)
free(pp[i]);
size_t diff = after - before;

View File

@ -2,22 +2,22 @@
// RUN: %run %t 2>&1 | FileCheck %s
#include <stdlib.h>
#include <unistd.h>
#include <sanitizer/allocator_interface.h>
extern "C" {
int __msan_get_ownership(const void *p);
void *global_ptr;
const volatile void *global_ptr;
// Note: avoid calling functions that allocate memory in malloc/free
// to avoid infinite recursion.
void __msan_malloc_hook(void *ptr, size_t sz) {
if (__msan_get_ownership(ptr)) {
void __sanitizer_malloc_hook(const volatile void *ptr, size_t sz) {
if (__sanitizer_get_ownership(ptr)) {
write(1, "MallocHook\n", sizeof("MallocHook\n"));
global_ptr = ptr;
}
}
void __msan_free_hook(void *ptr) {
if (__msan_get_ownership(ptr) && ptr == global_ptr)
void __sanitizer_free_hook(const volatile void *ptr) {
if (__sanitizer_get_ownership(ptr) && ptr == global_ptr)
write(1, "FreeHook\n", sizeof("FreeHook\n"));
}
} // extern "C"

View File

@ -4,18 +4,19 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <sanitizer/allocator_interface.h>
static int malloc_count;
static int free_count;
extern "C" {
void __tsan_malloc_hook(void *ptr, size_t size) {
void __sanitizer_malloc_hook(const volatile void *ptr, size_t size) {
(void)ptr;
(void)size;
__sync_fetch_and_add(&malloc_count, 1);
}
void __tsan_free_hook(void *ptr) {
void __sanitizer_free_hook(const volatile void *ptr) {
(void)ptr;
__sync_fetch_and_add(&free_count, 1);
}