Skip to content

Commit

Permalink
Switch libc's malloc with mimalloc
Browse files Browse the repository at this point in the history
  • Loading branch information
andronat committed May 26, 2020
1 parent 34df09d commit c19ab74
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 11 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ if (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "x86_64")
endif()

include("${CMAKE_SOURCE_DIR}/cmake/sabre_add_component.cmake")
include("${CMAKE_SOURCE_DIR}/cmake/mimalloc.cmake")

# Sources
add_subdirectory("arch/${CMAKE_SYSTEM_PROCESSOR}" arch)
Expand Down
14 changes: 14 additions & 0 deletions cmake/mimalloc-sanitizer-compatibility.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
diff --git a/src/os.c b/src/os.c
index f33cfbc..536269e 100644
--- a/src/os.c
+++ b/src/os.c
@@ -405,7 +405,8 @@ static void* mi_unix_mmap(void* addr, size_t size, size_t try_alignment, int pro

// On 64-bit systems, we can do efficient aligned allocation by using
// the 4TiB to 30TiB area to allocate them.
-#if (MI_INTPTR_SIZE >= 8) && (defined(_WIN32) || (defined(MI_OS_USE_MMAP) && !defined(MAP_ALIGNED)))
+// #if (MI_INTPTR_SIZE >= 8) && (defined(_WIN32) || (defined(MI_OS_USE_MMAP) && !defined(MAP_ALIGNED)))
+#if 0
static volatile mi_decl_cache_align _Atomic(uintptr_t) aligned_base;

// Return a 4MiB aligned address that is probably available
35 changes: 35 additions & 0 deletions cmake/mimalloc.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
include(ExternalProject)

set(MIMALLOC_INSTALL_DIR ${CMAKE_CURRENT_BINARY_DIR}/mimalloc/install)

ExternalProject_Add(
mimalloc
PREFIX mimalloc
GIT_REPOSITORY https://github.com/microsoft/mimalloc.git
GIT_TAG v1.6.3
INSTALL_DIR ${MIMALLOC_INSTALL_DIR}
# We need to patch mimalloc's default mmap ranges as they interfere with
# sanitizers
# https://github.com/llvm/llvm-project/blob/master/compiler-rt/lib/tsan/rtl/tsan_platform.h#L67-L72
PATCH_COMMAND
patch -p1 <
${CMAKE_CURRENT_SOURCE_DIR}/cmake/mimalloc-sanitizer-compatibility.patch
UPDATE_COMMAND ""
CMAKE_ARGS
"-DCMAKE_INSTALL_PREFIX=${MIMALLOC_INSTALL_DIR};-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE};-DMI_LOCAL_DYNAMIC_TLS=ON;"
)

set(IS_DEBUG "")
string(TOLOWER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE_LC)
if(CMAKE_BUILD_TYPE_LC STREQUAL "debug")
set(IS_DEBUG "-debug")
endif()

find_package(Threads REQUIRED)
add_library(mimalloc-static STATIC IMPORTED GLOBAL)
add_dependencies(mimalloc-static mimalloc)
set_target_properties(
mimalloc-static
PROPERTIES IMPORTED_LOCATION
${MIMALLOC_INSTALL_DIR}/lib/mimalloc-1.6/libmimalloc${IS_DEBUG}.a
INTERFACE_LINK_LIBRARIES ${CMAKE_THREAD_LIBS_INIT})
6 changes: 4 additions & 2 deletions cmake/sabre_add_component.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,15 @@ function(sabre_add_executable exe_name)
else()
target_link_options(${exe_name} PRIVATE ${SABRE_EXE_LINK_FLAGS})
endif()
target_link_libraries(${exe_name} loader)
add_dependencies(${exe_name} mimalloc)
target_link_libraries(${exe_name} loader mimalloc-static)
endfunction()

function(sabre_add_plugin plugin_name)
add_library(${plugin_name} MODULE ${ARGN})
target_include_directories(${plugin_name} PUBLIC ${SABRE_PLUGIN_INCLUDE_DIRS})
target_compile_definitions(${plugin_name} PUBLIC ${SABRE_PLUGIN_C_DEFINES})
target_compile_options(${plugin_name} PUBLIC ${SABRE_PLUGIN_C_FLAGS})
target_link_libraries(${plugin_name} realsyscall)
add_dependencies(${plugin_name} mimalloc)
target_link_libraries(${plugin_name} realsyscall mimalloc-static)
endfunction()
15 changes: 6 additions & 9 deletions loader/loader.c
Original file line number Diff line number Diff line change
Expand Up @@ -154,15 +154,12 @@ void load(int argc, char *argv[], void **new_entry, void **new_stack_top)
exit(-1);
}

// There 2 mallocs in memory because SaBRe loads 2 libcs (one for SaBRe) and
// one for the client (which is intercepted). These two mallocs will overlap
// their arenas as malloc uses brk(NULL) to initialize its arena, and this
// brk(NULL) will always return the same pointer. To avoid this we force
// SaBRe's malloc to completely skip the arena initialization and keep objects
// into separate mmap() pages. This of course comes with a small performance
// decrease, and the potential to OOM if we allocate too many items.
int ret = mallopt(M_MMAP_THRESHOLD, 0);
assert(ret == 1);
// SaBRe and its plugins statically link with mimalloc now, and stay separate
// from client's libc malloc. Before, there were 2 libc mallocs (one for SaBRe
// + plugin) and one for the client (which is intercepted). These two mallocs
// had overlapping arenas as malloc uses brk(NULL) to initialize its arena,
// and this brk(NULL) will always return the same pointer. Now, mimalloc is
// using mmap and this is no longer a problem.

// Setup our custom TLS
register_first_tid();
Expand Down

0 comments on commit c19ab74

Please sign in to comment.