introduce llvm/gwp-asan

This commit is contained in:
Han Fei 2023-01-12 15:00:26 +01:00
parent f28b04fc59
commit f5e736e240
6 changed files with 115 additions and 1 deletions

View File

@ -114,6 +114,7 @@ endif()
add_contrib (llvm-project-cmake llvm-project) add_contrib (llvm-project-cmake llvm-project)
add_contrib (libfuzzer-cmake llvm-project) add_contrib (libfuzzer-cmake llvm-project)
add_contrib (gwpasan-cmake llvm-project)
add_contrib (libxml2-cmake libxml2) add_contrib (libxml2-cmake libxml2)
add_contrib (aws-cmake add_contrib (aws-cmake

View File

@ -0,0 +1,41 @@
set(COMPILER_RT_GWP_ASAN_SRC_DIR "${ClickHouse_SOURCE_DIR}/contrib/llvm-project/compiler-rt/lib/gwp_asan")
set(GWP_ASAN_SOURCES
${COMPILER_RT_GWP_ASAN_SRC_DIR}/common.cpp
${COMPILER_RT_GWP_ASAN_SRC_DIR}/crash_handler.cpp
${COMPILER_RT_GWP_ASAN_SRC_DIR}/platform_specific/common_posix.cpp
${COMPILER_RT_GWP_ASAN_SRC_DIR}/platform_specific/guarded_pool_allocator_posix.cpp
${COMPILER_RT_GWP_ASAN_SRC_DIR}/platform_specific/mutex_posix.cpp
${COMPILER_RT_GWP_ASAN_SRC_DIR}/platform_specific/utilities_posix.cpp
${COMPILER_RT_GWP_ASAN_SRC_DIR}/guarded_pool_allocator.cpp
${COMPILER_RT_GWP_ASAN_SRC_DIR}/stack_trace_compressor.cpp
${COMPILER_RT_GWP_ASAN_SRC_DIR}/optional/options_parser.cpp
#PARENT_SCOPE
)
#set(GWP_ASAN_LIBS RTGwpAsan RTGwpAsanOptionsParser RTGwpAsanBacktraceLibc RTGwpAsanSegvHandler)
set(GWP_ASAN_HEADERS "${ClickHouse_SOURCE_DIR}/contrib/llvm-project/compiler-rt/lib")
#set(GWP_ASAN_HEADERS_FILES
# ${COMPILER_RT_GWP_ASAN_SRC_DIR}/common.h
# ${COMPILER_RT_GWP_ASAN_SRC_DIR}/crash_handler.h
# ${COMPILER_RT_GWP_ASAN_SRC_DIR}/definitions.h
# ${COMPILER_RT_GWP_ASAN_SRC_DIR}/guarded_pool_allocator.h
# ${COMPILER_RT_GWP_ASAN_SRC_DIR}/mutex.h
# ${COMPILER_RT_GWP_ASAN_SRC_DIR}/options.h
# ${COMPILER_RT_GWP_ASAN_SRC_DIR}/options.inc
# ${COMPILER_RT_GWP_ASAN_SRC_DIR}/platform_specific/guarded_pool_allocator_fuchsia.h
# ${COMPILER_RT_GWP_ASAN_SRC_DIR}/platform_specific/guarded_pool_allocator_posix.h
# ${COMPILER_RT_GWP_ASAN_SRC_DIR}/platform_specific/guarded_pool_allocator_tls.h
# ${COMPILER_RT_GWP_ASAN_SRC_DIR}/platform_specific/mutex_fuchsia.h
# ${COMPILER_RT_GWP_ASAN_SRC_DIR}/platform_specific/mutex_posix.h
# ${COMPILER_RT_GWP_ASAN_SRC_DIR}/stack_trace_compressor.h
# ${COMPILER_RT_GWP_ASAN_SRC_DIR}/utilities.h
# PARENT_SCOPE
#)
add_library(_gwp_asan ${GWP_ASAN_SOURCES})
#target_link_libraries (_gwp_asan INTERFACE ${GWP_ASAN_SOURCES})
target_include_directories (_gwp_asan SYSTEM PUBLIC ${GWP_ASAN_HEADERS})
add_library(ch_contrib::gwp_asan ALIAS _gwp_asan)

View File

@ -19,6 +19,7 @@
#include <Common/StringUtils/StringUtils.h> #include <Common/StringUtils/StringUtils.h>
#include <Common/getHashOfLoadedBinary.h> #include <Common/getHashOfLoadedBinary.h>
#include <Common/gwp_asan.h>
#include <Common/IO.h> #include <Common/IO.h>
#include <base/phdr_cache.h> #include <base/phdr_cache.h>
@ -433,7 +434,6 @@ extern "C"
} }
#endif #endif
/// This allows to implement assert to forbid initialization of a class in static constructors. /// This allows to implement assert to forbid initialization of a class in static constructors.
/// Usage: /// Usage:
/// ///
@ -465,6 +465,8 @@ int main(int argc_, char ** argv_)
/// It is needed because LLVM library clobbers it. /// It is needed because LLVM library clobbers it.
std::set_new_handler(nullptr); std::set_new_handler(nullptr);
Memory::initGWPAsan();
std::vector<char *> argv(argv_, argv_ + argc_); std::vector<char *> argv(argv_, argv_ + argc_);
/// Print a basic help if nothing was matched /// Print a basic help if nothing was matched

View File

@ -310,6 +310,11 @@ if (TARGET ch_contrib::llvm)
dbms_target_link_libraries (PUBLIC ch_contrib::llvm) dbms_target_link_libraries (PUBLIC ch_contrib::llvm)
endif () endif ()
if (TARGET ch_contrib::gwp_asan)
target_link_libraries (clickhouse_common_io PUBLIC ch_contrib::gwp_asan)
target_link_libraries (clickhouse_new_delete PRIVATE ch_contrib::gwp_asan)
endif()
# Otherwise it will slow down stack traces printing too much. # Otherwise it will slow down stack traces printing too much.
set_source_files_properties( set_source_files_properties(
Common/Elf.cpp Common/Elf.cpp

20
src/Common/gwp_asan.h Normal file
View File

@ -0,0 +1,20 @@
#pragma once
#include <base/defines.h>
#include <gwp_asan/guarded_pool_allocator.h>
#include <gwp_asan/optional/options_parser.h>
namespace Memory
{
static gwp_asan::GuardedPoolAllocator GuardedAlloc;
inline ALWAYS_INLINE void initGWPAsan()
{
gwp_asan::options::initOptions();
gwp_asan::options::Options &opts = gwp_asan::options::getOptions();
GuardedAlloc.init(opts);
}
}

View File

@ -7,6 +7,7 @@
#include <Common/Concepts.h> #include <Common/Concepts.h>
#include <Common/CurrentMemoryTracker.h> #include <Common/CurrentMemoryTracker.h>
#include <Common/gwp_asan.h>
#include "config.h" #include "config.h"
#if USE_JEMALLOC #if USE_JEMALLOC
@ -29,6 +30,21 @@ template <std::same_as<std::align_val_t>... TAlign>
requires DB::OptionalArgument<TAlign...> requires DB::OptionalArgument<TAlign...>
inline ALWAYS_INLINE void * newImpl(std::size_t size, TAlign... align) inline ALWAYS_INLINE void * newImpl(std::size_t size, TAlign... align)
{ {
if (unlikely(GuardedAlloc.shouldSample()))
{
if constexpr (sizeof...(TAlign) == 1)
{
if (void * ptr = GuardedAlloc.allocate(size, alignToSizeT(align...)))
return ptr;
}
else
{
if (void * ptr = GuardedAlloc.allocate(size))
return ptr;
}
}
void * ptr = nullptr; void * ptr = nullptr;
if constexpr (sizeof...(TAlign) == 1) if constexpr (sizeof...(TAlign) == 1)
ptr = aligned_alloc(alignToSizeT(align...), size); ptr = aligned_alloc(alignToSizeT(align...), size);
@ -44,16 +60,31 @@ inline ALWAYS_INLINE void * newImpl(std::size_t size, TAlign... align)
inline ALWAYS_INLINE void * newNoExept(std::size_t size) noexcept inline ALWAYS_INLINE void * newNoExept(std::size_t size) noexcept
{ {
if (unlikely(GuardedAlloc.shouldSample()))
{
if (void * ptr = GuardedAlloc.allocate(size))
return ptr;
}
return malloc(size); return malloc(size);
} }
inline ALWAYS_INLINE void * newNoExept(std::size_t size, std::align_val_t align) noexcept inline ALWAYS_INLINE void * newNoExept(std::size_t size, std::align_val_t align) noexcept
{ {
if (unlikely(GuardedAlloc.shouldSample()))
{
if (void * ptr = GuardedAlloc.allocate(size, alignToSizeT(align)))
return ptr;
}
return aligned_alloc(static_cast<size_t>(align), size); return aligned_alloc(static_cast<size_t>(align), size);
} }
inline ALWAYS_INLINE void deleteImpl(void * ptr) noexcept inline ALWAYS_INLINE void deleteImpl(void * ptr) noexcept
{ {
if (unlikely(GuardedAlloc.pointerIsMine(ptr)))
{
GuardedAlloc.deallocate(ptr);
return;
}
free(ptr); free(ptr);
} }
@ -66,6 +97,12 @@ inline ALWAYS_INLINE void deleteSized(void * ptr, std::size_t size, TAlign... al
if (unlikely(ptr == nullptr)) if (unlikely(ptr == nullptr))
return; return;
if (unlikely(GuardedAlloc.pointerIsMine(ptr)))
{
GuardedAlloc.deallocate(ptr);
return;
}
if constexpr (sizeof...(TAlign) == 1) if constexpr (sizeof...(TAlign) == 1)
sdallocx(ptr, size, MALLOCX_ALIGN(alignToSizeT(align...))); sdallocx(ptr, size, MALLOCX_ALIGN(alignToSizeT(align...)));
else else
@ -122,6 +159,14 @@ template <std::same_as<std::align_val_t>... TAlign>
requires DB::OptionalArgument<TAlign...> requires DB::OptionalArgument<TAlign...>
inline ALWAYS_INLINE void untrackMemory(void * ptr [[maybe_unused]], std::size_t size [[maybe_unused]] = 0, TAlign... align [[maybe_unused]]) noexcept inline ALWAYS_INLINE void untrackMemory(void * ptr [[maybe_unused]], std::size_t size [[maybe_unused]] = 0, TAlign... align [[maybe_unused]]) noexcept
{ {
if (unlikely(GuardedAlloc.pointerIsMine(ptr)))
{
if (!size)
size = GuardedAlloc.getSize(ptr);
CurrentMemoryTracker::free(size);
return;
}
try try
{ {
#if USE_JEMALLOC #if USE_JEMALLOC