forked from OSchip/llvm-project
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:
parent
761439962b
commit
91bb8e0e3a
|
@ -1,4 +1,5 @@
|
||||||
set(SANITIZER_HEADERS
|
set(SANITIZER_HEADERS
|
||||||
|
sanitizer/allocator_interface.h
|
||||||
sanitizer/asan_interface.h
|
sanitizer/asan_interface.h
|
||||||
sanitizer/common_interface_defs.h
|
sanitizer/common_interface_defs.h
|
||||||
sanitizer/dfsan_interface.h
|
sanitizer/dfsan_interface.h
|
||||||
|
|
|
@ -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
|
|
@ -87,28 +87,42 @@ extern "C" {
|
||||||
// for request of "size" bytes. If ASan allocator can't allocate that much
|
// for request of "size" bytes. If ASan allocator can't allocate that much
|
||||||
// memory, returns the maximal possible allocation size, otherwise returns
|
// memory, returns the maximal possible allocation size, otherwise returns
|
||||||
// "size".
|
// "size".
|
||||||
|
/* DEPRECATED: Use __sanitizer_get_estimated_allocated_size instead. */
|
||||||
size_t __asan_get_estimated_allocated_size(size_t size);
|
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.
|
// Returns 1 if p was returned by the ASan allocator and is not yet freed.
|
||||||
// Otherwise returns 0.
|
// Otherwise returns 0.
|
||||||
|
/* DEPRECATED: Use __sanitizer_get_ownership instead. */
|
||||||
int __asan_get_ownership(const void *p);
|
int __asan_get_ownership(const void *p);
|
||||||
|
|
||||||
// Returns the number of bytes reserved for the pointer p.
|
// Returns the number of bytes reserved for the pointer p.
|
||||||
// Requires (get_ownership(p) == true) or (p == 0).
|
// Requires (get_ownership(p) == true) or (p == 0).
|
||||||
|
/* DEPRECATED: Use __sanitizer_get_allocated_size instead. */
|
||||||
size_t __asan_get_allocated_size(const void *p);
|
size_t __asan_get_allocated_size(const void *p);
|
||||||
|
|
||||||
// Number of bytes, allocated and not yet freed by the application.
|
// 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();
|
size_t __asan_get_current_allocated_bytes();
|
||||||
|
|
||||||
// Number of bytes, mmaped by asan allocator to fulfill allocation requests.
|
// Number of bytes, mmaped by asan allocator to fulfill allocation requests.
|
||||||
// Generally, for request of X bytes, allocator can reserve and add to free
|
// 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.
|
// 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
|
// All these chunks count toward the heap size. Currently, allocator never
|
||||||
// releases memory to OS (instead, it just puts freed chunks to free lists).
|
// 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();
|
size_t __asan_get_heap_size();
|
||||||
|
|
||||||
// Number of bytes, mmaped by asan allocator, which can be used to fulfill
|
// 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
|
// allocation requests. When a user program frees memory chunk, it can first
|
||||||
// fall into quarantine and will count toward __asan_get_free_bytes() later.
|
// 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();
|
size_t __asan_get_free_bytes();
|
||||||
|
|
||||||
// Number of bytes in unmapped pages, that are released to OS. Currently,
|
// Number of bytes in unmapped pages, that are released to OS. Currently,
|
||||||
// always returns 0.
|
// always returns 0.
|
||||||
|
/* DEPRECATED: Use __sanitizer_get_unmapped_bytes instead. */
|
||||||
size_t __asan_get_unmapped_bytes();
|
size_t __asan_get_unmapped_bytes();
|
||||||
|
|
||||||
// Prints accumulated stats to stderr. Used for debugging.
|
// Prints accumulated stats to stderr. Used for debugging.
|
||||||
void __asan_print_accumulated_stats();
|
void __asan_print_accumulated_stats();
|
||||||
|
|
||||||
|
@ -121,6 +135,7 @@ extern "C" {
|
||||||
// allocation of "size" bytes, which returned "ptr".
|
// allocation of "size" bytes, which returned "ptr".
|
||||||
// __asan_free_hook(ptr) is called immediately before
|
// __asan_free_hook(ptr) is called immediately before
|
||||||
// deallocation of "ptr".
|
// deallocation of "ptr".
|
||||||
|
/* DEPRECATED: Use __sanitizer_malloc_hook / __sanitizer_free_hook instead. */
|
||||||
void __asan_malloc_hook(void *ptr, size_t size);
|
void __asan_malloc_hook(void *ptr, size_t size);
|
||||||
void __asan_free_hook(void *ptr);
|
void __asan_free_hook(void *ptr);
|
||||||
|
|
||||||
|
|
|
@ -89,8 +89,8 @@ extern "C" {
|
||||||
a string containing Msan runtime options. See msan_flags.h for details. */
|
a string containing Msan runtime options. See msan_flags.h for details. */
|
||||||
const char* __msan_default_options();
|
const char* __msan_default_options();
|
||||||
|
|
||||||
// Sets the callback to be called right before death on error.
|
/* Sets the callback to be called right before death on error.
|
||||||
// Passing 0 will unset the callback.
|
Passing 0 will unset the callback. */
|
||||||
void __msan_set_death_callback(void (*callback)(void));
|
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
|
for request of "size" bytes. If Msan allocator can't allocate that much
|
||||||
memory, returns the maximal possible allocation size, otherwise returns
|
memory, returns the maximal possible allocation size, otherwise returns
|
||||||
"size". */
|
"size". */
|
||||||
|
/* DEPRECATED: Use __sanitizer_get_estimated_allocated_size instead. */
|
||||||
size_t __msan_get_estimated_allocated_size(size_t size);
|
size_t __msan_get_estimated_allocated_size(size_t size);
|
||||||
|
|
||||||
/* Returns true if p was returned by the Msan allocator and
|
/* Returns true if p was returned by the Msan allocator and
|
||||||
is not yet freed. */
|
is not yet freed. */
|
||||||
|
/* DEPRECATED: Use __sanitizer_get_ownership instead. */
|
||||||
int __msan_get_ownership(const volatile void *p);
|
int __msan_get_ownership(const volatile void *p);
|
||||||
|
|
||||||
/* Returns the number of bytes reserved for the pointer p.
|
/* Returns the number of bytes reserved for the pointer p.
|
||||||
Requires (get_ownership(p) == true) or (p == 0). */
|
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);
|
size_t __msan_get_allocated_size(const volatile void *p);
|
||||||
|
|
||||||
/* Number of bytes, allocated and not yet freed by the application. */
|
/* 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();
|
size_t __msan_get_current_allocated_bytes();
|
||||||
|
|
||||||
/* Number of bytes, mmaped by msan allocator to fulfill allocation requests.
|
/* 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
|
All these chunks count toward the heap size. Currently, allocator never
|
||||||
releases memory to OS (instead, it just puts freed chunks to free
|
releases memory to OS (instead, it just puts freed chunks to free
|
||||||
lists). */
|
lists). */
|
||||||
|
/* DEPRECATED: Use __sanitizer_get_heap_size instead. */
|
||||||
size_t __msan_get_heap_size();
|
size_t __msan_get_heap_size();
|
||||||
|
|
||||||
/* Number of bytes, mmaped by msan allocator, which can be used to fulfill
|
/* 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
|
allocation requests. When a user program frees memory chunk, it can first
|
||||||
fall into quarantine and will count toward __msan_get_free_bytes()
|
fall into quarantine and will count toward __msan_get_free_bytes()
|
||||||
later. */
|
later. */
|
||||||
|
/* DEPRECATED: Use __sanitizer_get_free_bytes instead. */
|
||||||
size_t __msan_get_free_bytes();
|
size_t __msan_get_free_bytes();
|
||||||
|
|
||||||
/* Number of bytes in unmapped pages, that are released to OS. Currently,
|
/* Number of bytes in unmapped pages, that are released to OS. Currently,
|
||||||
always returns 0. */
|
always returns 0. */
|
||||||
|
/* DEPRECATED: Use __sanitizer_get_unmapped_bytes instead. */
|
||||||
size_t __msan_get_unmapped_bytes();
|
size_t __msan_get_unmapped_bytes();
|
||||||
|
|
||||||
/* Malloc hooks that may be optionally provided by user.
|
/* Malloc hooks that may be optionally provided by user.
|
||||||
|
@ -136,8 +143,10 @@ extern "C" {
|
||||||
allocation of "size" bytes, which returned "ptr".
|
allocation of "size" bytes, which returned "ptr".
|
||||||
__msan_free_hook(ptr) is called immediately before
|
__msan_free_hook(ptr) is called immediately before
|
||||||
deallocation of "ptr". */
|
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_malloc_hook(const volatile void *ptr, size_t size);
|
||||||
void __msan_free_hook(const volatile void *ptr);
|
void __msan_free_hook(const volatile void *ptr);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include "asan_report.h"
|
#include "asan_report.h"
|
||||||
#include "asan_stack.h"
|
#include "asan_stack.h"
|
||||||
#include "asan_thread.h"
|
#include "asan_thread.h"
|
||||||
|
#include "sanitizer_common/sanitizer_allocator_interface.h"
|
||||||
#include "sanitizer_common/sanitizer_flags.h"
|
#include "sanitizer_common/sanitizer_flags.h"
|
||||||
#include "sanitizer_common/sanitizer_internal_defs.h"
|
#include "sanitizer_common/sanitizer_internal_defs.h"
|
||||||
#include "sanitizer_common/sanitizer_list.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
|
// 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.
|
// 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;
|
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);
|
uptr ptr = reinterpret_cast<uptr>(p);
|
||||||
return (AllocationSize(ptr) > 0);
|
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;
|
if (p == 0) return 0;
|
||||||
uptr ptr = reinterpret_cast<uptr>(p);
|
uptr ptr = reinterpret_cast<uptr>(p);
|
||||||
uptr allocated_size = AllocationSize(ptr);
|
uptr allocated_size = AllocationSize(ptr);
|
||||||
// Die if p is not malloced or if it is already freed.
|
// Die if p is not malloced or if it is already freed.
|
||||||
if (allocated_size == 0) {
|
if (allocated_size == 0) {
|
||||||
GET_STACK_TRACE_FATAL_HERE;
|
GET_STACK_TRACE_FATAL_HERE;
|
||||||
ReportAsanGetAllocatedSizeNotOwned(ptr, &stack);
|
ReportSanitizerGetAllocatedSizeNotOwned(ptr, &stack);
|
||||||
}
|
}
|
||||||
return allocated_size;
|
return allocated_size;
|
||||||
}
|
}
|
||||||
|
uptr __asan_get_allocated_size(const void *p) {
|
||||||
|
return __sanitizer_get_allocated_size(p);
|
||||||
|
}
|
||||||
|
|
||||||
#if !SANITIZER_SUPPORTS_WEAK_HOOKS
|
#if !SANITIZER_SUPPORTS_WEAK_HOOKS
|
||||||
// Provide default (no-op) implementation of malloc 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 __asan_free_hook(void *ptr) {
|
||||||
(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"
|
} // extern "C"
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -110,24 +110,26 @@ extern "C" {
|
||||||
SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
|
SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
|
||||||
/* OPTIONAL */ void __asan_on_error();
|
/* OPTIONAL */ void __asan_on_error();
|
||||||
|
|
||||||
|
// ---------------------------
|
||||||
|
// FIXME: Replace these functions with __sanitizer equivalent.
|
||||||
SANITIZER_INTERFACE_ATTRIBUTE
|
SANITIZER_INTERFACE_ATTRIBUTE
|
||||||
uptr __asan_get_estimated_allocated_size(uptr size);
|
uptr __asan_get_estimated_allocated_size(uptr size);
|
||||||
|
|
||||||
SANITIZER_INTERFACE_ATTRIBUTE int __asan_get_ownership(const void *p);
|
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_allocated_size(const void *p);
|
||||||
SANITIZER_INTERFACE_ATTRIBUTE uptr __asan_get_current_allocated_bytes();
|
SANITIZER_INTERFACE_ATTRIBUTE uptr __asan_get_current_allocated_bytes();
|
||||||
SANITIZER_INTERFACE_ATTRIBUTE uptr __asan_get_heap_size();
|
SANITIZER_INTERFACE_ATTRIBUTE uptr __asan_get_heap_size();
|
||||||
SANITIZER_INTERFACE_ATTRIBUTE uptr __asan_get_free_bytes();
|
SANITIZER_INTERFACE_ATTRIBUTE uptr __asan_get_free_bytes();
|
||||||
SANITIZER_INTERFACE_ATTRIBUTE uptr __asan_get_unmapped_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
|
SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
|
||||||
/* OPTIONAL */ void __asan_malloc_hook(void *ptr, uptr size);
|
/* OPTIONAL */ void __asan_malloc_hook(void *ptr, uptr size);
|
||||||
SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
|
SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
|
||||||
/* OPTIONAL */ void __asan_free_hook(void *ptr);
|
/* 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
|
// Global flag, copy of ASAN_OPTIONS=detect_stack_use_after_return
|
||||||
SANITIZER_INTERFACE_ATTRIBUTE
|
SANITIZER_INTERFACE_ATTRIBUTE
|
||||||
|
|
|
@ -112,9 +112,11 @@ bool PlatformHasDifferentMemcpyAndMemmove();
|
||||||
// Add convenient macro for interface functions that may be represented as
|
// Add convenient macro for interface functions that may be represented as
|
||||||
// weak hooks.
|
// weak hooks.
|
||||||
#define ASAN_MALLOC_HOOK(ptr, size) \
|
#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) \
|
#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() \
|
#define ASAN_ON_ERROR() \
|
||||||
if (&__asan_on_error) __asan_on_error()
|
if (&__asan_on_error) __asan_on_error()
|
||||||
|
|
||||||
|
|
|
@ -698,17 +698,17 @@ void ReportMallocUsableSizeNotOwned(uptr addr, StackTrace *stack) {
|
||||||
ReportErrorSummary("bad-malloc_usable_size", stack);
|
ReportErrorSummary("bad-malloc_usable_size", stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReportAsanGetAllocatedSizeNotOwned(uptr addr, StackTrace *stack) {
|
void ReportSanitizerGetAllocatedSizeNotOwned(uptr addr, StackTrace *stack) {
|
||||||
ScopedInErrorReport in_report;
|
ScopedInErrorReport in_report;
|
||||||
Decorator d;
|
Decorator d;
|
||||||
Printf("%s", d.Warning());
|
Printf("%s", d.Warning());
|
||||||
Report("ERROR: AddressSanitizer: attempting to call "
|
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);
|
"not owned: %p\n", addr);
|
||||||
Printf("%s", d.EndWarning());
|
Printf("%s", d.EndWarning());
|
||||||
stack->Print();
|
stack->Print();
|
||||||
DescribeHeapAddress(addr, 1);
|
DescribeHeapAddress(addr, 1);
|
||||||
ReportErrorSummary("bad-__asan_get_allocated_size", stack);
|
ReportErrorSummary("bad-__sanitizer_get_allocated_size", stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReportStringFunctionMemoryRangesOverlap(
|
void ReportStringFunctionMemoryRangesOverlap(
|
||||||
|
|
|
@ -43,8 +43,8 @@ void NORETURN ReportAllocTypeMismatch(uptr addr, StackTrace *free_stack,
|
||||||
AllocType dealloc_type);
|
AllocType dealloc_type);
|
||||||
void NORETURN ReportMallocUsableSizeNotOwned(uptr addr,
|
void NORETURN ReportMallocUsableSizeNotOwned(uptr addr,
|
||||||
StackTrace *stack);
|
StackTrace *stack);
|
||||||
void NORETURN ReportAsanGetAllocatedSizeNotOwned(uptr addr,
|
void NORETURN
|
||||||
StackTrace *stack);
|
ReportSanitizerGetAllocatedSizeNotOwned(uptr addr, StackTrace *stack);
|
||||||
void NORETURN ReportStringFunctionMemoryRangesOverlap(
|
void NORETURN ReportStringFunctionMemoryRangesOverlap(
|
||||||
const char *function, const char *offset1, uptr length1,
|
const char *function, const char *offset1, uptr length1,
|
||||||
const char *offset2, uptr length2, StackTrace *stack);
|
const char *offset2, uptr length2, StackTrace *stack);
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include "asan_internal.h"
|
#include "asan_internal.h"
|
||||||
#include "asan_stats.h"
|
#include "asan_stats.h"
|
||||||
#include "asan_thread.h"
|
#include "asan_thread.h"
|
||||||
|
#include "sanitizer_common/sanitizer_allocator_interface.h"
|
||||||
#include "sanitizer_common/sanitizer_mutex.h"
|
#include "sanitizer_common/sanitizer_mutex.h"
|
||||||
#include "sanitizer_common/sanitizer_stackdepot.h"
|
#include "sanitizer_common/sanitizer_stackdepot.h"
|
||||||
|
|
||||||
|
@ -139,7 +140,7 @@ static void PrintAccumulatedStats() {
|
||||||
// ---------------------- Interface ---------------- {{{1
|
// ---------------------- Interface ---------------- {{{1
|
||||||
using namespace __asan; // NOLINT
|
using namespace __asan; // NOLINT
|
||||||
|
|
||||||
uptr __asan_get_current_allocated_bytes() {
|
uptr __sanitizer_get_current_allocated_bytes() {
|
||||||
AsanStats stats;
|
AsanStats stats;
|
||||||
GetAccumulatedStats(&stats);
|
GetAccumulatedStats(&stats);
|
||||||
uptr malloced = stats.malloced;
|
uptr malloced = stats.malloced;
|
||||||
|
@ -148,14 +149,20 @@ uptr __asan_get_current_allocated_bytes() {
|
||||||
// way we update accumulated stats.
|
// way we update accumulated stats.
|
||||||
return (malloced > freed) ? malloced - freed : 1;
|
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;
|
AsanStats stats;
|
||||||
GetAccumulatedStats(&stats);
|
GetAccumulatedStats(&stats);
|
||||||
return stats.mmaped - stats.munmaped;
|
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;
|
AsanStats stats;
|
||||||
GetAccumulatedStats(&stats);
|
GetAccumulatedStats(&stats);
|
||||||
uptr total_free = stats.mmaped
|
uptr total_free = stats.mmaped
|
||||||
|
@ -168,10 +175,16 @@ uptr __asan_get_free_bytes() {
|
||||||
// way we update accumulated stats.
|
// way we update accumulated stats.
|
||||||
return (total_free > total_used) ? total_free - total_used : 1;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
uptr __asan_get_unmapped_bytes() {
|
||||||
|
return __sanitizer_get_unmapped_bytes();
|
||||||
|
}
|
||||||
|
|
||||||
void __asan_print_accumulated_stats() {
|
void __asan_print_accumulated_stats() {
|
||||||
PrintAccumulatedStats();
|
PrintAccumulatedStats();
|
||||||
|
|
|
@ -11,18 +11,19 @@
|
||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
#include "asan_test_utils.h"
|
#include "asan_test_utils.h"
|
||||||
#include "sanitizer/asan_interface.h"
|
#include <sanitizer/allocator_interface.h>
|
||||||
|
#include <sanitizer/asan_interface.h>
|
||||||
|
|
||||||
TEST(AddressSanitizerInterface, GetEstimatedAllocatedSize) {
|
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 };
|
const size_t sizes[] = { 1, 30, 1<<30 };
|
||||||
for (size_t i = 0; i < 3; i++) {
|
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 =
|
static const char* kGetAllocatedSizeErrorMsg =
|
||||||
"attempting to call __asan_get_allocated_size";
|
"attempting to call __sanitizer_get_allocated_size";
|
||||||
|
|
||||||
TEST(AddressSanitizerInterface, GetAllocatedSizeAndOwnershipTest) {
|
TEST(AddressSanitizerInterface, GetAllocatedSizeAndOwnershipTest) {
|
||||||
const size_t kArraySize = 100;
|
const size_t kArraySize = 100;
|
||||||
|
@ -31,38 +32,41 @@ TEST(AddressSanitizerInterface, GetAllocatedSizeAndOwnershipTest) {
|
||||||
|
|
||||||
// Allocated memory is owned by allocator. Allocated size should be
|
// Allocated memory is owned by allocator. Allocated size should be
|
||||||
// equal to requested size.
|
// equal to requested size.
|
||||||
EXPECT_EQ(true, __asan_get_ownership(array));
|
EXPECT_EQ(true, __sanitizer_get_ownership(array));
|
||||||
EXPECT_EQ(kArraySize, __asan_get_allocated_size(array));
|
EXPECT_EQ(kArraySize, __sanitizer_get_allocated_size(array));
|
||||||
EXPECT_EQ(true, __asan_get_ownership(int_ptr));
|
EXPECT_EQ(true, __sanitizer_get_ownership(int_ptr));
|
||||||
EXPECT_EQ(sizeof(int), __asan_get_allocated_size(int_ptr));
|
EXPECT_EQ(sizeof(int), __sanitizer_get_allocated_size(int_ptr));
|
||||||
|
|
||||||
// We cannot call GetAllocatedSize from the memory we didn't map,
|
// We cannot call GetAllocatedSize from the memory we didn't map,
|
||||||
// and from the interior pointers (not returned by previous malloc).
|
// and from the interior pointers (not returned by previous malloc).
|
||||||
void *wild_addr = (void*)0x1;
|
void *wild_addr = (void*)0x1;
|
||||||
EXPECT_FALSE(__asan_get_ownership(wild_addr));
|
EXPECT_FALSE(__sanitizer_get_ownership(wild_addr));
|
||||||
EXPECT_DEATH(__asan_get_allocated_size(wild_addr), kGetAllocatedSizeErrorMsg);
|
EXPECT_DEATH(__sanitizer_get_allocated_size(wild_addr),
|
||||||
EXPECT_FALSE(__asan_get_ownership(array + kArraySize / 2));
|
kGetAllocatedSizeErrorMsg);
|
||||||
EXPECT_DEATH(__asan_get_allocated_size(array + kArraySize / 2),
|
EXPECT_FALSE(__sanitizer_get_ownership(array + kArraySize / 2));
|
||||||
|
EXPECT_DEATH(__sanitizer_get_allocated_size(array + kArraySize / 2),
|
||||||
kGetAllocatedSizeErrorMsg);
|
kGetAllocatedSizeErrorMsg);
|
||||||
|
|
||||||
// NULL is not owned, but is a valid argument for __asan_get_allocated_size().
|
// NULL is not owned, but is a valid argument for
|
||||||
EXPECT_FALSE(__asan_get_ownership(NULL));
|
// __sanitizer_get_allocated_size().
|
||||||
EXPECT_EQ(0U, __asan_get_allocated_size(NULL));
|
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
|
// When memory is freed, it's not owned, and call to GetAllocatedSize
|
||||||
// is forbidden.
|
// is forbidden.
|
||||||
free(array);
|
free(array);
|
||||||
EXPECT_FALSE(__asan_get_ownership(array));
|
EXPECT_FALSE(__sanitizer_get_ownership(array));
|
||||||
EXPECT_DEATH(__asan_get_allocated_size(array), kGetAllocatedSizeErrorMsg);
|
EXPECT_DEATH(__sanitizer_get_allocated_size(array),
|
||||||
|
kGetAllocatedSizeErrorMsg);
|
||||||
delete int_ptr;
|
delete int_ptr;
|
||||||
|
|
||||||
void *zero_alloc = Ident(malloc(0));
|
void *zero_alloc = Ident(malloc(0));
|
||||||
if (zero_alloc != 0) {
|
if (zero_alloc != 0) {
|
||||||
// If malloc(0) is not null, this pointer is owned and should have valid
|
// If malloc(0) is not null, this pointer is owned and should have valid
|
||||||
// allocated size.
|
// 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.
|
// 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);
|
free(zero_alloc);
|
||||||
}
|
}
|
||||||
|
@ -71,14 +75,14 @@ TEST(AddressSanitizerInterface, GetCurrentAllocatedBytesTest) {
|
||||||
size_t before_malloc, after_malloc, after_free;
|
size_t before_malloc, after_malloc, after_free;
|
||||||
char *array;
|
char *array;
|
||||||
const size_t kMallocSize = 100;
|
const size_t kMallocSize = 100;
|
||||||
before_malloc = __asan_get_current_allocated_bytes();
|
before_malloc = __sanitizer_get_current_allocated_bytes();
|
||||||
|
|
||||||
array = Ident((char*)malloc(kMallocSize));
|
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);
|
EXPECT_EQ(before_malloc + kMallocSize, after_malloc);
|
||||||
|
|
||||||
free(array);
|
free(array);
|
||||||
after_free = __asan_get_current_allocated_bytes();
|
after_free = __sanitizer_get_current_allocated_bytes();
|
||||||
EXPECT_EQ(before_malloc, after_free);
|
EXPECT_EQ(before_malloc, after_free);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,11 +92,11 @@ TEST(AddressSanitizerInterface, GetHeapSizeTest) {
|
||||||
// otherwise it will be stuck in quarantine instead of being unmaped.
|
// otherwise it will be stuck in quarantine instead of being unmaped.
|
||||||
static const size_t kLargeMallocSize = (1 << 28) + 1; // 256M
|
static const size_t kLargeMallocSize = (1 << 28) + 1; // 256M
|
||||||
free(Ident(malloc(kLargeMallocSize))); // Drain quarantine.
|
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++) {
|
for (int i = 0; i < 3; i++) {
|
||||||
// fprintf(stderr, "allocating %zu bytes:\n", kLargeMallocSize);
|
// fprintf(stderr, "allocating %zu bytes:\n", kLargeMallocSize);
|
||||||
free(Ident(malloc(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) {
|
TEST(AddressSanitizerInterface, ManyThreadsWithStatsStressTest) {
|
||||||
size_t before_test, after_test, i;
|
size_t before_test, after_test, i;
|
||||||
pthread_t threads[kManyThreadsNumThreads];
|
pthread_t threads[kManyThreadsNumThreads];
|
||||||
before_test = __asan_get_current_allocated_bytes();
|
before_test = __sanitizer_get_current_allocated_bytes();
|
||||||
for (i = 0; i < kManyThreadsNumThreads; i++) {
|
for (i = 0; i < kManyThreadsNumThreads; i++) {
|
||||||
PTHREAD_CREATE(&threads[i], 0,
|
PTHREAD_CREATE(&threads[i], 0,
|
||||||
(void* (*)(void *x))ManyThreadsWithStatsWorker, (void*)i);
|
(void* (*)(void *x))ManyThreadsWithStatsWorker, (void*)i);
|
||||||
|
@ -124,7 +128,7 @@ TEST(AddressSanitizerInterface, ManyThreadsWithStatsStressTest) {
|
||||||
for (i = 0; i < kManyThreadsNumThreads; i++) {
|
for (i = 0; i < kManyThreadsNumThreads; i++) {
|
||||||
PTHREAD_JOIN(threads[i], 0);
|
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,
|
// ASan stats also reflect memory usage of internal ASan RTL structs,
|
||||||
// so we can't check for equality here.
|
// so we can't check for equality here.
|
||||||
EXPECT_LT(after_test, before_test + (1UL<<20));
|
EXPECT_LT(after_test, before_test + (1UL<<20));
|
||||||
|
@ -417,11 +421,11 @@ TEST(AddressSanitizerInterface, GetOwnershipStressTest) {
|
||||||
sizes.push_back(size);
|
sizes.push_back(size);
|
||||||
}
|
}
|
||||||
for (size_t i = 0; i < 4000000; i++) {
|
for (size_t i = 0; i < 4000000; i++) {
|
||||||
EXPECT_FALSE(__asan_get_ownership(&pointers));
|
EXPECT_FALSE(__sanitizer_get_ownership(&pointers));
|
||||||
EXPECT_FALSE(__asan_get_ownership((void*)0x1234));
|
EXPECT_FALSE(__sanitizer_get_ownership((void*)0x1234));
|
||||||
size_t idx = i % kNumMallocs;
|
size_t idx = i % kNumMallocs;
|
||||||
EXPECT_TRUE(__asan_get_ownership(pointers[idx]));
|
EXPECT_TRUE(__sanitizer_get_ownership(pointers[idx]));
|
||||||
EXPECT_EQ(sizes[idx], __asan_get_allocated_size(pointers[idx]));
|
EXPECT_EQ(sizes[idx], __sanitizer_get_allocated_size(pointers[idx]));
|
||||||
}
|
}
|
||||||
for (size_t i = 0, n = pointers.size(); i < n; i++)
|
for (size_t i = 0, n = pointers.size(); i < n; i++)
|
||||||
free(pointers[i]);
|
free(pointers[i]);
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include "asan_internal.h"
|
#include "asan_internal.h"
|
||||||
#include "asan_mapping.h"
|
#include "asan_mapping.h"
|
||||||
#include "asan_test_utils.h"
|
#include "asan_test_utils.h"
|
||||||
|
#include <sanitizer/allocator_interface.h>
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -175,12 +176,12 @@ void *ThreadedQuarantineTestWorker(void *unused) {
|
||||||
// destroyed.
|
// destroyed.
|
||||||
TEST(AddressSanitizer, ThreadedQuarantineTest) {
|
TEST(AddressSanitizer, ThreadedQuarantineTest) {
|
||||||
const int n_threads = 3000;
|
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++) {
|
for (int i = 0; i < n_threads; i++) {
|
||||||
pthread_t t;
|
pthread_t t;
|
||||||
PTHREAD_CREATE(&t, NULL, ThreadedQuarantineTestWorker, 0);
|
PTHREAD_CREATE(&t, NULL, ThreadedQuarantineTestWorker, 0);
|
||||||
PTHREAD_JOIN(t, 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));
|
EXPECT_LT(mmaped2 - mmaped1, 320U * (1 << 20));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -141,8 +141,10 @@ void MsanTSDDtor(void *tsd);
|
||||||
} // namespace __msan
|
} // namespace __msan
|
||||||
|
|
||||||
#define MSAN_MALLOC_HOOK(ptr, size) \
|
#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) \
|
#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
|
#endif // MSAN_H
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#include "sanitizer_common/sanitizer_allocator.h"
|
#include "sanitizer_common/sanitizer_allocator.h"
|
||||||
|
#include "sanitizer_common/sanitizer_allocator_interface.h"
|
||||||
#include "sanitizer_common/sanitizer_stackdepot.h"
|
#include "sanitizer_common/sanitizer_stackdepot.h"
|
||||||
#include "msan.h"
|
#include "msan.h"
|
||||||
#include "msan_allocator.h"
|
#include "msan_allocator.h"
|
||||||
|
@ -182,24 +183,45 @@ static uptr AllocationSize(const void *p) {
|
||||||
|
|
||||||
using namespace __msan;
|
using namespace __msan;
|
||||||
|
|
||||||
uptr __msan_get_current_allocated_bytes() {
|
uptr __sanitizer_get_current_allocated_bytes() {
|
||||||
uptr stats[AllocatorStatCount];
|
uptr stats[AllocatorStatCount];
|
||||||
allocator.GetStats(stats);
|
allocator.GetStats(stats);
|
||||||
return stats[AllocatorStatAllocated];
|
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];
|
uptr stats[AllocatorStatCount];
|
||||||
allocator.GetStats(stats);
|
allocator.GetStats(stats);
|
||||||
return stats[AllocatorStatMapped];
|
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);
|
||||||
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include "msan_thread.h"
|
#include "msan_thread.h"
|
||||||
#include "sanitizer_common/sanitizer_platform_limits_posix.h"
|
#include "sanitizer_common/sanitizer_platform_limits_posix.h"
|
||||||
#include "sanitizer_common/sanitizer_allocator.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_allocator_internal.h"
|
||||||
#include "sanitizer_common/sanitizer_atomic.h"
|
#include "sanitizer_common/sanitizer_atomic.h"
|
||||||
#include "sanitizer_common/sanitizer_common.h"
|
#include "sanitizer_common/sanitizer_common.h"
|
||||||
|
@ -208,7 +209,7 @@ INTERCEPTOR(void, cfree, void *ptr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERCEPTOR(uptr, malloc_usable_size, 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
|
// This function actually returns a struct by value, but we can't unpoison a
|
||||||
|
|
|
@ -161,32 +161,27 @@ void __sanitizer_unaligned_store32(uu32 *p, u32 x);
|
||||||
SANITIZER_INTERFACE_ATTRIBUTE
|
SANITIZER_INTERFACE_ATTRIBUTE
|
||||||
void __sanitizer_unaligned_store64(uu64 *p, u64 x);
|
void __sanitizer_unaligned_store64(uu64 *p, u64 x);
|
||||||
|
|
||||||
|
// ---------------------------
|
||||||
|
// FIXME: Replace these functions with __sanitizer equivalent.
|
||||||
SANITIZER_INTERFACE_ATTRIBUTE
|
SANITIZER_INTERFACE_ATTRIBUTE
|
||||||
uptr __msan_get_estimated_allocated_size(uptr size);
|
uptr __msan_get_estimated_allocated_size(uptr size);
|
||||||
|
|
||||||
SANITIZER_INTERFACE_ATTRIBUTE
|
SANITIZER_INTERFACE_ATTRIBUTE
|
||||||
int __msan_get_ownership(const void *p);
|
int __msan_get_ownership(const void *p);
|
||||||
|
|
||||||
SANITIZER_INTERFACE_ATTRIBUTE
|
SANITIZER_INTERFACE_ATTRIBUTE
|
||||||
uptr __msan_get_allocated_size(const void *p);
|
uptr __msan_get_allocated_size(const void *p);
|
||||||
|
|
||||||
SANITIZER_INTERFACE_ATTRIBUTE
|
SANITIZER_INTERFACE_ATTRIBUTE
|
||||||
uptr __msan_get_current_allocated_bytes();
|
uptr __msan_get_current_allocated_bytes();
|
||||||
|
|
||||||
SANITIZER_INTERFACE_ATTRIBUTE
|
SANITIZER_INTERFACE_ATTRIBUTE
|
||||||
uptr __msan_get_heap_size();
|
uptr __msan_get_heap_size();
|
||||||
|
|
||||||
SANITIZER_INTERFACE_ATTRIBUTE
|
SANITIZER_INTERFACE_ATTRIBUTE
|
||||||
uptr __msan_get_free_bytes();
|
uptr __msan_get_free_bytes();
|
||||||
|
|
||||||
SANITIZER_INTERFACE_ATTRIBUTE
|
SANITIZER_INTERFACE_ATTRIBUTE
|
||||||
uptr __msan_get_unmapped_bytes();
|
uptr __msan_get_unmapped_bytes();
|
||||||
|
|
||||||
SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
|
SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
|
||||||
/* OPTIONAL */ void __msan_malloc_hook(void *ptr, uptr size);
|
/* OPTIONAL */ void __msan_malloc_hook(void *ptr, uptr size);
|
||||||
|
|
||||||
SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
|
SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
|
||||||
/* OPTIONAL */ void __msan_free_hook(void *ptr);
|
/* OPTIONAL */ void __msan_free_hook(void *ptr);
|
||||||
|
// ---------------------------
|
||||||
|
|
||||||
SANITIZER_INTERFACE_ATTRIBUTE
|
SANITIZER_INTERFACE_ATTRIBUTE
|
||||||
void __msan_dr_is_initialized();
|
void __msan_dr_is_initialized();
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
|
|
||||||
#include "sanitizer_common/tests/sanitizer_test_utils.h"
|
#include "sanitizer_common/tests/sanitizer_test_utils.h"
|
||||||
|
|
||||||
|
#include "sanitizer/allocator_interface.h"
|
||||||
#include "sanitizer/msan_interface.h"
|
#include "sanitizer/msan_interface.h"
|
||||||
#include "msandr_test_so.h"
|
#include "msandr_test_so.h"
|
||||||
|
|
||||||
|
@ -3022,12 +3023,12 @@ TEST(MemorySanitizer, valloc) {
|
||||||
TEST(MemorySanitizer, pvalloc) {
|
TEST(MemorySanitizer, pvalloc) {
|
||||||
void *p = pvalloc(kPageSize + 100);
|
void *p = pvalloc(kPageSize + 100);
|
||||||
EXPECT_EQ(0U, (uintptr_t)p % kPageSize);
|
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);
|
free(p);
|
||||||
|
|
||||||
p = pvalloc(0); // pvalloc(0) should allocate at least one page.
|
p = pvalloc(0); // pvalloc(0) should allocate at least one page.
|
||||||
EXPECT_EQ(0U, (uintptr_t)p % kPageSize);
|
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);
|
free(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4076,7 +4077,7 @@ TEST(MemorySanitizerStress, DISABLED_MallocStackTrace) {
|
||||||
TEST(MemorySanitizerAllocator, get_estimated_allocated_size) {
|
TEST(MemorySanitizerAllocator, get_estimated_allocated_size) {
|
||||||
size_t sizes[] = {0, 20, 5000, 1<<20};
|
size_t sizes[] = {0, 20, 5000, 1<<20};
|
||||||
for (size_t i = 0; i < sizeof(sizes) / sizeof(*sizes); ++i) {
|
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]);
|
EXPECT_EQ(alloc_size, sizes[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4085,26 +4086,26 @@ TEST(MemorySanitizerAllocator, get_allocated_size_and_ownership) {
|
||||||
char *array = reinterpret_cast<char*>(malloc(100));
|
char *array = reinterpret_cast<char*>(malloc(100));
|
||||||
int *int_ptr = new int;
|
int *int_ptr = new int;
|
||||||
|
|
||||||
EXPECT_TRUE(__msan_get_ownership(array));
|
EXPECT_TRUE(__sanitizer_get_ownership(array));
|
||||||
EXPECT_EQ(100U, __msan_get_allocated_size(array));
|
EXPECT_EQ(100U, __sanitizer_get_allocated_size(array));
|
||||||
|
|
||||||
EXPECT_TRUE(__msan_get_ownership(int_ptr));
|
EXPECT_TRUE(__sanitizer_get_ownership(int_ptr));
|
||||||
EXPECT_EQ(sizeof(*int_ptr), __msan_get_allocated_size(int_ptr));
|
EXPECT_EQ(sizeof(*int_ptr), __sanitizer_get_allocated_size(int_ptr));
|
||||||
|
|
||||||
void *wild_addr = reinterpret_cast<void*>(0x1);
|
void *wild_addr = reinterpret_cast<void*>(0x1);
|
||||||
EXPECT_FALSE(__msan_get_ownership(wild_addr));
|
EXPECT_FALSE(__sanitizer_get_ownership(wild_addr));
|
||||||
EXPECT_EQ(0U, __msan_get_allocated_size(wild_addr));
|
EXPECT_EQ(0U, __sanitizer_get_allocated_size(wild_addr));
|
||||||
|
|
||||||
EXPECT_FALSE(__msan_get_ownership(array + 50));
|
EXPECT_FALSE(__sanitizer_get_ownership(array + 50));
|
||||||
EXPECT_EQ(0U, __msan_get_allocated_size(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);
|
free(array);
|
||||||
EXPECT_FALSE(__msan_get_ownership(array));
|
EXPECT_FALSE(__sanitizer_get_ownership(array));
|
||||||
EXPECT_EQ(0U, __msan_get_allocated_size(array));
|
EXPECT_EQ(0U, __sanitizer_get_allocated_size(array));
|
||||||
|
|
||||||
delete int_ptr;
|
delete int_ptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,6 +45,7 @@ set(SANITIZER_LIBCDEP_SOURCES
|
||||||
set(SANITIZER_HEADERS
|
set(SANITIZER_HEADERS
|
||||||
sanitizer_addrhashmap.h
|
sanitizer_addrhashmap.h
|
||||||
sanitizer_allocator.h
|
sanitizer_allocator.h
|
||||||
|
sanitizer_allocator_interface.h
|
||||||
sanitizer_allocator_internal.h
|
sanitizer_allocator_internal.h
|
||||||
sanitizer_atomic.h
|
sanitizer_atomic.h
|
||||||
sanitizer_atomic_clang.h
|
sanitizer_atomic_clang.h
|
||||||
|
|
|
@ -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
|
|
@ -10,6 +10,7 @@
|
||||||
// This file is a part of ThreadSanitizer (TSan), a race detector.
|
// 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_common.h"
|
||||||
#include "sanitizer_common/sanitizer_placement_new.h"
|
#include "sanitizer_common/sanitizer_placement_new.h"
|
||||||
#include "tsan_mman.h"
|
#include "tsan_mman.h"
|
||||||
|
@ -22,10 +23,17 @@ extern "C" void WEAK __tsan_malloc_hook(void *ptr, uptr size) {
|
||||||
(void)ptr;
|
(void)ptr;
|
||||||
(void)size;
|
(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) {
|
extern "C" void WEAK __tsan_free_hook(void *ptr) {
|
||||||
(void)ptr;
|
(void)ptr;
|
||||||
}
|
}
|
||||||
|
extern "C" void WEAK __sanitizer_free_hook(void *ptr) {
|
||||||
|
(void)ptr;
|
||||||
|
}
|
||||||
|
|
||||||
namespace __tsan {
|
namespace __tsan {
|
||||||
|
|
||||||
|
@ -128,7 +136,7 @@ void *user_realloc(ThreadState *thr, uptr pc, void *p, uptr sz) {
|
||||||
return p2;
|
return p2;
|
||||||
}
|
}
|
||||||
|
|
||||||
uptr user_alloc_usable_size(void *p) {
|
uptr user_alloc_usable_size(const void *p) {
|
||||||
if (p == 0)
|
if (p == 0)
|
||||||
return 0;
|
return 0;
|
||||||
MBlock *b = ctx->metamap.GetBlock((uptr)p);
|
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)
|
if (ctx == 0 || !ctx->initialized || thr->ignore_interceptors)
|
||||||
return;
|
return;
|
||||||
__tsan_malloc_hook(ptr, size);
|
__tsan_malloc_hook(ptr, size);
|
||||||
|
__sanitizer_malloc_hook(ptr, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void invoke_free_hook(void *ptr) {
|
void invoke_free_hook(void *ptr) {
|
||||||
|
@ -147,6 +156,7 @@ void invoke_free_hook(void *ptr) {
|
||||||
if (ctx == 0 || !ctx->initialized || thr->ignore_interceptors)
|
if (ctx == 0 || !ctx->initialized || thr->ignore_interceptors)
|
||||||
return;
|
return;
|
||||||
__tsan_free_hook(ptr);
|
__tsan_free_hook(ptr);
|
||||||
|
__sanitizer_free_hook(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *internal_alloc(MBlockType typ, uptr sz) {
|
void *internal_alloc(MBlockType typ, uptr sz) {
|
||||||
|
@ -173,37 +183,58 @@ void internal_free(void *p) {
|
||||||
using namespace __tsan;
|
using namespace __tsan;
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
uptr __tsan_get_current_allocated_bytes() {
|
uptr __sanitizer_get_current_allocated_bytes() {
|
||||||
uptr stats[AllocatorStatCount];
|
uptr stats[AllocatorStatCount];
|
||||||
allocator()->GetStats(stats);
|
allocator()->GetStats(stats);
|
||||||
return stats[AllocatorStatAllocated];
|
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];
|
uptr stats[AllocatorStatCount];
|
||||||
allocator()->GetStats(stats);
|
allocator()->GetStats(stats);
|
||||||
return stats[AllocatorStatMapped];
|
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() {
|
uptr __tsan_get_free_bytes() {
|
||||||
return 1;
|
return __sanitizer_get_free_bytes();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uptr __sanitizer_get_unmapped_bytes() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
uptr __tsan_get_unmapped_bytes() {
|
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;
|
return size;
|
||||||
}
|
}
|
||||||
|
uptr __tsan_get_estimated_allocated_size(uptr size) {
|
||||||
bool __tsan_get_ownership(void *p) {
|
return __sanitizer_get_estimated_allocated_size(size);
|
||||||
return allocator()->GetBlockBegin(p) != 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
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() {
|
void __tsan_on_thread_idle() {
|
||||||
ThreadState *thr = cur_thread();
|
ThreadState *thr = cur_thread();
|
||||||
|
|
|
@ -31,7 +31,7 @@ void *user_alloc(ThreadState *thr, uptr pc, uptr sz,
|
||||||
void user_free(ThreadState *thr, uptr pc, void *p);
|
void user_free(ThreadState *thr, uptr pc, void *p);
|
||||||
void *user_realloc(ThreadState *thr, uptr pc, void *p, uptr sz);
|
void *user_realloc(ThreadState *thr, uptr pc, void *p, uptr sz);
|
||||||
void *user_alloc_aligned(ThreadState *thr, uptr pc, uptr sz, uptr align);
|
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.
|
// Invoking malloc/free hooks that may be installed by the user.
|
||||||
void invoke_malloc_hook(void *ptr, uptr size);
|
void invoke_malloc_hook(void *ptr, uptr size);
|
||||||
|
|
|
@ -11,20 +11,11 @@
|
||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
#include <sanitizer/allocator_interface.h>
|
||||||
#include "tsan_mman.h"
|
#include "tsan_mman.h"
|
||||||
#include "tsan_rtl.h"
|
#include "tsan_rtl.h"
|
||||||
#include "gtest/gtest.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 {
|
namespace __tsan {
|
||||||
|
|
||||||
TEST(Mman, Internal) {
|
TEST(Mman, Internal) {
|
||||||
|
@ -118,30 +109,30 @@ TEST(Mman, UsableSize) {
|
||||||
TEST(Mman, Stats) {
|
TEST(Mman, Stats) {
|
||||||
ThreadState *thr = cur_thread();
|
ThreadState *thr = cur_thread();
|
||||||
|
|
||||||
uptr alloc0 = __tsan_get_current_allocated_bytes();
|
uptr alloc0 = __sanitizer_get_current_allocated_bytes();
|
||||||
uptr heap0 = __tsan_get_heap_size();
|
uptr heap0 = __sanitizer_get_heap_size();
|
||||||
uptr free0 = __tsan_get_free_bytes();
|
uptr free0 = __sanitizer_get_free_bytes();
|
||||||
uptr unmapped0 = __tsan_get_unmapped_bytes();
|
uptr unmapped0 = __sanitizer_get_unmapped_bytes();
|
||||||
|
|
||||||
EXPECT_EQ(__tsan_get_estimated_allocated_size(10), (uptr)10);
|
EXPECT_EQ(10U, __sanitizer_get_estimated_allocated_size(10));
|
||||||
EXPECT_EQ(__tsan_get_estimated_allocated_size(20), (uptr)20);
|
EXPECT_EQ(20U, __sanitizer_get_estimated_allocated_size(20));
|
||||||
EXPECT_EQ(__tsan_get_estimated_allocated_size(100), (uptr)100);
|
EXPECT_EQ(100U, __sanitizer_get_estimated_allocated_size(100));
|
||||||
|
|
||||||
char *p = (char*)user_alloc(thr, 0, 10);
|
char *p = (char*)user_alloc(thr, 0, 10);
|
||||||
EXPECT_EQ(__tsan_get_ownership(p), true);
|
EXPECT_TRUE(__sanitizer_get_ownership(p));
|
||||||
EXPECT_EQ(__tsan_get_allocated_size(p), (uptr)10);
|
EXPECT_EQ(10U, __sanitizer_get_allocated_size(p));
|
||||||
|
|
||||||
EXPECT_EQ(__tsan_get_current_allocated_bytes(), alloc0 + 16);
|
EXPECT_EQ(alloc0 + 16, __sanitizer_get_current_allocated_bytes());
|
||||||
EXPECT_GE(__tsan_get_heap_size(), heap0);
|
EXPECT_GE(__sanitizer_get_heap_size(), heap0);
|
||||||
EXPECT_EQ(__tsan_get_free_bytes(), free0);
|
EXPECT_EQ(free0, __sanitizer_get_free_bytes());
|
||||||
EXPECT_EQ(__tsan_get_unmapped_bytes(), unmapped0);
|
EXPECT_EQ(unmapped0, __sanitizer_get_unmapped_bytes());
|
||||||
|
|
||||||
user_free(thr, 0, p);
|
user_free(thr, 0, p);
|
||||||
|
|
||||||
EXPECT_EQ(__tsan_get_current_allocated_bytes(), alloc0);
|
EXPECT_EQ(alloc0, __sanitizer_get_current_allocated_bytes());
|
||||||
EXPECT_GE(__tsan_get_heap_size(), heap0);
|
EXPECT_GE(__sanitizer_get_heap_size(), heap0);
|
||||||
EXPECT_EQ(__tsan_get_free_bytes(), free0);
|
EXPECT_EQ(free0, __sanitizer_get_free_bytes());
|
||||||
EXPECT_EQ(__tsan_get_unmapped_bytes(), unmapped0);
|
EXPECT_EQ(unmapped0, __sanitizer_get_unmapped_bytes());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Mman, CallocOverflow) {
|
TEST(Mman, CallocOverflow) {
|
||||||
|
|
|
@ -6,8 +6,8 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <sanitizer/allocator_interface.h>
|
||||||
|
|
||||||
extern "C" size_t __asan_get_heap_size();
|
|
||||||
static pthread_key_t tsd_key;
|
static pthread_key_t tsd_key;
|
||||||
|
|
||||||
void *Thread(void *) {
|
void *Thread(void *) {
|
||||||
|
@ -30,7 +30,7 @@ int main() {
|
||||||
pthread_t t;
|
pthread_t t;
|
||||||
pthread_create(&t, 0, Thread, 0);
|
pthread_create(&t, 0, Thread, 0);
|
||||||
pthread_join(t, 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);
|
fprintf(stderr, "heap size: new: %zd old: %zd\n", new_heap_size, old_heap_size);
|
||||||
if (old_heap_size)
|
if (old_heap_size)
|
||||||
assert(old_heap_size == new_heap_size);
|
assert(old_heap_size == new_heap_size);
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <sanitizer/asan_interface.h>
|
#include <sanitizer/allocator_interface.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
@ -17,12 +17,12 @@ void* allocate(void *arg) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void* check_stats(void *arg) {
|
void* check_stats(void *arg) {
|
||||||
assert(__asan_get_current_allocated_bytes() > 0);
|
assert(__sanitizer_get_current_allocated_bytes() > 0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main() {
|
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);
|
printf("Before: %zu\n", used_mem);
|
||||||
const int kNumIterations = 1000;
|
const int kNumIterations = 1000;
|
||||||
for (int iter = 0; iter < kNumIterations; iter++) {
|
for (int iter = 0; iter < kNumIterations; iter++) {
|
||||||
|
@ -33,7 +33,7 @@ int main() {
|
||||||
}
|
}
|
||||||
for (int j = 0; j < 4; j++)
|
for (int j = 0; j < 4; j++)
|
||||||
assert(0 == pthread_join(thr[j], 0));
|
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) {
|
if (used_mem > kLargeAlloc) {
|
||||||
printf("After iteration %d: %zu\n", iter, used_mem);
|
printf("After iteration %d: %zu\n", iter, used_mem);
|
||||||
return 1;
|
return 1;
|
||||||
|
|
|
@ -7,11 +7,12 @@
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <sanitizer/allocator_interface.h>
|
||||||
|
|
||||||
static void *glob_ptr;
|
static void *glob_ptr;
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
void __asan_free_hook(void *ptr) {
|
void __sanitizer_free_hook(const volatile void *ptr) {
|
||||||
if (ptr == glob_ptr) {
|
if (ptr == glob_ptr) {
|
||||||
*(int*)ptr = 0;
|
*(int*)ptr = 0;
|
||||||
write(1, "FreeHook\n", sizeof("FreeHook\n"));
|
write(1, "FreeHook\n", sizeof("FreeHook\n"));
|
||||||
|
|
|
@ -6,22 +6,21 @@
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <sanitizer/allocator_interface.h>
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
bool __asan_get_ownership(const void *p);
|
const volatile void *global_ptr;
|
||||||
|
|
||||||
void *global_ptr;
|
|
||||||
|
|
||||||
// Note: avoid calling functions that allocate memory in malloc/free
|
// Note: avoid calling functions that allocate memory in malloc/free
|
||||||
// to avoid infinite recursion.
|
// to avoid infinite recursion.
|
||||||
void __asan_malloc_hook(void *ptr, size_t sz) {
|
void __sanitizer_malloc_hook(const volatile void *ptr, size_t sz) {
|
||||||
if (__asan_get_ownership(ptr)) {
|
if (__sanitizer_get_ownership(ptr)) {
|
||||||
write(1, "MallocHook\n", sizeof("MallocHook\n"));
|
write(1, "MallocHook\n", sizeof("MallocHook\n"));
|
||||||
global_ptr = ptr;
|
global_ptr = ptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void __asan_free_hook(void *ptr) {
|
void __sanitizer_free_hook(const volatile void *ptr) {
|
||||||
if (__asan_get_ownership(ptr) && ptr == global_ptr)
|
if (__sanitizer_get_ownership(ptr) && ptr == global_ptr)
|
||||||
write(1, "FreeHook\n", sizeof("FreeHook\n"));
|
write(1, "FreeHook\n", sizeof("FreeHook\n"));
|
||||||
}
|
}
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
|
|
|
@ -8,17 +8,17 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <sanitizer/asan_interface.h>
|
#include <sanitizer/allocator_interface.h>
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
if (argc < 2)
|
if (argc < 2)
|
||||||
return 1;
|
return 1;
|
||||||
bool large_redzone = atoi(argv[1]);
|
bool large_redzone = atoi(argv[1]);
|
||||||
size_t before = __asan_get_heap_size();
|
size_t before = __sanitizer_get_heap_size();
|
||||||
void *pp[10000];
|
void *pp[10000];
|
||||||
for (int i = 0; i < 10000; ++i)
|
for (int i = 0; i < 10000; ++i)
|
||||||
pp[i] = malloc(4096 - 64);
|
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)
|
for (int i = 0; i < 10000; ++i)
|
||||||
free(pp[i]);
|
free(pp[i]);
|
||||||
size_t diff = after - before;
|
size_t diff = after - before;
|
||||||
|
|
|
@ -2,22 +2,22 @@
|
||||||
// RUN: %run %t 2>&1 | FileCheck %s
|
// RUN: %run %t 2>&1 | FileCheck %s
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <sanitizer/allocator_interface.h>
|
||||||
|
|
||||||
extern "C" {
|
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
|
// Note: avoid calling functions that allocate memory in malloc/free
|
||||||
// to avoid infinite recursion.
|
// to avoid infinite recursion.
|
||||||
void __msan_malloc_hook(void *ptr, size_t sz) {
|
void __sanitizer_malloc_hook(const volatile void *ptr, size_t sz) {
|
||||||
if (__msan_get_ownership(ptr)) {
|
if (__sanitizer_get_ownership(ptr)) {
|
||||||
write(1, "MallocHook\n", sizeof("MallocHook\n"));
|
write(1, "MallocHook\n", sizeof("MallocHook\n"));
|
||||||
global_ptr = ptr;
|
global_ptr = ptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void __msan_free_hook(void *ptr) {
|
void __sanitizer_free_hook(const volatile void *ptr) {
|
||||||
if (__msan_get_ownership(ptr) && ptr == global_ptr)
|
if (__sanitizer_get_ownership(ptr) && ptr == global_ptr)
|
||||||
write(1, "FreeHook\n", sizeof("FreeHook\n"));
|
write(1, "FreeHook\n", sizeof("FreeHook\n"));
|
||||||
}
|
}
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
|
|
|
@ -4,18 +4,19 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <sanitizer/allocator_interface.h>
|
||||||
|
|
||||||
static int malloc_count;
|
static int malloc_count;
|
||||||
static int free_count;
|
static int free_count;
|
||||||
|
|
||||||
extern "C" {
|
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)ptr;
|
||||||
(void)size;
|
(void)size;
|
||||||
__sync_fetch_and_add(&malloc_count, 1);
|
__sync_fetch_and_add(&malloc_count, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void __tsan_free_hook(void *ptr) {
|
void __sanitizer_free_hook(const volatile void *ptr) {
|
||||||
(void)ptr;
|
(void)ptr;
|
||||||
__sync_fetch_and_add(&free_count, 1);
|
__sync_fetch_and_add(&free_count, 1);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue