-
Notifications
You must be signed in to change notification settings - Fork 13.4k
[nsan] Add shared runtime #98415
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[nsan] Add shared runtime #98415
Conversation
Created using spr 1.3.5-bogner
@llvm/pr-subscribers-compiler-rt-sanitizer @llvm/pr-subscribers-clang-driver Author: Fangrui Song (MaskRay) Changesso that Shared runtime is preferred for some platforms (Android, Apple, Fuchsia;
Note: The driver change will be pushed as a separate commit. Full diff: https://github.com/llvm/llvm-project/pull/98415.diff 8 Files Affected:
diff --git a/clang/lib/Driver/SanitizerArgs.cpp b/clang/lib/Driver/SanitizerArgs.cpp
index 86825a6ccf7a1..1fd870b72286e 100644
--- a/clang/lib/Driver/SanitizerArgs.cpp
+++ b/clang/lib/Driver/SanitizerArgs.cpp
@@ -285,8 +285,8 @@ bool SanitizerArgs::needsFuzzerInterceptors() const {
bool SanitizerArgs::needsUbsanRt() const {
// All of these include ubsan.
- if (needsAsanRt() || needsMsanRt() || needsHwasanRt() || needsTsanRt() ||
- needsDfsanRt() || needsLsanRt() || needsCfiDiagRt() ||
+ if (needsAsanRt() || needsMsanRt() || needsNsanRt() || needsHwasanRt() ||
+ needsTsanRt() || needsDfsanRt() || needsLsanRt() || needsCfiDiagRt() ||
(needsScudoRt() && !requiresMinimalRuntime()))
return false;
diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp
index ab1590104b790..80a2b2bf31183 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -1409,6 +1409,8 @@ collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
if (!Args.hasArg(options::OPT_shared) && !TC.getTriple().isAndroid())
HelperStaticRuntimes.push_back("memprof-preinit");
}
+ if (SanArgs.needsNsanRt())
+ SharedRuntimes.push_back("nsan");
if (SanArgs.needsUbsanRt()) {
if (SanArgs.requiresMinimalRuntime())
SharedRuntimes.push_back("ubsan_minimal");
@@ -1479,7 +1481,7 @@ collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
if (SanArgs.linkCXXRuntimes())
StaticRuntimes.push_back("msan_cxx");
}
- if (SanArgs.needsNsanRt())
+ if (!SanArgs.needsSharedRt() && SanArgs.needsNsanRt())
StaticRuntimes.push_back("nsan");
if (!SanArgs.needsSharedRt() && SanArgs.needsTsanRt()) {
StaticRuntimes.push_back("tsan");
diff --git a/clang/test/Driver/sanitizer-ld.c b/clang/test/Driver/sanitizer-ld.c
index e215c034070e0..48e4ea1f7dcb5 100644
--- a/clang/test/Driver/sanitizer-ld.c
+++ b/clang/test/Driver/sanitizer-ld.c
@@ -646,6 +646,24 @@
// CHECK-NSAN-LINUX: libclang_rt.nsan.a"
// CHECK-NSAN-LINUX: "-lpthread" "-lrt" "-lm" "-ldl" "-lresolv"
+// RUN: %clang -### %s 2>&1 --target=x86_64-unknown-linux -fuse-ld=ld -fsanitize=numerical -shared-libsan \
+// RUN: -resource-dir=%S/Inputs/resource_dir \
+// RUN: --sysroot=%S/Inputs/basic_linux_tree \
+// RUN: | FileCheck --check-prefix=CHECK-NSAN-SHARED-LINUX %s
+
+// CHECK-NSAN-SHARED-LINUX: libclang_rt.nsan.so"
+// CHECK-NSAN-SHARED-LINUX-NOT: "-lpthread"
+// CHECK-NSAN-SHARED-LINUX-NOT: "-ldl"
+// CHECK-NSAN-SHARED-LINUX-NOT: "--dynamic-list
+
+// RUN: %clang -### %s 2>&1 --target=x86_64-unknown-linux -fsanitize=numerical,undefined \
+// RUN: -resource-dir=%S/Inputs/resource_dir \
+// RUN: --sysroot=%S/Inputs/basic_linux_tree \
+// RUN: | FileCheck --check-prefix=CHECK-NSAN-UBSAN %s
+
+// CHECK-NSAN-UBSAN: "--whole-archive" "{{[^"]*}}libclang_rt.nsan.a" "--no-whole-archive"
+// CHECK-NSAN-UBSAN-NOT: libclang_rt.ubsan
+
// CFI by itself does not link runtime libraries.
// RUN: not %clang -fsanitize=cfi -### %s 2>&1 \
// RUN: --target=x86_64-unknown-linux -fuse-ld=ld -rtlib=platform \
diff --git a/compiler-rt/lib/nsan/CMakeLists.txt b/compiler-rt/lib/nsan/CMakeLists.txt
index aef9b651ab2ec..d67c3ac434d3a 100644
--- a/compiler-rt/lib/nsan/CMakeLists.txt
+++ b/compiler-rt/lib/nsan/CMakeLists.txt
@@ -6,6 +6,7 @@ set(NSAN_SOURCES
nsan.cpp
nsan_flags.cpp
nsan_interceptors.cpp
+ nsan_malloc_linux.cpp
nsan_stats.cpp
nsan_suppressions.cpp
)
@@ -24,30 +25,98 @@ append_list_if(COMPILER_RT_HAS_FPIC_FLAG -fPIC NSAN_CFLAGS)
set(NSAN_DYNAMIC_LINK_FLAGS ${SANITIZER_COMMON_LINK_FLAGS})
set(NSAN_CFLAGS ${SANITIZER_COMMON_CFLAGS})
+set(NSAN_DYNAMIC_CFLAGS ${NSAN_CFLAGS})
-foreach(arch ${NSAN_SUPPORTED_ARCH})
- add_compiler_rt_runtime(
- clang_rt.nsan
- STATIC
- ARCHS ${arch}
- SOURCES ${NSAN_SOURCES}
- $<TARGET_OBJECTS:RTInterception.${arch}>
- $<TARGET_OBJECTS:RTSanitizerCommon.${arch}>
- $<TARGET_OBJECTS:RTSanitizerCommonLibc.${arch}>
- $<TARGET_OBJECTS:RTSanitizerCommonCoverage.${arch}>
- $<TARGET_OBJECTS:RTSanitizerCommonSymbolizer.${arch}>
- $<TARGET_OBJECTS:RTUbsan.${arch}>
- ADDITIONAL_HEADERS ${NSAN_HEADERS}
- CFLAGS ${NSAN_CFLAGS}
- PARENT_TARGET nsan
- )
-endforeach()
-
-add_compiler_rt_object_libraries(RTNsan
+set(NSAN_COMMON_RUNTIME_OBJECT_LIBS
+ RTInterception
+ RTSanitizerCommon
+ RTSanitizerCommonLibc
+ RTSanitizerCommonCoverage
+ RTSanitizerCommonSymbolizer
+ RTSanitizerCommonSymbolizerInternal
+ RTUbsan)
+
+set(NSAN_DYNAMIC_LIBS
+ ${COMPILER_RT_UNWINDER_LINK_LIBS}
+ ${SANITIZER_CXX_ABI_LIBRARIES}
+ ${SANITIZER_COMMON_LINK_LIBS})
+
+append_list_if(COMPILER_RT_HAS_LIBDL dl NSAN_DYNAMIC_LIBS)
+append_list_if(COMPILER_RT_HAS_LIBRT rt NSAN_DYNAMIC_LIBS)
+append_list_if(COMPILER_RT_HAS_LIBM m NSAN_DYNAMIC_LIBS)
+append_list_if(COMPILER_RT_HAS_LIBPTHREAD pthread NSAN_DYNAMIC_LIBS)
+
+# Compile sources into an object library.
+
+add_compiler_rt_object_libraries(RTNsan_dynamic
+ ARCHS ${NSAN_SUPPORTED_ARCH}
+ SOURCES ${NSAN_SOURCES}
+ ADDITIONAL_HEADERS ${NSAN_HEADERS}
+ CFLAGS ${NSAN_CFLAGS})
+
+if(NOT APPLE)
+ add_compiler_rt_object_libraries(RTNsan
+ ARCHS ${NSAN_SUPPORTED_ARCH}
+ SOURCES ${NSAN_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}
- SOURCES ${NSAN_SOURCES}
- ADDITIONAL_HEADERS ${NSAN_HEADERS}
- CFLAGS ${NSAN_CFLAGS})
+ SOURCES ${CMAKE_CURRENT_BINARY_DIR}/dummy.cpp
+ CFLAGS ${NSAN_DYNAMIC_CFLAGS})
+endif()
+
+add_compiler_rt_runtime(
+ clang_rt.nsan
+ STATIC
+ ARCHS ${NSAN_SUPPORTED_ARCH}
+ OBJECT_LIBS RTNsan
+ ${NSAN_COMMON_RUNTIME_OBJECT_LIBS}
+ CFLAGS ${NSAN_CFLAGS}
+ PARENT_TARGET nsan)
+
+if(NOT APPLE)
+ foreach(arch ${NSAN_SUPPORTED_ARCH})
+ if (COMPILER_RT_HAS_VERSION_SCRIPT)
+ add_sanitizer_rt_version_list(clang_rt.nsan-dynamic-${arch}
+ LIBS clang_rt.nsan-${arch}
+ EXTRA nsan.syms.extra)
+ set(VERSION_SCRIPT_FLAG
+ -Wl,--version-script,${CMAKE_CURRENT_BINARY_DIR}/clang_rt.nsan-dynamic-${arch}.vers)
+ # The Solaris 11.4 linker supports a subset of GNU ld version scripts,
+ # but requires a special option to enable it.
+ if (COMPILER_RT_HAS_GNU_VERSION_SCRIPT_COMPAT)
+ list(APPEND VERSION_SCRIPT_FLAG -Wl,-z,gnu-version-script-compat)
+ endif()
+ set_property(SOURCE
+ ${CMAKE_CURRENT_BINARY_DIR}/dummy.cpp
+ APPEND PROPERTY
+ OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/clang_rt.nsan-dynamic-${arch}.vers)
+ else()
+ set(VERSION_SCRIPT_FLAG)
+ endif()
+
+ add_compiler_rt_runtime(
+ clang_rt.nsan
+ SHARED
+ ARCHS ${arch}
+ OBJECT_LIBS ${NSAN_COMMON_RUNTIME_OBJECT_LIBS}
+ RTNsan_dynamic
+ # The only purpose of RTNsan_dynamic_version_script_dummy is to
+ # carry a dependency of the shared runtime on the version script.
+ # Replacing it with a straightforward
+ # add_dependencies(clang_rt.nsan-dynamic-${arch} clang_rt.nsan-dynamic-${arch}-version-list)
+ # generates an order-only dependency in ninja.
+ RTNsan_dynamic_version_script_dummy
+ CFLAGS ${NSAN_DYNAMIC_CFLAGS}
+ LINK_FLAGS ${NSAN_DYNAMIC_LINK_FLAGS}
+ ${VERSION_SCRIPT_FLAG}
+ LINK_LIBS ${NSAN_DYNAMIC_LIBS}
+ PARENT_TARGET nsan)
+ endforeach()
+endif()
if(COMPILER_RT_INCLUDE_TESTS)
add_subdirectory(tests)
diff --git a/compiler-rt/lib/nsan/nsan.h b/compiler-rt/lib/nsan/nsan.h
index 896e5379dfc37..0fb998b049854 100644
--- a/compiler-rt/lib/nsan/nsan.h
+++ b/compiler-rt/lib/nsan/nsan.h
@@ -55,6 +55,7 @@ extern bool nsan_initialized;
extern bool nsan_init_is_running;
void InitializeInterceptors();
+void InitializeMallocInterceptors();
// See notes in nsan_platform.
// printf-free (see comment in nsan_interceptors.cc).
diff --git a/compiler-rt/lib/nsan/nsan.syms.extra b/compiler-rt/lib/nsan/nsan.syms.extra
index f3be6d39736b7..53ce5833520b8 100644
--- a/compiler-rt/lib/nsan/nsan.syms.extra
+++ b/compiler-rt/lib/nsan/nsan.syms.extra
@@ -1,2 +1,2 @@
-nsan_*
__nsan_*
+__ubsan_*
diff --git a/compiler-rt/lib/nsan/nsan_interceptors.cpp b/compiler-rt/lib/nsan/nsan_interceptors.cpp
index 68127f169ee46..544b44f53cc42 100644
--- a/compiler-rt/lib/nsan/nsan_interceptors.cpp
+++ b/compiler-rt/lib/nsan/nsan_interceptors.cpp
@@ -1,4 +1,4 @@
-//===-- nsan_interceptors.cc ----------------------------------------------===//
+//===- nsan_interceptors.cpp ----------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -29,26 +29,8 @@ using namespace __sanitizer;
using __nsan::nsan_init_is_running;
using __nsan::nsan_initialized;
-constexpr uptr kEarlyAllocBufSize = 16384;
-static uptr allocated_bytes;
-static char early_alloc_buf[kEarlyAllocBufSize];
-
-static bool isInEarlyAllocBuf(const void *ptr) {
- return ((uptr)ptr >= (uptr)early_alloc_buf &&
- ((uptr)ptr - (uptr)early_alloc_buf) < sizeof(early_alloc_buf));
-}
-
template <typename T> T min(T a, T b) { return a < b ? a : b; }
-// Handle allocation requests early (before all interceptors are setup). dlsym,
-// for example, calls calloc.
-static void *HandleEarlyAlloc(uptr size) {
- void *Mem = (void *)&early_alloc_buf[allocated_bytes];
- allocated_bytes += size;
- CHECK_LT(allocated_bytes, kEarlyAllocBufSize);
- return Mem;
-}
-
INTERCEPTOR(void *, memset, void *dst, int v, uptr size) {
// NOTE: This guard is needed because nsan's initialization code might call
// memset.
@@ -105,90 +87,6 @@ INTERCEPTOR(wchar_t *, wmemcpy, wchar_t *dst, const wchar_t *src, uptr size) {
return res;
}
-INTERCEPTOR(void *, malloc, uptr size) {
- // NOTE: This guard is needed because nsan's initialization code might call
- // malloc.
- if (nsan_init_is_running && REAL(malloc) == nullptr)
- return HandleEarlyAlloc(size);
-
- void *res = REAL(malloc)(size);
- if (res)
- __nsan_set_value_unknown(static_cast<u8 *>(res), size);
- return res;
-}
-
-INTERCEPTOR(void *, realloc, void *ptr, uptr size) {
- void *res = REAL(realloc)(ptr, size);
- // FIXME: We might want to copy the types from the original allocation
- // (although that would require that we know its size).
- if (res)
- __nsan_set_value_unknown(static_cast<u8 *>(res), size);
- return res;
-}
-
-INTERCEPTOR(void *, calloc, uptr Nmemb, uptr size) {
- // NOTE: This guard is needed because nsan's initialization code might call
- // calloc.
- if (nsan_init_is_running && REAL(calloc) == nullptr) {
- // Note: EarlyAllocBuf is initialized with zeros.
- return HandleEarlyAlloc(Nmemb * size);
- }
-
- void *res = REAL(calloc)(Nmemb, size);
- if (res)
- __nsan_set_value_unknown(static_cast<u8 *>(res), Nmemb * size);
- return res;
-}
-
-INTERCEPTOR(void, free, void *P) {
- // There are only a few early allocation requests, so we simply skip the free.
- if (isInEarlyAllocBuf(P))
- return;
- REAL(free)(P);
-}
-
-INTERCEPTOR(void *, valloc, uptr size) {
- void *const res = REAL(valloc)(size);
- if (res)
- __nsan_set_value_unknown(static_cast<u8 *>(res), size);
- return res;
-}
-
-INTERCEPTOR(void *, memalign, uptr align, uptr size) {
- void *const res = REAL(memalign)(align, size);
- if (res)
- __nsan_set_value_unknown(static_cast<u8 *>(res), size);
- return res;
-}
-
-INTERCEPTOR(void *, __libc_memalign, uptr align, uptr size) {
- void *const res = REAL(__libc_memalign)(align, size);
- if (res)
- __nsan_set_value_unknown(static_cast<u8 *>(res), size);
- return res;
-}
-
-INTERCEPTOR(void *, pvalloc, uptr size) {
- void *const res = REAL(pvalloc)(size);
- if (res)
- __nsan_set_value_unknown(static_cast<u8 *>(res), size);
- return res;
-}
-
-INTERCEPTOR(void *, aligned_alloc, uptr align, uptr size) {
- void *const res = REAL(aligned_alloc)(align, size);
- if (res)
- __nsan_set_value_unknown(static_cast<u8 *>(res), size);
- return res;
-}
-
-INTERCEPTOR(int, posix_memalign, void **memptr, uptr align, uptr size) {
- int res = REAL(posix_memalign)(memptr, align, size);
- if (res == 0 && *memptr)
- __nsan_set_value_unknown(static_cast<u8 *>(*memptr), size);
- return res;
-}
-
INTERCEPTOR(char *, strfry, char *s) {
const auto Len = internal_strlen(s);
char *res = REAL(strfry)(s);
@@ -317,16 +215,7 @@ void __nsan::InitializeInterceptors() {
mallopt(-3, 32 * 1024); // M_MMAP_THRESHOLD
#endif
- INTERCEPT_FUNCTION(malloc);
- INTERCEPT_FUNCTION(calloc);
- INTERCEPT_FUNCTION(free);
- INTERCEPT_FUNCTION(realloc);
- INTERCEPT_FUNCTION(valloc);
- INTERCEPT_FUNCTION(memalign);
- INTERCEPT_FUNCTION(__libc_memalign);
- INTERCEPT_FUNCTION(pvalloc);
- INTERCEPT_FUNCTION(aligned_alloc);
- INTERCEPT_FUNCTION(posix_memalign);
+ InitializeMallocInterceptors();
INTERCEPT_FUNCTION(memset);
INTERCEPT_FUNCTION(wmemset);
diff --git a/compiler-rt/lib/nsan/nsan_malloc_linux.cpp b/compiler-rt/lib/nsan/nsan_malloc_linux.cpp
new file mode 100644
index 0000000000000..3bfc16f69b9be
--- /dev/null
+++ b/compiler-rt/lib/nsan/nsan_malloc_linux.cpp
@@ -0,0 +1,137 @@
+//===- nsan_malloc_linux.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
+//
+//===----------------------------------------------------------------------===//
+//
+// Interceptors for memory allocation functions on ELF OSes.
+//
+//===----------------------------------------------------------------------===//
+
+#include "interception/interception.h"
+#include "nsan/nsan.h"
+#include "sanitizer_common/sanitizer_allocator_dlsym.h"
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_platform.h"
+#include "sanitizer_common/sanitizer_platform_interceptors.h"
+
+#if !SANITIZER_APPLE && !SANITIZER_WINDOWS
+using namespace __sanitizer;
+using __nsan::nsan_initialized;
+
+struct DlsymAlloc : public DlSymAllocator<DlsymAlloc> {
+ static bool UseImpl() { return !nsan_initialized; }
+};
+
+INTERCEPTOR(void *, aligned_alloc, uptr align, uptr size) {
+ void *res = REAL(aligned_alloc)(align, size);
+ if (res)
+ __nsan_set_value_unknown(static_cast<u8 *>(res), size);
+ return res;
+}
+
+INTERCEPTOR(void *, calloc, uptr nmemb, uptr size) {
+ if (DlsymAlloc::Use())
+ return DlsymAlloc::Callocate(nmemb, size);
+
+ void *res = REAL(calloc)(nmemb, size);
+ if (res)
+ __nsan_set_value_unknown(static_cast<u8 *>(res), nmemb * size);
+ return res;
+}
+
+INTERCEPTOR(void, free, void *ptr) {
+ if (DlsymAlloc::PointerIsMine(ptr))
+ return DlsymAlloc::Free(ptr);
+ REAL(free)(ptr);
+}
+
+INTERCEPTOR(void *, realloc, void *ptr, uptr size) {
+ if (DlsymAlloc::Use() || DlsymAlloc::PointerIsMine(ptr))
+ return DlsymAlloc::Realloc(ptr, size);
+ void *res = REAL(realloc)(ptr, size);
+ // TODO: We might want to copy the types from the original allocation
+ // (although that would require that we know its size).
+ if (res)
+ __nsan_set_value_unknown(static_cast<u8 *>(res), size);
+ return res;
+}
+
+INTERCEPTOR(void *, malloc, uptr size) {
+ if (DlsymAlloc::Use())
+ return DlsymAlloc::Allocate(size);
+
+ void *res = REAL(malloc)(size);
+ if (res)
+ __nsan_set_value_unknown(static_cast<u8 *>(res), size);
+ return res;
+}
+
+INTERCEPTOR(int, posix_memalign, void **memptr, uptr align, uptr size) {
+ int res = REAL(posix_memalign)(memptr, align, size);
+ if (res == 0 && *memptr)
+ __nsan_set_value_unknown(static_cast<u8 *>(*memptr), size);
+ return res;
+}
+
+#if SANITIZER_INTERCEPT_REALLOCARRAY
+INTERCEPTOR(void *, reallocarray, void *ptr, uptr nmemb, uptr size) {
+ void *res = REAL(reallocarray)(ptr, nmemb, size);
+ if (res)
+ __nsan_set_value_unknown(static_cast<u8 *>(res), size);
+}
+#endif // SANITIZER_INTERCEPT_REALLOCARRAY
+
+// Deprecated allocation functions (memalign, pvalloc, valloc, etc).
+#if SANITIZER_INTERCEPT_MEMALIGN
+INTERCEPTOR(void *, memalign, uptr align, uptr size) {
+ void *const res = REAL(memalign)(align, size);
+ if (res)
+ __nsan_set_value_unknown(static_cast<u8 *>(res), size);
+ return res;
+}
+
+INTERCEPTOR(void *, __libc_memalign, uptr align, uptr size) {
+ void *const res = REAL(__libc_memalign)(align, size);
+ if (res)
+ __nsan_set_value_unknown(static_cast<u8 *>(res), size);
+ return res;
+}
+#endif
+
+#if SANITIZER_INTERCEPT_PVALLOC
+INTERCEPTOR(void *, pvalloc, uptr size) {
+ void *const res = REAL(pvalloc)(size);
+ if (res)
+ __nsan_set_value_unknown(static_cast<u8 *>(res), size);
+ return res;
+}
+#endif
+
+INTERCEPTOR(void *, valloc, uptr size) {
+ void *const res = REAL(valloc)(size);
+ if (res)
+ __nsan_set_value_unknown(static_cast<u8 *>(res), size);
+ return res;
+}
+
+void __nsan::InitializeMallocInterceptors() {
+ INTERCEPT_FUNCTION(aligned_alloc);
+ INTERCEPT_FUNCTION(calloc);
+ INTERCEPT_FUNCTION(free);
+ INTERCEPT_FUNCTION(malloc);
+ INTERCEPT_FUNCTION(posix_memalign);
+ INTERCEPT_FUNCTION(realloc);
+
+ INTERCEPT_FUNCTION(memalign);
+ INTERCEPT_FUNCTION(__libc_memalign);
+ INTERCEPT_FUNCTION(pvalloc);
+ INTERCEPT_FUNCTION(valloc);
+#if SANITIZER_INTERCEPT_REALLOCARRAY
+ INTERCEPT_FUNCTION(reallocarray);
+#endif
+}
+
+#endif
|
…bsan * `-fsanitize=numerical,undefined`: don't link in the ubsan standalone runtime. * `-shared-libsan`: link against `libclang_rt.nsan.so` The compiler-rt part will be properly fixed by #98415
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LG, thanks
It seems to cause a build failure: |
It seems the issue was due to old system linker. If I use lld to build compier-rt the build passes. I will fix the buildbot llvm/llvm-zorg#225 |
Thanks. This is a real issue that GNU ld doesn't like |
It still fails to build after a git pull
|
The fix was reverted in 0b15f89 because it broke the sanitizer bot. |
#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: #98564
…bsan * `-fsanitize=numerical,undefined`: don't link in the ubsan standalone runtime. * `-shared-libsan`: link against `libclang_rt.nsan.so` The compiler-rt part will be properly fixed by llvm#98415
so that `clang -fsanitize=numerical -shared-libsan` will use `libclang_rt.nsan.so` on Linux. Shared runtime is preferred for some platforms (Android, Apple, Fuchsia; though they are not supported yet) and helps plugin use cases (llvm#98302). * Update `ninja nsan` to build `libclang_rt.nsan.so` * Fix `nsan.syms.extra`: `nsan_*` is unneeded. Add `__ubsan_*` so that `-fsanitize=numerical,undefined -shared-libsan` works. * Move allocation functions to `nsan_malloc_linux.cpp`. While Apple platforms aren't supported yet, this separation makes it easier to add Apple support. * Delete interceptors for very obsoleted pvalloc/valloc but retain memalign. * Replace `HandleEarlyAlloc` with `DlsymAlloc`. Pull Request: llvm#98415
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
so that
clang -fsanitize=numerical -shared-libsan
will uselibclang_rt.nsan.so
on Linux.Shared runtime is preferred for some platforms (Android, Apple, Fuchsia;
though they are not supported yet) and helps plugin use cases (#98302).
ninja nsan
to buildlibclang_rt.nsan.so
nsan.syms.extra
:nsan_*
is unneeded. Add__ubsan_*
so that-fsanitize=numerical,undefined -shared-libsan
works.nsan_malloc_linux.cpp
. While Appleplatforms aren't supported yet, this separation makes it easier to add
Apple support.
memalign.
HandleEarlyAlloc
withDlsymAlloc
.