Skip to content

Commit 53a81d4

Browse files
Reland [asan][windows] Eliminate the static asan runtime on windows (#107899)
This reapplies 8fa66c6 ([asan][windows] Eliminate the static asan runtime on windows) for a second time. That PR bounced off the tests because it caused failures in the other sanitizer runtimes, these have been fixed by only building interception, sanitizer_common, and asan with /MD, and continuing to build the rest of the runtimes with /MT. This does mean that any usage of the static ubsan/fuzzer/etc runtimes will mean you're mixing different runtime library linkages in the same app, the interception, sanitizer_common, and asan runtimes are designed for this, however it does result in some linker warnings. Additionally, it turns out when building in release-mode with LLVM_ENABLE_PDBs the build system forced /OPT:ICF. This totally breaks asan's "new" method of doing "weak" functions on windows, and so /OPT:NOICF was explicitly added to asan's link flags. --------- Co-authored-by: Amy Wishnousky <[email protected]>
1 parent 3403438 commit 53a81d4

File tree

58 files changed

+1315
-1092
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+1315
-1092
lines changed

clang/lib/Driver/SanitizerArgs.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -929,10 +929,16 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
929929
DiagnoseErrors);
930930
}
931931

932-
SharedRuntime =
933-
Args.hasFlag(options::OPT_shared_libsan, options::OPT_static_libsan,
934-
TC.getTriple().isAndroid() || TC.getTriple().isOSFuchsia() ||
935-
TC.getTriple().isOSDarwin());
932+
SharedRuntime = Args.hasFlag(
933+
options::OPT_shared_libsan, options::OPT_static_libsan,
934+
TC.getTriple().isAndroid() || TC.getTriple().isOSFuchsia() ||
935+
TC.getTriple().isOSDarwin() || TC.getTriple().isOSWindows());
936+
if (!SharedRuntime && TC.getTriple().isOSWindows()) {
937+
Arg *A =
938+
Args.getLastArg(options::OPT_shared_libsan, options::OPT_static_libsan);
939+
D.Diag(clang::diag::err_drv_unsupported_opt_for_target)
940+
<< A->getSpelling() << TC.getTriple().str();
941+
}
936942

937943
ImplicitCfiRuntime = TC.getTriple().isAndroid();
938944

clang/lib/Driver/ToolChains/MSVC.cpp

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -201,10 +201,10 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
201201
if (TC.getSanitizerArgs(Args).needsAsanRt()) {
202202
CmdArgs.push_back(Args.MakeArgString("-debug"));
203203
CmdArgs.push_back(Args.MakeArgString("-incremental:no"));
204-
if (TC.getSanitizerArgs(Args).needsSharedRt() ||
205-
Args.hasArg(options::OPT__SLASH_MD, options::OPT__SLASH_MDd)) {
206-
for (const auto &Lib : {"asan_dynamic", "asan_dynamic_runtime_thunk"})
207-
CmdArgs.push_back(TC.getCompilerRTArgString(Args, Lib));
204+
CmdArgs.push_back(TC.getCompilerRTArgString(Args, "asan_dynamic"));
205+
auto defines = Args.getAllArgValues(options::OPT_D);
206+
if (Args.hasArg(options::OPT__SLASH_MD, options::OPT__SLASH_MDd) ||
207+
find(begin(defines), end(defines), "_DLL") != end(defines)) {
208208
// Make sure the dynamic runtime thunk is not optimized out at link time
209209
// to ensure proper SEH handling.
210210
CmdArgs.push_back(Args.MakeArgString(
@@ -213,19 +213,15 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
213213
: "-include:__asan_seh_interceptor"));
214214
// Make sure the linker consider all object files from the dynamic runtime
215215
// thunk.
216-
CmdArgs.push_back(Args.MakeArgString(std::string("-wholearchive:") +
216+
CmdArgs.push_back(Args.MakeArgString(
217+
std::string("-wholearchive:") +
217218
TC.getCompilerRT(Args, "asan_dynamic_runtime_thunk")));
218-
} else if (DLL) {
219-
CmdArgs.push_back(TC.getCompilerRTArgString(Args, "asan_dll_thunk"));
220219
} else {
221-
for (const auto &Lib : {"asan", "asan_cxx"}) {
222-
CmdArgs.push_back(TC.getCompilerRTArgString(Args, Lib));
223-
// Make sure the linker consider all object files from the static lib.
224-
// This is necessary because instrumented dlls need access to all the
225-
// interface exported by the static lib in the main executable.
226-
CmdArgs.push_back(Args.MakeArgString(std::string("-wholearchive:") +
227-
TC.getCompilerRT(Args, Lib)));
228-
}
220+
// Make sure the linker consider all object files from the static runtime
221+
// thunk.
222+
CmdArgs.push_back(Args.MakeArgString(
223+
std::string("-wholearchive:") +
224+
TC.getCompilerRT(Args, "asan_static_runtime_thunk")));
229225
}
230226
}
231227

clang/test/Driver/cl-link.c

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,15 @@
1313
// ASAN: link.exe
1414
// ASAN: "-debug"
1515
// ASAN: "-incremental:no"
16-
// ASAN: "{{[^"]*}}clang_rt.asan.lib"
17-
// ASAN: "-wholearchive:{{.*}}clang_rt.asan.lib"
18-
// ASAN: "{{[^"]*}}clang_rt.asan_cxx.lib"
19-
// ASAN: "-wholearchive:{{.*}}clang_rt.asan_cxx.lib"
16+
// ASAN: "{{[^"]*}}clang_rt.asan_dynamic.lib"
17+
// ASAN: "-wholearchive:{{.*}}clang_rt.asan_static_runtime_thunk.lib"
2018
// ASAN: "{{.*}}cl-link{{.*}}.obj"
2119

2220
// 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
2321
// ASAN-MD: link.exe
2422
// ASAN-MD: "-debug"
2523
// ASAN-MD: "-incremental:no"
2624
// ASAN-MD: "{{.*}}clang_rt.asan_dynamic.lib"
27-
// ASAN-MD: "{{[^"]*}}clang_rt.asan_dynamic_runtime_thunk.lib"
2825
// ASAN-MD: "-include:___asan_seh_interceptor"
2926
// ASAN-MD: "-wholearchive:{{.*}}clang_rt.asan_dynamic_runtime_thunk.lib"
3027
// ASAN-MD: "{{.*}}cl-link{{.*}}.obj"
@@ -40,7 +37,8 @@
4037
// ASAN-DLL: "-dll"
4138
// ASAN-DLL: "-debug"
4239
// ASAN-DLL: "-incremental:no"
43-
// ASAN-DLL: "{{.*}}clang_rt.asan_dll_thunk.lib"
40+
// ASAN-DLL: "{{.*}}clang_rt.asan_dynamic.lib"
41+
// ASAN-DLL: "-wholearchive:{{.*}}clang_rt.asan_static_runtime_thunk.lib"
4442
// ASAN-DLL: "{{.*}}cl-link{{.*}}.obj"
4543

4644
// RUN: %clang_cl /Zi /Tc%s -fuse-ld=link -### 2>&1 | FileCheck --check-prefix=DEBUG %s

compiler-rt/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,7 @@ if("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "s390x")
381381
endif()
382382

383383
if(MSVC)
384-
# FIXME: In fact, sanitizers should support both /MT and /MD, see PR20214.
384+
385385
set(CMAKE_MSVC_RUNTIME_LIBRARY MultiThreaded)
386386

387387
# Remove any /M[DT][d] flags, and strip any definitions of _DEBUG.

compiler-rt/lib/asan/CMakeLists.txt

Lines changed: 94 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,20 @@ set(ASAN_SOURCES
3232
asan_win.cpp
3333
)
3434

35+
if(WIN32)
36+
set(ASAN_DYNAMIC_RUNTIME_THUNK_SOURCES
37+
asan_globals_win.cpp
38+
asan_win_common_runtime_thunk.cpp
39+
asan_win_dynamic_runtime_thunk.cpp
40+
)
41+
set(ASAN_STATIC_RUNTIME_THUNK_SOURCES
42+
asan_globals_win.cpp
43+
asan_malloc_win_thunk.cpp
44+
asan_win_common_runtime_thunk.cpp
45+
asan_win_static_runtime_thunk.cpp
46+
)
47+
endif()
48+
3549
if (NOT WIN32 AND NOT APPLE)
3650
list(APPEND ASAN_SOURCES
3751
asan_interceptors_vfork.S
@@ -83,7 +97,13 @@ SET(ASAN_HEADERS
8397
)
8498

8599
include_directories(..)
86-
100+
if(MSVC)
101+
# asan on windows only supports the release dll version of the runtimes, in the interest of
102+
# only having one asan dll to support/test. Having asan statically linked
103+
# with the runtime might be possible, but it multiplies the number of scenerios to test.
104+
# the program USING sanitizers can use whatever version of the runtime it wants to.
105+
set(CMAKE_MSVC_RUNTIME_LIBRARY MultiThreadedDLL)
106+
endif()
87107
set(ASAN_CFLAGS ${SANITIZER_COMMON_CFLAGS})
88108

89109
append_list_if(MSVC /Zl ASAN_CFLAGS)
@@ -117,7 +137,11 @@ append_list_if(WIN32 INTERCEPTION_DYNAMIC_CRT ASAN_DYNAMIC_DEFINITIONS)
117137
set(ASAN_DYNAMIC_CFLAGS ${ASAN_CFLAGS})
118138
append_list_if(COMPILER_RT_HAS_FTLS_MODEL_INITIAL_EXEC
119139
-ftls-model=initial-exec ASAN_DYNAMIC_CFLAGS)
120-
append_list_if(MSVC /DEBUG ASAN_DYNAMIC_LINK_FLAGS)
140+
141+
# LLVM turns /OPT:ICF back on when LLVM_ENABLE_PDBs is set
142+
# we _REALLY_ need to turn it back off for ASAN, because the way
143+
# asan emulates weak functions from DLLs requires NOICF
144+
append_list_if(MSVC "/DEBUG;/OPT:NOICF" ASAN_DYNAMIC_LINK_FLAGS)
121145

122146
set(ASAN_DYNAMIC_LIBS
123147
${COMPILER_RT_UNWINDER_LINK_LIBS}
@@ -136,7 +160,7 @@ append_list_if(MINGW "${MINGW_LIBRARIES}" ASAN_DYNAMIC_LIBS)
136160
add_compiler_rt_object_libraries(RTAsan_dynamic
137161
OS ${SANITIZER_COMMON_SUPPORTED_OS}
138162
ARCHS ${ASAN_SUPPORTED_ARCH}
139-
SOURCES ${ASAN_SOURCES} ${ASAN_CXX_SOURCES}
163+
SOURCES ${ASAN_SOURCES}
140164
ADDITIONAL_HEADERS ${ASAN_HEADERS}
141165
CFLAGS ${ASAN_DYNAMIC_CFLAGS}
142166
DEFS ${ASAN_DYNAMIC_DEFINITIONS})
@@ -221,46 +245,52 @@ else()
221245
RTSanitizerCommonSymbolizerInternal
222246
RTLSanCommon
223247
RTUbsan)
248+
if (NOT WIN32)
249+
add_compiler_rt_runtime(clang_rt.asan
250+
STATIC
251+
ARCHS ${ASAN_SUPPORTED_ARCH}
252+
OBJECT_LIBS RTAsan_preinit
253+
RTAsan
254+
${ASAN_COMMON_RUNTIME_OBJECT_LIBS}
255+
CFLAGS ${ASAN_CFLAGS}
256+
DEFS ${ASAN_COMMON_DEFINITIONS}
257+
PARENT_TARGET asan)
224258

225-
add_compiler_rt_runtime(clang_rt.asan
226-
STATIC
227-
ARCHS ${ASAN_SUPPORTED_ARCH}
228-
OBJECT_LIBS RTAsan_preinit
229-
RTAsan
230-
${ASAN_COMMON_RUNTIME_OBJECT_LIBS}
231-
CFLAGS ${ASAN_CFLAGS}
232-
DEFS ${ASAN_COMMON_DEFINITIONS}
233-
PARENT_TARGET asan)
234-
235-
add_compiler_rt_runtime(clang_rt.asan_cxx
236-
STATIC
237-
ARCHS ${ASAN_SUPPORTED_ARCH}
238-
OBJECT_LIBS RTAsan_cxx
239-
RTUbsan_cxx
240-
CFLAGS ${ASAN_CFLAGS}
241-
DEFS ${ASAN_COMMON_DEFINITIONS}
242-
PARENT_TARGET asan)
259+
add_compiler_rt_runtime(clang_rt.asan_cxx
260+
STATIC
261+
ARCHS ${ASAN_SUPPORTED_ARCH}
262+
OBJECT_LIBS RTAsan_cxx
263+
RTUbsan_cxx
264+
CFLAGS ${ASAN_CFLAGS}
265+
DEFS ${ASAN_COMMON_DEFINITIONS}
266+
PARENT_TARGET asan)
243267

244-
add_compiler_rt_runtime(clang_rt.asan_static
245-
STATIC
246-
ARCHS ${ASAN_SUPPORTED_ARCH}
247-
OBJECT_LIBS RTAsan_static
248-
CFLAGS ${ASAN_CFLAGS}
249-
DEFS ${ASAN_COMMON_DEFINITIONS}
250-
PARENT_TARGET asan)
268+
add_compiler_rt_runtime(clang_rt.asan_static
269+
STATIC
270+
ARCHS ${ASAN_SUPPORTED_ARCH}
271+
OBJECT_LIBS RTAsan_static
272+
CFLAGS ${ASAN_CFLAGS}
273+
DEFS ${ASAN_COMMON_DEFINITIONS}
274+
PARENT_TARGET asan)
251275

252-
add_compiler_rt_runtime(clang_rt.asan-preinit
253-
STATIC
254-
ARCHS ${ASAN_SUPPORTED_ARCH}
255-
OBJECT_LIBS RTAsan_preinit
256-
CFLAGS ${ASAN_CFLAGS}
257-
DEFS ${ASAN_COMMON_DEFINITIONS}
258-
PARENT_TARGET asan)
276+
add_compiler_rt_runtime(clang_rt.asan-preinit
277+
STATIC
278+
ARCHS ${ASAN_SUPPORTED_ARCH}
279+
OBJECT_LIBS RTAsan_preinit
280+
CFLAGS ${ASAN_CFLAGS}
281+
DEFS ${ASAN_COMMON_DEFINITIONS}
282+
PARENT_TARGET asan)
283+
endif()
259284

260285
foreach(arch ${ASAN_SUPPORTED_ARCH})
261286
if (COMPILER_RT_HAS_VERSION_SCRIPT)
287+
if(WIN32)
288+
set(SANITIZER_RT_VERSION_LIST_LIBS clang_rt.asan-${arch})
289+
else()
290+
set(SANITIZER_RT_VERSION_LIST_LIBS clang_rt.asan-${arch} clang_rt.asan_cxx-${arch})
291+
endif()
262292
add_sanitizer_rt_version_list(clang_rt.asan-dynamic-${arch}
263-
LIBS clang_rt.asan-${arch} clang_rt.asan_cxx-${arch}
293+
LIBS ${SANITIZER_RT_VERSION_LIST_LIBS}
264294
EXTRA asan.syms.extra)
265295
set(VERSION_SCRIPT_FLAG
266296
-Wl,--version-script,${CMAKE_CURRENT_BINARY_DIR}/clang_rt.asan-dynamic-${arch}.vers)
@@ -278,25 +308,11 @@ else()
278308
endif()
279309

280310
set(ASAN_DYNAMIC_WEAK_INTERCEPTION)
281-
if (WIN32)
282-
add_compiler_rt_object_libraries(AsanWeakInterception
283-
${SANITIZER_COMMON_SUPPORTED_OS}
284-
ARCHS ${arch}
285-
SOURCES
286-
asan_win_weak_interception.cpp
287-
CFLAGS ${ASAN_CFLAGS} -DSANITIZER_DYNAMIC
288-
DEFS ${ASAN_COMMON_DEFINITIONS})
289-
set(ASAN_DYNAMIC_WEAK_INTERCEPTION
290-
AsanWeakInterception
291-
UbsanWeakInterception
292-
SancovWeakInterception
293-
SanitizerCommonWeakInterception)
294-
endif()
295-
296311
add_compiler_rt_runtime(clang_rt.asan
297312
SHARED
298313
ARCHS ${arch}
299314
OBJECT_LIBS ${ASAN_COMMON_RUNTIME_OBJECT_LIBS}
315+
RTAsan_cxx
300316
RTAsan_dynamic
301317
# The only purpose of RTAsan_dynamic_version_script_dummy is to
302318
# carry a dependency of the shared runtime on the version script.
@@ -324,49 +340,48 @@ else()
324340
endif()
325341

326342
if (WIN32)
327-
add_compiler_rt_object_libraries(AsanDllThunk
328-
${SANITIZER_COMMON_SUPPORTED_OS}
329-
ARCHS ${arch}
330-
SOURCES asan_globals_win.cpp
331-
asan_win_dll_thunk.cpp
332-
CFLAGS ${ASAN_CFLAGS} -DSANITIZER_DLL_THUNK
333-
DEFS ${ASAN_COMMON_DEFINITIONS})
334-
335-
add_compiler_rt_runtime(clang_rt.asan_dll_thunk
336-
STATIC
337-
ARCHS ${arch}
338-
OBJECT_LIBS AsanDllThunk
339-
UbsanDllThunk
340-
SancovDllThunk
341-
SanitizerCommonDllThunk
342-
SOURCES $<TARGET_OBJECTS:RTInterception.${arch}>
343-
PARENT_TARGET asan)
344-
345343
set(DYNAMIC_RUNTIME_THUNK_CFLAGS "-DSANITIZER_DYNAMIC_RUNTIME_THUNK")
346-
if(MSVC)
347-
list(APPEND DYNAMIC_RUNTIME_THUNK_CFLAGS "-Zl")
348-
elseif(CMAKE_C_COMPILER_ID MATCHES Clang)
349-
list(APPEND DYNAMIC_RUNTIME_THUNK_CFLAGS "-nodefaultlibs")
350-
endif()
351344

352345
add_compiler_rt_object_libraries(AsanDynamicRuntimeThunk
353346
${SANITIZER_COMMON_SUPPORTED_OS}
354347
ARCHS ${arch}
355-
SOURCES asan_globals_win.cpp
356-
asan_win_dynamic_runtime_thunk.cpp
348+
SOURCES ${ASAN_DYNAMIC_RUNTIME_THUNK_SOURCES}
357349
CFLAGS ${ASAN_CFLAGS} ${DYNAMIC_RUNTIME_THUNK_CFLAGS}
358350
DEFS ${ASAN_COMMON_DEFINITIONS})
359351

360352
add_compiler_rt_runtime(clang_rt.asan_dynamic_runtime_thunk
361353
STATIC
362354
ARCHS ${arch}
363355
OBJECT_LIBS AsanDynamicRuntimeThunk
364-
UbsanDynamicRuntimeThunk
365-
SancovDynamicRuntimeThunk
366-
SanitizerCommonDynamicRuntimeThunk
356+
UbsanRuntimeThunk
357+
SancovRuntimeThunk
358+
SanitizerRuntimeThunk
367359
CFLAGS ${ASAN_CFLAGS} ${DYNAMIC_RUNTIME_THUNK_CFLAGS}
368360
DEFS ${ASAN_COMMON_DEFINITIONS}
369361
PARENT_TARGET asan)
362+
363+
# mingw does not support static linkage of the CRT
364+
if(NOT MINGW)
365+
set(STATIC_RUNTIME_THUNK_CFLAGS "-DSANITIZER_STATIC_RUNTIME_THUNK")
366+
367+
add_compiler_rt_object_libraries(AsanStaticRuntimeThunk
368+
${SANITIZER_COMMON_SUPPORTED_OS}
369+
ARCHS ${arch}
370+
SOURCES ${ASAN_STATIC_RUNTIME_THUNK_SOURCES}
371+
CFLAGS ${ASAN_DYNAMIC_CFLAGS} ${STATIC_RUNTIME_THUNK_CFLAGS}
372+
DEFS ${ASAN_DYNAMIC_DEFINITIONS})
373+
374+
add_compiler_rt_runtime(clang_rt.asan_static_runtime_thunk
375+
STATIC
376+
ARCHS ${arch}
377+
OBJECT_LIBS AsanStaticRuntimeThunk
378+
UbsanRuntimeThunk
379+
SancovRuntimeThunk
380+
SanitizerRuntimeThunk
381+
CFLAGS ${ASAN_DYNAMIC_CFLAGS} ${STATIC_RUNTIME_THUNK_CFLAGS}
382+
DEFS ${ASAN_DYNAMIC_DEFINITIONS}
383+
PARENT_TARGET asan)
384+
endif()
370385
endif()
371386
endforeach()
372387
endif()

0 commit comments

Comments
 (0)