Skip to content

Commit 8fa66c6

Browse files
[asan][windows] Eliminate the static asan runtime on windows (#93770)
Re-Apply: 246234a Originally #81677 The static asan runtime on windows had various buggy hacks to ensure loaded dlls got the executable's copy of asan, these never worked all that well, so we have eliminated the static runtime altogether and made the dynamic runtime work for applications linking any flavor of the CRT. Among other things this allows non-asan-instrumented applications to load asan-instrumented dlls that link against the static CRT. Co-authored-by: Amy Wishnousky <[email protected]>
1 parent 747d670 commit 8fa66c6

Some content is hidden

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

56 files changed

+1291
-1069
lines changed

clang/lib/Driver/SanitizerArgs.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -909,10 +909,16 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
909909
DiagnoseErrors);
910910
}
911911

912-
SharedRuntime =
913-
Args.hasFlag(options::OPT_shared_libsan, options::OPT_static_libsan,
914-
TC.getTriple().isAndroid() || TC.getTriple().isOSFuchsia() ||
915-
TC.getTriple().isOSDarwin());
912+
SharedRuntime = Args.hasFlag(
913+
options::OPT_shared_libsan, options::OPT_static_libsan,
914+
TC.getTriple().isAndroid() || TC.getTriple().isOSFuchsia() ||
915+
TC.getTriple().isOSDarwin() || TC.getTriple().isOSWindows());
916+
if (!SharedRuntime && TC.getTriple().isOSWindows()) {
917+
Arg *A =
918+
Args.getLastArg(options::OPT_shared_libsan, options::OPT_static_libsan);
919+
D.Diag(clang::diag::err_drv_unsupported_opt_for_target)
920+
<< A->getSpelling() << TC.getTriple().str();
921+
}
916922

917923
ImplicitCfiRuntime = TC.getTriple().isAndroid();
918924

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: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -378,8 +378,12 @@ if("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "s390x")
378378
endif()
379379

380380
if(MSVC)
381-
# FIXME: In fact, sanitizers should support both /MT and /MD, see PR20214.
382-
set(CMAKE_MSVC_RUNTIME_LIBRARY MultiThreaded)
381+
382+
# asan on windows only supports the release dll version of the runtimes, in the interest of
383+
# only having one asan dll to support/test. Having asan statically linked
384+
# with the runtime might be possible, but it multiplies the number of scenerios to test.
385+
# the program USING sanitizers can use whatever version of the runtime it wants to.
386+
set(CMAKE_MSVC_RUNTIME_LIBRARY MultiThreadedDLL)
383387

384388
# Remove any /M[DT][d] flags, and strip any definitions of _DEBUG.
385389
# Since we're using CMAKE_MSVC_RUNTIME_LIBRARY (CMP0091 set to NEW),

compiler-rt/lib/asan/CMakeLists.txt

Lines changed: 82 additions & 77 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
@@ -136,7 +150,7 @@ append_list_if(MINGW "${MINGW_LIBRARIES}" ASAN_DYNAMIC_LIBS)
136150
add_compiler_rt_object_libraries(RTAsan_dynamic
137151
OS ${SANITIZER_COMMON_SUPPORTED_OS}
138152
ARCHS ${ASAN_SUPPORTED_ARCH}
139-
SOURCES ${ASAN_SOURCES} ${ASAN_CXX_SOURCES}
153+
SOURCES ${ASAN_SOURCES}
140154
ADDITIONAL_HEADERS ${ASAN_HEADERS}
141155
CFLAGS ${ASAN_DYNAMIC_CFLAGS}
142156
DEFS ${ASAN_DYNAMIC_DEFINITIONS})
@@ -221,46 +235,52 @@ else()
221235
RTSanitizerCommonSymbolizerInternal
222236
RTLSanCommon
223237
RTUbsan)
238+
if (NOT WIN32)
239+
add_compiler_rt_runtime(clang_rt.asan
240+
STATIC
241+
ARCHS ${ASAN_SUPPORTED_ARCH}
242+
OBJECT_LIBS RTAsan_preinit
243+
RTAsan
244+
${ASAN_COMMON_RUNTIME_OBJECT_LIBS}
245+
CFLAGS ${ASAN_CFLAGS}
246+
DEFS ${ASAN_COMMON_DEFINITIONS}
247+
PARENT_TARGET asan)
224248

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)
249+
add_compiler_rt_runtime(clang_rt.asan_cxx
250+
STATIC
251+
ARCHS ${ASAN_SUPPORTED_ARCH}
252+
OBJECT_LIBS RTAsan_cxx
253+
RTUbsan_cxx
254+
CFLAGS ${ASAN_CFLAGS}
255+
DEFS ${ASAN_COMMON_DEFINITIONS}
256+
PARENT_TARGET asan)
243257

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)
258+
add_compiler_rt_runtime(clang_rt.asan_static
259+
STATIC
260+
ARCHS ${ASAN_SUPPORTED_ARCH}
261+
OBJECT_LIBS RTAsan_static
262+
CFLAGS ${ASAN_CFLAGS}
263+
DEFS ${ASAN_COMMON_DEFINITIONS}
264+
PARENT_TARGET asan)
251265

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)
266+
add_compiler_rt_runtime(clang_rt.asan-preinit
267+
STATIC
268+
ARCHS ${ASAN_SUPPORTED_ARCH}
269+
OBJECT_LIBS RTAsan_preinit
270+
CFLAGS ${ASAN_CFLAGS}
271+
DEFS ${ASAN_COMMON_DEFINITIONS}
272+
PARENT_TARGET asan)
273+
endif()
259274

260275
foreach(arch ${ASAN_SUPPORTED_ARCH})
261276
if (COMPILER_RT_HAS_VERSION_SCRIPT)
277+
if(WIN32)
278+
set(SANITIZER_RT_VERSION_LIST_LIBS clang_rt.asan-${arch})
279+
else()
280+
set(SANITIZER_RT_VERSION_LIST_LIBS clang_rt.asan-${arch} clang_rt.asan_cxx-${arch})
281+
endif()
262282
add_sanitizer_rt_version_list(clang_rt.asan-dynamic-${arch}
263-
LIBS clang_rt.asan-${arch} clang_rt.asan_cxx-${arch}
283+
LIBS ${SANITIZER_RT_VERSION_LIST_LIBS}
264284
EXTRA asan.syms.extra)
265285
set(VERSION_SCRIPT_FLAG
266286
-Wl,--version-script,${CMAKE_CURRENT_BINARY_DIR}/clang_rt.asan-dynamic-${arch}.vers)
@@ -278,25 +298,11 @@ else()
278298
endif()
279299

280300
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-
296301
add_compiler_rt_runtime(clang_rt.asan
297302
SHARED
298303
ARCHS ${arch}
299304
OBJECT_LIBS ${ASAN_COMMON_RUNTIME_OBJECT_LIBS}
305+
RTAsan_cxx
300306
RTAsan_dynamic
301307
# The only purpose of RTAsan_dynamic_version_script_dummy is to
302308
# carry a dependency of the shared runtime on the version script.
@@ -324,49 +330,48 @@ else()
324330
endif()
325331

326332
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-
345333
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()
351334

352335
add_compiler_rt_object_libraries(AsanDynamicRuntimeThunk
353336
${SANITIZER_COMMON_SUPPORTED_OS}
354337
ARCHS ${arch}
355-
SOURCES asan_globals_win.cpp
356-
asan_win_dynamic_runtime_thunk.cpp
338+
SOURCES ${ASAN_DYNAMIC_RUNTIME_THUNK_SOURCES}
357339
CFLAGS ${ASAN_CFLAGS} ${DYNAMIC_RUNTIME_THUNK_CFLAGS}
358340
DEFS ${ASAN_COMMON_DEFINITIONS})
359341

360342
add_compiler_rt_runtime(clang_rt.asan_dynamic_runtime_thunk
361343
STATIC
362344
ARCHS ${arch}
363345
OBJECT_LIBS AsanDynamicRuntimeThunk
364-
UbsanDynamicRuntimeThunk
365-
SancovDynamicRuntimeThunk
366-
SanitizerCommonDynamicRuntimeThunk
346+
UbsanRuntimeThunk
347+
SancovRuntimeThunk
348+
SanitizerRuntimeThunk
367349
CFLAGS ${ASAN_CFLAGS} ${DYNAMIC_RUNTIME_THUNK_CFLAGS}
368350
DEFS ${ASAN_COMMON_DEFINITIONS}
369351
PARENT_TARGET asan)
352+
353+
# mingw does not support static linkage of the CRT
354+
if(NOT MINGW)
355+
set(STATIC_RUNTIME_THUNK_CFLAGS "-DSANITIZER_STATIC_RUNTIME_THUNK")
356+
357+
add_compiler_rt_object_libraries(AsanStaticRuntimeThunk
358+
${SANITIZER_COMMON_SUPPORTED_OS}
359+
ARCHS ${arch}
360+
SOURCES ${ASAN_STATIC_RUNTIME_THUNK_SOURCES}
361+
CFLAGS ${ASAN_DYNAMIC_CFLAGS} ${STATIC_RUNTIME_THUNK_CFLAGS}
362+
DEFS ${ASAN_DYNAMIC_DEFINITIONS})
363+
364+
add_compiler_rt_runtime(clang_rt.asan_static_runtime_thunk
365+
STATIC
366+
ARCHS ${arch}
367+
OBJECT_LIBS AsanStaticRuntimeThunk
368+
UbsanRuntimeThunk
369+
SancovRuntimeThunk
370+
SanitizerRuntimeThunk
371+
CFLAGS ${ASAN_DYNAMIC_CFLAGS} ${STATIC_RUNTIME_THUNK_CFLAGS}
372+
DEFS ${ASAN_DYNAMIC_DEFINITIONS}
373+
PARENT_TARGET asan)
374+
endif()
370375
endif()
371376
endforeach()
372377
endif()

0 commit comments

Comments
 (0)