-
Notifications
You must be signed in to change notification settings - Fork 13.6k
[asan][windows] Eliminate the static asan runtime on windows #93770
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
[asan][windows] Eliminate the static asan runtime on windows #93770
Conversation
@llvm/pr-subscribers-platform-windows Author: Charlie Barto (barcharcraz) ChangesOriginally #81677 That PR was reverted due to breaking the MSVC build. The breakage in question was just msvc not understanding the "optnone" attribute, which has been corrected. Patch is 130.66 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/93770.diff 56 Files Affected:
diff --git a/clang/lib/Driver/SanitizerArgs.cpp b/clang/lib/Driver/SanitizerArgs.cpp
index 273f215ca94a8..7b7fd2d9d4742 100644
--- a/clang/lib/Driver/SanitizerArgs.cpp
+++ b/clang/lib/Driver/SanitizerArgs.cpp
@@ -909,10 +909,16 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
DiagnoseErrors);
}
- SharedRuntime =
- Args.hasFlag(options::OPT_shared_libsan, options::OPT_static_libsan,
- TC.getTriple().isAndroid() || TC.getTriple().isOSFuchsia() ||
- TC.getTriple().isOSDarwin());
+ SharedRuntime = Args.hasFlag(
+ options::OPT_shared_libsan, options::OPT_static_libsan,
+ TC.getTriple().isAndroid() || TC.getTriple().isOSFuchsia() ||
+ TC.getTriple().isOSDarwin() || TC.getTriple().isOSWindows());
+ if (!SharedRuntime && TC.getTriple().isOSWindows()) {
+ Arg *A =
+ Args.getLastArg(options::OPT_shared_libsan, options::OPT_static_libsan);
+ D.Diag(clang::diag::err_drv_unsupported_opt_for_target)
+ << A->getSpelling() << TC.getTriple().str();
+ }
ImplicitCfiRuntime = TC.getTriple().isAndroid();
diff --git a/clang/lib/Driver/ToolChains/MSVC.cpp b/clang/lib/Driver/ToolChains/MSVC.cpp
index b7021d4b996dd..bf54f04363851 100644
--- a/clang/lib/Driver/ToolChains/MSVC.cpp
+++ b/clang/lib/Driver/ToolChains/MSVC.cpp
@@ -201,10 +201,10 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (TC.getSanitizerArgs(Args).needsAsanRt()) {
CmdArgs.push_back(Args.MakeArgString("-debug"));
CmdArgs.push_back(Args.MakeArgString("-incremental:no"));
- if (TC.getSanitizerArgs(Args).needsSharedRt() ||
- Args.hasArg(options::OPT__SLASH_MD, options::OPT__SLASH_MDd)) {
- for (const auto &Lib : {"asan_dynamic", "asan_dynamic_runtime_thunk"})
- CmdArgs.push_back(TC.getCompilerRTArgString(Args, Lib));
+ CmdArgs.push_back(TC.getCompilerRTArgString(Args, "asan_dynamic"));
+ auto defines = Args.getAllArgValues(options::OPT_D);
+ if (Args.hasArg(options::OPT__SLASH_MD, options::OPT__SLASH_MDd) ||
+ find(begin(defines), end(defines), "_DLL") != end(defines)) {
// Make sure the dynamic runtime thunk is not optimized out at link time
// to ensure proper SEH handling.
CmdArgs.push_back(Args.MakeArgString(
@@ -213,19 +213,15 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
: "-include:__asan_seh_interceptor"));
// Make sure the linker consider all object files from the dynamic runtime
// thunk.
- CmdArgs.push_back(Args.MakeArgString(std::string("-wholearchive:") +
+ CmdArgs.push_back(Args.MakeArgString(
+ std::string("-wholearchive:") +
TC.getCompilerRT(Args, "asan_dynamic_runtime_thunk")));
- } else if (DLL) {
- CmdArgs.push_back(TC.getCompilerRTArgString(Args, "asan_dll_thunk"));
} else {
- for (const auto &Lib : {"asan", "asan_cxx"}) {
- CmdArgs.push_back(TC.getCompilerRTArgString(Args, Lib));
- // Make sure the linker consider all object files from the static lib.
- // This is necessary because instrumented dlls need access to all the
- // interface exported by the static lib in the main executable.
- CmdArgs.push_back(Args.MakeArgString(std::string("-wholearchive:") +
- TC.getCompilerRT(Args, Lib)));
- }
+ // Make sure the linker consider all object files from the static runtime
+ // thunk.
+ CmdArgs.push_back(Args.MakeArgString(
+ std::string("-wholearchive:") +
+ TC.getCompilerRT(Args, "asan_static_runtime_thunk")));
}
}
diff --git a/clang/test/Driver/cl-link.c b/clang/test/Driver/cl-link.c
index ffd0b5ac4bade..f526044276045 100644
--- a/clang/test/Driver/cl-link.c
+++ b/clang/test/Driver/cl-link.c
@@ -13,10 +13,8 @@
// ASAN: link.exe
// ASAN: "-debug"
// ASAN: "-incremental:no"
-// ASAN: "{{[^"]*}}clang_rt.asan.lib"
-// ASAN: "-wholearchive:{{.*}}clang_rt.asan.lib"
-// ASAN: "{{[^"]*}}clang_rt.asan_cxx.lib"
-// ASAN: "-wholearchive:{{.*}}clang_rt.asan_cxx.lib"
+// ASAN: "{{[^"]*}}clang_rt.asan_dynamic.lib"
+// ASAN: "-wholearchive:{{.*}}clang_rt.asan_static_runtime_thunk.lib"
// ASAN: "{{.*}}cl-link{{.*}}.obj"
// RUN: %clang_cl -m32 -arch:IA32 --target=i386-pc-win32 /MD /Tc%s -fuse-ld=link -### -fsanitize=address 2>&1 | FileCheck --check-prefix=ASAN-MD %s
@@ -24,7 +22,6 @@
// ASAN-MD: "-debug"
// ASAN-MD: "-incremental:no"
// ASAN-MD: "{{.*}}clang_rt.asan_dynamic.lib"
-// ASAN-MD: "{{[^"]*}}clang_rt.asan_dynamic_runtime_thunk.lib"
// ASAN-MD: "-include:___asan_seh_interceptor"
// ASAN-MD: "-wholearchive:{{.*}}clang_rt.asan_dynamic_runtime_thunk.lib"
// ASAN-MD: "{{.*}}cl-link{{.*}}.obj"
@@ -40,7 +37,8 @@
// ASAN-DLL: "-dll"
// ASAN-DLL: "-debug"
// ASAN-DLL: "-incremental:no"
-// ASAN-DLL: "{{.*}}clang_rt.asan_dll_thunk.lib"
+// ASAN-DLL: "{{.*}}clang_rt.asan_dynamic.lib"
+// ASAN-DLL: "-wholearchive:{{.*}}clang_rt.asan_static_runtime_thunk.lib"
// ASAN-DLL: "{{.*}}cl-link{{.*}}.obj"
// RUN: %clang_cl /Zi /Tc%s -fuse-ld=link -### 2>&1 | FileCheck --check-prefix=DEBUG %s
diff --git a/compiler-rt/CMakeLists.txt b/compiler-rt/CMakeLists.txt
index 6ce451e3cac2e..158fa270c3f15 100644
--- a/compiler-rt/CMakeLists.txt
+++ b/compiler-rt/CMakeLists.txt
@@ -378,8 +378,12 @@ if("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "s390x")
endif()
if(MSVC)
- # FIXME: In fact, sanitizers should support both /MT and /MD, see PR20214.
- set(CMAKE_MSVC_RUNTIME_LIBRARY MultiThreaded)
+
+ # asan on windows only supports the release dll version of the runtimes, in the interest of
+ # only having one asan dll to support/test. Having asan statically linked
+ # with the runtime might be possible, but it multiplies the number of scenerios to test.
+ # the program USING sanitizers can use whatever version of the runtime it wants to.
+ set(CMAKE_MSVC_RUNTIME_LIBRARY MultiThreadedDLL)
# Remove any /M[DT][d] flags, and strip any definitions of _DEBUG.
# Since we're using CMAKE_MSVC_RUNTIME_LIBRARY (CMP0091 set to NEW),
diff --git a/compiler-rt/lib/asan/CMakeLists.txt b/compiler-rt/lib/asan/CMakeLists.txt
index 463ea233b37aa..f992419c6d982 100644
--- a/compiler-rt/lib/asan/CMakeLists.txt
+++ b/compiler-rt/lib/asan/CMakeLists.txt
@@ -32,6 +32,20 @@ set(ASAN_SOURCES
asan_win.cpp
)
+if(WIN32)
+ set(ASAN_DYNAMIC_RUNTIME_THUNK_SOURCES
+ asan_globals_win.cpp
+ asan_win_common_runtime_thunk.cpp
+ asan_win_dynamic_runtime_thunk.cpp
+ )
+ set(ASAN_STATIC_RUNTIME_THUNK_SOURCES
+ asan_globals_win.cpp
+ asan_malloc_win_thunk.cpp
+ asan_win_common_runtime_thunk.cpp
+ asan_win_static_runtime_thunk.cpp
+ )
+endif()
+
if (NOT WIN32 AND NOT APPLE)
list(APPEND ASAN_SOURCES
asan_interceptors_vfork.S
@@ -136,7 +150,7 @@ append_list_if(MINGW "${MINGW_LIBRARIES}" ASAN_DYNAMIC_LIBS)
add_compiler_rt_object_libraries(RTAsan_dynamic
OS ${SANITIZER_COMMON_SUPPORTED_OS}
ARCHS ${ASAN_SUPPORTED_ARCH}
- SOURCES ${ASAN_SOURCES} ${ASAN_CXX_SOURCES}
+ SOURCES ${ASAN_SOURCES}
ADDITIONAL_HEADERS ${ASAN_HEADERS}
CFLAGS ${ASAN_DYNAMIC_CFLAGS}
DEFS ${ASAN_DYNAMIC_DEFINITIONS})
@@ -221,46 +235,52 @@ else()
RTSanitizerCommonSymbolizerInternal
RTLSanCommon
RTUbsan)
+ if (NOT WIN32)
+ add_compiler_rt_runtime(clang_rt.asan
+ STATIC
+ ARCHS ${ASAN_SUPPORTED_ARCH}
+ OBJECT_LIBS RTAsan_preinit
+ RTAsan
+ ${ASAN_COMMON_RUNTIME_OBJECT_LIBS}
+ CFLAGS ${ASAN_CFLAGS}
+ DEFS ${ASAN_COMMON_DEFINITIONS}
+ PARENT_TARGET asan)
- add_compiler_rt_runtime(clang_rt.asan
- STATIC
- ARCHS ${ASAN_SUPPORTED_ARCH}
- OBJECT_LIBS RTAsan_preinit
- RTAsan
- ${ASAN_COMMON_RUNTIME_OBJECT_LIBS}
- CFLAGS ${ASAN_CFLAGS}
- DEFS ${ASAN_COMMON_DEFINITIONS}
- PARENT_TARGET asan)
-
- add_compiler_rt_runtime(clang_rt.asan_cxx
- STATIC
- ARCHS ${ASAN_SUPPORTED_ARCH}
- OBJECT_LIBS RTAsan_cxx
- RTUbsan_cxx
- CFLAGS ${ASAN_CFLAGS}
- DEFS ${ASAN_COMMON_DEFINITIONS}
- PARENT_TARGET asan)
+ add_compiler_rt_runtime(clang_rt.asan_cxx
+ STATIC
+ ARCHS ${ASAN_SUPPORTED_ARCH}
+ OBJECT_LIBS RTAsan_cxx
+ RTUbsan_cxx
+ CFLAGS ${ASAN_CFLAGS}
+ DEFS ${ASAN_COMMON_DEFINITIONS}
+ PARENT_TARGET asan)
- add_compiler_rt_runtime(clang_rt.asan_static
- STATIC
- ARCHS ${ASAN_SUPPORTED_ARCH}
- OBJECT_LIBS RTAsan_static
- CFLAGS ${ASAN_CFLAGS}
- DEFS ${ASAN_COMMON_DEFINITIONS}
- PARENT_TARGET asan)
+ add_compiler_rt_runtime(clang_rt.asan_static
+ STATIC
+ ARCHS ${ASAN_SUPPORTED_ARCH}
+ OBJECT_LIBS RTAsan_static
+ CFLAGS ${ASAN_CFLAGS}
+ DEFS ${ASAN_COMMON_DEFINITIONS}
+ PARENT_TARGET asan)
- add_compiler_rt_runtime(clang_rt.asan-preinit
- STATIC
- ARCHS ${ASAN_SUPPORTED_ARCH}
- OBJECT_LIBS RTAsan_preinit
- CFLAGS ${ASAN_CFLAGS}
- DEFS ${ASAN_COMMON_DEFINITIONS}
- PARENT_TARGET asan)
+ add_compiler_rt_runtime(clang_rt.asan-preinit
+ STATIC
+ ARCHS ${ASAN_SUPPORTED_ARCH}
+ OBJECT_LIBS RTAsan_preinit
+ CFLAGS ${ASAN_CFLAGS}
+ DEFS ${ASAN_COMMON_DEFINITIONS}
+ PARENT_TARGET asan)
+ endif()
foreach(arch ${ASAN_SUPPORTED_ARCH})
if (COMPILER_RT_HAS_VERSION_SCRIPT)
+ if(WIN32)
+ set(SANITIZER_RT_VERSION_LIST_LIBS clang_rt.asan-${arch})
+ else()
+ set(SANITIZER_RT_VERSION_LIST_LIBS clang_rt.asan-${arch} clang_rt.asan_cxx-${arch})
+ endif()
add_sanitizer_rt_version_list(clang_rt.asan-dynamic-${arch}
- LIBS clang_rt.asan-${arch} clang_rt.asan_cxx-${arch}
+ LIBS ${SANITIZER_RT_VERSION_LIST_LIBS}
EXTRA asan.syms.extra)
set(VERSION_SCRIPT_FLAG
-Wl,--version-script,${CMAKE_CURRENT_BINARY_DIR}/clang_rt.asan-dynamic-${arch}.vers)
@@ -278,25 +298,11 @@ else()
endif()
set(ASAN_DYNAMIC_WEAK_INTERCEPTION)
- if (WIN32)
- add_compiler_rt_object_libraries(AsanWeakInterception
- ${SANITIZER_COMMON_SUPPORTED_OS}
- ARCHS ${arch}
- SOURCES
- asan_win_weak_interception.cpp
- CFLAGS ${ASAN_CFLAGS} -DSANITIZER_DYNAMIC
- DEFS ${ASAN_COMMON_DEFINITIONS})
- set(ASAN_DYNAMIC_WEAK_INTERCEPTION
- AsanWeakInterception
- UbsanWeakInterception
- SancovWeakInterception
- SanitizerCommonWeakInterception)
- endif()
-
add_compiler_rt_runtime(clang_rt.asan
SHARED
ARCHS ${arch}
OBJECT_LIBS ${ASAN_COMMON_RUNTIME_OBJECT_LIBS}
+ RTAsan_cxx
RTAsan_dynamic
# The only purpose of RTAsan_dynamic_version_script_dummy is to
# carry a dependency of the shared runtime on the version script.
@@ -324,36 +330,12 @@ else()
endif()
if (WIN32)
- add_compiler_rt_object_libraries(AsanDllThunk
- ${SANITIZER_COMMON_SUPPORTED_OS}
- ARCHS ${arch}
- SOURCES asan_globals_win.cpp
- asan_win_dll_thunk.cpp
- CFLAGS ${ASAN_CFLAGS} -DSANITIZER_DLL_THUNK
- DEFS ${ASAN_COMMON_DEFINITIONS})
-
- add_compiler_rt_runtime(clang_rt.asan_dll_thunk
- STATIC
- ARCHS ${arch}
- OBJECT_LIBS AsanDllThunk
- UbsanDllThunk
- SancovDllThunk
- SanitizerCommonDllThunk
- SOURCES $<TARGET_OBJECTS:RTInterception.${arch}>
- PARENT_TARGET asan)
-
set(DYNAMIC_RUNTIME_THUNK_CFLAGS "-DSANITIZER_DYNAMIC_RUNTIME_THUNK")
- if(MSVC)
- list(APPEND DYNAMIC_RUNTIME_THUNK_CFLAGS "-Zl")
- elseif(CMAKE_C_COMPILER_ID MATCHES Clang)
- list(APPEND DYNAMIC_RUNTIME_THUNK_CFLAGS "-nodefaultlibs")
- endif()
add_compiler_rt_object_libraries(AsanDynamicRuntimeThunk
${SANITIZER_COMMON_SUPPORTED_OS}
ARCHS ${arch}
- SOURCES asan_globals_win.cpp
- asan_win_dynamic_runtime_thunk.cpp
+ SOURCES ${ASAN_DYNAMIC_RUNTIME_THUNK_SOURCES}
CFLAGS ${ASAN_CFLAGS} ${DYNAMIC_RUNTIME_THUNK_CFLAGS}
DEFS ${ASAN_COMMON_DEFINITIONS})
@@ -361,12 +343,35 @@ else()
STATIC
ARCHS ${arch}
OBJECT_LIBS AsanDynamicRuntimeThunk
- UbsanDynamicRuntimeThunk
- SancovDynamicRuntimeThunk
- SanitizerCommonDynamicRuntimeThunk
+ UbsanRuntimeThunk
+ SancovRuntimeThunk
+ SanitizerRuntimeThunk
CFLAGS ${ASAN_CFLAGS} ${DYNAMIC_RUNTIME_THUNK_CFLAGS}
DEFS ${ASAN_COMMON_DEFINITIONS}
PARENT_TARGET asan)
+
+ # mingw does not support static linkage of the CRT
+ if(NOT MINGW)
+ set(STATIC_RUNTIME_THUNK_CFLAGS "-DSANITIZER_STATIC_RUNTIME_THUNK")
+
+ add_compiler_rt_object_libraries(AsanStaticRuntimeThunk
+ ${SANITIZER_COMMON_SUPPORTED_OS}
+ ARCHS ${arch}
+ SOURCES ${ASAN_STATIC_RUNTIME_THUNK_SOURCES}
+ CFLAGS ${ASAN_DYNAMIC_CFLAGS} ${STATIC_RUNTIME_THUNK_CFLAGS}
+ DEFS ${ASAN_DYNAMIC_DEFINITIONS})
+
+ add_compiler_rt_runtime(clang_rt.asan_static_runtime_thunk
+ STATIC
+ ARCHS ${arch}
+ OBJECT_LIBS AsanStaticRuntimeThunk
+ UbsanRuntimeThunk
+ SancovRuntimeThunk
+ SanitizerRuntimeThunk
+ CFLAGS ${ASAN_DYNAMIC_CFLAGS} ${STATIC_RUNTIME_THUNK_CFLAGS}
+ DEFS ${ASAN_DYNAMIC_DEFINITIONS}
+ PARENT_TARGET asan)
+ endif()
endif()
endforeach()
endif()
diff --git a/compiler-rt/lib/asan/asan_flags.cpp b/compiler-rt/lib/asan/asan_flags.cpp
index 2398984332321..56deb1b0d082b 100644
--- a/compiler-rt/lib/asan/asan_flags.cpp
+++ b/compiler-rt/lib/asan/asan_flags.cpp
@@ -11,14 +11,16 @@
// ASan flag parsing logic.
//===----------------------------------------------------------------------===//
-#include "asan_activation.h"
#include "asan_flags.h"
+
+#include "asan_activation.h"
#include "asan_interface_internal.h"
#include "asan_stack.h"
#include "lsan/lsan_common.h"
#include "sanitizer_common/sanitizer_common.h"
-#include "sanitizer_common/sanitizer_flags.h"
#include "sanitizer_common/sanitizer_flag_parser.h"
+#include "sanitizer_common/sanitizer_flags.h"
+#include "sanitizer_common/sanitizer_win_interception.h"
#include "ubsan/ubsan_flags.h"
#include "ubsan/ubsan_platform.h"
@@ -47,7 +49,21 @@ static void RegisterAsanFlags(FlagParser *parser, Flags *f) {
#undef ASAN_FLAG
}
-void InitializeFlags() {
+static void DisplayHelpMessages(FlagParser *parser) {
+ // TODO(eugenis): dump all flags at verbosity>=2?
+ if (Verbosity()) {
+ ReportUnrecognizedFlags();
+ }
+
+ if (common_flags()->help) {
+ parser->PrintFlagDescriptions();
+ }
+}
+
+static void InitializeDefaultFlags() {
+ Flags *f = flags();
+ FlagParser asan_parser;
+
// Set the default values and prepare for parsing ASan and common flags.
SetCommonFlagsDefaults();
{
@@ -60,10 +76,8 @@ void InitializeFlags() {
cf.exitcode = 1;
OverrideCommonFlags(cf);
}
- Flags *f = flags();
f->SetDefaults();
- FlagParser asan_parser;
RegisterAsanFlags(&asan_parser, f);
RegisterCommonFlags(&asan_parser);
@@ -126,13 +140,12 @@ void InitializeFlags() {
InitializeCommonFlags();
- // TODO(eugenis): dump all flags at verbosity>=2?
- if (Verbosity()) ReportUnrecognizedFlags();
+ // TODO(samsonov): print all of the flags (ASan, LSan, common).
+ DisplayHelpMessages(&asan_parser);
+}
- if (common_flags()->help) {
- // TODO(samsonov): print all of the flags (ASan, LSan, common).
- asan_parser.PrintFlagDescriptions();
- }
+static void ProcessFlags() {
+ Flags *f = flags();
// Flag validation:
if (!CAN_SANITIZE_LEAKS && common_flags()->detect_leaks) {
@@ -199,6 +212,67 @@ void InitializeFlags() {
}
}
+void InitializeFlags() {
+ InitializeDefaultFlags();
+ ProcessFlags();
+
+#if SANITIZER_WINDOWS
+ // On Windows, weak symbols are emulated by having the user program
+ // register which weak functions are defined.
+ // The ASAN DLL will initialize flags prior to user module initialization,
+ // so __asan_default_options will not point to the user definition yet.
+ // We still want to ensure we capture when options are passed via
+ // __asan_default_options, so we add a callback to be run
+ // when it is registered with the runtime.
+
+ // There is theoretically time between the initial ProcessFlags and
+ // registering the weak callback where a weak function could be added and we
+ // would miss it, but in practice, InitializeFlags will always happen under
+ // the loader lock (if built as a DLL) and so will any calls to
+ // __sanitizer_register_weak_function.
+ AddRegisterWeakFunctionCallback(
+ reinterpret_cast<uptr>(__asan_default_options), []() {
+ FlagParser asan_parser;
+
+ RegisterAsanFlags(&asan_parser, flags());
+ RegisterCommonFlags(&asan_parser);
+ asan_parser.ParseString(__asan_default_options());
+
+ DisplayHelpMessages(&asan_parser);
+ ProcessFlags();
+ });
+
+# if CAN_SANITIZE_UB
+ AddRegisterWeakFunctionCallback(
+ reinterpret_cast<uptr>(__ubsan_default_options), []() {
+ FlagParser ubsan_parser;
+
+ __ubsan::RegisterUbsanFlags(&ubsan_parser, __ubsan::flags());
+ RegisterCommonFlags(&ubsan_parser);
+ ubsan_parser.ParseString(__ubsan_default_options());
+
+ // To match normal behavior, do not print UBSan help.
+ ProcessFlags();
+ });
+# endif
+
+# if CAN_SANITIZE_LEAKS
+ AddRegisterWeakFunctionCallback(
+ reinterpret_cast<uptr>(__lsan_default_options), []() {
+ FlagParser lsan_parser;
+
+ __lsan::RegisterLsanFlags(&lsan_parser, __lsan::flags());
+ RegisterCommonFlags(&lsan_parser);
+ lsan_parser.ParseString(__lsan_default_options());
+
+ // To match normal behavior, do not print LSan help.
+ ProcessFlags();
+ });
+# endif
+
+#endif
+}
+
} // namespace __asan
SANITIZER_INTERFACE_WEAK_DEF(const char*, __asan_default_options, void) {
diff --git a/compiler-rt/lib/asan/asan_globals_win.cpp b/compiler-rt/lib/asan/asan_globals_win.cpp
index 19af88ab12b40..8267f07b9cce4 100644
--- a/compiler-rt/lib/asan/asan_globals_win.cpp
+++ b/compiler-rt/lib/asan/asan_globals_win.cpp
@@ -28,7 +28,9 @@ static void call_on_globals(void (*hook)(__asan_global *, uptr)) {
__asan_global *end = &__asan_globals_end;
uptr bytediff = (uptr)end - (uptr)start;
if (bytediff % sizeof(__asan_global) != 0) {
-#if defined(SANITIZER_DLL_THUNK) || defined(SANITIZER_DYNAMIC_RUNTIME_THUNK)
+# if defined(SANITIZER_DLL_THUNK) || \
+ defined(SANITIZER_DYNAMIC_RUNTIME_THUNK) || \
+ defined(SANITIZER_STATIC_RUNTIME_THUNK)
__debugbreak();
#else
CHECK("corrupt asan global array");
diff --git a/compiler-rt/lib/asan/asan_malloc_win.cpp b/compiler-rt/lib/asan/asan_malloc_win.cpp
index 7e1d04c36dd58..3278f07219876 100644
--- a/compiler-rt/lib/asan/asan_malloc_win.cpp
+++ b/compiler-rt/lib/asan/asan_malloc_win.cpp
@@ -58,97 +58,69 @@ using namespace __asan;
// MD: Memory allocation functions are defined in the CRT .dll,
// so we have to intercept them before they are called for the first time.
-#if ASAN_DYNAMIC
-# define ALLOCATION_FUNCTION_ATTRIBUTE
-#else
-# define ALLOCATION_FUNCTION_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
-#endif
-
extern "C" {
-ALLOCATION_FUNCTION_ATTRIBUTE
-size_t _msize(void *ptr) {
+__declspec(noinline) size_t _msize(void *ptr) {
GET_CURRENT_PC_BP_SP;
(void)sp;
return asan_malloc_usable_size(ptr, pc, bp);
}
-ALLOCATION_FUNCTION_ATTRIBUTE
-size_t _msize_base(void *ptr) {
- return _msize(ptr);
-}
+__declspec(noinline) size_t _msize_base(void *ptr) { return _msize(ptr); }
-ALLOCATION_FUNCTION_ATTRIBUTE
-void free(void *ptr) {
+__declspec(noinline) void free(void *ptr) {
GET_STACK_TRACE_FREE;
return asan_free(ptr, &stack, FROM_MALLOC);
}
-ALLOCATION_FUNCTION_ATTRIBUTE
-void _free_dbg(void *ptr, int) {
- free(ptr);
-}
+__declspec(noinline) void _free_dbg(void *ptr, int) { free(ptr); }
-ALLOCATION_FUNCTION_ATTRIBUTE
-void _free_base(void *ptr) {
- free(ptr);
-}
+__declspec(noinlin...
[truncated]
|
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.
latest commit LGTM
The profiling runtime is still built with /MT, as it does not work with /MD (and not well supported on windows) Co-authored-by: Amy Wishnousky <[email protected]>
Instead build only ONE asan runtime on windows. File Overview: * asan_malloc_win_thunk.cpp Contains interceptors for malloc/free for applications using the static CRT. These are intercepted with an oldnames style library that takes precedence over the CRT because of linker search order. This is used instead of the library interception routines used for other functions so that we can intercept mallocs that happen before our interceptors run. Some other CRT functions are also included here, because they are provided by the same objects as allocation functions in the debug CRT. * asan_win_common_runtime_thunk.cpp just the common init code for both static and dynamic CRTs * asan_win_static_runtime_thunk.cpp static CRT specific initialization * asan_win_dynamic_runtime_thunk.cpp dynamic crt initialization, most of the content that was here has been moved to the common runtime thunk * asan_win_dll_thunk.cpp This used to provide functionality to redirect calls from DLLs to asan instrumented functions in the main library, but this never worked that well and was a nightmare. It's gone now * sanitizer_common/sanitizer_common_interface.inc: The added functions are for the thunks to be able to delegate to the asan runtime DLL in order to override functions that live in the application executable at initialization. The ASAN dll can't do this itself because it doesn't have a way to get the addresses of these functions. * sanitizer_common/sanitizer_win_immortalize: This is just an implementation of call_once that doens't require the CRT or C++ stdlib. We need this because we need to do this sort of thing before the CRT has initialized. This infrastructure is kinda ugly, we're sorry. * sanitizer_common/sanitizer_win_interception.cpp: Provides the interface inside the sanitizer runtime DLL that instramented apps call to intercept stuff. * sanitizer_common/sanitizer_win_thunk_interception.cpp: this is the code to setup and run the static initializers and/or TLS initializers, implemented basically how any initializers are on windows, these ones are registered before all the CRT initializers. * sanitizer_common/sanitizer_win_thunk_interception.h INTERCEPT_LIBRARY_FUNCTION and REGISTER_WEAK_FUNCTION are the called initializers for each relevant function inside the instrumented binary. Note the optimizer is disabled for weak function registration routines because it detects that the two functions being compared have different names and deduces they must be the same, and no actual codegen for the if is required, causing an infinite loop. Clang does this in debug mode as well as release mode, and the cast to uintptr_t is required to suppress it in debug mode. Co-Authored-By: Amy Wishnousky <[email protected]>
Now that the static runtime is gone the required librares are different. Note that /MD or -D_DLL causes the dynamic runtime to get linked, this is a little gross but emulates the behavior of MSVC. "Real" msvc will link the debug build of asan if you specify /DEBUG or _DEBUG, but that's not really necessary and requires building multiple configurations from the same tree.
weak functions are registered after the asan runtime initializes. This means __asan_default_options isn't available during asan runtime initialization. Thus we split asan flag processing into two parts and register a callback for the second part that's executed after __asan_default_options is registered. Co-Authored-By: Amy Wishnousky <[email protected]>
ALLOCATION_FUNCTION_ATTRIBUTE wasn't used elsewhere, and was just one attribute, so abstracting it through a macro wasn't doing much good now that it's not conditional on runtime type. We're always in the dynamic runtime now so eliminate the preprocessor conditional. The new exported functions are the interface used by the intercepted malloc/free family in the instrumented binary to call the asan versions inside the dll runtime. Co-authored-by: Amy Wishnousky <[email protected]>
…runtime thunks and the fact we're "always" using the dynamic asan runtime. python formatting
… config After the windows static runtime is removed these static=static CRT and dynamic=dynamic CRT, both using the dynamic asan runtime.
This is required because now that there's only one asan runtime dll the dynamic/static CRT wholearchived runtime thunk "flavor" is determined by passing the /MD or /MDd options, or defining -D_DLL.
089fc39
to
3cea849
Compare
Originally #81677
That PR was reverted due to breaking the MSVC build. The breakage in question was just msvc not understanding the "optnone" attribute, which has been corrected.
I had applied this fix to our internal fork already, but didn't bring it over as for some reason I figured clang-specific code was OK (no idea why I thought this, at least the build should pass).
I have further changes that make the tests pass when building/running with msvc as well, but as the failures are pre-existing there's no need to include them here and make this diff even bigger.