From 2811e7c7551c5ec56f1afbfd1749e1f42d264dbf Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Mon, 17 Jul 2023 20:32:03 -0700 Subject: [PATCH] Address Sanitizer support in CoreCLR (#74623) * Enable AddressSanitizer in CoreCLR, Libs, and Host and update runtime-sanitized to run tests with ASAN on Linux and Mac * Unify on HAS_ADDRESS_SANITIZER define name Centralize setting up sanitizer flags. Remove last usage of CLR_CMAKE_ENABLE_ASAN outside of eng/native Remove unnecessary diffs Use the cpuid intrinsic and enable ASAN on InitJitHelpers1. Add comments for the places where we have ASAN disabled Undo changes to src/coreclr/jit/CMakeLists.txt Add docs and fix the docs in the build script. Add docs for the SkipVCEnvInit hook * Remove CRT runtime changes. We won't need this when we finally onboard to Windows with some changes they have coming down the pipeline, so remove them for now to reduce the diff of this PR. * Remove suppression now that we've fixed the underlying issue. * Remove some Windows-only sanitizer CMake that we won't need when ASAN is ready for us to consume on Windows. * Set schedule for runtime-sanitized pipeline * Remove workaround in JIT memory set/copy helpers now that the JIT bug has been fixed. * Add missing helix queues setup template. * Fix missing command to build nativeaot runtime tests as nativeaot. * Add a scenario name to trigger the extended timeout in the libraries test helix configuration. * Remove extraneous whitespace. * Fix using the cross-targetting ILC when sanitizers are enabled. Also pass through our TargetOS and TargetArchitecture variables to the publish command for our native sanitizers targets to correctly do their extra logic. * Disable LSAN on the CustomMain test. * Disable some tests on sanitized runtimes. * Copy the sanitizer runtime for OSX NativeAOT runtime tests. * A little cleanup to try to get the build right now that we are always doing cross-builds on Linux. * Fix crossgen-corelib.proj syntax. * Fix cross-os dac builds to not include the host architecture in the output path. * Split the debugger components into a separate component and make the "unsanitized cross components" build into an "unsanitized debugger components" build as it can't be part of the regular cross-components build * Always write out the host-arch path on Windows and update the cross-dac build script to expect that. * Change to use the dynamic runtime on Windows, as ASAN in VS is moving to a dynamic-only model. * Update docker images to include the sanitizer runtimes in the crossrootfs images. * Fix explicit image tags * The unsanitized build should be of the target architecture, not the host architecture. As a result, we still need a cross-arch build for the cross-arch use cases when sanitized, as well as an unsanitized target arch build for the debugger tools. * Turn off using the sigaltstack for NativeAOT tests that don't use the asansupport.cpp default options * Make sure the shared ASAN runtime is present for the nativeaot/SmokeTests/SharedLibrary test. * Disable crossgen2 tests with sanitizers as they don't get us interesting coverage. * Fix custom default options and disable some more crossgen2-based tests. * Simplify lookup of asan runtime on mac and fix copying the shared runtime for the SharedLibrary NativeAOT test. * Disable test that's failing for weird reasons. * Fix one more alloc-dealloc mismatch that only started to show up after test merging increased allocations in the runtime * Disable the System.Text.Json test suite on sanitized builds as it causes SO failures on Mac * Fix test exclusion * PR feedback. * Fix mac build * Do review changes * Add libbootstrapper object files to the platform manifest now that NativeAOT has * Disable tests that check size on sanitized builds * Use the built-in `include_guard` option * Disable use-after-return checking in ASAN. CoreCLR doesn't do well with parallel stacks. * Only pass the no UAR flag on C and CXX with Clang (not AppleClang). --- .../building/coreclr/linux-instructions.md | 16 ++ .../building/coreclr/macos-instructions.md | 16 ++ docs/workflow/building/coreclr/nativeaot.md | 4 + .../building/coreclr/windows-instructions.md | 20 ++ docs/workflow/building/libraries/README.md | 10 + eng/Subsets.props | 29 ++- eng/build.ps1 | 15 +- eng/build.sh | 16 ++ eng/liveBuilds.targets | 2 +- eng/native/build-commons.sh | 12 + eng/native/configurecompiler.cmake | 217 +++++++++++++----- eng/native/functions.cmake | 45 ++-- eng/native/ijw/IJW.cmake | 13 +- eng/native/init-vs-env.cmd | 10 +- eng/nativeSanitizers.targets | 24 ++ eng/pipelines/common/global-build-job.yml | 5 +- .../build-runtime-tests-and-send-to-helix.yml | 2 - .../runtimes/build-runtime-tests.yml | 5 +- .../templates/runtimes/test-variables.yml | 18 ++ .../coreclr/nativeaot-post-build-steps.yml | 2 +- .../coreclr/templates/crossdac-build.yml | 5 +- eng/pipelines/runtime-sanitized.yml | 102 +++++++- eng/pipelines/runtime.yml | 3 + eng/testing/linker/project.csproj.template | 1 + eng/testing/linker/trimmingTests.targets | 14 +- eng/testing/tests.singlefile.targets | 2 +- src/coreclr/build-runtime.cmd | 27 ++- src/coreclr/build-runtime.sh | 13 ++ src/coreclr/components.cmake | 4 + src/coreclr/crossgen-corelib.proj | 8 +- src/coreclr/dlls/mscordac/CMakeLists.txt | 2 +- src/coreclr/dlls/mscordbi/CMakeLists.txt | 3 +- src/coreclr/enablesanitizers.sh | 24 +- src/coreclr/hosts/corerun/CMakeLists.txt | 5 + .../nativeaot/Bootstrap/CMakeLists.txt | 18 ++ .../nativeaot/Bootstrap/base/CMakeLists.txt | 9 +- .../nativeaot/Bootstrap/dll/CMakeLists.txt | 4 +- src/coreclr/nativeaot/Bootstrap/main.cpp | 7 + .../Microsoft.NETCore.Native.Unix.targets | 4 +- .../Microsoft.NETCore.Native.Windows.targets | 4 +- .../Runtime/windows/PalRedhawkMinWin.cpp | 1 + src/coreclr/pal/src/arch/amd64/context2.S | 2 +- .../pal/src/arch/amd64/exceptionhelper.S | 2 +- src/coreclr/pal/src/arch/arm/context2.S | 2 +- .../pal/src/arch/arm/exceptionhelper.S | 2 +- src/coreclr/pal/src/arch/arm64/context2.S | 4 +- .../pal/src/arch/arm64/exceptionhelper.S | 2 +- src/coreclr/pal/src/arch/i386/context2.S | 2 +- .../pal/src/arch/i386/exceptionhelper.S | 2 +- .../pal/src/arch/loongarch64/context2.S | 2 +- .../src/arch/loongarch64/exceptionhelper.S | 2 +- .../pal/src/exception/machexception.cpp | 46 ++-- src/coreclr/pal/src/thread/thread.cpp | 2 +- src/coreclr/runtime.proj | 10 +- .../tools/aot/crossgen2/crossgen2.csproj | 3 +- .../utilcode/clrhost_nodependencies.cpp | 11 - src/coreclr/vm/frames.h | 6 +- src/coreclr/vm/i386/asmhelpers.asm | 16 ++ src/coreclr/vm/i386/jitinterfacex86.cpp | 15 +- src/coreclr/vm/i386/stublinkerx86.cpp | 12 +- src/coreclr/vm/jithelpers.cpp | 1 + src/coreclr/vm/threads.cpp | 2 + src/coreclr/vm/threadsuspend.cpp | 2 + src/coreclr/vm/wks/CMakeLists.txt | 1 - .../Directory.Build.props | 4 +- src/libraries/Directory.Build.targets | 1 + src/libraries/externals.csproj | 18 ++ src/libraries/tests.proj | 5 + src/mono/CMakeLists.txt | 6 + src/native/corehost/CMakeLists.txt | 6 + .../corehost/apphost/static/CMakeLists.txt | 2 + src/native/corehost/build.cmd | 2 + src/native/corehost/corehost.proj | 3 + src/native/corehost/exe.cmake | 2 + src/native/corehost/test/testexe.cmake | 4 +- src/native/libs/CMakeLists.txt | 20 -- src/native/libs/build-native.cmd | 5 +- src/native/libs/build-native.proj | 1 + src/native/libs/verify-so.sh | 6 +- src/native/minipal/asansupport.cpp | 19 ++ src/native/minipal/utils.h | 58 +++++ src/tests/Common/Directory.Build.targets | 43 ++-- src/tests/Common/helixpublishwitharcade.proj | 1 + src/tests/Common/publishdependency.targets | 2 +- src/tests/Directory.Build.props | 1 + src/tests/Directory.Build.targets | 9 +- .../DefaultInterfaces/CMakeLists.txt | 4 + .../COM/NativeClients/Dispatch/CMakeLists.txt | 4 + .../COM/NativeClients/Events/CMakeLists.txt | 4 + .../NativeClients/Licensing/CMakeLists.txt | 4 + .../NativeClients/Primitives/CMakeLists.txt | 4 + src/tests/build.cmd | 4 + src/tests/build.sh | 4 +- .../nativeaot/CustomMain/CustomMainNative.cpp | 11 + .../GenerateUnmanagedEntryPoints.csproj | 5 + .../SmokeTests/DwarfDump/DwarfDump.csproj | 2 + .../HardwareIntrinsics/X64Avx.csproj | 2 + .../HardwareIntrinsics/X64Avx2.csproj | 2 + .../HardwareIntrinsics/X64Avx512.csproj | 2 + .../HardwareIntrinsics/X64Avx_NoAvx2.csproj | 2 + .../HardwareIntrinsics/X64Baseline.csproj | 2 + .../HardwareIntrinsics/X64Sse42.csproj | 2 + .../SmokeTests/SharedLibrary/CMakeLists.txt | 6 +- .../SharedLibrary/SharedLibrary.cpp | 7 + .../SharedLibrary/SharedLibrary.csproj | 2 + .../coreroot_determinism.csproj | 2 + .../determinism/crossgen2determinism.csproj | 2 + .../readytorun/multifolder/multifolder.csproj | 2 + 108 files changed, 938 insertions(+), 249 deletions(-) create mode 100644 eng/nativeSanitizers.targets create mode 100644 src/native/minipal/asansupport.cpp diff --git a/docs/workflow/building/coreclr/linux-instructions.md b/docs/workflow/building/coreclr/linux-instructions.md index f5dd0693b83b2..8e7457ff52185 100644 --- a/docs/workflow/building/coreclr/linux-instructions.md +++ b/docs/workflow/building/coreclr/linux-instructions.md @@ -99,3 +99,19 @@ Just like you can use specialized Docker images, you can also do any of the supp ## Create the Core_Root The Core_Root provides one of the main ways to test your build. Full instructions on how to build it in the [CoreCLR testing doc](/docs/workflow/testing/coreclr/testing.md), and we also have a detailed guide on how to use it for your own testing in [its own dedicated doc](/docs/workflow/testing/using-corerun-and-coreroot.md). + +## Native Sanitizers + +CoreCLR can be built with native sanitizers like AddressSanitizer to help catch memory safety issues. To build the project with native sanitizers, add the `-fsanitize address` argument to the build script like the following: + +```bash +build.sh -s clr -fsanitize address +``` + +When building the repo with any native sanitizers, you should build all native components in the repo with the same set of sanitizers. + +The following sanitizers are supported for CoreCLR on Linux: + +| Sanitizer Name | `-fsanitize` argument | Support Status | +|-----------------|-----------------------|----------------| +| AddressSanitize | `address` | regularly tested on x64 | diff --git a/docs/workflow/building/coreclr/macos-instructions.md b/docs/workflow/building/coreclr/macos-instructions.md index df55d20420537..8deaf4578bcce 100644 --- a/docs/workflow/building/coreclr/macos-instructions.md +++ b/docs/workflow/building/coreclr/macos-instructions.md @@ -32,3 +32,19 @@ It is possible to get a macOS ARM64 build using an Intel x64 Mac and vice versa, ## Create the Core_Root The Core_Root provides one of the main ways to test your build. Full instructions on how to build it in the [CoreCLR testing doc](/docs/workflow/testing/coreclr/testing.md), and we also have a detailed guide on how to use it for your own testing in [its own dedicated doc](/docs/workflow/testing/using-corerun-and-coreroot.md). + +## Native Sanitizers + +CoreCLR can be built with native sanitizers like AddressSanitizer to help catch memory safety issues. To build the project with native sanitizers, add the `-fsanitize address` argument to the build script like the following: + +```bash +build.sh -s clr -fsanitize address +``` + +When building the repo with any native sanitizers, you should build all native components in the repo with the same set of sanitizers. + +The following sanitizers are supported for CoreCLR on macOS: + +| Sanitizer Name | `-fsanitize` argument | Support Status | +|-----------------|-----------------------|----------------| +| AddressSanitize | `address` | regularly tested on x64 | diff --git a/docs/workflow/building/coreclr/nativeaot.md b/docs/workflow/building/coreclr/nativeaot.md index f13368867afc5..31783578b9fde 100644 --- a/docs/workflow/building/coreclr/nativeaot.md +++ b/docs/workflow/building/coreclr/nativeaot.md @@ -109,6 +109,10 @@ Build library tests by passing the `libs.tests` subset together with the `/p:Tes * [ILC Compiler Architecture](/docs/design/coreclr/botr/ilc-architecture.md) * [Managed Type System](/docs/design/coreclr/botr/managed-type-system.md) +## Native Sanitizers + +Using native sanitizers with NativeAOT requires additional care compared to using them with CoreCLR. In addition to passing the `-fsanitize` flag to the command that builds NativeAOT, you must also pass the `EnableNativeSanitizers` MSBuild property to any commands that build projects with a sanitized NativeAOT build to ensure that any sanitizer runtimes are correctly linked with the project. + ## Further Reading If you want to know more about working with _NativeAOT_ in general, you can check out their [more in-depth docs](/src/coreclr/nativeaot/docs/README.md) in the `src/coreclr/nativeaot` subtree. diff --git a/docs/workflow/building/coreclr/windows-instructions.md b/docs/workflow/building/coreclr/windows-instructions.md index 38ca5af6f513d..3ab6b33bc0474 100644 --- a/docs/workflow/building/coreclr/windows-instructions.md +++ b/docs/workflow/building/coreclr/windows-instructions.md @@ -45,3 +45,23 @@ build.cmd -s clr -c Release -arch arm64 -msbuild ``` Since this is still in an experimental phase, the recommended way for building ARM64 is cross-compiling from an x64 machine. Instructions on how to do this can be found at the [cross-building doc](/docs/workflow/building/coreclr/cross-building.md#cross-compiling-for-arm32-and-arm64). + +## Native Sanitizers + +CoreCLR can be built with native sanitizers like AddressSanitizer to help catch memory safety issues. To build the project with native sanitizers, add the `-fsanitize address` argument to the build script like the following: + +```cmd +build.cmd -s clr -fsanitize address +``` + +When building the repo with any native sanitizers, you should build all native components in the repo with the same set of sanitizers. + +The following sanitizers are supported for CoreCLR on Windows: + +| Sanitizer Name | Minimum VS Version | `-fsanitize` argument | Support Status | +|----------------|--------------------|-----------------------|----------------| +| AddressSanitizer | not yet released | `address` | experimental | + +## Using a custom compiler environment + +If you ever need to use a custom compiler environment for the native builds on Windows, you can set the `SkipVCEnvInit` environment variable to `1`. The build system will skip discovering Visual Studio and initializing its development environment when this flag is used. This is only required for very advanced scenarios and should be used rarely. diff --git a/docs/workflow/building/libraries/README.md b/docs/workflow/building/libraries/README.md index f24d47e608271..f1e0726e69074 100644 --- a/docs/workflow/building/libraries/README.md +++ b/docs/workflow/building/libraries/README.md @@ -105,6 +105,16 @@ By default the `build` script only builds the product libraries and none of the For Windows, replace `./build.sh` with `build.cmd`. +### Building the native components with native sanitizers + +The libraries native components can be built with native sanitizers like AddressSanitizer to help catch memory safety issues. To build the project with native sanitizers, add the `-fsanitize` argument to the build script like the following: + +```bash +build.sh -s libs -fsanitize address +``` + +When building the repo with any native sanitizers, you should build all native components in the repo with the same set of sanitizers. + ### How to build native components only The libraries build contains some native code. This includes shims over libc, openssl, gssapi, and zlib. The build system uses CMake to generate Makefiles using clang. The build also uses git for generating some version information. diff --git a/eng/Subsets.props b/eng/Subsets.props index 6bd09ac2261a5..4f98634f6372e 100644 --- a/eng/Subsets.props +++ b/eng/Subsets.props @@ -253,8 +253,11 @@ Category="clr" /> - - + + + + + + + @@ -317,8 +338,8 @@ - - + + diff --git a/eng/build.ps1 b/eng/build.ps1 index fc2712fcafe51..67440febafd5c 100644 --- a/eng/build.ps1 +++ b/eng/build.ps1 @@ -22,6 +22,7 @@ Param( [switch]$msbuild, [string]$cmakeargs, [switch]$pgoinstrument, + [string[]]$fsanitize, [Parameter(ValueFromRemainingArguments=$true)][String[]]$properties ) @@ -84,10 +85,13 @@ function Get-Help() { Write-Host "" Write-Host "Native build settings:" - Write-Host " -cmakeargs User-settable additional arguments passed to CMake." - Write-Host " -ninja Use Ninja to drive the native build. (default)" - Write-Host " -msbuild Use MSBuild to drive the native build. This is a no-op for Mono." - Write-Host " -pgoinstrument Build the CLR with PGO instrumentation." + Write-Host " -cmakeargs User-settable additional arguments passed to CMake." + Write-Host " -ninja Use Ninja to drive the native build. (default)" + Write-Host " -msbuild Use MSBuild to drive the native build. This is a no-op for Mono." + Write-Host " -pgoinstrument Build the CLR with PGO instrumentation." + Write-Host " -fsanitize (address) Build the native components with the specified sanitizers." + Write-Host " Sanitizers can be specified with a comma-separated list." + Write-Host "" Write-Host "Command-line arguments not listed above are passed through to MSBuild." Write-Host "The above arguments can be shortened as much as to be unambiguous." @@ -220,7 +224,7 @@ if ($vs) { # Put our local dotnet.exe on PATH first so Visual Studio knows which one to use $env:PATH=($env:DOTNET_ROOT + ";" + $env:PATH); - + # Disable .NET runtime signature validation errors which errors for local builds $env:VSDebugger_ValidateDotnetDebugLibSignatures=0; @@ -269,6 +273,7 @@ foreach ($argument in $PSBoundParameters.Keys) # configuration and arch can be specified multiple times, so they should be no-ops here "configuration" {} "arch" {} + "fsanitize" { $arguments += " /p:EnableNativeSanitizers=$($PSBoundParameters[$argument])"} default { $arguments += " /p:$argument=$($PSBoundParameters[$argument])" } } } diff --git a/eng/build.sh b/eng/build.sh index c4f18b3051df2..772d7ac8be82c 100755 --- a/eng/build.sh +++ b/eng/build.sh @@ -84,6 +84,7 @@ usage() echo " --keepnativesymbols Optional argument: set to true to keep native symbols/debuginfo in generated binaries." echo " --ninja Optional argument: set to true to use Ninja instead of Make to run the native build." echo " --pgoinstrument Optional argument: build PGO-instrumented runtime" + echo " --fsanitize Optional argument: Specify native sanitizers to instrument the native build with. Supported values are: 'address'." echo "" echo "Command line arguments starting with '/p:' are passed through to MSBuild." @@ -509,6 +510,21 @@ while [[ $# > 0 ]]; do shift 1 ;; + -fsanitize) + if [ -z ${2+x} ]; then + echo "No value for -fsanitize is supplied. See help (--help) for supported values." 1>&2 + exit 1 + fi + arguments="$arguments /p:EnableNativeSanitizers=$2" + shift 2 + ;; + + -fsanitize=*) + sanitizers="${opt/#-fsanitize=/}" # -fsanitize=address => address + arguments="$arguments /p:EnableNativeSanitizers=$sanitizers" + shift 2 + ;; + *) extraargs="$extraargs $1" shift 1 diff --git a/eng/liveBuilds.targets b/eng/liveBuilds.targets index 3830816fc037a..efdf7a9c865a2 100644 --- a/eng/liveBuilds.targets +++ b/eng/liveBuilds.targets @@ -25,7 +25,7 @@ $([MSBuild]::NormalizeDirectory('$(CoreCLRArtifactsPath)', 'sharedFramework')) $([MSBuild]::NormalizeDirectory('$(CoreCLRArtifactsPath)', 'crossgen2')) $([MSBuild]::NormalizeDirectory('$(CoreCLRArtifactsPath)', 'ilc-published')) - $([MSBuild]::NormalizeDirectory('$(CoreCLRArtifactsPath)', '$(BuildArchitecture)', 'ilc')) + $([MSBuild]::NormalizeDirectory('$(CoreCLRArtifactsPath)', '$(BuildArchitecture)', 'ilc')) $([MSBuild]::NormalizeDirectory('$(CoreCLRArtifactsPath)', 'aotsdk')) $([MSBuild]::NormalizeDirectory('$(CoreCLRArtifactsPath)', 'build')) diff --git a/eng/native/build-commons.sh b/eng/native/build-commons.sh index 410aab20b0a02..d9eb04cd8aaab 100755 --- a/eng/native/build-commons.sh +++ b/eng/native/build-commons.sh @@ -270,6 +270,7 @@ usage() echo "-portablebuild: pass -portablebuild=false to force a non-portable build." echo "-skipconfigure: skip build configuration." echo "-keepnativesymbols: keep native/unmanaged debug symbols." + echo "-fsanitize: Enable native sanitizers" echo "-verbose: optional argument to enable verbose build output." echo "" echo "Additional Options:" @@ -392,6 +393,17 @@ while :; do __CMakeArgs="$__CMakeArgs -DCLR_CMAKE_KEEP_NATIVE_SYMBOLS=true" ;; + -fsanitize) + __CMakeArgs="$__CMakeArgs -DCLR_CMAKE_ENABLE_SANITIZERS=$2" + EnableNativeSanitizers=$2 + shift + ;; + -fsanitize=*) + sanitizers="${lowerI/#-fsanitize=/}" # -fsanitize=address => address + __CMakeArgs="$__CMakeArgs -DCLR_CMAKE_ENABLE_SANITIZERS=$sanitizers" + EnableNativeSanitizers=$sanitizers + ;; + ninja|-ninja) __UseNinja=1 ;; diff --git a/eng/native/configurecompiler.cmake b/eng/native/configurecompiler.cmake index ee8e324db96f8..bb734c59d5557 100644 --- a/eng/native/configurecompiler.cmake +++ b/eng/native/configurecompiler.cmake @@ -1,3 +1,7 @@ +# Due to how we build the libraries native build as part of the CoreCLR build as well as standalone, +# we can end up coming to this file twice. Only run it once to simplify our build. +include_guard() + include(${CMAKE_CURRENT_LIST_DIR}/configuretools.cmake) # Set initial flags for each configuration @@ -78,7 +82,15 @@ if (MSVC) set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /DEBUG") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /DEBUGTYPE:CV,FIXUP") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /PDBCOMPRESS") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /STACK:1572864") + # For sanitized builds, we bump up the stack size to 8MB to match behavior on Unix platforms. + # Sanitized builds can use significantly more stack space than non-sanitized builds due to instrumentation. + # We don't want to change the default stack size for all builds, as that will likely cause confusion and will + # increase memory usage. + if (CLR_CMAKE_ENABLE_SANITIZERS) + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /STACK:0x800000") + else() + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /STACK:0x180000") + endif() if(EXISTS ${CLR_SOURCELINK_FILE_PATH}) set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /sourcelink:${CLR_SOURCELINK_FILE_PATH}") @@ -112,10 +124,6 @@ if (MSVC) add_linker_flag(/OPT:ICF RELWITHDEBINFO) set(CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO} /LTCG") - # Force uCRT to be dynamically linked for Release build - add_linker_flag(/NODEFAULTLIB:libucrt.lib RELEASE) - add_linker_flag(/DEFAULTLIB:ucrt.lib RELEASE) - elseif (CLR_CMAKE_HOST_UNIX) # Set the values to display when interactively configuring CMAKE_BUILD_TYPE set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "DEBUG;CHECKED;RELEASE;RELWITHDEBINFO") @@ -123,62 +131,6 @@ elseif (CLR_CMAKE_HOST_UNIX) # Use uppercase CMAKE_BUILD_TYPE for the string comparisons below string(TOUPPER ${CMAKE_BUILD_TYPE} UPPERCASE_CMAKE_BUILD_TYPE) - set(CLR_SANITIZE_CXX_OPTIONS "") - set(CLR_SANITIZE_LINK_OPTIONS "") - - # set the CLANG sanitizer flags for debug build - if(UPPERCASE_CMAKE_BUILD_TYPE STREQUAL DEBUG OR UPPERCASE_CMAKE_BUILD_TYPE STREQUAL CHECKED) - # obtain settings from running enablesanitizers.sh - string(FIND "$ENV{DEBUG_SANITIZERS}" "asan" __ASAN_POS) - string(FIND "$ENV{DEBUG_SANITIZERS}" "ubsan" __UBSAN_POS) - if ((${__ASAN_POS} GREATER -1) OR (${__UBSAN_POS} GREATER -1)) - list(APPEND CLR_SANITIZE_CXX_OPTIONS -fsanitize-blacklist=${CMAKE_CURRENT_SOURCE_DIR}/sanitizerblacklist.txt) - set (CLR_CXX_SANITIZERS "") - set (CLR_LINK_SANITIZERS "") - if (${__ASAN_POS} GREATER -1) - list(APPEND CLR_CXX_SANITIZERS address) - list(APPEND CLR_LINK_SANITIZERS address) - set(CLR_SANITIZE_CXX_FLAGS "${CLR_SANITIZE_CXX_FLAGS}address,") - set(CLR_SANITIZE_LINK_FLAGS "${CLR_SANITIZE_LINK_FLAGS}address,") - add_definitions(-DHAS_ASAN) - message("Address Sanitizer (asan) enabled") - endif () - if (${__UBSAN_POS} GREATER -1) - # all sanitizer flags are enabled except alignment (due to heavy use of __unaligned modifier) - list(APPEND CLR_CXX_SANITIZERS - "bool" - bounds - enum - float-cast-overflow - float-divide-by-zero - "function" - integer - nonnull-attribute - null - object-size - "return" - returns-nonnull-attribute - shift - unreachable - vla-bound - vptr) - list(APPEND CLR_LINK_SANITIZERS - undefined) - message("Undefined Behavior Sanitizer (ubsan) enabled") - endif () - list(JOIN CLR_CXX_SANITIZERS "," CLR_CXX_SANITIZERS_OPTIONS) - list(APPEND CLR_SANITIZE_CXX_OPTIONS "-fsanitize=${CLR_CXX_SANITIZERS_OPTIONS}") - list(JOIN CLR_LINK_SANITIZERS "," CLR_LINK_SANITIZERS_OPTIONS) - list(APPEND CLR_SANITIZE_LINK_OPTIONS "-fsanitize=${CLR_LINK_SANITIZERS_OPTIONS}") - - # -O1: optimization level used instead of -O0 to avoid compile error "invalid operand for inline asm constraint" - add_compile_options("$<$,$>:${CLR_SANITIZE_CXX_OPTIONS};-fdata-sections;-O1>") - add_linker_flag("${CLR_SANITIZE_LINK_OPTIONS}" DEBUG CHECKED) - # -Wl and --gc-sections: drop unused sections\functions (similar to Windows /Gy function-level-linking) - add_linker_flag("-Wl,--gc-sections" DEBUG CHECKED) - endif () - endif(UPPERCASE_CMAKE_BUILD_TYPE STREQUAL DEBUG OR UPPERCASE_CMAKE_BUILD_TYPE STREQUAL CHECKED) - if(CLR_CMAKE_HOST_BROWSER OR CLR_CMAKE_HOST_WASI) # The emscripten build has additional warnings so -Werror breaks add_compile_options(-Wno-unused-parameter) @@ -187,6 +139,129 @@ elseif (CLR_CMAKE_HOST_UNIX) endif() endif(MSVC) +if (CLR_CMAKE_ENABLE_SANITIZERS) + set (CLR_CMAKE_BUILD_SANITIZERS "") + set (CLR_CMAKE_SANITIZER_RUNTIMES "") + string(FIND "${CLR_CMAKE_ENABLE_SANITIZERS}" "address" __ASAN_POS) + if(${__ASAN_POS} GREATER -1) + # Set up build flags for AddressSanitizer + set (CLR_CMAKE_ENABLE_ASAN ON) + if (MSVC) + # /RTC1 is added by default by CMake and incompatible with ASAN, so remove it. + string(REPLACE "/RTC1" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}") + string(REPLACE "/RTC1" "" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}") + string(REPLACE "/RTC1" "" CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG}") + string(REPLACE "/RTC1" "" CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG}") + endif() + # For Mac and Windows platforms, we install the ASAN runtime next to the rest of our outputs to ensure that it's present when we execute our tests on Helix machines + # The rest of our platforms use statically-linked ASAN so this isn't a concern for those platforms. + if (CLR_CMAKE_TARGET_OSX OR CLR_CMAKE_TARGET_MACCATALYST) + function(getSanitizerRuntimeDirectory output) + enable_language(C) + execute_process( + COMMAND ${CMAKE_C_COMPILER} -print-resource-dir + OUTPUT_VARIABLE compilerResourceDir + OUTPUT_STRIP_TRAILING_WHITESPACE) + set(${output} "${compilerResourceDir}/lib/darwin/" PARENT_SCOPE) + endfunction() + getSanitizerRuntimeDirectory(sanitizerRuntimeDirectory) + find_library(ASAN_RUNTIME clang_rt.asan_osx_dynamic PATHS ${sanitizerRuntimeDirectory}) + add_compile_definitions(SANITIZER_SHARED_RUNTIME) + elseif (CLR_CMAKE_TARGET_WIN32) + function(getSanitizerRuntimeDirectory output archSuffixOutput) + get_filename_component(compiler_directory "${CMAKE_C_COMPILER}" DIRECTORY) + set(${output} "${compiler_directory}" PARENT_SCOPE) + if (CLR_CMAKE_TARGET_ARCH_I386) + set(${archSuffixOutput} "i386" PARENT_SCOPE) + elseif (CLR_CMAKE_TARGET_ARCH_AMD64) + set(${archSuffixOutput} "x86_64" PARENT_SCOPE) + elseif (CLR_CMAKE_TARGET_ARCH_ARM) + set(${archSuffixOutput} "armhf" PARENT_SCOPE) + elseif (CLR_CMAKE_TARGET_ARCH_ARM64) + set(${archSuffixOutput} "aarch64" PARENT_SCOPE) + endif() + endfunction() + getSanitizerRuntimeDirectory(sanitizerRuntimeDirectory archSuffix) + set(ASAN_RUNTIME "${sanitizerRuntimeDirectory}/clang_rt.asan_dynamic-${archSuffix}.dll") + add_compile_definitions(SANITIZER_SHARED_RUNTIME) + endif() + if (CLR_CMAKE_ENABLE_ASAN) + message("-- Address Sanitizer (asan) enabled") + list(APPEND CLR_CMAKE_BUILD_SANITIZERS + address) + list(APPEND CLR_CMAKE_SANITIZER_RUNTIMES + address) + # We can't use preprocessor defines to determine if we're building with ASAN in assembly, so we'll + # define the preprocessor define ourselves. + add_compile_definitions($<$:HAS_ADDRESS_SANITIZER>) + + # Disable the use-after-return check for ASAN on Clang. This is because we have a lot of code that + # depends on the fact that our locals are not saved in a parallel stack, so we can't enable this today. + # If we ever have a way to detect a parallel stack and track its bounds, we can re-enable this check. + add_compile_options($<$:-fsanitize-address-use-after-return=never>) + add_compile_options($<$:-fsanitize-address-use-after-return=never>) + endif() + endif() + + # Set up build flags for UBSanitizer + if (CLR_CMAKE_HOST_UNIX) + + set (CLR_CMAKE_ENABLE_UBSAN OFF) + # COMPAT: Allow enabling UBSAN in Debug/Checked builds via an environment variable. + if(UPPERCASE_CMAKE_BUILD_TYPE STREQUAL DEBUG OR UPPERCASE_CMAKE_BUILD_TYPE STREQUAL CHECKED) + # obtain settings from running enablesanitizers.sh + string(FIND "$ENV{DEBUG_SANITIZERS}" "ubsan" __UBSAN_ENV_POS) + if (${__UBSAN_ENV_POS} GREATER -1) + set(CLR_CMAKE_ENABLE_UBSAN ON) + endif() + endif() + string(FIND "${CLR_CMAKE_ENABLE_SANITIZERS}" "undefined" __UBSAN_POS) + if (${__UBSAN_POS} GREATER -1) + set(CLR_CMAKE_ENABLE_UBSAN ON) + endif() + + # set the CLANG sanitizer flags for debug build + if(CLR_CMAKE_ENABLE_UBSAN) + list(APPEND CLR_CMAKE_BUILD_SANITIZE_OPTIONS -fsanitize-blacklist=${CMAKE_CURRENT_SOURCE_DIR}/sanitizerblacklist.txt) + # all sanitizer flags are enabled except alignment (due to heavy use of __unaligned modifier) + list(APPEND CLR_CMAKE_BUILD_SANITIZERS + "bool" + bounds + enum + float-cast-overflow + float-divide-by-zero + "function" + integer + nonnull-attribute + null + object-size + "return" + returns-nonnull-attribute + shift + unreachable + vla-bound + vptr) + list(APPEND CLR_CMAKE_SANITIZER_RUNTIMES + undefined) + message("-- Undefined Behavior Sanitizer (ubsan) enabled") + endif () + endif() + list(JOIN CLR_CMAKE_BUILD_SANITIZERS "," CLR_CMAKE_BUILD_SANITIZERS) + list(JOIN CLR_CMAKE_SANITIZER_RUNTIMES "," CLR_LINK_SANITIZERS_OPTIONS) + if (CLR_CMAKE_BUILD_SANITIZERS) + list(APPEND CLR_CMAKE_BUILD_SANITIZE_OPTIONS "-fsanitize=${CLR_CMAKE_BUILD_SANITIZERS}") + endif() + if (CLR_CMAKE_SANITIZER_RUNTIMES) + list(APPEND CLR_CMAKE_LINK_SANITIZE_OPTIONS "-fsanitize=${CLR_CMAKE_SANITIZER_RUNTIMES}") + endif() + if (MSVC) + add_compile_options("$<$:${CLR_CMAKE_BUILD_SANITIZE_OPTIONS}>") + else() + add_compile_options("$<$:${CLR_CMAKE_BUILD_SANITIZE_OPTIONS}>") + add_linker_flag("${CLR_CMAKE_LINK_SANITIZE_OPTIONS}") + endif() +endif() + # CLR_ADDITIONAL_LINKER_FLAGS - used for passing additional arguments to linker # CLR_ADDITIONAL_COMPILER_OPTIONS - used for passing additional arguments to compiler # @@ -511,7 +586,7 @@ if (CLR_CMAKE_HOST_UNIX) add_compile_options($<$:-Wno-misleading-indentation>) add_compile_options($<$:-Wno-stringop-overflow>) add_compile_options($<$:-Wno-restrict>) - add_compile_options($<$:-Wno-stringop-truncation>) + add_compile_options($<$:-Wno-stringop-truncation>) if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 12.0) # this warning is only reported by g++ 11 in debug mode when building @@ -785,6 +860,15 @@ if (MSVC) # production-time scenarios. set(CMAKE_MSVC_RUNTIME_LIBRARY MultiThreaded$<$,$>,$>>>:Debug>) + if (NOT CLR_CMAKE_ENABLE_SANITIZERS) + # Force uCRT to be dynamically linked for Release build + # We won't do this for sanitized builds as the dynamic CRT is not compatible with the static sanitizer runtime and + # the dynamic sanitizer runtime is not redistributable. Sanitized runtime builds are not production-time scenarios + # so we don't get the benefits of a dynamic CRT for sanitized runtime builds. + add_linker_flag(/NODEFAULTLIB:libucrt.lib RELEASE) + add_linker_flag(/DEFAULTLIB:ucrt.lib RELEASE) + endif() + add_compile_options($<$:/ZH:SHA_256>) if (CLR_CMAKE_TARGET_ARCH_ARM OR CLR_CMAKE_TARGET_ARCH_ARM64) @@ -796,6 +880,15 @@ if (MSVC) add_compile_options($<$:/nologo>) endif (MSVC) +# Configure non-MSVC compiler flags that apply to all platforms (unix-like or otherwise) +if (NOT MSVC) + # Check for sometimes suppressed warnings + check_c_compiler_flag(-Wreserved-identifier COMPILER_SUPPORTS_W_RESERVED_IDENTIFIER) + if(COMPILER_SUPPORTS_W_RESERVED_IDENTIFIER) + add_compile_definitions(COMPILER_SUPPORTS_W_RESERVED_IDENTIFIER) + endif() +endif() + if(CLR_CMAKE_ENABLE_CODE_COVERAGE) if(CLR_CMAKE_HOST_UNIX) diff --git a/eng/native/functions.cmake b/eng/native/functions.cmake index 5b8e47c0a43c4..d5ef9ed625996 100644 --- a/eng/native/functions.cmake +++ b/eng/native/functions.cmake @@ -89,9 +89,11 @@ function(get_compile_definitions DefinitionName) set(LastGeneratorExpression "") foreach(DEFINITION IN LISTS COMPILE_DEFINITIONS_LIST) # If there is a definition that uses the $ generator expression + # or the $ generator expression, # we need to remove it since that generator expression is only valid on binary targets. # Assume that the value is 0. string(REGEX REPLACE "\\$]+>" "0" DEFINITION "${DEFINITION}") + string(REGEX REPLACE "\\$]+(,[^>]+)*>" "0" DEFINITION "${DEFINITION}") if (${DEFINITION} MATCHES "^\\$<(.+):([^>]+)(>?)$") if("${CMAKE_MATCH_3}" STREQUAL "") @@ -631,25 +633,34 @@ function(link_natvis_sources_for_target targetName linkKind) endforeach() endfunction() +# Add sanitizer runtime support code to the target. +function(add_sanitizer_runtime_support targetName) + # Add sanitizer support functions. + if (CLR_CMAKE_ENABLE_ASAN) + target_sources(${targetName} PRIVATE "$<$,EXECUTABLE>:${CLR_SRC_NATIVE_DIR}/minipal/asansupport.cpp>") + endif() +endfunction() + function(add_executable_clr targetName) - if(NOT WIN32) - add_executable(${ARGV} ${VERSION_FILE_PATH}) - disable_pax_mprotect(${ARGV}) - else() - add_executable(${ARGV}) - endif(NOT WIN32) - if(NOT CLR_CMAKE_KEEP_NATIVE_SYMBOLS) - strip_symbols(${ARGV0} symbolFile) - endif() + if(NOT WIN32) + add_executable(${ARGV} ${VERSION_FILE_PATH}) + disable_pax_mprotect(${ARGV}) + else() + add_executable(${ARGV}) + endif(NOT WIN32) + add_sanitizer_runtime_support(${targetName}) + if(NOT CLR_CMAKE_KEEP_NATIVE_SYMBOLS) + strip_symbols(${ARGV0} symbolFile) + endif() endfunction() function(add_library_clr targetName kind) - if(NOT WIN32 AND "${kind}" STREQUAL "SHARED") - add_library(${ARGV} ${VERSION_FILE_PATH}) - else() - add_library(${ARGV}) - endif() - if("${kind}" STREQUAL "SHARED" AND NOT CLR_CMAKE_KEEP_NATIVE_SYMBOLS) - strip_symbols(${ARGV0} symbolFile) - endif() + if(NOT WIN32 AND "${kind}" STREQUAL "SHARED") + add_library(${ARGV} ${VERSION_FILE_PATH}) + else() + add_library(${ARGV}) + endif() + if("${kind}" STREQUAL "SHARED" AND NOT CLR_CMAKE_KEEP_NATIVE_SYMBOLS) + strip_symbols(${ARGV0} symbolFile) + endif() endfunction() diff --git a/eng/native/ijw/IJW.cmake b/eng/native/ijw/IJW.cmake index 4222b9b15b9de..9ef90525dda8b 100644 --- a/eng/native/ijw/IJW.cmake +++ b/eng/native/ijw/IJW.cmake @@ -1,8 +1,7 @@ if (CLR_CMAKE_HOST_WIN32) function(remove_ijw_incompatible_options options updatedOptions) - - # IJW isn't compatible with Ehsc, which CMake enables by default, + # IJW isn't compatible with Ehsc, which CMake enables by default if(options MATCHES "/EHsc") string(REPLACE "/EHsc" "" options "${options}") endif() @@ -22,6 +21,12 @@ if (CLR_CMAKE_HOST_WIN32) string(REPLACE "/GR-" "" options "${options}") endif() + # Disable native sanitizers for IJW since we don't want to have to locate + # and copy the sanitizer runtimes and IJW must be built with a dynamic CRT. + if (options MATCHES "-fsanitize=") + string(REGEX REPLACE "-fsanitize=[a-zA-z,]+" "" options "${options}") + endif() + SET(${updatedOptions} "${options}" PARENT_SCOPE) endfunction() @@ -61,6 +66,10 @@ if (CLR_CMAKE_HOST_WIN32) remove_ijw_incompatible_options("${CMAKE_CXX_FLAGS}" CMAKE_CXX_FLAGS) + get_directory_property(dirCompileOptions COMPILE_OPTIONS) + remove_ijw_incompatible_options("${dirCompileOptions}" dirCompileOptions) + set_directory_properties(PROPERTIES COMPILE_OPTIONS "${dirCompileOptions}") + set(CLR_SDK_REF_PACK_OUTPUT "") set(CLR_SDK_REF_PACK_DISCOVERY_ERROR "") set(CLR_SDK_REF_PACK_DISCOVERY_RESULT 0) diff --git a/eng/native/init-vs-env.cmd b/eng/native/init-vs-env.cmd index 6c1ad8f3a1786..273f49b3392c2 100644 --- a/eng/native/init-vs-env.cmd +++ b/eng/native/init-vs-env.cmd @@ -61,9 +61,13 @@ exit /b 1 if "%__VCBuildArch%"=="" exit /b 0 :: Set the environment for the native build -if not exist "%VCINSTALLDIR%Auxiliary\Build\vcvarsall.bat" goto :VSMissing -call "%VCINSTALLDIR%Auxiliary\Build\vcvarsall.bat" %__VCBuildArch% -if not "%ErrorLevel%"=="0" exit /b 1 +:: We can set SkipVCEnvInit to skip setting up the MSVC environment from VS and instead assume that the current environment is set up correctly. +:: This is very useful for testing with new MSVC versions that aren't in a VS build yet. +if not defined SkipVCEnvInit ( + if not exist "%VCINSTALLDIR%Auxiliary\Build\vcvarsall.bat" goto :VSMissing + call "%VCINSTALLDIR%Auxiliary\Build\vcvarsall.bat" %__VCBuildArch% + if not "%ErrorLevel%"=="0" exit /b 1 +) set "__VCBuildArch=" diff --git a/eng/nativeSanitizers.targets b/eng/nativeSanitizers.targets new file mode 100644 index 0000000000000..69ec76b93487c --- /dev/null +++ b/eng/nativeSanitizers.targets @@ -0,0 +1,24 @@ + + + + x86_64 + + + i386 + + + armhf + + + arm64 + + + + + + + + + + + diff --git a/eng/pipelines/common/global-build-job.yml b/eng/pipelines/common/global-build-job.yml index 3ac90ee3387b4..e6a07c9b4c603 100644 --- a/eng/pipelines/common/global-build-job.yml +++ b/eng/pipelines/common/global-build-job.yml @@ -115,6 +115,10 @@ jobs: - name: _monoAotCrossCompileArg value: 'cross' + # Set no native sanitizers by default + - name: _nativeSanitizersArg + value: '' + - ${{ each variableTemplate in parameters.extraVariablesTemplates }}: - template: ${{ variableTemplate.template }} parameters: @@ -138,7 +142,6 @@ jobs: - ${{ each variable in parameters.variables }}: - ${{ variable }} - steps: - checkout: self clean: true diff --git a/eng/pipelines/common/templates/runtimes/build-runtime-tests-and-send-to-helix.yml b/eng/pipelines/common/templates/runtimes/build-runtime-tests-and-send-to-helix.yml index 3da6cc22300cd..396fd6e87c324 100644 --- a/eng/pipelines/common/templates/runtimes/build-runtime-tests-and-send-to-helix.yml +++ b/eng/pipelines/common/templates/runtimes/build-runtime-tests-and-send-to-helix.yml @@ -6,7 +6,6 @@ parameters: testBuildArgs: '' crossBuild: false readyToRun: false - liveLibrariesBuildConfig: '' compositeBuildMode: false helixQueues: '' displayNameArgs: '' @@ -36,7 +35,6 @@ steps: osSubgroup: ${{ parameters.osSubgroup }} archType: ${{ parameters.archType }} buildConfig: ${{ parameters.buildConfig }} - liveLibrariesBuildConfig: ${{ parameters.liveLibrariesBuildConfig }} testBuildArgs: ${{ parameters.testBuildArgs }} # Build a Mono LLVM AOT cross-compiler for non-amd64 targets (in this case, just arm64) diff --git a/eng/pipelines/common/templates/runtimes/build-runtime-tests.yml b/eng/pipelines/common/templates/runtimes/build-runtime-tests.yml index bba48b87c9ab6..f9ef84a49c164 100644 --- a/eng/pipelines/common/templates/runtimes/build-runtime-tests.yml +++ b/eng/pipelines/common/templates/runtimes/build-runtime-tests.yml @@ -3,7 +3,6 @@ parameters: osSubgroup: '' archType: '' buildConfig: '' - liveLibrariesBuildConfig: '' testBuildArgs: '' #arcade-specific parameters condition: always() @@ -17,8 +16,8 @@ parameters: steps: - ${{ if eq(parameters.osGroup, 'windows') }}: - - script: $(Build.SourcesDirectory)/src/tests/build$(scriptExt) $(crossArg) ci ${{ parameters.archType }} $(buildConfigUpper) $(priorityArg) $(runtimeFlavorArgs) ${{ parameters.testBuildArgs }} $(runtimeVariantArg) /p:LibrariesConfiguration=${{ coalesce(parameters.liveLibrariesBuildConfig, parameters.buildConfig) }} + - script: $(Build.SourcesDirectory)/src/tests/build$(scriptExt) $(crossArg) ci ${{ parameters.archType }} $(buildConfigUpper) $(_nativeSanitizersArg) $(priorityArg) $(runtimeFlavorArgs) ${{ parameters.testBuildArgs }} $(runtimeVariantArg) $(librariesConfigurationArg) displayName: Build Tests - ${{ if ne(parameters.osGroup, 'windows') }}: - - script: $(Build.SourcesDirectory)/src/tests/build$(scriptExt) $(crossArg) ci os ${{ parameters.osGroup }} ${{ parameters.archType }} $(buildConfigUpper) $(priorityArg) $(runtimeFlavorArgs) ${{ parameters.testBuildArgs }} $(runtimeVariantArg) /p:LibrariesConfiguration=${{ coalesce(parameters.liveLibrariesBuildConfig, parameters.buildConfig) }} + - script: $(Build.SourcesDirectory)/src/tests/build$(scriptExt) $(crossArg) ci os ${{ parameters.osGroup }} ${{ parameters.archType }} $(buildConfigUpper) $(_nativeSanitizersArg) $(priorityArg) $(runtimeFlavorArgs) ${{ parameters.testBuildArgs }} $(runtimeVariantArg) $(librariesConfigurationArg) displayName: Build Tests diff --git a/eng/pipelines/common/templates/runtimes/test-variables.yml b/eng/pipelines/common/templates/runtimes/test-variables.yml index d3eb48f309df7..285f13caeb082 100644 --- a/eng/pipelines/common/templates/runtimes/test-variables.yml +++ b/eng/pipelines/common/templates/runtimes/test-variables.yml @@ -1,8 +1,10 @@ parameters: testGroup: 'innerloop' readyToRun: false + sanitizers: '' runtimeFlavor: '' runtimeVariant: '' + liveLibrariesBuildConfig: '' variables: @@ -28,6 +30,15 @@ variables: - ${{ if in(parameters.testGroup, 'outerloop') }}: - name: timeoutPerTestCollectionInMinutes value: 120 + # AddressSanitizer can have up to a 2x slowdown + - ${{ if eq(parameters.sanitizers, 'address') }}: + - name: timeoutPerTestInMinutes + value: 20 + - name: timeoutPerTestCollectionInMinutes + value: 60 + - ${{ if in(parameters.testGroup, 'outerloop') }}: + - name: timeoutPerTestCollectionInMinutes + value: 240 - ${{ if eq(parameters.readyToRun, true) }}: - name: timeoutPerTestCollectionInMinutes value: 90 @@ -102,3 +113,10 @@ variables: - ${{ if eq(parameters.osGroup, 'windows') }}: - name: priorityArg value: '-priority=1' + + - name: librariesConfigurationArg + value: '/p:LibrariesConfiguration=$(buildConfigUpper)' + + - ${{ if ne(parameters.liveLibrariesBuildConfig, '') }}: + - name: librariesConfigurationArg + value: '/p:LibrariesConfiguration=${{ parameters.liveLibrariesBuildConfig }}' diff --git a/eng/pipelines/coreclr/nativeaot-post-build-steps.yml b/eng/pipelines/coreclr/nativeaot-post-build-steps.yml index c3d65b8281fd1..94761028f48ab 100644 --- a/eng/pipelines/coreclr/nativeaot-post-build-steps.yml +++ b/eng/pipelines/coreclr/nativeaot-post-build-steps.yml @@ -27,5 +27,5 @@ steps: # Publishing tooling doesn't support different configs between runtime and libs, so only run tests in Release config - ${{ if eq(parameters.buildConfig, 'release') }}: - - script: $(Build.SourcesDirectory)$(dir)build$(scriptExt) -ci -arch ${{ parameters.archType }} $(_osParameter) -s libs.tests -c $(_BuildConfig) $(crossArg) /p:TestAssemblies=false /p:RunNativeAotTestApps=true $(_officialBuildParameter) /bl:$(Build.SourcesDirectory)/artifacts/log/$(buildConfigUpper)/NativeAotTests.binlog ${{ parameters.extraTestArgs }} + - script: $(Build.SourcesDirectory)$(dir)build$(scriptExt) -ci -arch ${{ parameters.archType }} $(_osParameter) -s libs.tests -c $(_BuildConfig) $(crossArg) $(_nativeSanitizersArg) /p:TestAssemblies=false /p:RunNativeAotTestApps=true $(_officialBuildParameter) /bl:$(Build.SourcesDirectory)/artifacts/log/$(buildConfigUpper)/NativeAotTests.binlog ${{ parameters.extraTestArgs }} displayName: Run NativeAot Library Tests diff --git a/eng/pipelines/coreclr/templates/crossdac-build.yml b/eng/pipelines/coreclr/templates/crossdac-build.yml index f0ac5d36f0047..a8accb9d2e3d2 100644 --- a/eng/pipelines/coreclr/templates/crossdac-build.yml +++ b/eng/pipelines/coreclr/templates/crossdac-build.yml @@ -22,10 +22,7 @@ steps: [Parameter(Mandatory)][string]$targetDir ) - if ('${{ parameters.archType }}' -ne '${{ parameters.hostArchType }}') - { - $crossDacDir = Join-Path $crossDacDir -ChildPath '${{ parameters.hostArchType }}' - } + $crossDacDir = Join-Path $crossDacDir -ChildPath '${{ parameters.hostArchType }}' $availableFiles = ls -File $crossDacDir diff --git a/eng/pipelines/runtime-sanitized.yml b/eng/pipelines/runtime-sanitized.yml index 32023c6fa9f12..3bc49fec69083 100644 --- a/eng/pipelines/runtime-sanitized.yml +++ b/eng/pipelines/runtime-sanitized.yml @@ -1,8 +1,14 @@ # This pipeline provides an easy mechanism for us to run runtime and libaries tests with native sanitizers enabled -# without having to compilcate the runtime.yml pipeline. This pipeline is intended to be run on a rolling basis -# but a schedule is yet to be determined. +# without having to compilcate the runtime.yml pipeline. trigger: none +schedules: +- cron: "0 11 * * 2" + displayName: Tuesday at 3:00 AM (UTC-8:00) + branches: + include: + - main + variables: - template: /eng/pipelines/common/variables.yml @@ -10,5 +16,95 @@ extends: template: /eng/pipelines/common/templates/pipeline-with-resources.yml parameters: stages: - - stage: Build + - stage: AddressSanitizer jobs: + # + # Build the whole product with CoreCLR and run runtime tests with AddressSanitizer + # + - template: /eng/pipelines/common/platform-matrix.yml + parameters: + jobTemplate: /eng/pipelines/common/global-build-job.yml + helixQueuesTemplate: /eng/pipelines/coreclr/templates/helix-queues-setup.yml + buildConfig: Checked + runtimeFlavor: coreclr + platforms: + - linux_x64 + - osx_x64 + variables: + - name: _nativeSanitizersArg + value: -fsanitize address + jobParameters: + nameSuffix: CoreCLR_RuntimeTests + buildArgs: -s clr+libs -c $(_BuildConfig) $(_nativeSanitizersArg) + timeoutInMinutes: 300 + # extra steps, run tests + extraStepsTemplate: /eng/pipelines/common/templates/runtimes/build-runtime-tests-and-send-to-helix.yml + extraStepsParameters: + creator: dotnet-bot + testRunNamePrefixSuffix: CoreCLR_$(_BuildConfig) + scenarios: + - normal + - no_tiered_compilation + extraVariablesTemplates: + - template: /eng/pipelines/common/templates/runtimes/test-variables.yml + parameters: + testGroup: outerloop + sanitizers: 'address' + + # + # Build the whole product with CoreCLR and run libraries tests with AddressSanitizer + # + - template: /eng/pipelines/common/platform-matrix.yml + parameters: + jobTemplate: /eng/pipelines/common/global-build-job.yml + helixQueuesTemplate: /eng/pipelines/libraries/helix-queues-setup.yml + buildConfig: Debug + runtimeFlavor: coreclr + platforms: + - linux_x64 + - osx_x64 + variables: + - name: _nativeSanitizersArg + value: -fsanitize address + jobParameters: + testGroup: innerloop + nameSuffix: CoreCLR_LibrariesTests + buildArgs: -s clr+libs+libs.tests -c $(_BuildConfig) -rc Checked $(_nativeSanitizersArg) /p:ArchiveTests=true + timeoutInMinutes: 180 + # extra steps, run tests + extraStepsTemplate: /eng/pipelines/libraries/helix.yml + extraStepsParameters: + creator: dotnet-bot + testRunNamePrefixSuffix: Libraries_$(_BuildConfig) + scenarios: + - normal + + # + # NativeAOT release build and smoke tests with AddressSanitizer + # + - template: /eng/pipelines/common/platform-matrix.yml + parameters: + jobTemplate: /eng/pipelines/common/global-build-job.yml + helixQueuesTemplate: /eng/pipelines/coreclr/templates/helix-queues-setup.yml + buildConfig: release + platforms: + - linux_x64 + - osx_x64 + variables: + - name: _nativeSanitizersArg + value: -fsanitize address + jobParameters: + testGroup: innerloop + timeoutInMinutes: 120 + nameSuffix: NativeAOT + buildArgs: -s clr.aot+host.native+libs -rc $(_BuildConfig) -lc Release -hc Release $(_nativeSanitizersArg) + extraStepsTemplate: /eng/pipelines/coreclr/nativeaot-post-build-steps.yml + extraStepsParameters: + creator: dotnet-bot + testBuildArgs: nativeaot tree nativeaot + liveLibrariesBuildConfig: Release + extraVariablesTemplates: + - template: /eng/pipelines/common/templates/runtimes/test-variables.yml + parameters: + sanitizers: 'address' + liveLibrariesBuildConfig: Release diff --git a/eng/pipelines/runtime.yml b/eng/pipelines/runtime.yml index 8edd9927a2c0a..68b3a915ce645 100644 --- a/eng/pipelines/runtime.yml +++ b/eng/pipelines/runtime.yml @@ -219,6 +219,7 @@ extends: - template: /eng/pipelines/common/templates/runtimes/test-variables.yml parameters: testGroup: innerloop + liveLibrariesBuildConfig: Release condition: >- or( eq(dependencies.evaluate_paths.outputs['SetPathVars_coreclr.containsChange'], true), @@ -255,6 +256,7 @@ extends: - template: /eng/pipelines/common/templates/runtimes/test-variables.yml parameters: testGroup: innerloop + liveLibrariesBuildConfig: Release condition: >- or( eq(dependencies.evaluate_paths.outputs['SetPathVars_coreclr.containsChange'], true), @@ -297,6 +299,7 @@ extends: - template: /eng/pipelines/common/templates/runtimes/test-variables.yml parameters: testGroup: innerloop + liveLibrariesBuildConfig: Release condition: >- or( eq(dependencies.evaluate_paths.outputs['SetPathVars_coreclr.containsChange'], true), diff --git a/eng/testing/linker/project.csproj.template b/eng/testing/linker/project.csproj.template index ab498732e2ebf..2295ab9c0e3cb 100644 --- a/eng/testing/linker/project.csproj.template +++ b/eng/testing/linker/project.csproj.template @@ -82,4 +82,5 @@ + diff --git a/eng/testing/linker/trimmingTests.targets b/eng/testing/linker/trimmingTests.targets index 24315195a66f0..e192887f54233 100644 --- a/eng/testing/linker/trimmingTests.targets +++ b/eng/testing/linker/trimmingTests.targets @@ -1,4 +1,9 @@ + + $(CoreCLRILCompilerDir) + $(CoreCLRCrossILCompilerDir) + + @@ -54,7 +59,7 @@ <_additionalProjectReferenceTemp Include="$(AdditionalProjectReferences)" /> <_additionalProjectReference Include="<ProjectReference Include="$(LibrariesProjectRoot)%(_additionalProjectReferenceTemp.Identity)\src\%(_additionalProjectReferenceTemp.Identity).csproj" SkipUseReferenceAssembly="true" />" /> - + <_additionalProjectReferencesString>@(_additionalProjectReference, '%0a') @@ -66,7 +71,7 @@ <_switchesAsItems Include="%(TestConsoleApps.DisabledFeatureSwitches)" Value="false" /> <_switchesAsItems Include="%(TestConsoleApps.EnabledFeatureSwitches)" Value="true" /> - + <_propertiesAsItems Include="%(TestConsoleApps.DisabledProperties)" Value="false" /> <_propertiesAsItems Include="%(TestConsoleApps.EnabledProperties)" Value="true" /> @@ -87,7 +92,7 @@ .Replace('{MicrosoftNETILLinkTasksVersion}', '$(MicrosoftNETILLinkTasksVersion)') .Replace('{ExtraTrimmerArgs}', '%(TestConsoleApps.ExtraTrimmerArgs)') .Replace('{AdditionalProperties}', '$(_additionalPropertiesString)') - .Replace('{IlcToolsPath}', '$(CoreCLRILCompilerDir)') + .Replace('{IlcToolsPath}', '$(IlcToolsPath)') .Replace('{IlcBuildTasksPath}', '$(CoreCLRILCompilerDir)netstandard/ILCompiler.Build.Tasks.dll') .Replace('{IlcSdkPath}', '$(CoreCLRAotSdkDir)') .Replace('{IlcFrameworkPath}', '$(MicrosoftNetCoreAppRuntimePackRidLibTfmDir)') @@ -108,6 +113,7 @@ .Replace('{MicrosoftNetCoreAppFrameworkName}', '$(MicrosoftNetCoreAppFrameworkName)') .Replace('{MicrosoftNetCoreAppRefPackDir}', '$(MicrosoftNetCoreAppRefPackDir)') .Replace('{MicrosoftNetCoreAppRuntimePackDir}', '$(MicrosoftNetCoreAppRuntimePackDir)') + .Replace('{NativeSanitizersTargets}', '$(RepositoryEngineeringDir)nativeSanitizers.targets') .Replace('{AppHostSourcePath}', '$(AppHostSourcePath)') .Replace('{SingleFileHostSourcePath}', '$(SingleFileHostSourcePath)'))" Overwrite="true" /> @@ -131,7 +137,7 @@ + Properties="Configuration=$(Configuration);BuildProjectReferences=false;TargetOS=$(TargetOS);TargetArchitecture=$(TargetArchitecture)" /> $(CoreCLRILCompilerDir) - $(CoreCLRCrossILCompilerDir) + $(CoreCLRCrossILCompilerDir) $(ROOTFS_DIR) $(CoreCLRILCompilerDir)netstandard/ILCompiler.Build.Tasks.dll $(CoreCLRAotSdkDir) diff --git a/src/coreclr/build-runtime.cmd b/src/coreclr/build-runtime.cmd index a8fca255b8611..ec6887c78d84c 100644 --- a/src/coreclr/build-runtime.cmd +++ b/src/coreclr/build-runtime.cmd @@ -65,12 +65,13 @@ set __UnprocessedBuildArgs= set __BuildNative=1 set __RestoreOptData=1 set __HostArch= -set __HostArch2= set __PgoOptDataPath= set __CMakeArgs= set __Ninja=1 set __RequestedBuildComponents= set __OutputRid= +set __ExplicitHostArch= +set __SubDir= :Arg_Loop if "%1" == "" goto ArgsDone @@ -127,9 +128,10 @@ if [!__PassThroughArgs!]==[] ( set "__PassThroughArgs=%__PassThroughArgs% %1" ) -if /i "%1" == "-hostarch" (set __HostArch=%2&shift&shift&goto Arg_Loop) +if /i "%1" == "-hostarch" (set __HostArch=%2&set __ExplicitHostArch=1&shift&shift&goto Arg_Loop) if /i "%1" == "-os" (set __TargetOS=%2&shift&shift&goto Arg_Loop) if /i "%1" == "-outputrid" (set __OutputRid=%2&shift&shift&goto Arg_Loop) +if /i "%1" == "-subdir" (set __SubDir=%2&shift&shift&goto Arg_Loop) if /i "%1" == "-cmakeargs" (set __CMakeArgs=%2 %__CMakeArgs%&set __remainingArgs="!__remainingArgs:*%2=!"&shift&shift&goto Arg_Loop) if /i "%1" == "-configureonly" (set __ConfigureOnly=1&set __BuildNative=1&shift&goto Arg_Loop) @@ -142,6 +144,7 @@ if /i "%1" == "-pgoinstrument" (set __PgoInstrument=1&shift&goto Arg_Loop) if /i "%1" == "-enforcepgo" (set __EnforcePgo=1&shift&goto Arg_Loop) if /i "%1" == "-pgodatapath" (set __PgoOptDataPath=%2&set __PgoOptimize=1&shift&shift&goto Arg_Loop) if /i "%1" == "-component" (set __RequestedBuildComponents=%__RequestedBuildComponents%-%2&set "__remainingArgs=!__remainingArgs:*%2=!"&shift&shift&goto Arg_Loop) +if /i "%1" == "-fsanitize" (set __CMakeArgs=%__CMakeArgs% "-DCLR_CMAKE_ENABLE_SANITIZERS=%2"&shift&shift&goto Arg_Loop) REM TODO these are deprecated remove them eventually REM don't add more, use the - syntax instead @@ -216,9 +219,15 @@ set "__ArtifactsIntermediatesDir=%__RepoRootDir%\artifacts\obj\coreclr\" if "%__Ninja%"=="0" (set "__IntermediatesDir=%__IntermediatesDir%\ide") set "__PackagesBinDir=%__BinDir%\.nuget" +if "%__ExplicitHostArch%" == "1" ( + set __BinDir=%__BinDir%\%__HostArch% + set __IntermediatesDir=%__IntermediatesDir%\%__HostArch% +) -if NOT "%__HostArch%" == "%__TargetArch%" set __BinDir=%__BinDir%\%__HostArch% -if NOT "%__HostArch%" == "%__TargetArch%" set __IntermediatesDir=%__IntermediatesDir%\%__HostArch% +if NOT "%__SubDir%"=="" ( + set __BinDir=%__BinDir%\%__SubDir% + set __IntermediatesDir=%__IntermediatesDir%\%__SubDir% +) REM Generate path to be set for CMAKE_INSTALL_PREFIX to contain forward slash set "__CMakeBinDir=%__BinDir%" @@ -318,6 +327,9 @@ for /f "delims=" %%a in ("-%__RequestedBuildComponents%-") do ( if not "!string:-crosscomponents-=!"=="!string!" ( set __CMakeTarget=!__CMakeTarget! crosscomponents ) + if not "!string:-debug-=!"=="!string!" ( + set __CMakeTarget=!__CMakeTarget! debug + ) ) if "!__CMakeTarget!" == "" ( set __CMakeTarget=install @@ -353,8 +365,10 @@ if %__BuildNative% EQU 1 ( set __VCTargetArch=x86_arm64 ) - echo %__MsgPrefix%Using environment: "%__VCToolsRoot%\vcvarsall.bat" !__VCTargetArch! - call "%__VCToolsRoot%\vcvarsall.bat" !__VCTargetArch! + if NOT DEFINED SkipVCEnvInit ( + echo %__MsgPrefix%Using environment: "%__VCToolsRoot%\vcvarsall.bat" !__VCTargetArch! + call "%__VCToolsRoot%\vcvarsall.bat" !__VCTargetArch! + ) @if defined _echo @echo on if defined __SkipConfigure goto SkipConfigure @@ -555,6 +569,7 @@ echo -cmakeargs: user-settable additional arguments passed to CMake. echo -configureonly: skip all builds; only run CMake ^(default: CMake and builds are run^) echo -skipconfigure: skip CMake ^(default: CMake is run^) echo -skipnative: skip building native components ^(default: native components are built^). +echo -fsanitize ^: Enable the specified sanitizers. This script does not handle converting 'true' to the default sanitizers. echo. echo Examples: echo build-runtime diff --git a/src/coreclr/build-runtime.sh b/src/coreclr/build-runtime.sh index 31c5cc286d530..06f79ec34b420 100755 --- a/src/coreclr/build-runtime.sh +++ b/src/coreclr/build-runtime.sh @@ -23,6 +23,7 @@ usage_list+=("-pgoinstrument: generate instrumented code for profile guided opti usage_list+=("-skipcrossarchnative: Skip building cross-architecture native binaries.") usage_list+=("-staticanalyzer: use scan_build static analyzer.") usage_list+=("-component: Build individual components instead of the full project. Available options are 'hosts', 'jit', 'runtime', 'paltests', 'alljits', 'iltools', 'nativeaot', and 'spmi'. Can be specified multiple times.") +usage_list+=("-subdir: Append a directory with the provided name to the obj and bin paths.") setup_dirs_local() { @@ -53,6 +54,12 @@ handle_arguments_local() { __RequestedBuildComponents="$__RequestedBuildComponents $2" __ShiftArgs=1 ;; + + subdir|-subdir) + __SubDir="$2" + __ShiftArgs=1 + ;; + *) __UnprocessedBuildArgs="$__UnprocessedBuildArgs $1" ;; @@ -97,6 +104,7 @@ __UseNinja=0 __VerboseBuild=0 __CMakeArgs="" __RequestedBuildComponents="" +__SubDir="" source "$__ProjectRoot"/_build-commons.sh @@ -121,6 +129,11 @@ if [[ "$__ExplicitHostArch" == 1 ]]; then __BinDir="$__BinDir/$__HostArch" fi +if [[ -n "$__SubDir" ]]; then + __IntermediatesDir="$__IntermediatesDir/$__SubDir" + __BinDir="$__BinDir/$__SubDir" +fi + # CI_SPECIFIC - On CI machines, $HOME may not be set. In such a case, create a subfolder and set the variable to set. # This is needed by CLI to function. if [[ -z "$HOME" ]]; then diff --git a/src/coreclr/components.cmake b/src/coreclr/components.cmake index 3eaa2c966bf32..70dd081376f67 100644 --- a/src/coreclr/components.cmake +++ b/src/coreclr/components.cmake @@ -7,6 +7,7 @@ add_component(paltests paltests_install) add_component(iltools) add_component(nativeaot) add_component(spmi) +add_component(debug) # Define coreclr_all as the fallback component and make every component depend on this component. # iltools and paltests should be minimal subsets, so don't add a dependency on coreclr_misc @@ -19,6 +20,9 @@ add_dependencies(runtime coreclr_misc) # The runtime build requires the clrjit and iltools builds add_dependencies(runtime jit iltools) +# The runtime build requires the debugger tools builds +add_dependencies(runtime debug) + add_dependencies(runtime hosts) # The cross-components build is separate, so we don't need to add a dependency on coreclr_misc diff --git a/src/coreclr/crossgen-corelib.proj b/src/coreclr/crossgen-corelib.proj index 1d7eb27679749..2dc62b8151a3c 100644 --- a/src/coreclr/crossgen-corelib.proj +++ b/src/coreclr/crossgen-corelib.proj @@ -1,8 +1,12 @@ + + true + + - - + + diff --git a/src/coreclr/dlls/mscordac/CMakeLists.txt b/src/coreclr/dlls/mscordac/CMakeLists.txt index b736de536a798..36124262f7f93 100644 --- a/src/coreclr/dlls/mscordac/CMakeLists.txt +++ b/src/coreclr/dlls/mscordac/CMakeLists.txt @@ -196,7 +196,7 @@ endif(CLR_CMAKE_HOST_UNIX) target_link_libraries(mscordaccore PRIVATE ${COREDAC_LIBRARIES}) # add the install targets -install_clr(TARGETS mscordaccore DESTINATIONS . sharedFramework COMPONENT runtime) +install_clr(TARGETS mscordaccore DESTINATIONS . sharedFramework COMPONENT debug) if(CLR_CMAKE_HOST_WIN32) set(LONG_NAME_HOST_ARCH ${CLR_CMAKE_HOST_ARCH}) diff --git a/src/coreclr/dlls/mscordbi/CMakeLists.txt b/src/coreclr/dlls/mscordbi/CMakeLists.txt index 9f8a442c1b55c..1940f64e94b09 100644 --- a/src/coreclr/dlls/mscordbi/CMakeLists.txt +++ b/src/coreclr/dlls/mscordbi/CMakeLists.txt @@ -55,6 +55,7 @@ else(CLR_CMAKE_HOST_WIN32) endif(CLR_CMAKE_HOST_WIN32) add_library_clr(mscordbi SHARED ${MSCORDBI_SOURCES}) +set_target_properties(mscordbi PROPERTIES DBI_COMPONENT TRUE) target_precompile_headers(mscordbi PRIVATE $<$:stdafx.h>) if(CLR_CMAKE_HOST_UNIX) @@ -125,4 +126,4 @@ elseif(CLR_CMAKE_HOST_UNIX) endif(CLR_CMAKE_HOST_WIN32) # add the install targets -install_clr(TARGETS mscordbi DESTINATIONS . sharedFramework COMPONENT runtime) +install_clr(TARGETS mscordbi DESTINATIONS . sharedFramework COMPONENT debug) diff --git a/src/coreclr/enablesanitizers.sh b/src/coreclr/enablesanitizers.sh index c79ef8c69ddf3..a5f88be30636d 100755 --- a/src/coreclr/enablesanitizers.sh +++ b/src/coreclr/enablesanitizers.sh @@ -9,8 +9,7 @@ if [ $# -eq 0 ]; then else echo " cd $(dirname $0);. enablesanitizers.sh [options]; cd -" fi - echo "Usage: [asan] [ubsan] [lsan] [all] [off] [clangx.y]" - echo " asan: optional argument to enable Address Sanitizer." + echo "Usage: [ubsan] [lsan] [all] [off] [clangx.y]" echo " ubsan: optional argument to enable Undefined Behavior Sanitizer." echo " lsan - optional argument to enable memory Leak Sanitizer." echo " all - optional argument to enable asan, ubsan and lsan." @@ -21,7 +20,6 @@ else __ClangMajorVersion=3 __ClangMinorVersion=6 - __EnableASan=0 __EnableUBSan=0 __EnableLSan=0 __TurnOff=0 @@ -32,18 +30,13 @@ else do lowerI="$(echo $i | tr "[:upper:]" "[:lower:]")" case $lowerI in - asan) - __EnableASan=1 - ;; ubsan) __EnableUBSan=1 ;; lsan) - __EnableASan=1 __EnableLSan=1 ;; all) - __EnableASan=1 __EnableUBSan=1 __EnableLSan=1 ;; @@ -83,22 +76,16 @@ else unset DEBUG_SANITIZERS echo "Setting DEBUG_SANITIZERS=" else - # for now, specify alloc_dealloc_mismatch=0 as there are too many error reports that are not an issue. - # Also specify use_sigaltstack=0 as coreclr uses own alternate stack for signal handlers - ASAN_OPTIONS="symbolize=1 alloc_dealloc_mismatch=0 use_sigaltstack=0" # when Clang 3.8 available, add: suppressions=$(readlink -f sanitizersuppressions.txt) UBSAN_OPTIONS="print_stacktrace=1" - if [[ "$__EnableASan" == 1 ]]; then - __Options="$__Options asan" - fi - if [[ "$__EnableUBSan" == 1 ]]; then + if [ $__EnableUBSan == 1 ]; then __Options="$__Options ubsan" fi - if [[ "$__EnableLSan" == 1 ]]; then - ASAN_OPTIONS="$ASAN_OPTIONS detect_leaks=1" + if [ $__EnableLSan == 1 ]; then + LSAN_OPTIONS="detect_leaks=1" else - ASAN_OPTIONS="$ASAN_OPTIONS detect_leaks=0" + LSAN_OPTIONS="detect_leaks=0" fi # passed to build.sh @@ -128,7 +115,6 @@ else unset __ClangMajorVersion unset __ClangMinorVersion - unset __EnableASan unset __EnableUBSan unset __EnableLSan unset __TurnOff diff --git a/src/coreclr/hosts/corerun/CMakeLists.txt b/src/coreclr/hosts/corerun/CMakeLists.txt index 86ae704780d96..9540fc3b006b9 100644 --- a/src/coreclr/hosts/corerun/CMakeLists.txt +++ b/src/coreclr/hosts/corerun/CMakeLists.txt @@ -39,3 +39,8 @@ else(CLR_CMAKE_HOST_WIN32) endif(CLR_CMAKE_HOST_WIN32) install_clr(TARGETS corerun DESTINATIONS . COMPONENT hosts) + +# If there's a dynamic ASAN runtime, then install it in the directory where we put our executable. +if (NOT "${ASAN_RUNTIME}" STREQUAL "") + install(FILES ${ASAN_RUNTIME} DESTINATION .) +endif() \ No newline at end of file diff --git a/src/coreclr/nativeaot/Bootstrap/CMakeLists.txt b/src/coreclr/nativeaot/Bootstrap/CMakeLists.txt index 02fb30aad9f0c..081da0b05a4c9 100644 --- a/src/coreclr/nativeaot/Bootstrap/CMakeLists.txt +++ b/src/coreclr/nativeaot/Bootstrap/CMakeLists.txt @@ -1,2 +1,20 @@ + +function(install_bootstrapper_object targetName destination) + add_dependencies(nativeaot ${targetName}) + if (MSVC) + set_target_properties(${targetName} PROPERTIES COMPILE_PDB_NAME ${targetName}) + endif() + if (MSVC) + install (FILES $ DESTINATION ${destination} COMPONENT nativeaot RENAME ${targetName}.obj) + if (CMAKE_GENERATOR MATCHES "Visual Studio") + install (FILES ${CMAKE_CURRENT_BINARY_DIR}/$/${targetName}.pdb DESTINATION ${destination} COMPONENT nativeaot) + else() + install (FILES ${CMAKE_CURRENT_BINARY_DIR}/${targetName}.pdb DESTINATION ${destination} COMPONENT nativeaot) + endif() + else() + install (FILES $ DESTINATION ${destination} COMPONENT nativeaot RENAME lib${targetName}.o) + endif() +endfunction() + add_subdirectory(base) add_subdirectory(dll) diff --git a/src/coreclr/nativeaot/Bootstrap/base/CMakeLists.txt b/src/coreclr/nativeaot/Bootstrap/base/CMakeLists.txt index 370dfd0712b21..3ffc81ac648b0 100644 --- a/src/coreclr/nativeaot/Bootstrap/base/CMakeLists.txt +++ b/src/coreclr/nativeaot/Bootstrap/base/CMakeLists.txt @@ -4,13 +4,14 @@ set(SOURCES ../main.cpp ) -add_library(bootstrapper STATIC ${SOURCES}) +add_library(bootstrapper OBJECT ${SOURCES}) +set_target_properties(bootstrapper PROPERTIES OUTPUT_NAME bootstrapper) -install_static_library(bootstrapper aotsdk nativeaot) +install_bootstrapper_object(bootstrapper aotsdk) if (CLR_CMAKE_TARGET_WIN32) - add_library(bootstrapper.GuardCF STATIC ${SOURCES}) - install_static_library(bootstrapper.GuardCF aotsdk nativeaot) + add_library(bootstrapper.GuardCF OBJECT ${SOURCES}) + install_bootstrapper_object(bootstrapper.GuardCF aotsdk) target_compile_options(bootstrapper.GuardCF PRIVATE $<$,$>:/guard:cf>) else() add_library(stdc++compat STATIC ../stdcppshim.cpp) diff --git a/src/coreclr/nativeaot/Bootstrap/dll/CMakeLists.txt b/src/coreclr/nativeaot/Bootstrap/dll/CMakeLists.txt index b1a99ebc3b225..14eb3ece8e1e0 100644 --- a/src/coreclr/nativeaot/Bootstrap/dll/CMakeLists.txt +++ b/src/coreclr/nativeaot/Bootstrap/dll/CMakeLists.txt @@ -8,10 +8,10 @@ set(SOURCES add_library(bootstrapperdll STATIC ${SOURCES}) -install_static_library(bootstrapperdll aotsdk nativeaot) +install_bootstrapper_object(bootstrapperdll aotsdk) if (CLR_CMAKE_TARGET_WIN32) add_library(bootstrapperdll.GuardCF STATIC ${SOURCES}) - install_static_library(bootstrapperdll.GuardCF aotsdk nativeaot) + install_bootstrapper_object(bootstrapperdll.GuardCF aotsdk) target_compile_options(bootstrapperdll.GuardCF PRIVATE $<$,$>:/guard:cf>) endif() diff --git a/src/coreclr/nativeaot/Bootstrap/main.cpp b/src/coreclr/nativeaot/Bootstrap/main.cpp index 5e30ae1f0f495..8115fc870c23e 100644 --- a/src/coreclr/nativeaot/Bootstrap/main.cpp +++ b/src/coreclr/nativeaot/Bootstrap/main.cpp @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. #include +#include "minipal/utils.h" // // This is the mechanism whereby multiple linked modules contribute their global data for initialization at @@ -217,6 +218,12 @@ int main(int argc, char* argv[]) return __managed__Main(argc, argv); } + +// We need to build the bootstrapper as a single object file, to ensure +// the linker can detect that we have ASAN components early enough in the build. +// Include our asan support sources for executable projects here to ensure they +// are compiled into the bootstrapper object. +#include "minipal/asansupport.cpp" #endif // !NATIVEAOT_DLL #ifdef NATIVEAOT_DLL diff --git a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.targets b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.targets index bb1b8c435a137..e0c506bd01268 100644 --- a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.targets +++ b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.targets @@ -55,8 +55,8 @@ The .NET Foundation licenses this file to you under the MIT license. - - + + diff --git a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Windows.targets b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Windows.targets index 9512bf826c40b..5c6dd32cb6a4b 100644 --- a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Windows.targets +++ b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Windows.targets @@ -16,7 +16,9 @@ The .NET Foundation licenses this file to you under the MIT license. link lib + .obj .lib + .GuardCF.obj .GuardCF.lib Runtime.WorkstationGC Runtime.ServerGC @@ -35,7 +37,7 @@ The .NET Foundation licenses this file to you under the MIT license. - + diff --git a/src/coreclr/nativeaot/Runtime/windows/PalRedhawkMinWin.cpp b/src/coreclr/nativeaot/Runtime/windows/PalRedhawkMinWin.cpp index 6691df67ada46..902483765b20d 100644 --- a/src/coreclr/nativeaot/Runtime/windows/PalRedhawkMinWin.cpp +++ b/src/coreclr/nativeaot/Runtime/windows/PalRedhawkMinWin.cpp @@ -438,6 +438,7 @@ REDHAWK_PALEXPORT _Success_(return) bool REDHAWK_PALAPI PalSetThreadContext(HAND REDHAWK_PALEXPORT void REDHAWK_PALAPI PalRestoreContext(CONTEXT * pCtx) { + __asan_handle_no_return(); RtlRestoreContext(pCtx, NULL); } diff --git a/src/coreclr/pal/src/arch/amd64/context2.S b/src/coreclr/pal/src/arch/amd64/context2.S index 87a1277270c49..dba772f9dbbf5 100644 --- a/src/coreclr/pal/src/arch/amd64/context2.S +++ b/src/coreclr/pal/src/arch/amd64/context2.S @@ -89,7 +89,7 @@ LEAF_ENTRY RtlRestoreContext, _TEXT push_nonvol_reg rbp alloc_stack (IRetFrameLengthAligned) -#ifdef HAS_ASAN +#ifdef HAS_ADDRESS_SANITIZER test BYTE PTR [rdi + CONTEXT_ContextFlags], CONTEXT_CONTROL je LOCAL_LABEL(Restore_CONTEXT_FLOATING_POINT) diff --git a/src/coreclr/pal/src/arch/amd64/exceptionhelper.S b/src/coreclr/pal/src/arch/amd64/exceptionhelper.S index 1e61336bfd540..ac5dc157a104e 100644 --- a/src/coreclr/pal/src/arch/amd64/exceptionhelper.S +++ b/src/coreclr/pal/src/arch/amd64/exceptionhelper.S @@ -13,7 +13,7 @@ // Then it uses the ThrowExceptionHelper to throw the passed in exception from that context. // EXTERN_C void ThrowExceptionFromContextInternal(CONTEXT* context, PAL_SEHException* ex); LEAF_ENTRY ThrowExceptionFromContextInternal, _TEXT -#ifdef HAS_ASAN +#ifdef HAS_ADDRESS_SANITIZER // Need to call __asan_handle_no_return explicitly here because we re-initialize RSP before // throwing exception in ThrowExceptionHelper push_nonvol_reg rdi diff --git a/src/coreclr/pal/src/arch/arm/context2.S b/src/coreclr/pal/src/arch/arm/context2.S index edb5d35bf1e40..32983c196969f 100644 --- a/src/coreclr/pal/src/arch/arm/context2.S +++ b/src/coreclr/pal/src/arch/arm/context2.S @@ -118,7 +118,7 @@ LEAF_END RtlCaptureContext, _TEXT LEAF_ENTRY RtlRestoreContext, _TEXT END_PROLOGUE -#ifdef HAS_ASAN +#ifdef HAS_ADDRESS_SANITIZER ldr r2, [r0, #(CONTEXT_ContextFlags)] tst r2, #(CONTEXT_CONTROL) beq LOCAL_LABEL(Restore_CONTEXT_FLOATING_POINT) diff --git a/src/coreclr/pal/src/arch/arm/exceptionhelper.S b/src/coreclr/pal/src/arch/arm/exceptionhelper.S index 18878894b0602..e450af68ec593 100644 --- a/src/coreclr/pal/src/arch/arm/exceptionhelper.S +++ b/src/coreclr/pal/src/arch/arm/exceptionhelper.S @@ -12,7 +12,7 @@ // EXTERN_C void ThrowExceptionFromContextInternal(CONTEXT* context, PAL_SEHException* ex); LEAF_ENTRY ThrowExceptionFromContextInternal, _TEXT // Ported from src/pal/src/arch/amd64/exceptionhelper.S -#ifdef HAS_ASAN +#ifdef HAS_ADDRESS_SANITIZER // Need to call __asan_handle_no_return explicitly here because we re-initialize SP before // throwing exception in ThrowExceptionHelper push_nonvol_reg "{r0, r1}" diff --git a/src/coreclr/pal/src/arch/arm64/context2.S b/src/coreclr/pal/src/arch/arm64/context2.S index ecbb10ca8fdea..23bc0c065581e 100644 --- a/src/coreclr/pal/src/arch/arm64/context2.S +++ b/src/coreclr/pal/src/arch/arm64/context2.S @@ -135,7 +135,7 @@ LEAF_END RtlCaptureContext, _TEXT // LEAF_ENTRY RtlRestoreContext, _TEXT -#ifdef HAS_ASAN +#ifdef HAS_ADDRESS_SANITIZER ldr w17, [x0, #(CONTEXT_ContextFlags)] tbz w17, #CONTEXT_CONTROL_BIT, LOCAL_LABEL(Restore_CONTEXT_FLOATING_POINT) @@ -220,7 +220,7 @@ LEAF_END RtlRestoreContext, _TEXT // x1: Exception* // LEAF_ENTRY RestoreCompleteContext, _TEXT - // We cannot restore all registers in the user mode code, so we rely on a help from kernel here. + // We cannot restore all registers in the user mode code, so we rely on a help from kernel here. // The following instruction is an undefined instruction. In the hardware exception handler, we check // if the faulting address is the RtlRestoreContext and in case it is, we update the context of // the faulting thread using the CONTEXT pointed to by the x0 register. diff --git a/src/coreclr/pal/src/arch/arm64/exceptionhelper.S b/src/coreclr/pal/src/arch/arm64/exceptionhelper.S index 7ad1ae4c58b26..5690a40f9c30d 100644 --- a/src/coreclr/pal/src/arch/arm64/exceptionhelper.S +++ b/src/coreclr/pal/src/arch/arm64/exceptionhelper.S @@ -11,7 +11,7 @@ // Then it uses the ThrowExceptionHelper to throw the passed in exception from that context. // EXTERN_C void ThrowExceptionFromContextInternal(CONTEXT* context, PAL_SEHException* ex); LEAF_ENTRY ThrowExceptionFromContextInternal, _TEXT -#ifdef HAS_ASAN +#ifdef HAS_ADDRESS_SANITIZER // Need to call __asan_handle_no_return explicitly here because we re-initialize SP before // throwing exception in ThrowExceptionHelper stp x0, x1, [sp, -16]! diff --git a/src/coreclr/pal/src/arch/i386/context2.S b/src/coreclr/pal/src/arch/i386/context2.S index bfcc25b09f403..cf5b464c27d0c 100644 --- a/src/coreclr/pal/src/arch/i386/context2.S +++ b/src/coreclr/pal/src/arch/i386/context2.S @@ -94,7 +94,7 @@ LEAF_END RtlCaptureContext, _TEXT LEAF_ENTRY RtlRestoreContext, _TEXT -#ifdef HAS_ASAN +#ifdef HAS_ADDRESS_SANITIZER call EXTERNAL_C_FUNC(__asan_handle_no_return) #endif mov eax, [esp + 4] diff --git a/src/coreclr/pal/src/arch/i386/exceptionhelper.S b/src/coreclr/pal/src/arch/i386/exceptionhelper.S index 9bada09b2cfd3..aec51ceb6d650 100644 --- a/src/coreclr/pal/src/arch/i386/exceptionhelper.S +++ b/src/coreclr/pal/src/arch/i386/exceptionhelper.S @@ -17,7 +17,7 @@ ////////////////////////////////////////////////////////////////////////// LEAF_ENTRY ThrowExceptionFromContextInternal, _TEXT -#ifdef HAS_ASAN +#ifdef HAS_ADDRESS_SANITIZER // Need to call __asan_handle_no_return explicitly here because we re-initialize ESP before // throwing exception in ThrowExceptionHelper call EXTERNAL_C_FUNC(__asan_handle_no_return) diff --git a/src/coreclr/pal/src/arch/loongarch64/context2.S b/src/coreclr/pal/src/arch/loongarch64/context2.S index 97e02574fb436..701bd39fb8b38 100644 --- a/src/coreclr/pal/src/arch/loongarch64/context2.S +++ b/src/coreclr/pal/src/arch/loongarch64/context2.S @@ -14,7 +14,7 @@ // a1: Exception* // LEAF_ENTRY RtlRestoreContext, _TEXT -#ifdef HAS_ASAN +#ifdef HAS_ADDRESS_SANITIZER ld.w $r21, $a0, CONTEXT_ContextFlags ext $r21, $r21, CONTEXT_FLOATING_POINT_BIT, 1 beq $r21, $r0, LOCAL_LABEL(Restore_CONTEXT_FLOATING_POINT) diff --git a/src/coreclr/pal/src/arch/loongarch64/exceptionhelper.S b/src/coreclr/pal/src/arch/loongarch64/exceptionhelper.S index 157e4149df5eb..b86450da1d067 100644 --- a/src/coreclr/pal/src/arch/loongarch64/exceptionhelper.S +++ b/src/coreclr/pal/src/arch/loongarch64/exceptionhelper.S @@ -11,7 +11,7 @@ // Then it uses the ThrowExceptionHelper to throw the passed in exception from that context. // EXTERN_C void ThrowExceptionFromContextInternal(CONTEXT* context, PAL_SEHException* ex); LEAF_ENTRY ThrowExceptionFromContextInternal, _TEXT -#ifdef HAS_ASAN +#ifdef HAS_ADDRESS_SANITIZER #pragma error("LLVM v3.9 ASAN unimplemented on LOONGARCH yet") #endif addi.d $sp, $sp, -16 diff --git a/src/coreclr/pal/src/exception/machexception.cpp b/src/coreclr/pal/src/exception/machexception.cpp index bce0ae4774a43..50db83248fe7a 100644 --- a/src/coreclr/pal/src/exception/machexception.cpp +++ b/src/coreclr/pal/src/exception/machexception.cpp @@ -31,6 +31,7 @@ SET_DEFAULT_DEBUG_CHANNEL(EXCEPT); // some headers have code with asserts, so do #include "pal/virtual.h" #include "pal/map.hpp" #include "pal/environ.h" +#include #include "machmessage.h" @@ -356,27 +357,23 @@ PAL_ERROR CorUnix::CPalThread::DisableMachExceptions() return palError; } -#if defined(HOST_AMD64) -// Since HijackFaultingThread pushed the context, exception record and info on the stack, we need to adjust the -// signature of PAL_DispatchException such that the corresponding arguments are considered to be on the stack -// per GCC64 calling convention rules. Hence, the first 6 dummy arguments (corresponding to RDI, RSI, RDX,RCX, R8, R9). -extern "C" -void PAL_DispatchException(DWORD64 dwRDI, DWORD64 dwRSI, DWORD64 dwRDX, DWORD64 dwRCX, DWORD64 dwR8, DWORD64 dwR9, PCONTEXT pContext, PEXCEPTION_RECORD pExRecord, MachExceptionInfo *pMachExceptionInfo) -#elif defined(HOST_ARM64) - +#if defined(HOST_ARM64) extern "C" void RestoreCompleteContext( PCONTEXT ContextRecord, PEXCEPTION_RECORD ExceptionRecord ); - -extern "C" -void PAL_DispatchException(PCONTEXT pContext, PEXCEPTION_RECORD pExRecord, MachExceptionInfo *pMachExceptionInfo) #endif -{ - CPalThread *pThread = InternalGetCurrentThread(); +__attribute__((noinline)) +static void PAL_DispatchExceptionInner(PCONTEXT pContext, PEXCEPTION_RECORD pExRecord) +{ + // Stash the inner context record into a local in a frame other than PAL_DispatchException + // to ensure we have a compiler-defined callee stack frame state to record the context record + // local before we call SEHProcessException. The instrumentation introduced by native sanitizers + // doesn't interface that well with the fake caller frames we define for PAL_DispatchException, + // but they work fine for any callees of PAL_DispatchException. CONTEXT *contextRecord = pContext; g_hardware_exception_context_locvar_offset = (int)((char*)&contextRecord - (char*)__builtin_frame_address(0)); @@ -400,6 +397,7 @@ void PAL_DispatchException(PCONTEXT pContext, PEXCEPTION_RECORD pExRecord, MachE if (continueExecution) { + __asan_handle_no_return(); #if defined(HOST_ARM64) // RtlRestoreContext assembly corrupts X16 & X17, so it cannot be // used for GCStress=C restore @@ -408,6 +406,28 @@ void PAL_DispatchException(PCONTEXT pContext, PEXCEPTION_RECORD pExRecord, MachE RtlRestoreContext(pContext, pExRecord); #endif } +} + +#if defined(HOST_AMD64) +// Since HijackFaultingThread pushed the context, exception record and info on the stack, we need to adjust the +// signature of PAL_DispatchException such that the corresponding arguments are considered to be on the stack +// per GCC64 calling convention rules. Hence, the first 6 dummy arguments (corresponding to RDI, RSI, RDX,RCX, R8, R9). +extern "C" +void PAL_DispatchException(DWORD64 dwRDI, DWORD64 dwRSI, DWORD64 dwRDX, DWORD64 dwRCX, DWORD64 dwR8, DWORD64 dwR9, PCONTEXT pContext, PEXCEPTION_RECORD pExRecord, MachExceptionInfo *pMachExceptionInfo) +#elif defined(HOST_ARM64) + +extern "C" +void PAL_DispatchException(PCONTEXT pContext, PEXCEPTION_RECORD pExRecord, MachExceptionInfo *pMachExceptionInfo) +#endif +{ + // At the time of executing this function, this thread's stack is a lie. + // This frame and the calling frame were never actually pushed onto the stack + // and were synthetically added by HijackFaultingThread. + // We need to let ASAN know that its stack tracking is out of date. + __asan_handle_no_return(); + CPalThread *pThread = InternalGetCurrentThread(); + + PAL_DispatchExceptionInner(pContext, pExRecord); // Send the forward request to the exception thread to process MachMessage sSendMessage; diff --git a/src/coreclr/pal/src/thread/thread.cpp b/src/coreclr/pal/src/thread/thread.cpp index 0daa011e6fc63..90501bbafbde5 100644 --- a/src/coreclr/pal/src/thread/thread.cpp +++ b/src/coreclr/pal/src/thread/thread.cpp @@ -2449,7 +2449,7 @@ CPalThread::EnsureSignalAlternateStack() // We include the size of the SignalHandlerWorkerReturnPoint in the alternate stack size since the // context contained in it is large and the SIGSTKSZ was not sufficient on ARM64 during testing. int altStackSize = SIGSTKSZ + ALIGN_UP(sizeof(SignalHandlerWorkerReturnPoint), 16) + GetVirtualPageSize(); -#ifdef HAS_ASAN +#ifdef HAS_ADDRESS_SANITIZER // Asan also uses alternate stack so we increase its size on the SIGSTKSZ * 4 that enough for asan // (see kAltStackSize in compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cc) altStackSize += SIGSTKSZ * 4; diff --git a/src/coreclr/runtime.proj b/src/coreclr/runtime.proj index 0b936f4579c56..4164484606c1b 100644 --- a/src/coreclr/runtime.proj +++ b/src/coreclr/runtime.proj @@ -1,7 +1,7 @@ - ClrFullNativeBuild;ClrRuntimeSubset;ClrJitSubset;ClrPalTestsSubset;ClrAllJitsSubset;ClrILToolsSubset;ClrNativeAotSubset;ClrSpmiSubset;ClrCrossComponentsSubset;HostArchitecture;PgoInstrument;NativeOptimizationDataSupported;CMakeArgs + ClrFullNativeBuild;ClrRuntimeSubset;ClrJitSubset;ClrPalTestsSubset;ClrAllJitsSubset;ClrILToolsSubset;ClrNativeAotSubset;ClrSpmiSubset;ClrCrossComponentsSubset;ClrDebugSubset;HostArchitecture;PgoInstrument;NativeOptimizationDataSupported;CMakeArgs <_IcuDir Condition="'$(PkgMicrosoft_NETCore_Runtime_ICU_Transport)' != ''">$(PkgMicrosoft_NETCore_Runtime_ICU_Transport)/runtimes/$(TargetOS)-$(TargetArchitecture)$(_RuntimeVariant)/native <_BuildNativeTargetOS>$(TargetOS) @@ -22,8 +22,9 @@ DependsOnTargets="GetPgoDataPackagePath" BeforeTargets="Build"> + <_CMakeArgs Include="$(CMakeArgs)" /> + <_CoreClrBuildArg Include="@(_CMakeArgs->'-cmakeargs "%(Identity)"')" /> <_CoreClrBuildArg Condition="'$(TargetArchitecture)' != ''" Include="-$(TargetArchitecture)" /> - <_CoreClrBuildArg Condition="'$(CMakeArgs)' != ''" Include="-cmakeargs "$(CMakeArgs)"" /> <_CoreClrBuildArg Include="-$(Configuration.ToLower())" /> <_CoreClrBuildArg Include="$(Compiler)" /> <_CoreClrBuildArg Condition="'$(ConfigureOnly)' == 'true'" Include="-configureonly" /> @@ -45,8 +46,10 @@ <_CoreClrBuildArg Condition="'$(PgoInstrument)' == 'true'" Include="-pgoinstrument" /> <_CoreClrBuildArg Condition="'$(NativeOptimizationDataSupported)' == 'true' and '$(NoPgoOptimize)' != 'true' and '$(PgoInstrument)' != 'true'" Include="-pgodatapath "$(PgoPackagePath)"" /> <_CoreClrBuildArg Condition="'$(HostArchitecture)' != ''" Include="-hostarch $(HostArchitecture)" /> + <_CoreClrBuildArg Condition="'$(EnableNativeSanitizers)' != ''" Include="-fsanitize $(EnableNativeSanitizers)" /> <_CoreClrBuildArg Condition="'$(HostCrossOS)' != ''" Include="-hostos $(HostCrossOS)" /> <_CoreClrBuildArg Include="-outputrid $(OutputRID)" /> + <_CoreClrBuildArg Condition="'$(BuildSubdirectory)' != ''" Include="-subdir $(BuildSubdirectory)" /> @@ -59,6 +62,7 @@ <_CoreClrBuildArg Condition="'$(ClrNativeAotSubset)' == 'true'" Include="-component nativeaot" /> <_CoreClrBuildArg Condition="'$(ClrSpmiSubset)' == 'true'" Include="-component spmi" /> <_CoreClrBuildArg Condition="'$(ClrCrossComponentsSubset)' == 'true'" Include="-component crosscomponents" /> + <_CoreClrBuildArg Condition="'$(ClrDebugSubset)' == 'true'" Include="-component debug" /> @@ -90,4 +94,6 @@ + + diff --git a/src/coreclr/tools/aot/crossgen2/crossgen2.csproj b/src/coreclr/tools/aot/crossgen2/crossgen2.csproj index 3702d32900776..199ec842608eb 100644 --- a/src/coreclr/tools/aot/crossgen2/crossgen2.csproj +++ b/src/coreclr/tools/aot/crossgen2/crossgen2.csproj @@ -30,7 +30,7 @@ $(CoreCLRILCompilerDir) - $(CoreCLRCrossILCompilerDir) + $(CoreCLRCrossILCompilerDir) $(ROOTFS_DIR) $(CoreCLRILCompilerDir)netstandard/ILCompiler.Build.Tasks.dll $(CoreCLRAotSdkDir) @@ -46,6 +46,7 @@ + Esp, Ebx, Esi, Edi, Ebp, and Eip are initialized _CallJitEHFilterHelper@8 PROC public + ; Call ___asan_handle_no_return here as we touch registers that ASAN uses. +ifdef HAS_ADDRESS_SANITIZER + call ___asan_handle_no_return +endif push ebp mov ebp, esp push ebx @@ -334,6 +346,10 @@ _CallJitEHFilterHelper@8 ENDP ; void __stdcall CallJITEHFinallyHelper(size_t *pShadowSP, EHContext *pContext); ; on entry, only the pContext->Esp, Ebx, Esi, Edi, Ebp, and Eip are initialized _CallJitEHFinallyHelper@8 PROC public + ; Call ___asan_handle_no_return here as we touch registers that ASAN uses. +ifdef HAS_ADDRESS_SANITIZER + call ___asan_handle_no_return +endif push ebp mov ebp, esp push ebx diff --git a/src/coreclr/vm/i386/jitinterfacex86.cpp b/src/coreclr/vm/i386/jitinterfacex86.cpp index 7e5c59135b85c..e51a324813ef4 100644 --- a/src/coreclr/vm/i386/jitinterfacex86.cpp +++ b/src/coreclr/vm/i386/jitinterfacex86.cpp @@ -962,18 +962,11 @@ void InitJITHelpers1() // Get CPU features and check for SSE2 support. // This code should eventually probably be moved into codeman.cpp, // where we set the cpu feature flags for the JIT based on CPU type and features. - DWORD dwCPUFeaturesECX; - DWORD dwCPUFeaturesEDX; + int cpuFeatures[4]; + __cpuid(cpuFeatures, 1); - __asm - { - pushad - mov eax, 1 - cpuid - mov dwCPUFeaturesECX, ecx - mov dwCPUFeaturesEDX, edx - popad - } + DWORD dwCPUFeaturesECX = cpuFeatures[2]; + DWORD dwCPUFeaturesEDX = cpuFeatures[3]; // If bit 26 (SSE2) is set, then we can use the SSE2 flavors // and faster x87 implementation for the P4 of Dbl2Lng. diff --git a/src/coreclr/vm/i386/stublinkerx86.cpp b/src/coreclr/vm/i386/stublinkerx86.cpp index fde6801c289b6..76d888c0c5275 100644 --- a/src/coreclr/vm/i386/stublinkerx86.cpp +++ b/src/coreclr/vm/i386/stublinkerx86.cpp @@ -77,7 +77,11 @@ extern "C" VOID __cdecl DebugCheckStubUnwindInfo(); #endif // TARGET_AMD64 #ifdef FEATURE_COMINTEROP -Thread* __stdcall CreateThreadBlockReturnHr(ComMethodFrame *pFrame); +// Use a type alias as MSVC has issues parsing the pointer, the calling convention, and the declspec +// in the same signature. +// Disable ASAN here as this method uses inline assembly and touches registers that ASAN uses. +using ThreadPointer = Thread*; +ThreadPointer DISABLE_ASAN __stdcall CreateThreadBlockReturnHr(ComMethodFrame *pFrame); #endif @@ -4913,7 +4917,7 @@ VOID StubLinkerCPU::EmitDebugBreak() // global optimizations. #pragma warning (disable : 4731) #endif // _MSC_VER -Thread* __stdcall CreateThreadBlockReturnHr(ComMethodFrame *pFrame) +ThreadPointer __stdcall CreateThreadBlockReturnHr(ComMethodFrame *pFrame) { WRAPPER_NO_CONTRACT; @@ -4931,6 +4935,10 @@ Thread* __stdcall CreateThreadBlockReturnHr(ComMethodFrame *pFrame) UINT numArgStackBytes = pFrame->GetNumCallerStackBytes(); unsigned frameSize = sizeof(Frame) + sizeof(LPVOID); LPBYTE iEsp = ((LPBYTE)pFrame) + ComMethodFrame::GetOffsetOfCalleeSavedRegisters(); + + // Let ASAN that we aren't going to return so it can do some cleanup + __asan_handle_no_return(); + __asm { mov eax, hr diff --git a/src/coreclr/vm/jithelpers.cpp b/src/coreclr/vm/jithelpers.cpp index d5945f36582bb..e78f312ea3f58 100644 --- a/src/coreclr/vm/jithelpers.cpp +++ b/src/coreclr/vm/jithelpers.cpp @@ -5658,6 +5658,7 @@ HCIMPL1(VOID, JIT_PartialCompilationPatchpoint, int ilOffset) ::SetLastError(dwLastError); // Transition! + __asan_handle_no_return(); RtlRestoreContext(&frameContext, NULL); } HCIMPLEND diff --git a/src/coreclr/vm/threads.cpp b/src/coreclr/vm/threads.cpp index 6312d08b06d56..edbd6a011f33b 100644 --- a/src/coreclr/vm/threads.cpp +++ b/src/coreclr/vm/threads.cpp @@ -8241,8 +8241,10 @@ void ClrRestoreNonvolatileContext(PCONTEXT ContextRecord) { #if defined(TARGET_WINDOWS) && defined(TARGET_AMD64) DWORD64 ssp = GetSSP(ContextRecord); + __asan_handle_no_return(); ClrRestoreNonvolatileContextWorker(ContextRecord, ssp); #else + __asan_handle_no_return(); // Falling back to RtlRestoreContext() for now, though it should be possible to have simpler variants for these cases RtlRestoreContext(ContextRecord, NULL); #endif diff --git a/src/coreclr/vm/threadsuspend.cpp b/src/coreclr/vm/threadsuspend.cpp index e7414425ece2d..94b809e9f2ad4 100644 --- a/src/coreclr/vm/threadsuspend.cpp +++ b/src/coreclr/vm/threadsuspend.cpp @@ -2764,6 +2764,7 @@ void __stdcall Thread::RedirectedHandledJITCase(RedirectReason reason) LOG((LF_SYNC, LL_INFO1000, "Resuming execution with RtlRestoreContext\n")); SetLastError(dwLastError); // END_PRESERVE_LAST_ERROR + __asan_handle_no_return(); #ifdef TARGET_X86 g_pfnRtlRestoreContext(pCtx, NULL); #else @@ -3931,6 +3932,7 @@ ThrowControlForThread( _ASSERTE(!"Should not reach here"); } #else // FEATURE_EH_FUNCLETS + __asan_handle_no_return(); RtlRestoreContext(pThread->m_OSContext, NULL); #endif // !FEATURE_EH_FUNCLETS _ASSERTE(!"Should not reach here"); diff --git a/src/coreclr/vm/wks/CMakeLists.txt b/src/coreclr/vm/wks/CMakeLists.txt index b0113575c1e05..b8c5b2a3698c3 100644 --- a/src/coreclr/vm/wks/CMakeLists.txt +++ b/src/coreclr/vm/wks/CMakeLists.txt @@ -1,4 +1,3 @@ - if (CLR_CMAKE_TARGET_WIN32) if(CLR_CMAKE_HOST_ARCH_ARM OR CLR_CMAKE_HOST_ARCH_ARM64) preprocess_files(VM_SOURCES_WKS_ARCH_ASM ${VM_SOURCES_WKS_ARCH_ASM}) diff --git a/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props b/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props index f13859dc19932..f5dc16b7677a2 100644 --- a/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props +++ b/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props @@ -176,8 +176,10 @@ - + + + diff --git a/src/libraries/Directory.Build.targets b/src/libraries/Directory.Build.targets index 467d900788282..805e947626c46 100644 --- a/src/libraries/Directory.Build.targets +++ b/src/libraries/Directory.Build.targets @@ -128,6 +128,7 @@ + diff --git a/src/libraries/externals.csproj b/src/libraries/externals.csproj index c3ba982bd8e33..7f85d5d67e31f 100644 --- a/src/libraries/externals.csproj +++ b/src/libraries/externals.csproj @@ -60,6 +60,12 @@ SkipUnchangedFiles="true" UseHardlinksIfPossible="$(UseHardlink)" /> + + + + + + + + + + + + + + + diff --git a/src/libraries/tests.proj b/src/libraries/tests.proj index 5a8dd2c2aef0b..edce0bafbf461 100644 --- a/src/libraries/tests.proj +++ b/src/libraries/tests.proj @@ -513,6 +513,11 @@ Include="@(HighAOTResourceRequiringProject)" /> + + + + + diff --git a/src/mono/CMakeLists.txt b/src/mono/CMakeLists.txt index 4ab4ece785c5c..922df30508e20 100644 --- a/src/mono/CMakeLists.txt +++ b/src/mono/CMakeLists.txt @@ -555,6 +555,12 @@ if(GCC) set(WERROR_C "${WERROR_C} -Werror=incompatible-pointer-types") endif() + # Check for sometimes suppressed warnings + check_c_compiler_flag(-Wreserved-identifier COMPILER_SUPPORTS_W_RESERVED_IDENTIFIER) + if(COMPILER_SUPPORTS_W_RESERVED_IDENTIFIER) + add_compile_definitions(COMPILER_SUPPORTS_W_RESERVED_IDENTIFIER) + endif() + if(HOST_WASI) # When building under WASI SDK, it's stricter about discarding 'const' qualifiers, causing some existing # code (e.g., mono-rand.c:315) to be rejected diff --git a/src/native/corehost/CMakeLists.txt b/src/native/corehost/CMakeLists.txt index b9674fdeb26e6..249e4d52cf264 100644 --- a/src/native/corehost/CMakeLists.txt +++ b/src/native/corehost/CMakeLists.txt @@ -30,6 +30,12 @@ add_subdirectory(dotnet) add_subdirectory(nethost) add_subdirectory(test) +# If there's a dynamic ASAN runtime, then install it in the directories where we put our executables. +if (NOT "${ASAN_RUNTIME}" STREQUAL "") + install(FILES ${ASAN_RUNTIME} DESTINATION corehost) + install(FILES ${ASAN_RUNTIME} DESTINATION corehost_test) +endif() + if (NOT RUNTIME_FLAVOR STREQUAL Mono) if(CLR_CMAKE_TARGET_WIN32) add_subdirectory(comhost) diff --git a/src/native/corehost/apphost/static/CMakeLists.txt b/src/native/corehost/apphost/static/CMakeLists.txt index 5fa066359e13a..e1a02ece41091 100644 --- a/src/native/corehost/apphost/static/CMakeLists.txt +++ b/src/native/corehost/apphost/static/CMakeLists.txt @@ -259,3 +259,5 @@ target_link_libraries( ${RUNTIMEINFO_LIB} ${END_WHOLE_ARCHIVE} ) + +add_sanitizer_runtime_support(singlefilehost) diff --git a/src/native/corehost/build.cmd b/src/native/corehost/build.cmd index e43bcae3cf3cc..89d9aa20a3d1e 100644 --- a/src/native/corehost/build.cmd +++ b/src/native/corehost/build.cmd @@ -21,6 +21,7 @@ set __ConfigureOnly=0 set __IncrementalNativeBuild=0 set __Ninja=1 set __OutputRid="" +set __ExtraCmakeParams= :Arg_Loop if [%1] == [] goto :InitVSEnv @@ -49,6 +50,7 @@ if /i [%1] == [rootDir] (set __rootDir=%2&&shift&&shift&goto Arg_Loop) if /i [%1] == [msbuild] (set __Ninja=0) if /i [%1] == [runtimeflavor] (set __RuntimeFlavor=%2&&shift&&shift&goto Arg_Loop) if /i [%1] == [runtimeconfiguration] (set __RuntimeConfiguration=%2&&shift&&shift&goto Arg_Loop) +if /i [%1] == [-fsanitize] ( set __ExtraCmakeParams=%__ExtraCmakeParams% "-DCLR_CMAKE_ENABLE_SANITIZERS=%2"&&shift&&shift&goto Arg_Loop) shift goto :Arg_Loop diff --git a/src/native/corehost/corehost.proj b/src/native/corehost/corehost.proj index 18ac25f41841d..9cdbfa0e434aa 100644 --- a/src/native/corehost/corehost.proj +++ b/src/native/corehost/corehost.proj @@ -81,6 +81,7 @@ $(BuildArgs) -cmakeargs "$(CMakeArgs)" $(BuildArgs) -ninja $(BuildArgs) -runtimeflavor $(RuntimeFlavor) + $(BuildArgs) -fsanitize=$(EnableNativeSanitizers) $(BuildArgs) /p:OfficialBuildId="$(OfficialBuildId)" $(BuildArgs) -outputrid $(OutputRID) @@ -141,6 +142,7 @@ $(BuildArgs) msbuild $(BuildArgs) runtimeflavor $(RuntimeFlavor) $(BuildArgs) runtimeconfiguration $(RuntimeConfiguration) + $(BuildArgs) -fsanitize=$(EnableNativeSanitizers) + + + + + + + + - + - + - + - + True - + - + True - + True - + @@ -93,26 +108,26 @@ Condition="'%(RuntimeArtifactsIncludeFolders.IncludeSubFolders)' != 'True'" Include="$(CoreCLRArtifactsPath)%(RunTimeArtifactsIncludeFolders.Identity)*" Exclude="@(RunTimeArtifactsExcludeFiles -> '$(CoreCLRArtifactsPath)%(Identity)')" - TargetDir="%(RunTimeArtifactsIncludeFolders.Identity)" /> + TargetDir="%(RunTimeArtifactsIncludeFolders.TargetDir)" /> + TargetDir="%(RunTimeArtifactsIncludeFolders.TargetDir)" /> - $(CoreCLRArtifactsPath)x64/crossgen2 + $(CoreCLRArtifactsPath)x64/crossgen2 diff --git a/src/tests/Common/helixpublishwitharcade.proj b/src/tests/Common/helixpublishwitharcade.proj index edc43366cd9e9..db4ce658d6c76 100644 --- a/src/tests/Common/helixpublishwitharcade.proj +++ b/src/tests/Common/helixpublishwitharcade.proj @@ -677,6 +677,7 @@ + diff --git a/src/tests/Common/publishdependency.targets b/src/tests/Common/publishdependency.targets index 4a16052008d7d..eff6edb3a1144 100644 --- a/src/tests/Common/publishdependency.targets +++ b/src/tests/Common/publishdependency.targets @@ -28,7 +28,7 @@ + Properties="Language=C#;RuntimeIdentifier=$(OutputRID);CORE_ROOT=$(CORE_ROOT);EnableNativeSanitizers=$(EnableNativeSanitizers)" /> diff --git a/src/tests/Directory.Build.props b/src/tests/Directory.Build.props index 4574f6cdb1501..90d5d9d17a2a7 100644 --- a/src/tests/Directory.Build.props +++ b/src/tests/Directory.Build.props @@ -19,6 +19,7 @@ $(__AltJitArch) + $(__EnableNativeSanitizers) diff --git a/src/tests/Directory.Build.targets b/src/tests/Directory.Build.targets index b5bec81d6845e..fe922918c11ec 100644 --- a/src/tests/Directory.Build.targets +++ b/src/tests/Directory.Build.targets @@ -99,6 +99,7 @@ <_WillCLRTestProjectBuild Condition="'$(DisableProjectBuild)' == 'true'">false <_WillCLRTestProjectBuild Condition="'$(NativeAotIncompatible)' == 'true' and '$(TestBuildMode)' == 'nativeaot'">false <_WillCLRTestProjectBuild Condition="'$(RuntimeFlavor)' == 'mono' And '$(AlwaysUseCrossgen2)' == 'true'">false + <_WillCLRTestProjectBuild Condition="'$(EnableNativeSanitizers)' != '' And '$(AlwaysUseCrossgen2)' == 'true'">false <_CopyNativeProjectBinaries Condition="'$(__CopyNativeTestBinaries)' != '1'">$(__CopyNativeProjectsAfterCombinedTestBuild) @@ -530,7 +531,7 @@ partial $(CoreCLRILCompilerDir) - $(CoreCLRCrossILCompilerDir) + $(CoreCLRCrossILCompilerDir) $(CoreCLRILCompilerDir)netstandard/ILCompiler.Build.Tasks.dll $(CoreCLRAotSdkDir) $(MicrosoftNetCoreAppRuntimePackRidLibTfmDir) @@ -564,8 +565,14 @@ + + + + + + diff --git a/src/tests/Interop/COM/NativeClients/DefaultInterfaces/CMakeLists.txt b/src/tests/Interop/COM/NativeClients/DefaultInterfaces/CMakeLists.txt index 8338be8220d4e..b58d8b34a2847 100644 --- a/src/tests/Interop/COM/NativeClients/DefaultInterfaces/CMakeLists.txt +++ b/src/tests/Interop/COM/NativeClients/DefaultInterfaces/CMakeLists.txt @@ -16,3 +16,7 @@ file(GENERATE OUTPUT $/CoreShim.X.manifest INPU # add the install targets install (TARGETS COMClientDefaultInterfaces DESTINATION bin) +# If there's a dynamic ASAN runtime, then copy it to project output. +if (NOT "${ASAN_RUNTIME}" STREQUAL "") + file(COPY "${ASAN_RUNTIME}" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}") +endif() diff --git a/src/tests/Interop/COM/NativeClients/Dispatch/CMakeLists.txt b/src/tests/Interop/COM/NativeClients/Dispatch/CMakeLists.txt index a3e35c353582f..6412f97931e45 100644 --- a/src/tests/Interop/COM/NativeClients/Dispatch/CMakeLists.txt +++ b/src/tests/Interop/COM/NativeClients/Dispatch/CMakeLists.txt @@ -15,3 +15,7 @@ file(GENERATE OUTPUT $/CoreShim.X.manifest IN # add the install targets install (TARGETS COMClientDispatch DESTINATION bin) +# If there's a dynamic ASAN runtime, then copy it to project output. +if (NOT "${ASAN_RUNTIME}" STREQUAL "") + file(COPY "${ASAN_RUNTIME}" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}") +endif() diff --git a/src/tests/Interop/COM/NativeClients/Events/CMakeLists.txt b/src/tests/Interop/COM/NativeClients/Events/CMakeLists.txt index 1443b6203727d..af9e12d0f35a9 100644 --- a/src/tests/Interop/COM/NativeClients/Events/CMakeLists.txt +++ b/src/tests/Interop/COM/NativeClients/Events/CMakeLists.txt @@ -16,3 +16,7 @@ file(GENERATE OUTPUT $/CoreShim.X.manifest INPU # add the install targets install (TARGETS COMClientEvents DESTINATION bin) +# If there's a dynamic ASAN runtime, then copy it to project output. +if (NOT "${ASAN_RUNTIME}" STREQUAL "") + file(COPY "${ASAN_RUNTIME}" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}") +endif() diff --git a/src/tests/Interop/COM/NativeClients/Licensing/CMakeLists.txt b/src/tests/Interop/COM/NativeClients/Licensing/CMakeLists.txt index ac9640e230f33..014a7824b3db5 100644 --- a/src/tests/Interop/COM/NativeClients/Licensing/CMakeLists.txt +++ b/src/tests/Interop/COM/NativeClients/Licensing/CMakeLists.txt @@ -16,3 +16,7 @@ file(GENERATE OUTPUT $/CoreShim.X.manifest INPU # add the install targets install (TARGETS COMClientLicensing DESTINATION bin) +# If there's a dynamic ASAN runtime, then copy it to project output. +if (NOT "${ASAN_RUNTIME}" STREQUAL "") + file(COPY "${ASAN_RUNTIME}" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}") +endif() diff --git a/src/tests/Interop/COM/NativeClients/Primitives/CMakeLists.txt b/src/tests/Interop/COM/NativeClients/Primitives/CMakeLists.txt index 0fcfe6dcce98d..096453469ffde 100644 --- a/src/tests/Interop/COM/NativeClients/Primitives/CMakeLists.txt +++ b/src/tests/Interop/COM/NativeClients/Primitives/CMakeLists.txt @@ -21,3 +21,7 @@ file(GENERATE OUTPUT $/CoreShim.X.manifest INPU # add the install targets install (TARGETS COMClientPrimitives DESTINATION bin) +# If there's a dynamic ASAN runtime, then copy it to project output. +if (NOT "${ASAN_RUNTIME}" STREQUAL "") + file(COPY "${ASAN_RUNTIME}" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}") +endif() diff --git a/src/tests/build.cmd b/src/tests/build.cmd index 7e70fa991dc1a..6e1b8f684d9f4 100644 --- a/src/tests/build.cmd +++ b/src/tests/build.cmd @@ -57,6 +57,7 @@ set __SkipGenerateLayout=0 set __GenerateLayoutOnly=0 set __Ninja=1 set __CMakeArgs= +set __EnableNativeSanitizers= set __Priority=0 set __BuildNeedTargetArg= @@ -121,6 +122,7 @@ if /i "%arg%" == "tree" (set __BuildTestTree=!__BuildTestTree!% if /i "%arg%" == "log" (set __BuildLogRootName=%2&set processedArgs=!processedArgs! %1 %2&shift&shift&goto Arg_Loop) if /i "%arg%" == "exclude" (set __Exclude=%2&set processedArgs=!processedArgs! %1 %2&shift&shift&goto Arg_Loop) if /i "%arg%" == "priority" (set __Priority=%2&set processedArgs=!processedArgs! %1 %2&shift&shift&goto Arg_Loop) +if /i "%arg%" == "fsanitize" (set __CMakeArgs=%__CMakeArgs% "-DCLR_CMAKE_ENABLE_SANITIZERS=%2"&set __EnableNativeSanitizers=%2&set processedArgs=!processedArgs! %1=%2&shift&shift&goto Arg_Loop) @REM The following arguments also consume two subsequent arguments if /i "%arg%" == "CMakeArgs" (set __CMakeArgs="%2=%3" %__CMakeArgs%&set "processedArgs=!processedArgs! %1 %2 %3"&shift&shift&shift&goto Arg_Loop) @@ -175,6 +177,7 @@ if defined __TestArgParsing ( echo.__Ninja=%__Ninja% echo.__CMakeArgs=%__CMakeArgs% echo.__Priority=%__Priority% + echo.__EnableNativeSanitizers=%__EnableNativeSanitizers% echo. ) @@ -405,6 +408,7 @@ echo -Log ^: Base file name to use for log files (used in lab pipelines th echo. echo -CMakeArgs ^=^: Specify argument values to pass directly to CMake. echo Can be used multiple times to provide multiple CMake arguments. +echo -fsanitize ^: Build the native test components with the specified native sanitizers. echo. echo -- : All arguments following this tag will be passed directly to MSBuild. echo. Any unrecognized arguments will also be passed directly to MSBuild. diff --git a/src/tests/build.sh b/src/tests/build.sh index 50efe6a764ebb..f222c69988c78 100755 --- a/src/tests/build.sh +++ b/src/tests/build.sh @@ -61,7 +61,7 @@ build_Tests() if [[ "$__SkipNative" != 1 && "$__BuildTestWrappersOnly" != 1 && "$__GenerateLayoutOnly" != 1 && "$__CopyNativeTestBinaries" != 1 && \ "$__TargetOS" != "browser" && "$__TargetOS" != "wasi" && "$__TargetOS" != "android" && "$__TargetOS" != "ios" && "$__TargetOS" != "iossimulator" && "$__TargetOS" != "tvos" && "$__TargetOS" != "tvossimulator" ]]; then - build_native "$__TargetOS" "$__TargetArch" "$__TestDir" "$__NativeTestIntermediatesDir" "install" "CoreCLR test component" + build_native "$__TargetOS" "$__TargetArch" "$__TestDir" "$__NativeTestIntermediatesDir" "install" "$__CMakeArgs" "CoreCLR test component" if [[ "$?" -ne 0 ]]; then echo "${__ErrMsgPrefix}${__MsgPrefix}Error: native test build failed. Refer to the build log files for details (above)" @@ -110,6 +110,7 @@ build_Tests() export __MsgPrefix export __ErrMsgPrefix export __Exclude + export EnableNativeSanitizers # Generate build command buildArgs=("$__RepoRootDir/src/tests/build.proj") @@ -363,6 +364,7 @@ __MonoAot=0 __MonoFullAot=0 __BuildLogRootName="TestBuild" CORE_ROOT= +EnableNativeSanitizers= source $__RepoRootDir/src/coreclr/_build-commons.sh diff --git a/src/tests/nativeaot/CustomMain/CustomMainNative.cpp b/src/tests/nativeaot/CustomMain/CustomMainNative.cpp index 590051f6c5e7f..e9bb1c25b9d46 100644 --- a/src/tests/nativeaot/CustomMain/CustomMainNative.cpp +++ b/src/tests/nativeaot/CustomMain/CustomMainNative.cpp @@ -4,6 +4,10 @@ #include #include +#ifndef TARGET_WINDOWS +#define __stdcall +#endif + #if defined(_WIN32) extern "C" int __managed__Main(int argc, wchar_t* argv[]); #else @@ -22,3 +26,10 @@ int main(int argc, char* argv[]) IncrementExitCode(61); return __managed__Main(argc, argv); } + +extern "C" const char* __stdcall __asan_default_options() +{ + // NativeAOT is not designed to be unloadable, so we'll leak a few allocations from the shared library. + // Disable leak detection as we don't care about these leaks as of now. + return "detect_leaks=0 use_sigaltstack=0"; +} diff --git a/src/tests/nativeaot/GenerateUnmanagedEntryPoints/GenerateUnmanagedEntryPoints.csproj b/src/tests/nativeaot/GenerateUnmanagedEntryPoints/GenerateUnmanagedEntryPoints.csproj index db5f0741f8d41..e2a1107993f8a 100644 --- a/src/tests/nativeaot/GenerateUnmanagedEntryPoints/GenerateUnmanagedEntryPoints.csproj +++ b/src/tests/nativeaot/GenerateUnmanagedEntryPoints/GenerateUnmanagedEntryPoints.csproj @@ -4,6 +4,11 @@ BuildAndRun true true + + true diff --git a/src/tests/nativeaot/SmokeTests/DwarfDump/DwarfDump.csproj b/src/tests/nativeaot/SmokeTests/DwarfDump/DwarfDump.csproj index 25eece838c4b4..b0645183024ec 100644 --- a/src/tests/nativeaot/SmokeTests/DwarfDump/DwarfDump.csproj +++ b/src/tests/nativeaot/SmokeTests/DwarfDump/DwarfDump.csproj @@ -6,6 +6,8 @@ 0 true + + true false diff --git a/src/tests/nativeaot/SmokeTests/HardwareIntrinsics/X64Avx.csproj b/src/tests/nativeaot/SmokeTests/HardwareIntrinsics/X64Avx.csproj index 3cf9043e062df..63f975aee907c 100644 --- a/src/tests/nativeaot/SmokeTests/HardwareIntrinsics/X64Avx.csproj +++ b/src/tests/nativeaot/SmokeTests/HardwareIntrinsics/X64Avx.csproj @@ -4,6 +4,8 @@ BuildAndRun 0 true + + true true $(DefineConstants);AVX_INTRINSICS;VECTORT128_INTRINSICS diff --git a/src/tests/nativeaot/SmokeTests/HardwareIntrinsics/X64Avx2.csproj b/src/tests/nativeaot/SmokeTests/HardwareIntrinsics/X64Avx2.csproj index 626f88edc7278..334d899e8ea51 100644 --- a/src/tests/nativeaot/SmokeTests/HardwareIntrinsics/X64Avx2.csproj +++ b/src/tests/nativeaot/SmokeTests/HardwareIntrinsics/X64Avx2.csproj @@ -4,6 +4,8 @@ BuildAndRun 0 true + + true true $(DefineConstants);AVX2_INTRINSICS;VECTORT256_INTRINSICS diff --git a/src/tests/nativeaot/SmokeTests/HardwareIntrinsics/X64Avx512.csproj b/src/tests/nativeaot/SmokeTests/HardwareIntrinsics/X64Avx512.csproj index 24da060cc6622..2f045ae5a4071 100644 --- a/src/tests/nativeaot/SmokeTests/HardwareIntrinsics/X64Avx512.csproj +++ b/src/tests/nativeaot/SmokeTests/HardwareIntrinsics/X64Avx512.csproj @@ -4,6 +4,8 @@ BuildAndRun 0 true + + true true $(DefineConstants);AVX512_INTRINSICS;VECTORT256_INTRINSICS diff --git a/src/tests/nativeaot/SmokeTests/HardwareIntrinsics/X64Avx_NoAvx2.csproj b/src/tests/nativeaot/SmokeTests/HardwareIntrinsics/X64Avx_NoAvx2.csproj index 9565259240f01..649e14453532c 100644 --- a/src/tests/nativeaot/SmokeTests/HardwareIntrinsics/X64Avx_NoAvx2.csproj +++ b/src/tests/nativeaot/SmokeTests/HardwareIntrinsics/X64Avx_NoAvx2.csproj @@ -4,6 +4,8 @@ BuildAndRun 0 true + + true true $(DefineConstants);AVX_INTRINSICS;VECTORT128_INTRINSICS diff --git a/src/tests/nativeaot/SmokeTests/HardwareIntrinsics/X64Baseline.csproj b/src/tests/nativeaot/SmokeTests/HardwareIntrinsics/X64Baseline.csproj index 9e5d0c79e268e..6da7c0da48559 100644 --- a/src/tests/nativeaot/SmokeTests/HardwareIntrinsics/X64Baseline.csproj +++ b/src/tests/nativeaot/SmokeTests/HardwareIntrinsics/X64Baseline.csproj @@ -4,6 +4,8 @@ BuildAndRun 0 true + + true true $(DefineConstants);BASELINE_INTRINSICS;VECTORT128_INTRINSICS diff --git a/src/tests/nativeaot/SmokeTests/HardwareIntrinsics/X64Sse42.csproj b/src/tests/nativeaot/SmokeTests/HardwareIntrinsics/X64Sse42.csproj index bf1a725b11a44..c2922e1883f45 100644 --- a/src/tests/nativeaot/SmokeTests/HardwareIntrinsics/X64Sse42.csproj +++ b/src/tests/nativeaot/SmokeTests/HardwareIntrinsics/X64Sse42.csproj @@ -4,6 +4,8 @@ BuildAndRun 0 true + + true true $(DefineConstants);SSE42_INTRINSICS;VECTORT128_INTRINSICS diff --git a/src/tests/nativeaot/SmokeTests/SharedLibrary/CMakeLists.txt b/src/tests/nativeaot/SmokeTests/SharedLibrary/CMakeLists.txt index 5af70a164ba56..82893d7af32a0 100644 --- a/src/tests/nativeaot/SmokeTests/SharedLibrary/CMakeLists.txt +++ b/src/tests/nativeaot/SmokeTests/SharedLibrary/CMakeLists.txt @@ -8,4 +8,8 @@ if (CLR_CMAKE_TARGET_UNIX) endif() # add the install targets -install (TARGETS PInvokeNative DESTINATION bin) +install (TARGETS SharedLibraryDriver DESTINATION bin) +# If there's a dynamic ASAN runtime, then copy it to project output. +if (NOT "${ASAN_RUNTIME}" STREQUAL "") + file(COPY "${ASAN_RUNTIME}" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}") +endif() diff --git a/src/tests/nativeaot/SmokeTests/SharedLibrary/SharedLibrary.cpp b/src/tests/nativeaot/SmokeTests/SharedLibrary/SharedLibrary.cpp index 331011165d54c..c76b3535b0302 100644 --- a/src/tests/nativeaot/SmokeTests/SharedLibrary/SharedLibrary.cpp +++ b/src/tests/nativeaot/SmokeTests/SharedLibrary/SharedLibrary.cpp @@ -82,3 +82,10 @@ int main(int argc, char* argv[]) return 100; } + +extern "C" const char* __stdcall __asan_default_options() +{ + // NativeAOT is not designed to be unloadable, so we'll leak a few allocations from the shared library. + // Disable leak detection as we don't care about these leaks as of now. + return "detect_leaks=0 use_sigaltstack=0"; +} diff --git a/src/tests/nativeaot/SmokeTests/SharedLibrary/SharedLibrary.csproj b/src/tests/nativeaot/SmokeTests/SharedLibrary/SharedLibrary.csproj index 09b36ffbd9fb7..aadb18279ffdf 100644 --- a/src/tests/nativeaot/SmokeTests/SharedLibrary/SharedLibrary.csproj +++ b/src/tests/nativeaot/SmokeTests/SharedLibrary/SharedLibrary.csproj @@ -11,12 +11,14 @@ nul +copy /y clang_rt.* native\ copy /y SharedLibraryDriver.exe native\SharedLibrary.exe ]]> diff --git a/src/tests/readytorun/coreroot_determinism/coreroot_determinism.csproj b/src/tests/readytorun/coreroot_determinism/coreroot_determinism.csproj index 5838f8fa81368..5f651694cc1c9 100644 --- a/src/tests/readytorun/coreroot_determinism/coreroot_determinism.csproj +++ b/src/tests/readytorun/coreroot_determinism/coreroot_determinism.csproj @@ -6,6 +6,8 @@ true false + + true 2.0 diff --git a/src/tests/readytorun/determinism/crossgen2determinism.csproj b/src/tests/readytorun/determinism/crossgen2determinism.csproj index c0219b2b48594..8544d11bd5257 100644 --- a/src/tests/readytorun/determinism/crossgen2determinism.csproj +++ b/src/tests/readytorun/determinism/crossgen2determinism.csproj @@ -2,6 +2,8 @@ exe true + + true true diff --git a/src/tests/readytorun/multifolder/multifolder.csproj b/src/tests/readytorun/multifolder/multifolder.csproj index 67e75c04322cb..0e1410f50bac0 100644 --- a/src/tests/readytorun/multifolder/multifolder.csproj +++ b/src/tests/readytorun/multifolder/multifolder.csproj @@ -7,6 +7,8 @@ true + + true false