mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-16 06:46:33 +00:00
[nsan] Add nsan_preinit.cpp and make it static library only
#94322 defines .preinit_array to initialize nsan early. DT_PREINIT_ARRAY can only be used with the main executable. GNU ld would complain when a DSO has .preinit_array. Therefore, nsan_preinit.cpp cannot be linked into `libclang_rt.nsan.so` (#98415). Working with @alexander-shaposhnikov, we noticed that `Nsan-x86_64-Test --gtest_output=json` without `.preinit_array` will sigsegv. This is because googletest with the JSON output calls `localtime_r` , which calls `free(0)` and fails when `REAL(free)` remains uninitialized (nullptr). This is benign with the default output because malloc/free are all paired and `REAL(free)(ptr)` is not called. To fix the unittest failure, `__nsan_init` needs to be called early (.preinit_array). `asan/tests/CMakeLists.txt:ASAN_UNITTEST_INSTRUMENTED_LINK_FLAGS` ues `-fsanitize=address` to ensure `asan_preinit.cpp.o` is linked into the unittest executable. Port the approach and remove `NSAN_TEST_RUNTIME_OBJECTS`. Fix #98523 Pull Request: https://github.com/llvm/llvm-project/pull/98564
This commit is contained in:
parent
1bafe77d77
commit
a853fe25df
@ -11,6 +11,9 @@ set(NSAN_SOURCES
|
||||
nsan_suppressions.cpp
|
||||
)
|
||||
|
||||
set(NSAN_PREINIT_SOURCES
|
||||
nsan_preinit.cpp)
|
||||
|
||||
set(NSAN_HEADERS
|
||||
nsan.h
|
||||
nsan_flags.h
|
||||
@ -61,6 +64,12 @@ if(NOT APPLE)
|
||||
ADDITIONAL_HEADERS ${NSAN_HEADERS}
|
||||
CFLAGS ${NSAN_CFLAGS})
|
||||
|
||||
add_compiler_rt_object_libraries(RTNsan_preinit
|
||||
ARCHS ${NSAN_SUPPORTED_ARCH}
|
||||
SOURCES ${NSAN_PREINIT_SOURCES}
|
||||
ADDITIONAL_HEADERS ${NSAN_HEADERS}
|
||||
CFLAGS ${NSAN_CFLAGS})
|
||||
|
||||
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/dummy.cpp "")
|
||||
add_compiler_rt_object_libraries(RTNsan_dynamic_version_script_dummy
|
||||
ARCHS ${NSAN_SUPPORTED_ARCH}
|
||||
@ -72,7 +81,7 @@ add_compiler_rt_runtime(
|
||||
clang_rt.nsan
|
||||
STATIC
|
||||
ARCHS ${NSAN_SUPPORTED_ARCH}
|
||||
OBJECT_LIBS RTNsan
|
||||
OBJECT_LIBS RTNsan_preinit RTNsan
|
||||
${NSAN_COMMON_RUNTIME_OBJECT_LIBS}
|
||||
CFLAGS ${NSAN_CFLAGS}
|
||||
PARENT_TARGET nsan)
|
||||
|
@ -801,8 +801,3 @@ extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __nsan_init() {
|
||||
nsan_init_is_running = false;
|
||||
nsan_initialized = true;
|
||||
}
|
||||
|
||||
#if SANITIZER_CAN_USE_PREINIT_ARRAY
|
||||
__attribute__((section(".preinit_array"),
|
||||
used)) static void (*nsan_init_ptr)() = __nsan_init;
|
||||
#endif
|
||||
|
@ -32,6 +32,8 @@ using __sanitizer::uptr;
|
||||
// Private nsan interface. Used e.g. by interceptors.
|
||||
extern "C" {
|
||||
|
||||
void __nsan_init();
|
||||
|
||||
// This marks the shadow type of the given block of application memory as
|
||||
// unknown.
|
||||
// printf-free (see comment in nsan_interceptors.cc).
|
||||
|
21
compiler-rt/lib/nsan/nsan_preinit.cpp
Normal file
21
compiler-rt/lib/nsan/nsan_preinit.cpp
Normal file
@ -0,0 +1,21 @@
|
||||
//===- nsan_preinit.cpp ---------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Call __nsan_init early using ELF DT_PREINIT_ARRAY.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "nsan/nsan.h"
|
||||
#include "sanitizer_common/sanitizer_internal_defs.h"
|
||||
|
||||
#if SANITIZER_CAN_USE_PREINIT_ARRAY
|
||||
|
||||
__attribute__((section(".preinit_array"), used)) static auto nsan_preinit =
|
||||
__nsan_init;
|
||||
|
||||
#endif
|
@ -15,6 +15,8 @@ set(NSAN_UNITTEST_LINK_FLAGS
|
||||
${COMPILER_RT_UNITTEST_LINK_FLAGS}
|
||||
${COMPILER_RT_UNWINDER_LINK_LIBS}
|
||||
${SANITIZER_TEST_CXX_LIBRARIES})
|
||||
set(NSAN_UNITTEST_INSTRUMENTED_LINK_FLAGS ${NSAN_UNITTEST_LINK_FLAGS})
|
||||
list(APPEND NSAN_UNITTEST_INSTRUMENTED_LINK_FLAGS -fsanitize=numerical)
|
||||
|
||||
file(GLOB NSAN_HEADERS ../*.h)
|
||||
set(NSAN_UNITTESTS
|
||||
@ -27,30 +29,13 @@ if(COMPILER_RT_DEFAULT_TARGET_ARCH IN_LIST NSAN_SUPPORTED_ARCH)
|
||||
# NSan unit tests are only run on the host machine.
|
||||
set(arch ${COMPILER_RT_DEFAULT_TARGET_ARCH})
|
||||
|
||||
set(NSAN_TEST_RUNTIME RTNsanTest.${arch})
|
||||
|
||||
set(NSAN_TEST_RUNTIME_OBJECTS
|
||||
$<TARGET_OBJECTS:RTNsan.${arch}>
|
||||
$<TARGET_OBJECTS:RTInterception.${arch}>
|
||||
$<TARGET_OBJECTS:RTSanitizerCommon.${arch}>
|
||||
$<TARGET_OBJECTS:RTSanitizerCommonLibc.${arch}>
|
||||
$<TARGET_OBJECTS:RTSanitizerCommonSymbolizer.${arch}>)
|
||||
|
||||
add_library(${NSAN_TEST_RUNTIME} STATIC
|
||||
${NSAN_TEST_RUNTIME_OBJECTS})
|
||||
|
||||
set_target_properties(${NSAN_TEST_RUNTIME} PROPERTIES
|
||||
ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||
FOLDER "Compiler-RT Runtime tests")
|
||||
|
||||
set(NsanTestObjects)
|
||||
generate_compiler_rt_tests(NsanTestObjects
|
||||
NsanUnitTests "Nsan-${arch}-Test" ${arch}
|
||||
SOURCES ${NSAN_UNITTESTS} ${COMPILER_RT_GTEST_SOURCE}
|
||||
RUNTIME ${NSAN_TEST_RUNTIME}
|
||||
DEPS ${NSAN_UNIT_TEST_HEADERS}
|
||||
CFLAGS ${NSAN_UNITTEST_CFLAGS}
|
||||
LINK_FLAGS ${NSAN_UNITTEST_LINK_FLAGS})
|
||||
LINK_FLAGS ${NSAN_UNITTEST_INSTRUMENTED_LINK_FLAGS})
|
||||
set_target_properties(NsanUnitTests PROPERTIES
|
||||
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||
endif()
|
||||
|
Loading…
x
Reference in New Issue
Block a user