mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-24 15:26:24 +00:00

This is one of the major changes we (Microsoft) have made in the version of asan we ship with Visual Studio. @amyw-msft wrote a blog post outlining this work at https://devblogs.microsoft.com/cppblog/msvc-address-sanitizer-one-dll-for-all-runtime-configurations/ > With Visual Studio 2022 version 17.7 Preview 3, we have refactored the MSVC Address Sanitizer (ASan) to depend on one runtime DLL regardless of the runtime configuration. This simplifies project onboarding and supports more scenarios, particularly for projects statically linked (/MT, /MTd) to the C Runtimes. However, static configurations have a new dependency on the ASan runtime DLL. > Summary of the changes: > ASan now works with /MT or /MTd built DLLs when the host EXE was not compiled with ASan. This includes Windows services, COM components, and plugins. Configuring your project with ASan is now simpler, since your project doesn’t need to uniformly specify the same [runtime configuration](https://learn.microsoft.com/en-us/cpp/build/reference/md-mt-ld-use-run-time-library?view=msvc-170) (/MT, /MTd, /MD, /MDd). ASan workflows and pipelines for /MT or /MTd built projects will need to ensure the ASan DLL (clang_rt.asan_dynamic-<arch>.dll) is available on PATH. The names of the ASan .lib files needed by the linker have changed (the linker normally takes care of this if not manually specifying lib names via /INFERASANLIBS) You cannot mix ASan-compiled binaries from previous versions of the MSVC Address Sanitizer (this is always true, but especially true in this case). Here's the description of these changes from our internal PR 1. Build one DLL that includes everything debug mode needs (not included here, already contributed upstream). * Remove #if _DEBUG checks everywhere. * In some places, this needed to be replaced with a runtime check. In asan_win.cpp, IsDebugRuntimePresent was added where we are searching for allocations prior to ASAN initialization. * In asan_win_runtime_functions.cpp and interception_win.cpp, we need to be aware of debug runtime DLLs even when not built with _DEBUG. 2. Redirect statically linked functions to the ASAN DLL for /MT * New exports for each of the C allocation APIs so that the statically linked portion of the runtime can call them (see asan_malloc_win.cpp, search MALLOC_DLL_EXPORT). Since we want our stack trace information to be accurate and without noise, this means we need to capture stack frame info from the original call and tell it to our DLL export. For this, I have reused the __asan_win_new_delete_data used for op new/delete support from asan_win_new_delete_thunk_common.h and moved it into asan_win_thunk_common.h renamed as __asan_win_stack_data. * For the C allocation APIs, a new file is included in the statically-linked /WHOLEARCHIVE lib - asan_malloc_win_thunk.cpp. These functions simply provide definitions for malloc/free/etc to be used instead of the UCRT's definitions for /MT and instead call the ASAN DLL export. /INFERASANLIBS ensures libucrt.lib will not take precedence via /WHOLEARCHIVE. * For other APIs, the interception code was called, so a new export is provided: __sanitizer_override_function. __sanitizer_override_function_by_addr is also provided to support __except_handler4 on x86 (due to the security cookie being per-module). 3. Support weak symbols for /MD * We have customers (CoreCLR) that rely on this behavior and would force /MT to get it. * There was sanitizer_win_weak_interception.cpp before, which did some stuff for setting up the .WEAK section, but this only worked on /MT. Now stuff registered in the .WEAK section is passed to the ASAN DLL via new export __sanitizer_register_weak_function (impl in sanitizer_win_interception.cpp). Unlike linux, multiple weak symbol registrations are possible here. Current behavior is to give priority on module load order such that whoever loads last (so priority is given to the EXE) will have their weak symbol registered. * Unfortunately, the registration can only occur during the user module startup, which is after ASAN DLL startup, so any weak symbols used by ASAN during initialization will not be picked up. This is most notable for __asan_default_options and friends (see asan_flags.cpp). A mechanism was made to add a callback for when a certain weak symbol was registered, so now we process __asan_default_options during module startup instead of ASAN startup. This is a change in behavior, but there's no real way around this due to how DLLs are. 4. Build reorganization * I noticed that our current build configuration is very MSVC-specific and so did a bit of reworking. Removed a lot of create_multiple_windows_obj_lib use since it's no longer needed and it changed how we needed to refer to each object_lib by adding runtime configuration to the name, conflicting with how it works for non-MSVC. * No more Win32 static build, use /MD everywhere. * Building with /Zl to avoid defaultlib warnings. In addition: * I've reapplied "[sanitizer][asan][win] Intercept _strdup on Windows instead of strdup" which broke the previous static asan runtime. That runtime is gone now and this change is required for the strdup tests to work. * I've modified the MSVC clang driver to support linking the correct asan libraries, including via defining _DLL (which triggers different defaultlibs and should result in the asan dll thunk being linked, along with the dll CRT (via defaultlib directives). * I've made passing -static-libsan an error on windows, and made -shared-libsan the default. I'm not sure I did this correctly, or in the best way. * Modified the test harnesses to add substitutions for the dynamic and static thunks and to make the library substitutions point to the dynamic asan runtime for all test configurations on windows. Both the static and dynamic windows test configurations remain, because they correspond to the static and dynamic CRT, not the static and dynamic asan runtime library. --------- Co-authored-by: Amy Wishnousky <amyw@microsoft.com>
Compiler-RT ================================ This directory and its subdirectories contain source code for the compiler support routines. Compiler-RT is open source software. You may freely distribute it under the terms of the license agreement found in LICENSE.txt. ================================