Skip to content

[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

Merged
merged 20 commits into from
May 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
9ca91de
Build ASAN libraries with /MD instead of /MT on winodws
barcharcraz Feb 13, 2024
116febd
Remove the static ASAN runtimes
barcharcraz Feb 13, 2024
f919912
make it an error to pass -static-libsan on windows and make shared th…
barcharcraz Feb 13, 2024
622f5e4
Teach the MSVC toolchain driver to link the correct asan libraries.
barcharcraz Feb 13, 2024
55f7692
Because all DLLs get initialized before the main module
barcharcraz Feb 13, 2024
ea4bb6c
Clean up asan_malloc_win.cpp and add exports
barcharcraz Feb 13, 2024
ea9094f
add new substitutions to the tests to support the new static/dynamic …
barcharcraz Feb 13, 2024
8f2ab9e
intercept atoll for the static runtime.
barcharcraz Feb 13, 2024
1bb8daa
Remove sanitizer_win_dll_thunk.h from the build
barcharcraz Feb 16, 2024
4c10b10
exclude windows specific interface symbols from linux/darwin tests.
barcharcraz Feb 16, 2024
9562707
correct asan library checks in clang driver tests.
barcharcraz Feb 16, 2024
9ea4ee7
remove unused files from asan windows build
barcharcraz Feb 20, 2024
f0e75d3
Clean up wording of comment in compiler-rt cmakelists file
barcharcraz Feb 20, 2024
4304ac7
rename sanitizer_win_thunk_interception.h header guard
barcharcraz Feb 26, 2024
838056e
Test fixups requiring functional changes
barcharcraz Mar 18, 2024
7113c4a
Add the compiler-rt libdir to path for lit in both static and dynamic…
barcharcraz Mar 19, 2024
3e7c6d2
Pass -D_DLL and -D_MT to the linker for tests
barcharcraz Apr 1, 2024
90ba834
clang-format
barcharcraz Apr 2, 2024
395b70b
[asan][windows] Yet more relaxation of tests
barcharcraz May 29, 2024
3cea849
[LLVM 19] don't optimize register_weak_<whatever> when building with …
barcharcraz Mar 4, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions clang/lib/Driver/SanitizerArgs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand Down
26 changes: 11 additions & 15 deletions clang/lib/Driver/ToolChains/MSVC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand All @@ -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")));
}
}

Expand Down
10 changes: 4 additions & 6 deletions clang/test/Driver/cl-link.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,15 @@
// 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
// ASAN-MD: link.exe
// 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"
Expand All @@ -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
Expand Down
8 changes: 6 additions & 2 deletions compiler-rt/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
159 changes: 82 additions & 77 deletions compiler-rt/lib/asan/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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})
Expand Down Expand Up @@ -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)
Expand All @@ -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.
Expand Down Expand Up @@ -324,49 +330,48 @@ 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})

add_compiler_rt_runtime(clang_rt.asan_dynamic_runtime_thunk
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()
Expand Down
Loading
Loading