Skip to content

Commit 812abfa

Browse files
MaskRayaaryanshukla
authored andcommitted
[nsan] Add nsan_preinit.cpp and make it static library only
llvm#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` (llvm#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 llvm#98523 Pull Request: llvm#98564
1 parent af23017 commit 812abfa

File tree

5 files changed

+36
-24
lines changed

5 files changed

+36
-24
lines changed

compiler-rt/lib/nsan/CMakeLists.txt

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ set(NSAN_SOURCES
1111
nsan_suppressions.cpp
1212
)
1313

14+
set(NSAN_PREINIT_SOURCES
15+
nsan_preinit.cpp)
16+
1417
set(NSAN_HEADERS
1518
nsan.h
1619
nsan_flags.h
@@ -61,6 +64,12 @@ if(NOT APPLE)
6164
ADDITIONAL_HEADERS ${NSAN_HEADERS}
6265
CFLAGS ${NSAN_CFLAGS})
6366

67+
add_compiler_rt_object_libraries(RTNsan_preinit
68+
ARCHS ${NSAN_SUPPORTED_ARCH}
69+
SOURCES ${NSAN_PREINIT_SOURCES}
70+
ADDITIONAL_HEADERS ${NSAN_HEADERS}
71+
CFLAGS ${NSAN_CFLAGS})
72+
6473
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/dummy.cpp "")
6574
add_compiler_rt_object_libraries(RTNsan_dynamic_version_script_dummy
6675
ARCHS ${NSAN_SUPPORTED_ARCH}
@@ -72,7 +81,7 @@ add_compiler_rt_runtime(
7281
clang_rt.nsan
7382
STATIC
7483
ARCHS ${NSAN_SUPPORTED_ARCH}
75-
OBJECT_LIBS RTNsan
84+
OBJECT_LIBS RTNsan_preinit RTNsan
7685
${NSAN_COMMON_RUNTIME_OBJECT_LIBS}
7786
CFLAGS ${NSAN_CFLAGS}
7887
PARENT_TARGET nsan)

compiler-rt/lib/nsan/nsan.cpp

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -801,8 +801,3 @@ extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __nsan_init() {
801801
nsan_init_is_running = false;
802802
nsan_initialized = true;
803803
}
804-
805-
#if SANITIZER_CAN_USE_PREINIT_ARRAY
806-
__attribute__((section(".preinit_array"),
807-
used)) static void (*nsan_init_ptr)() = __nsan_init;
808-
#endif

compiler-rt/lib/nsan/nsan.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ using __sanitizer::uptr;
3232
// Private nsan interface. Used e.g. by interceptors.
3333
extern "C" {
3434

35+
void __nsan_init();
36+
3537
// This marks the shadow type of the given block of application memory as
3638
// unknown.
3739
// printf-free (see comment in nsan_interceptors.cc).

compiler-rt/lib/nsan/nsan_preinit.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//===- nsan_preinit.cpp ---------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// Call __nsan_init early using ELF DT_PREINIT_ARRAY.
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#include "nsan/nsan.h"
14+
#include "sanitizer_common/sanitizer_internal_defs.h"
15+
16+
#if SANITIZER_CAN_USE_PREINIT_ARRAY
17+
18+
__attribute__((section(".preinit_array"), used)) static auto nsan_preinit =
19+
__nsan_init;
20+
21+
#endif

compiler-rt/lib/nsan/tests/CMakeLists.txt

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ set(NSAN_UNITTEST_LINK_FLAGS
1515
${COMPILER_RT_UNITTEST_LINK_FLAGS}
1616
${COMPILER_RT_UNWINDER_LINK_LIBS}
1717
${SANITIZER_TEST_CXX_LIBRARIES})
18+
set(NSAN_UNITTEST_INSTRUMENTED_LINK_FLAGS ${NSAN_UNITTEST_LINK_FLAGS})
19+
list(APPEND NSAN_UNITTEST_INSTRUMENTED_LINK_FLAGS -fsanitize=numerical)
1820

1921
file(GLOB NSAN_HEADERS ../*.h)
2022
set(NSAN_UNITTESTS
@@ -27,30 +29,13 @@ if(COMPILER_RT_DEFAULT_TARGET_ARCH IN_LIST NSAN_SUPPORTED_ARCH)
2729
# NSan unit tests are only run on the host machine.
2830
set(arch ${COMPILER_RT_DEFAULT_TARGET_ARCH})
2931

30-
set(NSAN_TEST_RUNTIME RTNsanTest.${arch})
31-
32-
set(NSAN_TEST_RUNTIME_OBJECTS
33-
$<TARGET_OBJECTS:RTNsan.${arch}>
34-
$<TARGET_OBJECTS:RTInterception.${arch}>
35-
$<TARGET_OBJECTS:RTSanitizerCommon.${arch}>
36-
$<TARGET_OBJECTS:RTSanitizerCommonLibc.${arch}>
37-
$<TARGET_OBJECTS:RTSanitizerCommonSymbolizer.${arch}>)
38-
39-
add_library(${NSAN_TEST_RUNTIME} STATIC
40-
${NSAN_TEST_RUNTIME_OBJECTS})
41-
42-
set_target_properties(${NSAN_TEST_RUNTIME} PROPERTIES
43-
ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
44-
FOLDER "Compiler-RT Runtime tests")
45-
4632
set(NsanTestObjects)
4733
generate_compiler_rt_tests(NsanTestObjects
4834
NsanUnitTests "Nsan-${arch}-Test" ${arch}
4935
SOURCES ${NSAN_UNITTESTS} ${COMPILER_RT_GTEST_SOURCE}
50-
RUNTIME ${NSAN_TEST_RUNTIME}
5136
DEPS ${NSAN_UNIT_TEST_HEADERS}
5237
CFLAGS ${NSAN_UNITTEST_CFLAGS}
53-
LINK_FLAGS ${NSAN_UNITTEST_LINK_FLAGS})
38+
LINK_FLAGS ${NSAN_UNITTEST_INSTRUMENTED_LINK_FLAGS})
5439
set_target_properties(NsanUnitTests PROPERTIES
5540
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
5641
endif()

0 commit comments

Comments
 (0)