From 10981ab1220400d65eab6429537344ac1b7cf7f0 Mon Sep 17 00:00:00 2001 From: Daan Leijen Date: Mon, 28 Nov 2022 10:55:19 -0800 Subject: [PATCH] add initial support for using mimalloc with address sanitizer support; use -DMI_ASAN=ON --- CMakeLists.txt | 23 +++++++++++++++++++++++ include/mimalloc-track.h | 23 +++++++++++++++++++++-- src/alloc-aligned.c | 2 +- src/alloc.c | 2 +- src/init.c | 1 + 5 files changed, 47 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4eebf2ca..4f118786 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,6 +11,7 @@ option(MI_OVERRIDE "Override the standard malloc interface (e.g. define option(MI_XMALLOC "Enable abort() call on memory allocation failure by default" OFF) option(MI_SHOW_ERRORS "Show error and warning messages by default (only enabled by default in DEBUG mode)" OFF) option(MI_VALGRIND "Compile with Valgrind support (adds a small overhead)" OFF) +option(MI_ASAN "Compile with address sanitizer support (adds a small overhead)" OFF) option(MI_USE_CXX "Use the C++ compiler to compile the library (instead of the C compiler)" OFF) option(MI_SEE_ASM "Generate assembly files" OFF) option(MI_OSX_INTERPOSE "Use interpose to override standard malloc on macOS" ON) @@ -139,6 +140,25 @@ if(MI_VALGRIND) endif() endif() +if(MI_ASAN) + if (MI_VALGRIND) + set(MI_ASAN OFF) + message(WARNING "Cannot enable address sanitizer support with also Valgrind support enabled (MI_ASAN=OFF)") + else() + CHECK_INCLUDE_FILES("sanitizer/asan_interface.h" MI_HAS_ASANH) + if (NOT MI_HAS_ASANH) + set(MI_ASAN OFF) + message(WARNING "Cannot find the 'sanitizer/asan_interface.h' -- install address sanitizer support first") + message(STATUS "Compile **without** address sanitizer support (MI_ASAN=OFF)") + else() + message(STATUS "Compile with address sanitizer support (MI_ASAN=ON)") + list(APPEND mi_defines MI_ASAN=1) + list(APPEND mi_cflags -fsanitize=address) + list(APPEND CMAKE_EXE_LINKER_FLAGS -fsanitize=address) + endif() + endif() +endif() + if(MI_SEE_ASM) message(STATUS "Generate assembly listings (MI_SEE_ASM=ON)") list(APPEND mi_cflags -save-temps) @@ -296,6 +316,9 @@ if(MI_SECURE) endif() if(MI_VALGRIND) set(mi_basename "${mi_basename}-valgrind") +endif() +if(MI_ASAN) + set(mi_basename "${mi_basename}-asan") endif() string(TOLOWER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE_LC) if(NOT(CMAKE_BUILD_TYPE_LC MATCHES "^(release|relwithdebinfo|minsizerel|none)$")) diff --git a/include/mimalloc-track.h b/include/mimalloc-track.h index bb9df4fa..3bb9527c 100644 --- a/include/mimalloc-track.h +++ b/include/mimalloc-track.h @@ -10,12 +10,13 @@ terms of the MIT license. A copy of the license can be found in the file // ------------------------------------------------------ // Track memory ranges with macros for tools like Valgrind -// or other memory checkers. +// address sanitizer, or other memory checkers. // ------------------------------------------------------ #if MI_VALGRIND #define MI_TRACK_ENABLED 1 +#define MI_TRACK_TOOL "valgrind" #include #include @@ -23,17 +24,35 @@ terms of the MIT license. A copy of the license can be found in the file #define mi_track_malloc(p,size,zero) VALGRIND_MALLOCLIKE_BLOCK(p,size,MI_PADDING_SIZE /*red zone*/,zero) #define mi_track_resize(p,oldsize,newsize) VALGRIND_RESIZEINPLACE_BLOCK(p,oldsize,newsize,MI_PADDING_SIZE /*red zone*/) #define mi_track_free(p) VALGRIND_FREELIKE_BLOCK(p,MI_PADDING_SIZE /*red zone*/) +#define mi_track_free_size(p,_size) mi_track_free(p) #define mi_track_mem_defined(p,size) VALGRIND_MAKE_MEM_DEFINED(p,size) #define mi_track_mem_undefined(p,size) VALGRIND_MAKE_MEM_UNDEFINED(p,size) #define mi_track_mem_noaccess(p,size) VALGRIND_MAKE_MEM_NOACCESS(p,size) +#elif MI_ASAN + +#define MI_TRACK_ENABLED 1 +#define MI_TRACK_TOOL "asan" + +#include + +#define mi_track_malloc(p,size,zero) ASAN_UNPOISON_MEMORY_REGION(p,size) +#define mi_track_resize(p,oldsize,newsize) ASAN_POISON_MEMORY_REGION(p,oldsize); ASAN_UNPOISON_MEMORY_REGION(p,newsize) +#define mi_track_free(p) ASAN_POISON_MEMORY_REGION(p,mi_usable_size(p)) +#define mi_track_free_size(p,size) ASAN_POISON_MEMORY_REGION(p,size) +#define mi_track_mem_defined(p,size) ASAN_UNPOISON_MEMORY_REGION(p,size) +#define mi_track_mem_undefined(p,size) ASAN_UNPOISON_MEMORY_REGION(p,size) +#define mi_track_mem_noaccess(p,size) ASAN_POISON_MEMORY_REGION(p,size) + #else #define MI_TRACK_ENABLED 0 +#define MI_TRACK_TOOL "none" #define mi_track_malloc(p,size,zero) #define mi_track_resize(p,oldsize,newsize) -#define mi_track_free(p) +#define mi_track_free(p,size) +#define mi_track_free_size(p,_size) #define mi_track_mem_defined(p,size) #define mi_track_mem_undefined(p,size) #define mi_track_mem_noaccess(p,size) diff --git a/src/alloc-aligned.c b/src/alloc-aligned.c index 73d5524c..04528d9d 100644 --- a/src/alloc-aligned.c +++ b/src/alloc-aligned.c @@ -80,7 +80,7 @@ static mi_decl_noinline void* mi_heap_malloc_zero_aligned_at_fallback(mi_heap_t* #if MI_TRACK_ENABLED if (p != aligned_p) { - mi_track_free(p); + mi_track_free_size(p, oversize); mi_track_malloc(aligned_p, size, zero); } else { diff --git a/src/alloc.c b/src/alloc.c index 7095dc67..01a0d4a4 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -697,7 +697,7 @@ void* _mi_heap_realloc_zero(mi_heap_t* heap, void* p, size_t newsize, bool zero) const size_t size = _mi_usable_size(p,"mi_realloc"); // also works if p == NULL (with size 0) if mi_unlikely(newsize <= size && newsize >= (size / 2) && newsize > 0) { // note: newsize must be > 0 or otherwise we return NULL for realloc(NULL,0) // todo: adjust potential padding to reflect the new size? - mi_track_free(p); + mi_track_free_size(p, size); mi_track_malloc(p,newsize,true); return p; // reallocation still fits and not more than 50% waste } diff --git a/src/init.c b/src/init.c index 3f71fa01..66c7e74b 100644 --- a/src/init.c +++ b/src/init.c @@ -558,6 +558,7 @@ void mi_process_init(void) mi_attr_noexcept { _mi_verbose_message("debug level : %d\n", MI_DEBUG); #endif _mi_verbose_message("secure level: %d\n", MI_SECURE); + _mi_verbose_message("mem tracking: %s\n", MI_TRACK_TOOL); mi_thread_init(); #if defined(_WIN32) && !defined(MI_SHARED_LIB)