diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index b0ca8df7b5fef..37cc0681fbf9d 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -15,7 +15,7 @@ ] }, "microsoft.dotnet.xharness.cli": { - "version": "1.0.0-prerelease.21370.1", + "version": "1.0.0-prerelease.21373.1", "commands": [ "xharness" ] diff --git a/Directory.Build.props b/Directory.Build.props index 88779ccdac029..556b399aa3dc0 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -139,6 +139,10 @@ <_runtimeOS Condition="$(_runtimeOS.StartsWith('tizen'))">linux <_runtimeOS Condition="'$(PortableBuild)' == 'true'">$(_portableOS) + + <_packageOS Condition="'$(CrossBuild)' == 'true'">$(_hostOS.ToLowerInvariant) + <_packageOS Condition="'$(_packageOS)' == '' and '$(PortableBuild)' == 'true'">$(_portableOS) + <_packageOS Condition="'$(_packageOS)' == ''">$(_runtimeOS) @@ -163,10 +167,11 @@ linux-$(_hostArch) $(_toolRuntimeRID) - <_packageRID Condition="'$(PortableBuild)' == 'true'">$(_portableOS)-$(TargetArchitecture) - <_packageRID Condition="'$(CrossBuild)' == 'true'">$(_hostOS.ToLowerInvariant)-$(TargetArchitecture) - $(_packageRID) - $(_runtimeOS)-$(TargetArchitecture) + $(_packageOS)-$(TargetArchitecture) + + + $(_packageOS)-arm + $(PackageRID) $(PackageRID) $(_portableOS)-$(TargetArchitecture) @@ -282,7 +287,7 @@ false - true + true diff --git a/docs/coding-guidelines/interop-guidelines.md b/docs/coding-guidelines/interop-guidelines.md index 00c05415425cf..997aa1fd3772a 100644 --- a/docs/coding-guidelines/interop-guidelines.md +++ b/docs/coding-guidelines/interop-guidelines.md @@ -55,7 +55,7 @@ internal static partial class Interop \Windows \mincore ... interop files - \Unix + \Unix \libc ... interop files \Linux diff --git a/docs/workflow/requirements/windows-requirements.md b/docs/workflow/requirements/windows-requirements.md index 2629df320d288..ee874e85abde5 100644 --- a/docs/workflow/requirements/windows-requirements.md +++ b/docs/workflow/requirements/windows-requirements.md @@ -22,21 +22,28 @@ git config --system core.longpaths true - Install [Visual Studio 2019](https://visualstudio.microsoft.com/downloads/). The Community edition is available free of charge. Visual Studio 2019 installation process: -- It's recommended to use 'Workloads' installation approach. The following are the minimum requirements: - - .NET Desktop Development with all default components. - - Desktop Development with C++ with all default components. -- To build for Arm32 or Arm64, make sure that you have the right architecture-specific compilers installed. In the "Individual components" window, in the "Compilers, build tools, and runtimes" section: - - For Arm32, check the box for "MSVC v142 - VS 2019 C++ ARM build tools (v14.23 or newer)". - - For Arm64, check the box for "MSVC v142 - VS 2019 C++ ARM64 build tools (v14.23 or newer)". +- It's recommended to use **Workloads** installation approach. The following are the minimum requirements: + - **.NET Desktop Development** with all default components, + - **Desktop Development with C++** with all default components. +- The build tools (CMake, Ninja and Python) can be downloaded and installed separately (see detailed instructions in the [section below](#build-tools)) or by selecting the following **Individual Components**: + - **C++ CMake tools for Windows** (includes Ninja), + - **Python 3 64-bit** (3.7.4 or newer). +- To build for Arm32 or Arm64, make sure that you have the right architecture-specific compilers installed. In the **Individual components** window, in the **Compilers, build tools, and runtimes** section: + - For Arm32, check the box for **MSVC v142 - VS 2019 C++ ARM build tools (Latest)** (v14.23 or newer), + - For Arm64, check the box for **MSVC v142 - VS 2019 C++ ARM64 build tools (Latest)** (v14.23 or newer). - To build the tests, you will need some additional components: - - Windows 10 SDK component version 10.0.18362 or newer. This component is installed by default as a part of 'Desktop Development with C++' workload. - - C++/CLI support for v142 build tools (v14.23 or newer) + - **Windows 10 SDK (10.0.19041)** or newer. This component is installed by default as a part of **Desktop Development with C++** workload. + - **C++/CLI support for v142 build tools (Latest)** (v14.23 or newer). A `.vsconfig` file is included in the root of the dotnet/runtime repository that includes all components needed to build the dotnet/runtime repository. You can [import `.vsconfig` in your Visual Studio installer](https://docs.microsoft.com/en-us/visualstudio/install/import-export-installation-configurations?view=vs-2019#import-a-configuration) to install all necessary components. Visual Studio 2019 16.6 or later is required for building the repository. Visual Studio 2019 16.10 is required to work with the libraries projects inside the Visual Studio IDE. -## CMake +## Build Tools + +These steps are required only in case the tools have not been installed as Visual Studio **Individual Components** (described above). + +### CMake - Install [CMake](https://cmake.org/download) for Windows. - Add its location (e.g. C:\Program Files (x86)\CMake\bin) to the PATH environment variable. @@ -44,13 +51,13 @@ Visual Studio 2019 16.6 or later is required for building the repository. Visual The dotnet/runtime repository recommends using CMake 3.16.4 or newer, but it may work with CMake 3.15.5. -## Ninja +### Ninja - Install Ninja in one of the two following ways - [Download the executable](https://github.com/ninja-build/ninja/releases) and add its location to [the Default PATH variable](#adding-to-the-default-path-variable). - [Install via a package manager](https://github.com/ninja-build/ninja/wiki/Pre-built-Ninja-packages), which should automatically add it to the PATH environment variable. -## Python +### Python - Install [Python](https://www.python.org/downloads/) for Windows. - Add its location (e.g. C:\Python*\) to the PATH environment variable. diff --git a/docs/workflow/testing/coreclr/windows-test-instructions.md b/docs/workflow/testing/coreclr/windows-test-instructions.md index 3819907618b4b..dccf41f9b86bc 100644 --- a/docs/workflow/testing/coreclr/windows-test-instructions.md +++ b/docs/workflow/testing/coreclr/windows-test-instructions.md @@ -15,6 +15,22 @@ By default, the test build uses Release as the libraries configuration. To use a src\tests\build.cmd /p:LibrariesConfiguration=Debug ``` +## Building Native Test Components + +Sometimes you want to only build the native test components instead of the managed and native components. To build the native test components only, pass the `skipmanaged` and `skipgeneratelayout` parameters to the build script as follows: + +``` +src\tests\build.cmd skipmanaged skipgeneratelayout +``` + +## Building C++/CLI native test components against the live ref assemblies + +By default, the C++/CLI native test components build against the ref pack from the SDK specified in the `global.json` file in the root of the repository. To build these components against the ref assemblies produced in the build, pass the `-cmakeargs -DCPP_CLI_LIVE_REF_ASSEMBLIES=1` parameters to the test build. For example: + +``` +src\tests\build.cmd skipmanaged -cmakeargs -DCPP_CLI_LIVE_REF_ASSEMBLIES=1 +``` + ## Building Precompiled Tests ``` diff --git a/docs/workflow/trimming/feature-switches.md b/docs/workflow/trimming/feature-switches.md index e7aa6be63cf97..5a693bd7bc00e 100644 --- a/docs/workflow/trimming/feature-switches.md +++ b/docs/workflow/trimming/feature-switches.md @@ -25,6 +25,7 @@ configurations but their defaults might vary as any SDK can set the defaults dif | EnableCppCLIHostActivation | System.Runtime.InteropServices.EnableCppCLIHostActivation | C++/CLI host activation code is disabled when set to false and related functionality can be trimmed. | | MetadataUpdaterSupport | System.Reflection.Metadata.MetadataUpdater.IsSupported | Metadata update related code to be trimmed when set to false | | _EnableConsumingManagedCodeFromNativeHosting | System.Runtime.InteropServices.EnableConsumingManagedCodeFromNativeHosting | Getting a managed function from native hosting is disabled when set to false and related functionality can be trimmed. | +| VerifyDependencyInjectionOpenGenericServiceTrimmability | Microsoft.Extensions.DependencyInjection.VerifyOpenGenericServiceTrimmability | When set to true, DependencyInjection will verify trimming annotations applied to open generic services are correct | | NullabilityInfoContextSupport | System.Reflection.NullabilityInfoContext.IsSupported | Nullable attributes can be trimmed when set to false | | _AggressiveAttributeTrimming | System.AggressiveAttributeTrimming | When set to true, aggressively trims attributes to allow for the most size savings possible, even if it could result in runtime behavior changes | diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 05e276bfa18d9..b1f8ce8b27f24 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -8,79 +8,79 @@ https://github.com/dotnet/msquic d7db669b70f4dd67ec001c192f9809c218cab88b - + https://github.com/dotnet/emsdk - 70549df51ec4b2561e2d11caa542e0b2a2903e0a + 7a7664b07a1625bc1682e0735019178e69fcfbec - + https://github.com/dotnet/arcade - 89806f0b9e93ad2bbe32c654412835c0801a2032 + c6a28c81f96d196338b3ea520bc1e6dc7c440ee2 - + https://github.com/dotnet/arcade - 89806f0b9e93ad2bbe32c654412835c0801a2032 + c6a28c81f96d196338b3ea520bc1e6dc7c440ee2 - + https://github.com/dotnet/arcade - 89806f0b9e93ad2bbe32c654412835c0801a2032 + c6a28c81f96d196338b3ea520bc1e6dc7c440ee2 - + https://github.com/dotnet/arcade - 89806f0b9e93ad2bbe32c654412835c0801a2032 + c6a28c81f96d196338b3ea520bc1e6dc7c440ee2 - + https://github.com/dotnet/arcade - 89806f0b9e93ad2bbe32c654412835c0801a2032 + c6a28c81f96d196338b3ea520bc1e6dc7c440ee2 - + https://github.com/dotnet/arcade - 89806f0b9e93ad2bbe32c654412835c0801a2032 + c6a28c81f96d196338b3ea520bc1e6dc7c440ee2 - + https://github.com/dotnet/arcade - 89806f0b9e93ad2bbe32c654412835c0801a2032 + c6a28c81f96d196338b3ea520bc1e6dc7c440ee2 - + https://github.com/dotnet/arcade - 89806f0b9e93ad2bbe32c654412835c0801a2032 + c6a28c81f96d196338b3ea520bc1e6dc7c440ee2 - + https://github.com/dotnet/arcade - 89806f0b9e93ad2bbe32c654412835c0801a2032 + c6a28c81f96d196338b3ea520bc1e6dc7c440ee2 - + https://github.com/dotnet/arcade - 89806f0b9e93ad2bbe32c654412835c0801a2032 + c6a28c81f96d196338b3ea520bc1e6dc7c440ee2 - + https://github.com/dotnet/arcade - 6224d1b573b73caaa84176bd83dabe75f202cdc7 + c6a28c81f96d196338b3ea520bc1e6dc7c440ee2 - + https://github.com/dotnet/arcade - 89806f0b9e93ad2bbe32c654412835c0801a2032 + c6a28c81f96d196338b3ea520bc1e6dc7c440ee2 - + https://github.com/dotnet/arcade - 89806f0b9e93ad2bbe32c654412835c0801a2032 + c6a28c81f96d196338b3ea520bc1e6dc7c440ee2 - + https://github.com/dotnet/arcade - 89806f0b9e93ad2bbe32c654412835c0801a2032 + c6a28c81f96d196338b3ea520bc1e6dc7c440ee2 - + https://github.com/dotnet/arcade - 89806f0b9e93ad2bbe32c654412835c0801a2032 + c6a28c81f96d196338b3ea520bc1e6dc7c440ee2 - + https://github.com/dotnet/arcade - 89806f0b9e93ad2bbe32c654412835c0801a2032 + c6a28c81f96d196338b3ea520bc1e6dc7c440ee2 - + https://github.com/dotnet/arcade - 89806f0b9e93ad2bbe32c654412835c0801a2032 + c6a28c81f96d196338b3ea520bc1e6dc7c440ee2 https://github.com/microsoft/vstest @@ -158,65 +158,65 @@ https://github.com/dotnet/runtime 38017c3935de95d0335bac04f4901ddfc2718656 - + https://github.com/dotnet/runtime - f7e4c261815c66fde2c1e750b744f193e236c17e + 95863758cd16c345d0b8fca067d5db5d6901e498 - + https://github.com/dotnet/runtime - f7e4c261815c66fde2c1e750b744f193e236c17e + 95863758cd16c345d0b8fca067d5db5d6901e498 - + https://github.com/dotnet/runtime - f7e4c261815c66fde2c1e750b744f193e236c17e + 95863758cd16c345d0b8fca067d5db5d6901e498 - + https://github.com/dotnet/runtime - f7e4c261815c66fde2c1e750b744f193e236c17e + 95863758cd16c345d0b8fca067d5db5d6901e498 - + https://github.com/dotnet/runtime - f7e4c261815c66fde2c1e750b744f193e236c17e + 95863758cd16c345d0b8fca067d5db5d6901e498 - + https://github.com/dotnet/runtime - f7e4c261815c66fde2c1e750b744f193e236c17e + 95863758cd16c345d0b8fca067d5db5d6901e498 - + https://github.com/dotnet/runtime - f7e4c261815c66fde2c1e750b744f193e236c17e + 95863758cd16c345d0b8fca067d5db5d6901e498 https://github.com/mono/linker 0cb9250a903cfc90cbac602ed79c0cbc588d8d3f - + https://github.com/dotnet/xharness - aa0da55569eaa42c2c735dd89abd2843fba4fe01 + ccb49ae05b6d98b29871a1779408d4579e16d6e5 - + https://github.com/dotnet/xharness - aa0da55569eaa42c2c735dd89abd2843fba4fe01 + ccb49ae05b6d98b29871a1779408d4579e16d6e5 - + https://github.com/dotnet/arcade - 89806f0b9e93ad2bbe32c654412835c0801a2032 + c6a28c81f96d196338b3ea520bc1e6dc7c440ee2 - + https://dev.azure.com/dnceng/internal/_git/dotnet-optimization - 2e172488a9ee56619a08c8303a708e69dc82503e + f8742ac0820e98221e7eec5f13989d9538579399 - + https://dev.azure.com/dnceng/internal/_git/dotnet-optimization - 2e172488a9ee56619a08c8303a708e69dc82503e + f8742ac0820e98221e7eec5f13989d9538579399 - + https://dev.azure.com/dnceng/internal/_git/dotnet-optimization - 2e172488a9ee56619a08c8303a708e69dc82503e + f8742ac0820e98221e7eec5f13989d9538579399 - + https://dev.azure.com/dnceng/internal/_git/dotnet-optimization - 2e172488a9ee56619a08c8303a708e69dc82503e + f8742ac0820e98221e7eec5f13989d9538579399 https://github.com/dotnet/hotreload-utils @@ -226,9 +226,9 @@ https://github.com/dotnet/runtime-assets bcfd1993de3767c54c6d8a522bf63770fba3c98d - + https://github.com/dotnet/roslyn-analyzers - 7e82240306d8a7a83ebbbc1894381393cebf9fb2 + 19af44783ceecc31842d7028e3b0ce83095ea166 diff --git a/eng/Versions.props b/eng/Versions.props index b13cc449379c0..2a4f7a6a74987 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -50,31 +50,31 @@ 3.10.0 3.10.0 - 6.0.0-rc1.21366.2 + 6.0.0-rc1.21375.2 - 6.0.0-beta.21370.12 - 6.0.0-beta.21370.12 - 6.0.0-beta.21370.12 - 6.0.0-beta.21370.12 - 6.0.0-beta.21370.12 - 6.0.0-beta.21370.12 - 2.5.1-beta.21370.12 - 6.0.0-beta.21370.12 - 6.0.0-beta.21370.12 - 6.0.0-beta.21370.12 - 6.0.0-beta.21372.16 - 6.0.0-beta.21370.12 - 6.0.0-beta.21370.12 - 6.0.0-beta.21370.12 + 6.0.0-beta.21373.11 + 6.0.0-beta.21373.11 + 6.0.0-beta.21373.11 + 6.0.0-beta.21373.11 + 6.0.0-beta.21373.11 + 6.0.0-beta.21373.11 + 2.5.1-beta.21373.11 + 6.0.0-beta.21373.11 + 6.0.0-beta.21373.11 + 6.0.0-beta.21373.11 + 6.0.0-beta.21373.11 + 6.0.0-beta.21373.11 + 6.0.0-beta.21373.11 + 6.0.0-beta.21402.1 6.0.0-preview.1.102 6.0.0-alpha.1.20612.4 - 6.0.0-rc.1.21369.2 - 6.0.0-rc.1.21369.2 + 6.0.0-rc.1.21375.2 + 6.0.0-rc.1.21375.2 3.1.0 - 6.0.0-rc.1.21369.2 + 6.0.0-rc.1.21375.2 5.0.0 4.3.0 @@ -108,11 +108,11 @@ 5.0.0 5.0.0 4.8.1 - 6.0.0-rc.1.21369.2 - 6.0.0-rc.1.21369.2 + 6.0.0-rc.1.21375.2 + 6.0.0-rc.1.21375.2 4.5.4 4.5.0 - 6.0.0-rc.1.21369.2 + 6.0.0-rc.1.21375.2 6.0.0-beta.21371.1 6.0.0-beta.21371.1 @@ -125,10 +125,10 @@ 6.0.0-beta.21371.1 6.0.0-beta.21371.1 - 1.0.0-prerelease.21371.3 - 1.0.0-prerelease.21371.3 - 1.0.0-prerelease.21371.3 - 1.0.0-prerelease.21371.3 + 1.0.0-prerelease.21374.3 + 1.0.0-prerelease.21374.3 + 1.0.0-prerelease.21374.3 + 1.0.0-prerelease.21374.3 16.9.0-beta1.21055.5 2.0.0-beta1.20253.1 @@ -152,8 +152,8 @@ 1.0.1-prerelease-00006 16.9.0-preview-20201201-01 - 1.0.0-prerelease.21370.1 - 1.0.0-prerelease.21370.1 + 1.0.0-prerelease.21373.1 + 1.0.0-prerelease.21373.1 1.0.1-alpha.0.21369.1 2.4.1 2.4.2 @@ -182,7 +182,7 @@ 11.1.0-alpha.1.21369.1 11.1.0-alpha.1.21369.1 - 6.0.0-rc.1.21369.1 + 6.0.0-rc.1.21376.4 $(MicrosoftNETWorkloadEmscriptenManifest60100Version) 1.1.87-gba258badda diff --git a/eng/common/templates/steps/source-build.yml b/eng/common/templates/steps/source-build.yml index e20637ed6a177..705b7a1c847b9 100644 --- a/eng/common/templates/steps/source-build.yml +++ b/eng/common/templates/steps/source-build.yml @@ -29,6 +29,11 @@ steps: officialBuildArgs='/p:DotNetPublishUsingPipelines=true /p:OfficialBuildId=$(BUILD.BUILDNUMBER)' fi + internalRuntimeDownloadArgs= + if [ '$(dotnetclimsrc-read-sas-token-base64)' != '$''(dotnetclimsrc-read-sas-token-base64)' ]; then + internalRuntimeDownloadArgs='--runtimesourcefeed https://dotnetclimsrc.blob.core.windows.net/dotnet --runtimesourcefeedkey $(dotnetclimsrc-read-sas-token-base64)' + fi + targetRidArgs= if [ '${{ parameters.platform.targetRID }}' != '' ]; then targetRidArgs='/p:TargetRid=${{ parameters.platform.targetRID }}' @@ -43,6 +48,7 @@ steps: --configuration $buildConfig \ --restore --build --pack $publishArgs -bl \ $officialBuildArgs \ + $internalRuntimeDownloadArgs \ $targetRidArgs \ /p:SourceBuildNonPortable=${{ parameters.platform.nonPortable }} \ /p:ArcadeBuildFromSource=true diff --git a/eng/packaging.targets b/eng/packaging.targets index d6344a0b666d7..6af2a73afc12d 100644 --- a/eng/packaging.targets +++ b/eng/packaging.targets @@ -8,6 +8,7 @@ true $(MSBuildThisFileDirectory)useSharedDesignerContext.txt $([MSBuild]::Subtract($(MajorVersion), 1)).0.0 + IncludeAnalyzersInPackage;$(BeforePack) + + + + + + + + <_TargetPathsToSymbols Include="@(_AnalyzerFile)" TargetPath="/%(_AnalyzerFile.PackagePath)" Condition="%(_AnalyzerFile.IsSymbol)" /> + + + + + + <_analyzerPath>analyzers/dotnet + <_analyzerPath Condition="'$(AnalyzerLanguage)' != ''">$(_analyzerPath)/$(AnalyzerLanguage) + + + <_AnalyzerPackFile Include="@(_BuildOutputInPackage)" IsSymbol="false" /> + <_AnalyzerPackFile Include="@(_TargetPathsToSymbols)" IsSymbol="true" /> + <_AnalyzerPackFile PackagePath="$(_analyzerPath)/%(TargetPath)" /> + + + diff --git a/eng/pipelines/coreclr/templates/build-job.yml b/eng/pipelines/coreclr/templates/build-job.yml index 699983fa0c38c..e94d630ba2e95 100644 --- a/eng/pipelines/coreclr/templates/build-job.yml +++ b/eng/pipelines/coreclr/templates/build-job.yml @@ -269,7 +269,7 @@ jobs: artifactName: $(buildProductArtifactName) displayName: 'product build' - - ${{ if and(in(parameters.osGroup, 'windows', 'Linux'), ne(parameters.archType, 'x86'), ne(parameters.compilerName, 'gcc'), ne(parameters.testGroup, 'clrTools')) }}: + - ${{ if and(in(parameters.osGroup, 'windows', 'Linux'), ne(parameters.archType, 'x86'), ne(parameters.compilerName, 'gcc'), ne(parameters.testGroup, 'clrTools'), eq(parameters.pgoType, '')) }}: - template: /eng/pipelines/coreclr/templates/crossdac-build.yml parameters: archType: ${{ parameters.archType }} diff --git a/eng/testing/performance/blazor_perf.proj b/eng/testing/performance/blazor_perf.proj index 1c3e46304dfa6..0c62c3a2ba62e 100644 --- a/eng/testing/performance/blazor_perf.proj +++ b/eng/testing/performance/blazor_perf.proj @@ -37,13 +37,13 @@ $(WorkItemDirectory) - cd $(BlazorMinDirectory);$(Python) pre.py publish --msbuild "/p:_TrimmerDumpDependencies=true" --msbuild-static AdditionalMonoLinkerOptions="%24(AdditionalMonoLinkerOptions) --dump-dependencies" + cd $(BlazorMinDirectory);$(Python) pre.py publish --msbuild "/p:_TrimmerDumpDependencies=true;/p:_MonoRuntimeComponentManifestJsonFilePath=$(WASMRuntimeConfigPath)" --msbuild-static AdditionalMonoLinkerOptions="%24(AdditionalMonoLinkerOptions) --dump-dependencies" $(Python) test.py sod --scenario-name "%(Identity)" $(WorkItemDirectory) - cd $(BlazorMinAOTDirectory);$(Python) pre.py publish --msbuild "/p:_TrimmerDumpDependencies=true" --msbuild-static AdditionalMonoLinkerOptions="%24(AdditionalMonoLinkerOptions) --dump-dependencies" + cd $(BlazorMinAOTDirectory);$(Python) pre.py publish --msbuild "/p:_TrimmerDumpDependencies=true;/p:_MonoRuntimeComponentManifestJsonFilePath=$(WASMRuntimeConfigPath)" --msbuild-static AdditionalMonoLinkerOptions="%24(AdditionalMonoLinkerOptions) --dump-dependencies" $(Python) test.py sod --scenario-name "%(Identity)" @@ -54,7 +54,7 @@ $(WorkItemDirectory) - cd $(BlazorAOTDirectory);$(Python) pre.py publish --msbuild %27/p:_TrimmerDumpDependencies=true%27 --msbuild-static AdditionalMonoLinkerOptions=%27"%24(AdditionalMonoLinkerOptions) --dump-dependencies"%27 --binlog %27./traces/blazor_publish.binlog%27 + cd $(BlazorAOTDirectory);$(Python) pre.py publish --msbuild "/p:_TrimmerDumpDependencies=true;/p:_MonoRuntimeComponentManifestJsonFilePath=$(WASMRuntimeConfigPath)" --msbuild-static AdditionalMonoLinkerOptions=%27"%24(AdditionalMonoLinkerOptions) --dump-dependencies"%27 --binlog %27./traces/blazor_publish.binlog%27 $(Python) test.py sod --scenario-name "%(Identity)" $(Python) post.py @@ -68,7 +68,7 @@ $(WorkItemDirectory) - cd $(BlazorPizzaAOTDirectory);$(Python) pre.py publish -f $(PerflabTargetFrameworks) --msbuild "/p:_TrimmerDumpDependencies=true" --msbuild-static AdditionalMonoLinkerOptions=%27"%24(AdditionalMonoLinkerOptions) --dump-dependencies"%27 --binlog %27./traces/blazor_publish.binlog%27 + cd $(BlazorPizzaAOTDirectory);$(Python) pre.py publish -f $(PerflabTargetFrameworks) --msbuild "/p:_TrimmerDumpDependencies=true;/p:_MonoRuntimeComponentManifestJsonFilePath=$(WASMRuntimeConfigPath)" --msbuild-static AdditionalMonoLinkerOptions=%27"%24(AdditionalMonoLinkerOptions) --dump-dependencies"%27 --binlog %27./traces/blazor_publish.binlog%27 $(Python) test.py sod --scenario-name "%(Identity)" --dirs $(PizzaAppPubLocation) $(Python) post.py 1:00 diff --git a/global.json b/global.json index f0a10200a5103..ad51e8c2d4275 100644 --- a/global.json +++ b/global.json @@ -1,24 +1,24 @@ { "sdk": { - "version": "6.0.100-preview.5.21302.13", + "version": "6.0.100-preview.6.21355.2", "allowPrerelease": true, "rollForward": "major" }, "tools": { - "dotnet": "6.0.100-preview.5.21302.13" + "dotnet": "6.0.100-preview.6.21355.2" }, "native-tools": { "cmake": "3.16.4", "python3": "3.7.1" }, "msbuild-sdks": { - "Microsoft.DotNet.Build.Tasks.TargetFramework.Sdk": "6.0.0-beta.21370.12", + "Microsoft.DotNet.Build.Tasks.TargetFramework.Sdk": "6.0.0-beta.21373.11", "Microsoft.DotNet.PackageValidation": "1.0.0-preview.7.21352.4", - "Microsoft.DotNet.Arcade.Sdk": "6.0.0-beta.21370.12", - "Microsoft.DotNet.Helix.Sdk": "6.0.0-beta.21370.12", - "Microsoft.DotNet.SharedFramework.Sdk": "6.0.0-beta.21370.12", + "Microsoft.DotNet.Arcade.Sdk": "6.0.0-beta.21373.11", + "Microsoft.DotNet.Helix.Sdk": "6.0.0-beta.21373.11", + "Microsoft.DotNet.SharedFramework.Sdk": "6.0.0-beta.21373.11", "Microsoft.Build.NoTargets": "3.0.4", "Microsoft.Build.Traversal": "3.0.23", - "Microsoft.NET.Sdk.IL": "6.0.0-rc.1.21369.2" + "Microsoft.NET.Sdk.IL": "6.0.0-rc.1.21375.2" } } diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/AssemblyBuilder.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/AssemblyBuilder.cs index 6f34f7dcef5f4..0914c0ca7600c 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/AssemblyBuilder.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/AssemblyBuilder.cs @@ -77,11 +77,13 @@ public override string[] GetManifestResourceNames() throw new NotSupportedException(SR.NotSupported_DynamicAssembly); } + [RequiresAssemblyFiles(ThrowingMessageInRAF)] public override FileStream GetFile(string name) { throw new NotSupportedException(SR.NotSupported_DynamicAssembly); } + [RequiresAssemblyFiles(ThrowingMessageInRAF)] public override FileStream[] GetFiles(bool getResourceModules) { throw new NotSupportedException(SR.NotSupported_DynamicAssembly); @@ -104,7 +106,7 @@ public override FileStream[] GetFiles(bool getResourceModules) public override string Location => throw new NotSupportedException(SR.NotSupported_DynamicAssembly); - [RequiresAssemblyFiles("The code will throw for assemblies embedded in a single-file app")] + [RequiresAssemblyFiles(ThrowingMessageInRAF)] public override string? CodeBase => throw new NotSupportedException(SR.NotSupported_DynamicAssembly); [RequiresUnreferencedCode("Types might be removed")] diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/ModuleBuilder.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/ModuleBuilder.cs index c1c243b8d0230..230bb06bd810e 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/ModuleBuilder.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/ModuleBuilder.cs @@ -706,6 +706,7 @@ internal Type[] GetTypesNoLock() return GetType(parameters, baseType); } + [RequiresAssemblyFiles(UnknownStringMessageInRAF)] public override string FullyQualifiedName => _moduleData._moduleName; [RequiresUnreferencedCode("Trimming changes metadata tokens")] @@ -785,6 +786,7 @@ public override MethodInfo[] GetMethods(BindingFlags bindingFlags) public override string ScopeName => InternalModule.ScopeName; + [RequiresAssemblyFiles(UnknownStringMessageInRAF)] public override string Name => InternalModule.Name; public override Assembly Assembly => _assemblyBuilder; diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs index cb7bd41495f6d..5a5fd3e8b129f 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs @@ -83,7 +83,7 @@ internal object SyncRoot return null; } - [RequiresAssemblyFiles("The code will throw for assemblies embedded in a single-file app")] + [RequiresAssemblyFiles(ThrowingMessageInRAF)] public override string? CodeBase { get @@ -372,6 +372,7 @@ internal static RuntimeAssembly InternalLoad(AssemblyName assemblyName, ref Stac // Returns the file in the File table of the manifest that matches the // given name. (Name should not include path.) + [RequiresAssemblyFiles(ThrowingMessageInRAF)] public override FileStream? GetFile(string name) { if (Location.Length == 0) @@ -389,6 +390,7 @@ internal static RuntimeAssembly InternalLoad(AssemblyName assemblyName, ref Stac FileAccess.Read, FileShare.Read, FileStream.DefaultBufferSize, false); } + [RequiresAssemblyFiles(ThrowingMessageInRAF)] public override FileStream[] GetFiles(bool getResourceModules) { if (Location.Length == 0) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeModule.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeModule.cs index a85a2226265b8..a5aad806bf07f 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeModule.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeModule.cs @@ -441,6 +441,7 @@ public override void GetObjectData(SerializationInfo info, StreamingContext cont return retType; } + [RequiresAssemblyFiles(UnknownStringMessageInRAF)] internal string GetFullyQualifiedName() { string? fullyQualifiedName = null; @@ -449,9 +450,10 @@ internal string GetFullyQualifiedName() return fullyQualifiedName!; } + [RequiresAssemblyFiles(UnknownStringMessageInRAF)] public override string FullyQualifiedName => GetFullyQualifiedName(); - [RequiresUnreferencedCode("Types might be removed")] + [RequiresUnreferencedCode("Types might be removed")] public override Type[] GetTypes() { return GetTypes(this); @@ -518,6 +520,7 @@ public override string ScopeName } } + [RequiresAssemblyFiles(UnknownStringMessageInRAF)] public override string Name { get diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.cs index 8538e63c06880..a6351198a2c59 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.cs @@ -300,6 +300,7 @@ public static void RegisterForTrackerSupport(ComWrappers instance) /// * P/Invokes with COM-related types /// * COM activation /// + [SupportedOSPlatform("windows")] public static void RegisterForMarshalling(ComWrappers instance) { if (instance == null) diff --git a/src/coreclr/clr.featuredefines.props b/src/coreclr/clr.featuredefines.props index 60e3883229519..511db52edc102 100644 --- a/src/coreclr/clr.featuredefines.props +++ b/src/coreclr/clr.featuredefines.props @@ -14,7 +14,7 @@ - true + true true true diff --git a/src/coreclr/debug/daccess/nidump.cpp b/src/coreclr/debug/daccess/nidump.cpp index e421e15aadd00..06f02a3d0da95 100644 --- a/src/coreclr/debug/daccess/nidump.cpp +++ b/src/coreclr/debug/daccess/nidump.cpp @@ -1623,7 +1623,8 @@ NativeImageDumper::PrintManifestTokenName(mdToken token, BOOL NativeImageDumper::HandleFixupForHistogram(PTR_CORCOMPILE_IMPORT_SECTION pSection, SIZE_T fixupIndex, - SIZE_T *fixupCell) + SIZE_T *fixupCell, + BOOL mayUsePrecompiledNDirectMethods) { COUNT_T nImportSections; PTR_CORCOMPILE_IMPORT_SECTION pImportSections = m_decoder.GetNativeImportSections(&nImportSections); @@ -3577,7 +3578,7 @@ size_t NativeImageDumper::TranslateSymbol(IXCLRDisassemblySupport *dis, return 0; } -BOOL NativeImageDumper::HandleFixupForMethodDump(PTR_CORCOMPILE_IMPORT_SECTION pSection, SIZE_T fixupIndex, SIZE_T *fixupCell) +BOOL NativeImageDumper::HandleFixupForMethodDump(PTR_CORCOMPILE_IMPORT_SECTION pSection, SIZE_T fixupIndex, SIZE_T *fixupCell, BOOL mayUsePrecompiledNDirectMethods) { PTR_SIZE_T fixupPtr(TO_TADDR(fixupCell)); m_display->StartElement( "Fixup" ); diff --git a/src/coreclr/debug/daccess/nidump.h b/src/coreclr/debug/daccess/nidump.h index a6e9461a475ae..f39b4db15a437 100644 --- a/src/coreclr/debug/daccess/nidump.h +++ b/src/coreclr/debug/daccess/nidump.h @@ -283,10 +283,10 @@ class NativeImageDumper IMetaDataAssemblyImport *m_manifestAssemblyImport; //helper for ComputeMethodFixupHistogram - BOOL HandleFixupForHistogram(PTR_CORCOMPILE_IMPORT_SECTION pSection, SIZE_T fixupIndex, SIZE_T *fixupCell); + BOOL HandleFixupForHistogram(PTR_CORCOMPILE_IMPORT_SECTION pSection, SIZE_T fixupIndex, SIZE_T *fixupCell, BOOL mayUsePrecompiledNDirectMethods = TRUE); //helper for DumpMethodFixups - BOOL HandleFixupForMethodDump(PTR_CORCOMPILE_IMPORT_SECTION pSection, SIZE_T fixupIndex, SIZE_T *fixupCell); + BOOL HandleFixupForMethodDump(PTR_CORCOMPILE_IMPORT_SECTION pSection, SIZE_T fixupIndex, SIZE_T *fixupCell, BOOL mayUsePrecompiledNDirectMethods = TRUE); // Dependencies diff --git a/src/coreclr/debug/daccess/request.cpp b/src/coreclr/debug/daccess/request.cpp index 968664489d890..4e729c8733964 100644 --- a/src/coreclr/debug/daccess/request.cpp +++ b/src/coreclr/debug/daccess/request.cpp @@ -2772,19 +2772,24 @@ ClrDataAccess::GetGCHeapDetails(CLRDATA_ADDRESS heap, struct DacpGcHeapDetails * HRESULT ClrDataAccess::GetGCHeapStaticData(struct DacpGcHeapDetails *detailsData) { + // Make sure ClrDataAccess::ServerGCHeapDetails() is updated as well. if (detailsData == NULL) + { return E_INVALIDARG; + } SOSDacEnter(); + detailsData->heapAddr = NULL; + detailsData->lowest_address = PTR_CDADDR(g_lowest_address); detailsData->highest_address = PTR_CDADDR(g_highest_address); - detailsData->card_table = PTR_CDADDR(g_card_table); - detailsData->heapAddr = NULL; + detailsData->current_c_gc_state = (CLRDATA_ADDRESS)*g_gcDacGlobals->current_c_gc_state; + detailsData->alloc_allocated = (CLRDATA_ADDRESS)*g_gcDacGlobals->alloc_allocated; detailsData->ephemeral_heap_segment = (CLRDATA_ADDRESS)*g_gcDacGlobals->ephemeral_heap_segment; + detailsData->card_table = PTR_CDADDR(g_card_table); detailsData->mark_array = (CLRDATA_ADDRESS)*g_gcDacGlobals->mark_array; - detailsData->current_c_gc_state = (CLRDATA_ADDRESS)*g_gcDacGlobals->current_c_gc_state; detailsData->next_sweep_obj = (CLRDATA_ADDRESS)*g_gcDacGlobals->next_sweep_obj; if (g_gcDacGlobals->saved_sweep_ephemeral_seg != nullptr) { @@ -2801,13 +2806,12 @@ ClrDataAccess::GetGCHeapStaticData(struct DacpGcHeapDetails *detailsData) detailsData->background_saved_lowest_address = (CLRDATA_ADDRESS)*g_gcDacGlobals->background_saved_lowest_address; detailsData->background_saved_highest_address = (CLRDATA_ADDRESS)*g_gcDacGlobals->background_saved_highest_address; - for (unsigned int i=0; i < *g_gcDacGlobals->max_gen + 2; i++) + // get bounds for the different generations + for (unsigned int i=0; i < DAC_NUMBERGENERATIONS; i++) { DPTR(dac_generation) generation = GenerationTableIndex(g_gcDacGlobals->generation_table, i); detailsData->generation_table[i].start_segment = (CLRDATA_ADDRESS) dac_cast(generation->start_segment); - detailsData->generation_table[i].allocation_start = (CLRDATA_ADDRESS) generation->allocation_start; - DPTR(gc_alloc_context) alloc_context = dac_cast(generation) + offsetof(dac_generation, allocation_context); detailsData->generation_table[i].allocContextPtr = (CLRDATA_ADDRESS)alloc_context->alloc_ptr; detailsData->generation_table[i].allocContextLimit = (CLRDATA_ADDRESS)alloc_context->alloc_limit; @@ -2817,7 +2821,7 @@ ClrDataAccess::GetGCHeapStaticData(struct DacpGcHeapDetails *detailsData) { DPTR(dac_finalize_queue) fq = Dereference(g_gcDacGlobals->finalize_queue); DPTR(uint8_t*) fillPointersTable = dac_cast(fq) + offsetof(dac_finalize_queue, m_FillPointers); - for (unsigned int i = 0; i<(*g_gcDacGlobals->max_gen + 2 + dac_finalize_queue::ExtraSegCount); i++) + for (unsigned int i = 0; i < DAC_NUMBERGENERATIONS + 3; i++) { detailsData->finalization_fill_pointers[i] = (CLRDATA_ADDRESS)*TableIndex(fillPointersTable, i, sizeof(uint8_t*)); } @@ -4699,13 +4703,13 @@ HRESULT ClrDataAccess::GetGenerationTableSvr(CLRDATA_ADDRESS heapAddr, unsigned } else { - DPTR(dac_gc_heap) pHeap = __DPtr(TO_TADDR(heapAddr)); + TADDR heapAddress = TO_TADDR(heapAddr); - if (pHeap.IsValid()) + if (heapAddress != 0) { for (unsigned int i = 0; i < numGenerationTableEntries; ++i) { - DPTR(dac_generation) generation = ServerGenerationTableIndex(pHeap, i); + DPTR(dac_generation) generation = ServerGenerationTableIndex(heapAddress, i); pGenerationData[i].start_segment = (CLRDATA_ADDRESS)dac_cast(generation->start_segment); pGenerationData[i].allocation_start = (CLRDATA_ADDRESS)(ULONG_PTR)generation->allocation_start; DPTR(gc_alloc_context) alloc_context = dac_cast(generation) + offsetof(dac_generation, allocation_context); @@ -4749,10 +4753,11 @@ HRESULT ClrDataAccess::GetFinalizationFillPointersSvr(CLRDATA_ADDRESS heapAddr, } else { - DPTR(dac_gc_heap) pHeap = __DPtr(TO_TADDR(heapAddr)); - - if (pHeap.IsValid()) + TADDR heapAddress = TO_TADDR(heapAddr); + if (heapAddress != 0) { + dac_gc_heap heap = LoadGcHeapData(heapAddress); + dac_gc_heap* pHeap = &heap; DPTR(dac_finalize_queue) fq = pHeap->finalize_queue; DPTR(uint8_t*) pFillPointerArray= dac_cast(fq) + offsetof(dac_finalize_queue, m_FillPointers); for (unsigned int i = 0; i < numFillPointers; ++i) diff --git a/src/coreclr/debug/daccess/request_common.h b/src/coreclr/debug/daccess/request_common.h index d5f60df957c8b..1b86b46380204 100644 --- a/src/coreclr/debug/daccess/request_common.h +++ b/src/coreclr/debug/daccess/request_common.h @@ -26,6 +26,16 @@ DPTR(T) Dereference(DPTR(T*) ptr) return __DPtr(ptr_base); } +// Indexes into the global heap table, returning a TADDR to the requested +// heap instance. +inline TADDR +HeapTableIndex(DPTR(opaque_gc_heap**) heaps, size_t index) +{ + DPTR(opaque_gc_heap*) heap_table = Dereference(heaps); + DPTR(opaque_gc_heap*) ptr = TableIndex(heap_table, index, sizeof(void*)); + return Dereference(ptr).GetAddr(); +} + // Indexes into a given generation table, returning a DPTR to the // requested element (the element at the given index) of the table. inline DPTR(dac_generation) @@ -34,24 +44,99 @@ GenerationTableIndex(DPTR(dac_generation) base, size_t index) return TableIndex(base, index, g_gcDacGlobals->generation_size); } +// Starting .NET 6, it is possible for the gc_heap object to have different layouts +// for coreclr.dll and clrgc.dll. Instead of using assuming dac_gc_heap and gc_heap +// have identical layout, we have the gc exported an array of field offsets instead. +// These offsets could be -1, indicating the field does not exist in the current +// gc_heap being used. + +// field_offset = g_gcDacGlobals->gc_heap_field_offsets +// p_field_offset = field_offset[field_index] +// p_field = heap + p_field_offset +// field_index++ +#define LOAD_BASE(field_name, field_type) \ + DPTR(int) p_##field_name##_offset = TableIndex(field_offsets, field_index, sizeof(int)); \ + int field_name##_offset = *p_##field_name##_offset; \ + DPTR(field_type) p_##field_name = heap + field_name##_offset; \ + field_index++; + +// if (field_offset != -1) +// result.field = *p_field +#define LOAD(field_name, field_type) \ + LOAD_BASE(field_name, field_type) \ + if (field_name##_offset != -1) \ + { \ + field_type field_name = *p_##field_name; \ + result.field_name = field_name; \ + } + +// if (field_offset != -1) +// result.field = DPTR(field_type)field_name +#define LOAD_DPTR(field_name, field_type) \ + LOAD_BASE(field_name, field_type*) \ + if (field_name##_offset != -1) \ + { \ + field_type* field_name = *p_##field_name; \ + result.field_name = DPTR(field_type)((TADDR)field_name); \ + } + +// if (field_offset != -1) +// for i from 0 to array_length - 1 +// result.field[i] = *p_field +// p_field = p_field + 1 +#define LOAD_ARRAY(field_name, field_type, array_length) \ + LOAD_BASE(field_name, field_type) \ + if (field_name##_offset != -1) \ + { \ + for (int i = 0; i < array_length; i++) \ + { \ + result.field_name[i] = *p_##field_name; \ + p_##field_name = p_##field_name + 1; \ + } \ + } + // Indexes into a heap's generation table, given the heap instance // and the desired index. Returns a DPTR to the requested element. inline DPTR(dac_generation) -ServerGenerationTableIndex(DPTR(dac_gc_heap) heap, size_t index) +ServerGenerationTableIndex(TADDR heap, size_t index) { - TADDR base_addr = dac_cast(heap) + offsetof(dac_gc_heap, generation_table); - DPTR(dac_generation) base = __DPtr(base_addr); - return TableIndex(base, index, g_gcDacGlobals->generation_size); + DPTR(int) field_offsets = g_gcDacGlobals->gc_heap_field_offsets; + int field_index = GENERATION_TABLE_FIELD_INDEX; + LOAD_BASE (generation_table, dac_generation); + assert (generation_table_offset != -1); + return TableIndex(p_generation_table, index, g_gcDacGlobals->generation_size); } -// Indexes into the global heap table, returning a DPTR to the requested -// heap instance. -inline DPTR(dac_gc_heap) -HeapTableIndex(DPTR(dac_gc_heap**) heaps, size_t index) +// Load an instance of dac_gc_heap for the heap pointed by heap. +// Fields that does not exist in the current gc_heap instance is zero initialized. +// Return the dac_gc_heap object. +inline dac_gc_heap +LoadGcHeapData(TADDR heap) { - DPTR(dac_gc_heap*) heap_table = Dereference(heaps); - DPTR(dac_gc_heap*) ptr = TableIndex(heap_table, index, sizeof(dac_gc_heap*)); - return Dereference(ptr); + dac_gc_heap result; + memset(&result, 0, sizeof(dac_gc_heap)); + + DPTR(int) field_offsets = g_gcDacGlobals->gc_heap_field_offsets; + int field_index = 0; + +#define ALL_FIELDS +#define DEFINE_FIELD(field_name, field_type) LOAD(field_name, field_type) +#define DEFINE_DPTR_FIELD(field_name, field_type) LOAD_DPTR(field_name, field_type) +#define DEFINE_ARRAY_FIELD(field_name, field_type, array_length) LOAD_ARRAY(field_name, field_type, array_length); + +#include "../../gc/gc_typefields.h" + +#undef DEFINE_ARRAY_FIELD +#undef DEFINE_DPTR_FIELD +#undef DEFINE_FIELD +#undef ALL_FIELDS + + return result; } +#undef LOAD_ARRAY +#undef LOAD_DPTR +#undef LOAD +#undef LOAD_BASE + #endif // _REQUEST_COMMON_H_ diff --git a/src/coreclr/debug/daccess/request_svr.cpp b/src/coreclr/debug/daccess/request_svr.cpp index 558ac0c33471b..691171f3af91c 100644 --- a/src/coreclr/debug/daccess/request_svr.cpp +++ b/src/coreclr/debug/daccess/request_svr.cpp @@ -64,7 +64,7 @@ HRESULT GetServerHeaps(CLRDATA_ADDRESS pGCHeaps[], ICorDebugDataTarget * pTarget // heap addresses. for (int i = 0; i < GCHeapCount(); i++) { - pGCHeaps[i] = (CLRDATA_ADDRESS)HeapTableIndex(g_gcDacGlobals->g_heaps, i).GetAddr(); + pGCHeaps[i] = (CLRDATA_ADDRESS)HeapTableIndex(g_gcDacGlobals->g_heaps, i); } return S_OK; @@ -86,7 +86,7 @@ HRESULT ClrDataAccess::GetServerAllocData(unsigned int count, struct DacpGenerat for (unsigned int n=0; n < heaps; n++) { - DPTR(dac_gc_heap) pHeap = HeapTableIndex(g_gcDacGlobals->g_heaps, n); + TADDR pHeap = HeapTableIndex(g_gcDacGlobals->g_heaps, n); for (int i=0;i(TO_TADDR(heapAddr)); - int i; + TADDR heapAddress = TO_TADDR(heapAddr); + dac_gc_heap heap = LoadGcHeapData(heapAddress); + dac_gc_heap* pHeap = &heap; //get global information first detailsData->heapAddr = heapAddr; detailsData->lowest_address = PTR_CDADDR(g_lowest_address); detailsData->highest_address = PTR_CDADDR(g_highest_address); - detailsData->card_table = PTR_CDADDR(g_card_table); + detailsData->current_c_gc_state = (CLRDATA_ADDRESS)*g_gcDacGlobals->current_c_gc_state; // now get information specific to this heap (server mode gives us several heaps; we're getting // information about only one of them. detailsData->alloc_allocated = (CLRDATA_ADDRESS)pHeap->alloc_allocated; detailsData->ephemeral_heap_segment = (CLRDATA_ADDRESS)dac_cast(pHeap->ephemeral_heap_segment); + detailsData->card_table = (CLRDATA_ADDRESS)pHeap->card_table; + detailsData->mark_array = (CLRDATA_ADDRESS)pHeap->mark_array; + detailsData->next_sweep_obj = (CLRDATA_ADDRESS)pHeap->next_sweep_obj; + if (pHeap->saved_sweep_ephemeral_seg.IsValid()) + { + detailsData->saved_sweep_ephemeral_seg = (CLRDATA_ADDRESS)dac_cast(pHeap->saved_sweep_ephemeral_seg); + detailsData->saved_sweep_ephemeral_start = (CLRDATA_ADDRESS)*pHeap->saved_sweep_ephemeral_start; + } + else + { + // with regions, we don't have these variables anymore + // use special value -1 in saved_sweep_ephemeral_seg to signal the region case + detailsData->saved_sweep_ephemeral_seg = (CLRDATA_ADDRESS)-1; + detailsData->saved_sweep_ephemeral_start = 0; + } + detailsData->background_saved_lowest_address = (CLRDATA_ADDRESS)pHeap->background_saved_lowest_address; + detailsData->background_saved_highest_address = (CLRDATA_ADDRESS)pHeap->background_saved_highest_address; // get bounds for the different generations - for (i=0; igeneration_table[i].start_segment = (CLRDATA_ADDRESS)dac_cast(generation->start_segment); detailsData->generation_table[i].allocation_start = (CLRDATA_ADDRESS)(ULONG_PTR)generation->allocation_start; DPTR(gc_alloc_context) alloc_context = dac_cast(generation) + offsetof(dac_generation, allocation_context); @@ -134,10 +158,13 @@ HRESULT ClrDataAccess::ServerGCHeapDetails(CLRDATA_ADDRESS heapAddr, DacpGcHeapD } DPTR(dac_finalize_queue) fq = pHeap->finalize_queue; - DPTR(uint8_t*) pFillPointerArray= dac_cast(fq) + offsetof(dac_finalize_queue, m_FillPointers); - for(i=0; i<(NUMBERGENERATIONS+dac_finalize_queue::ExtraSegCount); i++) + if (fq.IsValid()) { - detailsData->finalization_fill_pointers[i] = (CLRDATA_ADDRESS) pFillPointerArray[i]; + DPTR(uint8_t*) fillPointersTable = dac_cast(fq) + offsetof(dac_finalize_queue, m_FillPointers); + for (unsigned int i = 0; i < DAC_NUMBERGENERATIONS + 3; i++) + { + detailsData->finalization_fill_pointers[i] = (CLRDATA_ADDRESS)*TableIndex(fillPointersTable, i, sizeof(uint8_t*)); + } } return S_OK; @@ -146,7 +173,9 @@ HRESULT ClrDataAccess::ServerGCHeapDetails(CLRDATA_ADDRESS heapAddr, DacpGcHeapD HRESULT ClrDataAccess::ServerOomData(CLRDATA_ADDRESS addr, DacpOomData *oomData) { - DPTR(dac_gc_heap) pHeap = __DPtr(TO_TADDR(addr)); + TADDR heapAddress = TO_TADDR(addr); + dac_gc_heap heap = LoadGcHeapData(heapAddress); + dac_gc_heap* pHeap = &heap; oom_history pOOMInfo = pHeap->oom_info; oomData->reason = pOOMInfo.reason; @@ -193,7 +222,9 @@ HRESULT ClrDataAccess::ServerGCHeapAnalyzeData(CLRDATA_ADDRESS heapAddr, DacpGcH return E_INVALIDARG; } - DPTR(dac_gc_heap) pHeap = __DPtr(TO_TADDR(heapAddr)); + TADDR heapAddress = TO_TADDR(heapAddr); + dac_gc_heap heap = LoadGcHeapData(heapAddress); + dac_gc_heap* pHeap = &heap; analyzeData->heapAddr = heapAddr; analyzeData->internal_root_array = (CLRDATA_ADDRESS)pHeap->internal_root_array; @@ -221,7 +252,9 @@ ClrDataAccess::EnumSvrGlobalMemoryRegions(CLRDataEnumMemoryFlags flags) for (int i = 0; i < heaps; i++) { - DPTR(dac_gc_heap) pHeap = HeapTableIndex(g_gcDacGlobals->g_heaps, i); + TADDR heapAddress = HeapTableIndex(g_gcDacGlobals->g_heaps, i); + dac_gc_heap heap = LoadGcHeapData(heapAddress); + dac_gc_heap* pHeap = &heap; size_t gen_table_size = g_gcDacGlobals->generation_size * (*g_gcDacGlobals->max_gen + 2); DacEnumMemoryRegion(dac_cast(pHeap), sizeof(dac_gc_heap)); @@ -235,7 +268,7 @@ ClrDataAccess::EnumSvrGlobalMemoryRegions(CLRDataEnumMemoryFlags flags) // this is the convention in the GC so it is repeated here for (ULONG i = *g_gcDacGlobals->max_gen; i <= *g_gcDacGlobals->max_gen +1; i++) { - DPTR(dac_heap_segment) seg = ServerGenerationTableIndex(pHeap, i)->start_segment; + DPTR(dac_heap_segment) seg = ServerGenerationTableIndex(heapAddress, i)->start_segment; while (seg) { DacEnumMemoryRegion(PTR_HOST_TO_TADDR(seg), sizeof(dac_heap_segment)); @@ -270,18 +303,20 @@ HRESULT DacHeapWalker::InitHeapDataSvr(HeapData *&pHeaps, size_t &pCount) for (int i = 0; i < heaps; ++i) { // Basic heap info. - DPTR(dac_gc_heap) heap = HeapTableIndex(g_gcDacGlobals->g_heaps, i); - dac_generation gen0 = *ServerGenerationTableIndex(heap, 0); - dac_generation gen1 = *ServerGenerationTableIndex(heap, 1); - dac_generation gen2 = *ServerGenerationTableIndex(heap, 2); - dac_generation loh = *ServerGenerationTableIndex(heap, 3); - dac_generation poh = *ServerGenerationTableIndex(heap, 4); + TADDR heapAddress = HeapTableIndex(g_gcDacGlobals->g_heaps, i); + dac_gc_heap heap = LoadGcHeapData(heapAddress); + dac_gc_heap* pHeap = &heap; + dac_generation gen0 = *ServerGenerationTableIndex(heapAddress, 0); + dac_generation gen1 = *ServerGenerationTableIndex(heapAddress, 1); + dac_generation gen2 = *ServerGenerationTableIndex(heapAddress, 2); + dac_generation loh = *ServerGenerationTableIndex(heapAddress, 3); + dac_generation poh = *ServerGenerationTableIndex(heapAddress, 4); pHeaps[i].YoungestGenPtr = (CORDB_ADDRESS)gen0.allocation_context.alloc_ptr; pHeaps[i].YoungestGenLimit = (CORDB_ADDRESS)gen0.allocation_context.alloc_limit; pHeaps[i].Gen0Start = (CORDB_ADDRESS)gen0.allocation_start; - pHeaps[i].Gen0End = (CORDB_ADDRESS)heap->alloc_allocated; + pHeaps[i].Gen0End = (CORDB_ADDRESS)pHeap->alloc_allocated; pHeaps[i].Gen1Start = (CORDB_ADDRESS)gen1.allocation_start; // Segments @@ -300,9 +335,9 @@ HRESULT DacHeapWalker::InitHeapDataSvr(HeapData *&pHeaps, size_t &pCount) for (; seg && (j < count); ++j) { pHeaps[i].Segments[j].Start = (CORDB_ADDRESS)seg->mem; - if (seg.GetAddr() == heap->ephemeral_heap_segment.GetAddr()) + if (seg.GetAddr() == pHeap->ephemeral_heap_segment.GetAddr()) { - pHeaps[i].Segments[j].End = (CORDB_ADDRESS)heap->alloc_allocated; + pHeaps[i].Segments[j].End = (CORDB_ADDRESS)pHeap->alloc_allocated; pHeaps[i].EphemeralSegment = j; pHeaps[i].Segments[j].Generation = 1; } diff --git a/src/coreclr/gc/gc.cpp b/src/coreclr/gc/gc.cpp index b768bc2a588a2..9c8acf346ff42 100644 --- a/src/coreclr/gc/gc.cpp +++ b/src/coreclr/gc/gc.cpp @@ -1146,7 +1146,7 @@ class exclusive_sync { if (alloc_objects [i] != (uint8_t*)0) { - GCToOSInterface::DebugBreak(); + FATAL_GC_ERROR(); } } } @@ -15047,6 +15047,7 @@ BOOL gc_heap::a_fit_free_list_uoh_p (size_t size, if (loh_pad) { make_unused_array (free_list, loh_pad); + generation_free_obj_space (gen) += loh_pad; limit -= loh_pad; free_list += loh_pad; free_list_size -= loh_pad; @@ -15185,6 +15186,7 @@ BOOL gc_heap::a_fit_segment_end_p (int gen_number, if (gen_number == loh_generation) { make_unused_array (allocated, loh_pad); + generation_free_obj_space (generation_of (gen_number)) += loh_pad; allocated += loh_pad; limit -= loh_pad; } @@ -45567,6 +45569,27 @@ bool GCHeap::IsConcurrentGCEnabled() void PopulateDacVars(GcDacVars *gcDacVars) { #ifndef DACCESS_COMPILE + +#ifdef MULTIPLE_HEAPS + static int gc_heap_field_offsets[] = { + +#define DEFINE_FIELD(field_name, field_type) offsetof(gc_heap, field_name), +#define DEFINE_DPTR_FIELD(field_name, field_type) offsetof(gc_heap, field_name), +#define DEFINE_ARRAY_FIELD(field_name, field_type, array_length) offsetof(gc_heap, field_name), +#define DEFINE_MISSING_FIELD -1, + +#include "gc_typefields.h" + +#undef DEFINE_MISSING_FIELD +#undef DEFINE_ARRAY_FIELD +#undef DEFINE_DPTR_FIELD +#undef DEFINE_FIELD + + offsetof(gc_heap, generation_table) + }; + static_assert(sizeof(gc_heap_field_offsets) == (GENERATION_TABLE_FIELD_INDEX + 1) * sizeof(int), "GENERATION_TABLE_INDEX mismatch"); +#endif //MULTIPLE_HEAPS + assert(gcDacVars != nullptr); *gcDacVars = {}; // Note: these version numbers are not actually checked by SOS, so if you change @@ -45580,10 +45603,10 @@ void PopulateDacVars(GcDacVars *gcDacVars) gcDacVars->generation_size = sizeof(generation); gcDacVars->total_generation_count = total_generation_count; gcDacVars->max_gen = &g_max_generation; + gcDacVars->current_c_gc_state = const_cast(&gc_heap::current_c_gc_state); #ifndef MULTIPLE_HEAPS gcDacVars->mark_array = &gc_heap::mark_array; gcDacVars->ephemeral_heap_segment = reinterpret_cast(&gc_heap::ephemeral_heap_segment); - gcDacVars->current_c_gc_state = const_cast(&gc_heap::current_c_gc_state); #ifdef USE_REGIONS gcDacVars->saved_sweep_ephemeral_seg = 0; gcDacVars->saved_sweep_ephemeral_start = 0; @@ -45612,7 +45635,8 @@ void PopulateDacVars(GcDacVars *gcDacVars) #endif // HEAP_ANALYZE #else gcDacVars->n_heaps = &gc_heap::n_heaps; - gcDacVars->g_heaps = reinterpret_cast(&gc_heap::g_heaps); + gcDacVars->g_heaps = reinterpret_cast(&gc_heap::g_heaps); + gcDacVars->gc_heap_field_offsets = reinterpret_cast(&gc_heap_field_offsets); #endif // MULTIPLE_HEAPS #else UNREFERENCED_PARAMETER(gcDacVars); diff --git a/src/coreclr/gc/gc_typefields.h b/src/coreclr/gc/gc_typefields.h new file mode 100644 index 0000000000000..f690a6cddc8ea --- /dev/null +++ b/src/coreclr/gc/gc_typefields.h @@ -0,0 +1,32 @@ +DEFINE_FIELD (alloc_allocated, uint8_t*) +DEFINE_DPTR_FIELD (ephemeral_heap_segment, dac_heap_segment) +DEFINE_DPTR_FIELD (finalize_queue, dac_finalize_queue) +DEFINE_FIELD (oom_info, oom_history) +DEFINE_ARRAY_FIELD (interesting_data_per_heap, size_t, NUM_GC_DATA_POINTS) +DEFINE_ARRAY_FIELD (compact_reasons_per_heap, size_t, MAX_COMPACT_REASONS_COUNT) +DEFINE_ARRAY_FIELD (expand_mechanisms_per_heap, size_t, MAX_EXPAND_MECHANISMS_COUNT) +DEFINE_ARRAY_FIELD (interesting_mechanism_bits_per_heap,size_t, MAX_GC_MECHANISM_BITS_COUNT) +DEFINE_FIELD (internal_root_array, uint8_t*) +DEFINE_FIELD (internal_root_array_index, size_t) +DEFINE_FIELD (heap_analyze_success, BOOL) +DEFINE_FIELD (card_table, uint32_t*) +#if defined(ALL_FIELDS) || defined(BACKGROUND_GC) +DEFINE_FIELD (mark_array, uint32_t*) +DEFINE_FIELD (next_sweep_obj, uint8_t*) +DEFINE_FIELD (background_saved_lowest_address, uint8_t*) +DEFINE_FIELD (background_saved_highest_address, uint8_t*) +#if defined(ALL_FIELDS) || !defined(USE_REGIONS) +DEFINE_DPTR_FIELD (saved_sweep_ephemeral_seg, dac_heap_segment) +DEFINE_FIELD (saved_sweep_ephemeral_start, uint8_t*) +#else +DEFINE_MISSING_FIELD +DEFINE_MISSING_FIELD +#endif +#else +DEFINE_MISSING_FIELD +DEFINE_MISSING_FIELD +DEFINE_MISSING_FIELD +DEFINE_MISSING_FIELD +DEFINE_MISSING_FIELD +DEFINE_MISSING_FIELD +#endif diff --git a/src/coreclr/gc/gcinterface.dac.h b/src/coreclr/gc/gcinterface.dac.h index 348279b5b6911..3a4697a96da2b 100644 --- a/src/coreclr/gc/gcinterface.dac.h +++ b/src/coreclr/gc/gcinterface.dac.h @@ -136,17 +136,17 @@ struct oom_history // GC heap (of which there are multiple, with server GC). class dac_gc_heap { public: - uint8_t* alloc_allocated; - DPTR(dac_heap_segment) ephemeral_heap_segment; - DPTR(dac_finalize_queue) finalize_queue; - oom_history oom_info; - size_t interesting_data_per_heap[NUM_GC_DATA_POINTS]; - size_t compact_reasons_per_heap[MAX_COMPACT_REASONS_COUNT]; - size_t expand_mechanisms_per_heap[MAX_EXPAND_MECHANISMS_COUNT]; - size_t interesting_mechanism_bits_per_heap[MAX_GC_MECHANISM_BITS_COUNT]; - uint8_t* internal_root_array; - size_t internal_root_array_index; - BOOL heap_analyze_success; +#define ALL_FIELDS +#define DEFINE_FIELD(field_name, field_type) field_type field_name; +#define DEFINE_DPTR_FIELD(field_name, field_type) DPTR(field_type) field_name; +#define DEFINE_ARRAY_FIELD(field_name, field_type, array_length) field_type field_name[array_length]; + +#include "gc_typefields.h" + +#undef DEFINE_ARRAY_FIELD +#undef DEFINE_DPTR_FIELD +#undef DEFINE_FIELD +#undef ALL_FIELDS // The generation table must always be last, because the size of this array // (stored inline in the gc_heap class) can vary. @@ -162,6 +162,12 @@ class dac_gc_heap { dac_generation generation_table[1]; }; +#define GENERATION_TABLE_FIELD_INDEX 18 + +struct opaque_gc_heap +{ + uint8_t unused; +}; // The DAC links against six symbols that build as part of the VM DACCESS_COMPILE // build. These symbols are considered to be GC-private functions, but the DAC needs diff --git a/src/coreclr/gc/gcinterface.dacvars.def b/src/coreclr/gc/gcinterface.dacvars.def index b572e6cb3764b..2f27df72e1cbc 100644 --- a/src/coreclr/gc/gcinterface.dacvars.def +++ b/src/coreclr/gc/gcinterface.dacvars.def @@ -53,13 +53,14 @@ GC_DAC_PTR_VAR (uint8_t*, internal_root_array) GC_DAC_VAR (size_t, internal_root_array_index) GC_DAC_VAR (BOOL, heap_analyze_success) GC_DAC_VAR (int, n_heaps) -GC_DAC_PTR_VAR (dac_gc_heap*, g_heaps) +GC_DAC_PTR_VAR (opaque_gc_heap*, g_heaps) GC_DAC_VAR (int32_t, gc_structures_invalid_cnt) GC_DAC_ARRAY_VAR (size_t, interesting_data_per_heap) GC_DAC_ARRAY_VAR (size_t, compact_reasons_per_heap) GC_DAC_ARRAY_VAR (size_t, expand_mechanisms_per_heap) GC_DAC_ARRAY_VAR (size_t, interesting_mechanism_bits_per_heap) GC_DAC_VAR (dac_handle_table_map, handle_table_map) +GC_DAC_ARRAY_VAR (int, gc_heap_field_offsets) #undef GC_DAC_VAR #undef GC_DAC_ARRAY_VAR diff --git a/src/coreclr/gc/gcpriv.h b/src/coreclr/gc/gcpriv.h index 36a1e8326aff7..bbc7e055f2661 100644 --- a/src/coreclr/gc/gcpriv.h +++ b/src/coreclr/gc/gcpriv.h @@ -3426,9 +3426,6 @@ class gc_heap GCEvent bgc_start_event; #endif //BACKGROUND_GC - // The variables in this block are known to the DAC and must come first - // in the gc_heap class. - // Keeps track of the highest address allocated by Alloc PER_HEAP uint8_t* alloc_allocated; @@ -3468,12 +3465,9 @@ class gc_heap PER_HEAP BOOL heap_analyze_success; - // The generation table. Must always be last. PER_HEAP generation generation_table [total_generation_count]; - // End DAC zone - #ifdef USE_REGIONS #ifdef STRESS_REGIONS // TODO: could consider dynamically grow this. @@ -4941,26 +4935,6 @@ class gc_heap void update_collection_counts (); }; // class gc_heap -#define ASSERT_OFFSETS_MATCH(field) \ - static_assert(offsetof(dac_gc_heap, field) == offsetof(gc_heap, field), #field " offset mismatch") - -#ifndef USE_REGIONS -#ifdef MULTIPLE_HEAPS -ASSERT_OFFSETS_MATCH(alloc_allocated); -ASSERT_OFFSETS_MATCH(ephemeral_heap_segment); -ASSERT_OFFSETS_MATCH(finalize_queue); -ASSERT_OFFSETS_MATCH(oom_info); -ASSERT_OFFSETS_MATCH(interesting_data_per_heap); -ASSERT_OFFSETS_MATCH(compact_reasons_per_heap); -ASSERT_OFFSETS_MATCH(expand_mechanisms_per_heap); -ASSERT_OFFSETS_MATCH(interesting_mechanism_bits_per_heap); -ASSERT_OFFSETS_MATCH(internal_root_array); -ASSERT_OFFSETS_MATCH(internal_root_array_index); -ASSERT_OFFSETS_MATCH(heap_analyze_success); -ASSERT_OFFSETS_MATCH(generation_table); -#endif // MULTIPLE_HEAPS -#endif //USE_REGIONS - #ifdef FEATURE_PREMORTEM_FINALIZATION class CFinalize { diff --git a/src/coreclr/jit/assertionprop.cpp b/src/coreclr/jit/assertionprop.cpp index 410c57264c02b..917aa9420349e 100644 --- a/src/coreclr/jit/assertionprop.cpp +++ b/src/coreclr/jit/assertionprop.cpp @@ -3394,6 +3394,10 @@ GenTree* Compiler::optAssertionPropGlobal_RelOp(ASSERT_VALARG_TP assertions, Gen assert(vnStore->ConstantValue(vnCns) == 0); printf("null\n"); } + else if (op1->TypeGet() == TYP_BYREF) + { + printf("%d (byref)\n", static_cast(vnStore->ConstantValue(vnCns))); + } else { printf("??unknown\n"); @@ -3449,6 +3453,11 @@ GenTree* Compiler::optAssertionPropGlobal_RelOp(ASSERT_VALARG_TP assertions, Gen noway_assert(vnStore->ConstantValue(vnCns) == 0); op1->AsIntCon()->gtIconVal = 0; } + else if (op1->TypeGet() == TYP_BYREF) + { + op1->ChangeOperConst(GT_CNS_INT); + op1->AsIntCon()->gtIconVal = static_cast(vnStore->ConstantValue(vnCns)); + } else { noway_assert(!"unknown type in Global_RelOp"); diff --git a/src/coreclr/jit/fgprofile.cpp b/src/coreclr/jit/fgprofile.cpp index 31d7c208ebaf0..d5667a2b1c90c 100644 --- a/src/coreclr/jit/fgprofile.cpp +++ b/src/coreclr/jit/fgprofile.cpp @@ -3000,6 +3000,8 @@ bool flowList::setEdgeWeightMaxChecked(BasicBlock::weight_t newWeight, void flowList::setEdgeWeights(BasicBlock::weight_t theMinWeight, BasicBlock::weight_t theMaxWeight, BasicBlock* bDst) { assert(theMinWeight <= theMaxWeight); + assert(theMinWeight >= 0.0f); + assert(theMaxWeight >= 0.0f); JITDUMP("Setting edge weights for " FMT_BB " -> " FMT_BB " to [" FMT_WT " .. " FMT_WT "]\n", getBlock()->bbNum, bDst->bbNum, theMinWeight, theMaxWeight); diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp index 3517306b959a7..da396f145bfe0 100644 --- a/src/coreclr/jit/importer.cpp +++ b/src/coreclr/jit/importer.cpp @@ -14497,6 +14497,18 @@ void Compiler::impImportBlockCode(BasicBlock* block) } else { + // If we're newing up a finalizable object, spill anything that can cause exceptions. + // + bool hasSideEffects = false; + CorInfoHelpFunc newHelper = + info.compCompHnd->getNewHelper(&resolvedToken, info.compMethodHnd, &hasSideEffects); + + if (hasSideEffects) + { + JITDUMP("\nSpilling stack for finalizable newobj\n"); + impSpillSideEffects(true, (unsigned)CHECK_SPILL_ALL DEBUGARG("finalizable newobj spill")); + } + const bool useParent = true; op1 = gtNewAllocObjNode(&resolvedToken, useParent); if (op1 == nullptr) diff --git a/src/coreclr/jit/optimizer.cpp b/src/coreclr/jit/optimizer.cpp index 26e2e15f37571..3a5cfaa7f5b5b 100644 --- a/src/coreclr/jit/optimizer.cpp +++ b/src/coreclr/jit/optimizer.cpp @@ -4467,7 +4467,7 @@ bool Compiler::optInvertWhileLoop(BasicBlock* block) // Note "next" is the loop top block, not bTest's bbNext, // we'll call this latter block "after". // - BasicBlock::weight_t const testToNextLikelihood = weightNext / weightTest; + BasicBlock::weight_t const testToNextLikelihood = min(1.0f, weightNext / weightTest); BasicBlock::weight_t const testToAfterLikelihood = 1.0f - testToNextLikelihood; // Adjust edges out of bTest (which now has weight weightNext) diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs index ff268b787e440..d5dc33be71cf7 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs @@ -79,32 +79,26 @@ private static class JitPointerAccessor [DllImport(JitLibrary)] private extern static IntPtr getJit(); - public static IntPtr Get() - { - if (s_jit != IntPtr.Zero) - { - return s_jit; - } - - lock(typeof(JitPointerAccessor)) - { - s_jit = getJit(); - return s_jit; - } - } - [DllImport(JitSupportLibrary)] private extern static CorJitResult JitProcessShutdownWork(IntPtr jit); - public static void ShutdownJit() + static JitPointerAccessor() { + s_jit = getJit(); + if (s_jit != IntPtr.Zero) { - JitProcessShutdownWork(s_jit); + AppDomain.CurrentDomain.ProcessExit += (_, _) => JitProcessShutdownWork(s_jit); + AppDomain.CurrentDomain.UnhandledException += (_, _) => JitProcessShutdownWork(s_jit); } } - private static IntPtr s_jit; + public static IntPtr Get() + { + return s_jit; + } + + private static readonly IntPtr s_jit; } [DllImport(JitLibrary)] @@ -159,11 +153,6 @@ public static void Startup() jitStartup(GetJitHost(JitConfigProvider.Instance.UnmanagedInstance)); } - public static void ShutdownJit() - { - JitPointerAccessor.ShutdownJit(); - } - public CorInfoImpl() { _jit = JitPointerAccessor.Get(); diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilationBuilder.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilationBuilder.cs index 4b5d4a7ca3168..c1207a4b5b2f0 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilationBuilder.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilationBuilder.cs @@ -65,12 +65,6 @@ public sealed class ReadyToRunCodegenCompilationBuilder : CompilationBuilder ((ReadyToRunCompilerContext)context).SetCompilationGroup(group); } - // Shutdown the Jit if it has been loaded. This must only be called once per process - public static void ShutdownJit() - { - CorInfoImpl.ShutdownJit(); - } - public override CompilationBuilder UseBackendOptions(IEnumerable options) { var builder = new ArrayBuilder>(); diff --git a/src/coreclr/tools/aot/crossgen2/Program.cs b/src/coreclr/tools/aot/crossgen2/Program.cs index d5418516e1cd1..afae84f57f6fa 100644 --- a/src/coreclr/tools/aot/crossgen2/Program.cs +++ b/src/coreclr/tools/aot/crossgen2/Program.cs @@ -989,14 +989,7 @@ private static int Main(string[] args) #if DEBUG try { - try - { - return new Program().Run(args); - } - finally - { - ReadyToRunCodegenCompilationBuilder.ShutdownJit(); - } + return new Program().Run(args); } catch (CodeGenerationFailedException ex) when (DumpReproArguments(ex)) { @@ -1005,14 +998,7 @@ private static int Main(string[] args) #else try { - try - { - return new Program().Run(args); - } - finally - { - ReadyToRunCodegenCompilationBuilder.ShutdownJit(); - } + return new Program().Run(args); } catch (Exception e) { diff --git a/src/coreclr/tools/aot/crossgen2/crossgen2.csproj b/src/coreclr/tools/aot/crossgen2/crossgen2.csproj index 4b1fc1af49908..7959568995ac4 100644 --- a/src/coreclr/tools/aot/crossgen2/crossgen2.csproj +++ b/src/coreclr/tools/aot/crossgen2/crossgen2.csproj @@ -3,11 +3,7 @@ $(RuntimeBinDir)/crossgen2 true - - $(TargetArchitecture) - arm - - $(PackageRID) + $(Crossgen2PackageRID) diff --git a/src/coreclr/utilcode/loaderheap.cpp b/src/coreclr/utilcode/loaderheap.cpp index b3b381b2f9bef..4b6bd66803320 100644 --- a/src/coreclr/utilcode/loaderheap.cpp +++ b/src/coreclr/utilcode/loaderheap.cpp @@ -2181,6 +2181,21 @@ AllocMemTracker::~AllocMemTracker() } } +// We have seen evidence of memory corruption in this data structure. +// https://github.com/dotnet/runtime/issues/54469 +// m_pFirstBlock is intended to be a linked list terminating with +// &m_FirstBlock but we are finding a nullptr in the list before +// that point. In order to investigate further we need to observe +// the corrupted memory block(s) before they are deleted below +#ifdef _DEBUG + AllocMemTrackerBlock* pDebugBlock = m_pFirstBlock; + for (int i = 0; pDebugBlock != &m_FirstBlock; i++) + { + CONSISTENCY_CHECK_MSGF(i < 10000, ("Linked list is much longer than expected, memory corruption likely\n")); + CONSISTENCY_CHECK_MSGF(pDebugBlock != nullptr, ("Linked list pointer == NULL, memory corruption likely\n")); + pDebugBlock = pDebugBlock->m_pNext; + } +#endif AllocMemTrackerBlock *pBlock = m_pFirstBlock; while (pBlock != &m_FirstBlock) diff --git a/src/coreclr/vm/arm/stubs.cpp b/src/coreclr/vm/arm/stubs.cpp index 6b4f71f245530..6e32957944d13 100644 --- a/src/coreclr/vm/arm/stubs.cpp +++ b/src/coreclr/vm/arm/stubs.cpp @@ -281,8 +281,13 @@ void StubLinkerCPU::Init(void) // value of the global into a register. struct WriteBarrierDescriptor { - DWORD m_pFuncStart; // Offset to the start of the barrier function relative to this struct address - DWORD m_pFuncEnd; // Offset to the end of the barrier function relative to this struct address +#ifdef TARGET_UNIX + DWORD m_funcStartOffset; // Offset to the start of the barrier function relative to this struct address + DWORD m_funcEndOffset; // Offset to the end of the barrier function relative to this struct address +#else // TARGET_UNIX + BYTE * m_pFuncStart; // Pointer to the start of the barrier function + BYTE * m_pFuncEnd; // Pointer to the end of the barrier function +#endif // TARGET_UNIX DWORD m_dw_g_lowest_address_offset; // Offset of the instruction reading g_lowest_address DWORD m_dw_g_highest_address_offset; // Offset of the instruction reading g_highest_address DWORD m_dw_g_ephemeral_low_offset; // Offset of the instruction reading g_ephemeral_low @@ -436,18 +441,28 @@ void UpdateGCWriteBarriers(bool postGrow = false) // Iterate through the write barrier patch table created in the .clrwb section // (see write barrier asm code) WriteBarrierDescriptor * pDesc = &g_rgWriteBarrierDescriptors; +#ifdef TARGET_UNIX + while (pDesc->m_funcStartOffset) +#else // TARGET_UNIX while (pDesc->m_pFuncStart) +#endif // TARGET_UNIX { // If the write barrier is being currently used (as in copied over to the patchable site) // then read the patch location from the table and use the offset to patch the target asm code - PBYTE to = FindWBMapping((BYTE *)pDesc + pDesc->m_pFuncStart); +#ifdef TARGET_UNIX + PBYTE to = FindWBMapping((BYTE *)pDesc + pDesc->m_funcStartOffset); + size_t barrierSize = pDesc->m_funcEndOffset - pDesc->m_funcStartOffset; +#else // TARGET_UNIX + PBYTE to = FindWBMapping(pDesc->m_pFuncStart); + size_t barrierSize = pDesc->m_pFuncEnd - pDesc->m_pFuncStart; +#endif // TARGET_UNIX if(to) { to = (PBYTE)PCODEToPINSTR((PCODE)GetWriteBarrierCodeLocation(to)); ExecutableWriterHolder barrierWriterHolder; if (IsWriteBarrierCopyEnabled()) { - barrierWriterHolder = ExecutableWriterHolder(to, pDesc->m_pFuncEnd - pDesc->m_pFuncStart); + barrierWriterHolder = ExecutableWriterHolder(to, barrierSize); to = barrierWriterHolder.GetRW(); } GWB_PATCH_OFFSET(g_lowest_address); diff --git a/src/coreclr/vm/ceeload.cpp b/src/coreclr/vm/ceeload.cpp index c5a9d98ac6e4e..8540e907ffb45 100644 --- a/src/coreclr/vm/ceeload.cpp +++ b/src/coreclr/vm/ceeload.cpp @@ -5996,7 +5996,11 @@ static HMODULE GetIJWHostForModule(Module* module) if ((importNameTable[thunkIndex].u1.Ordinal & (1LL << (sizeof(importNameTable[thunkIndex].u1.Ordinal) * CHAR_BIT - 1))) == 0) { IMAGE_IMPORT_BY_NAME* nameImport = (IMAGE_IMPORT_BY_NAME*)(baseAddress + importNameTable[thunkIndex].u1.AddressOfData); - if (strcmp("_CorDllMain", nameImport->Name) == 0) + if (strcmp("_CorDllMain", nameImport->Name) == 0 +#ifdef TARGET_X86 + || strcmp("__CorDllMain@12", nameImport->Name) == 0 // The MSVC compiler can and will bind to the stdcall-decorated name of _CorDllMain if it exists, even if the _CorDllMain symbol also exists. +#endif + ) { HMODULE ijwHost; @@ -10262,7 +10266,7 @@ PTR_BYTE Module::GetNativeDebugInfo(MethodDesc * pMD) //----------------------------------------------------------------------------- -BOOL Module::FixupNativeEntry(CORCOMPILE_IMPORT_SECTION* pSection, SIZE_T fixupIndex, SIZE_T* fixupCell) +BOOL Module::FixupNativeEntry(CORCOMPILE_IMPORT_SECTION* pSection, SIZE_T fixupIndex, SIZE_T* fixupCell, BOOL mayUsePrecompiledNDirectMethods) { CONTRACTL { @@ -10280,7 +10284,7 @@ BOOL Module::FixupNativeEntry(CORCOMPILE_IMPORT_SECTION* pSection, SIZE_T fixupI { PTR_DWORD pSignatures = dac_cast(GetNativeOrReadyToRunImage()->GetRvaData(pSection->Signatures)); - if (!LoadDynamicInfoEntry(this, pSignatures[fixupIndex], fixupCell)) + if (!LoadDynamicInfoEntry(this, pSignatures[fixupIndex], fixupCell, mayUsePrecompiledNDirectMethods)) return FALSE; _ASSERTE(*fixupCell != NULL); @@ -10291,7 +10295,7 @@ BOOL Module::FixupNativeEntry(CORCOMPILE_IMPORT_SECTION* pSection, SIZE_T fixupI if (CORCOMPILE_IS_FIXUP_TAGGED(fixup, pSection)) { // Fixup has not been fixed up yet - if (!LoadDynamicInfoEntry(this, (RVA)CORCOMPILE_UNTAG_TOKEN(fixup), fixupCell)) + if (!LoadDynamicInfoEntry(this, (RVA)CORCOMPILE_UNTAG_TOKEN(fixup), fixupCell, mayUsePrecompiledNDirectMethods)) return FALSE; _ASSERTE(!CORCOMPILE_IS_FIXUP_TAGGED(*fixupCell, pSection)); diff --git a/src/coreclr/vm/ceeload.h b/src/coreclr/vm/ceeload.h index 81116102682c6..963ee16160554 100644 --- a/src/coreclr/vm/ceeload.h +++ b/src/coreclr/vm/ceeload.h @@ -2679,17 +2679,17 @@ class Module IMDInternalImport *GetNativeAssemblyImport(BOOL loadAllowed = TRUE); IMDInternalImport *GetNativeAssemblyImportIfLoaded(); - BOOL FixupNativeEntry(CORCOMPILE_IMPORT_SECTION * pSection, SIZE_T fixupIndex, SIZE_T *fixup); + BOOL FixupNativeEntry(CORCOMPILE_IMPORT_SECTION * pSection, SIZE_T fixupIndex, SIZE_T *fixup, BOOL mayUsePrecompiledNDirectMethods = TRUE); //this split exists to support new CLR Dump functionality in DAC. The //template removes any indirections. - BOOL FixupDelayList(TADDR pFixupList); + BOOL FixupDelayList(TADDR pFixupList, BOOL mayUsePrecompiledNDirectMethods = TRUE); template BOOL FixupDelayListAux(TADDR pFixupList, Ptr pThis, FixupNativeEntryCallback pfnCB, PTR_CORCOMPILE_IMPORT_SECTION pImportSections, COUNT_T nImportSections, - PEDecoder * pNativeImage); + PEDecoder * pNativeImage, BOOL mayUsePrecompiledNDirectMethods = TRUE); void RunEagerFixups(); void RunEagerFixupsUnlocked(); diff --git a/src/coreclr/vm/ceeload.inl b/src/coreclr/vm/ceeload.inl index d6dbe8e7b40ba..f71511cbb9ac3 100644 --- a/src/coreclr/vm/ceeload.inl +++ b/src/coreclr/vm/ceeload.inl @@ -463,21 +463,21 @@ FORCEINLINE PTR_DomainLocalModule Module::GetDomainLocalModule() #include "nibblestream.h" -FORCEINLINE BOOL Module::FixupDelayList(TADDR pFixupList) +FORCEINLINE BOOL Module::FixupDelayList(TADDR pFixupList, BOOL mayUsePrecompiledNDirectMethods) { WRAPPER_NO_CONTRACT; COUNT_T nImportSections; PTR_CORCOMPILE_IMPORT_SECTION pImportSections = GetImportSections(&nImportSections); - return FixupDelayListAux(pFixupList, this, &Module::FixupNativeEntry, pImportSections, nImportSections, GetNativeOrReadyToRunImage()); + return FixupDelayListAux(pFixupList, this, &Module::FixupNativeEntry, pImportSections, nImportSections, GetNativeOrReadyToRunImage(), mayUsePrecompiledNDirectMethods); } template BOOL Module::FixupDelayListAux(TADDR pFixupList, Ptr pThis, FixupNativeEntryCallback pfnCB, PTR_CORCOMPILE_IMPORT_SECTION pImportSections, COUNT_T nImportSections, - PEDecoder * pNativeImage) + PEDecoder * pNativeImage, BOOL mayUsePrecompiledNDirectMethods) { CONTRACTL { @@ -567,7 +567,7 @@ BOOL Module::FixupDelayListAux(TADDR pFixupList, { CONSISTENCY_CHECK(fixupIndex * sizeof(TADDR) < cbData); - if (!(pThis->*pfnCB)(pImportSection, fixupIndex, dac_cast(pData + fixupIndex * sizeof(TADDR)))) + if (!(pThis->*pfnCB)(pImportSection, fixupIndex, dac_cast(pData + fixupIndex * sizeof(TADDR)), mayUsePrecompiledNDirectMethods)) return FALSE; int delta = reader.ReadEncodedU32(); diff --git a/src/coreclr/vm/ecall.cpp b/src/coreclr/vm/ecall.cpp index c6d1b6d2f1edd..3dd1c44aa2649 100644 --- a/src/coreclr/vm/ecall.cpp +++ b/src/coreclr/vm/ecall.cpp @@ -659,6 +659,13 @@ LPVOID ECall::GetQCallImpl(MethodDesc * pMD) if (id == 0) { id = ECall::GetIDForMethod(pMD); + +#ifdef _DEBUG + CONSISTENCY_CHECK_MSGF(id != 0, + ("%s::%s is not registered in ecall.cpp", + pMD->m_pszDebugClassName, pMD->m_pszDebugMethodName)); +#endif + _ASSERTE(id != 0); // Cache the id diff --git a/src/coreclr/vm/eepolicy.cpp b/src/coreclr/vm/eepolicy.cpp index 1c250c7d40a09..9f1f9624941a5 100644 --- a/src/coreclr/vm/eepolicy.cpp +++ b/src/coreclr/vm/eepolicy.cpp @@ -616,6 +616,10 @@ void DECLSPEC_NORETURN EEPolicy::HandleFatalStackOverflow(EXCEPTION_POINTERS *pE WRAPPER_NO_CONTRACT; + // Disable GC stress triggering GC at this point, we don't want the GC to start running + // on this thread when we have only a very limited space left on the stack + GCStressPolicy::InhibitHolder iholder; + STRESS_LOG0(LF_EH, LL_INFO100, "In EEPolicy::HandleFatalStackOverflow\n"); FrameWithCookie fef; diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index 51c87fa8d678e..692c35eb6dae7 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -10162,6 +10162,20 @@ bool CEEInfo::pInvokeMarshalingRequired(CORINFO_METHOD_HANDLE method, CORINFO_SI #endif } + PrepareCodeConfig *config = GetThread()->GetCurrentPrepareCodeConfig(); + if (config != nullptr && config->IsForMulticoreJit()) + { + bool suppressGCTransition = false; + CorInfoCallConvExtension unmanagedCallConv = getUnmanagedCallConv(method, callSiteSig, &suppressGCTransition); + + if (suppressGCTransition) + { + // MultiCoreJit thread can't inline PInvoke with SuppressGCTransitionAttribute, + // because it can't be resolved in mcj thread + result = TRUE; + } + } + EE_TO_JIT_TRANSITION(); return result; @@ -13777,7 +13791,8 @@ bool IsInstructionSetSupported(CORJIT_FLAGS jitFlags, ReadyToRunInstructionSet r BOOL LoadDynamicInfoEntry(Module *currentModule, RVA fixupRva, - SIZE_T *entry) + SIZE_T *entry, + BOOL mayUsePrecompiledNDirectMethods) { STANDARD_VM_CONTRACT; @@ -14005,10 +14020,17 @@ BOOL LoadDynamicInfoEntry(Module *currentModule, case ENCODE_PINVOKE_TARGET: { - MethodDesc *pMethod = ZapSig::DecodeMethod(currentModule, pInfoModule, pBlob); + if (mayUsePrecompiledNDirectMethods) + { + MethodDesc *pMethod = ZapSig::DecodeMethod(currentModule, pInfoModule, pBlob); - _ASSERTE(pMethod->IsNDirect()); - result = (size_t)(LPVOID)NDirectMethodDesc::ResolveAndSetNDirectTarget((NDirectMethodDesc*)pMethod); + _ASSERTE(pMethod->IsNDirect()); + result = (size_t)(LPVOID)NDirectMethodDesc::ResolveAndSetNDirectTarget((NDirectMethodDesc*)pMethod); + } + else + { + return FALSE; + } } break; diff --git a/src/coreclr/vm/jitinterface.h b/src/coreclr/vm/jitinterface.h index feb9ed94f7e1f..c231cc865ccae 100644 --- a/src/coreclr/vm/jitinterface.h +++ b/src/coreclr/vm/jitinterface.h @@ -89,7 +89,8 @@ void getMethodInfoILMethodHeaderHelper( BOOL LoadDynamicInfoEntry(Module *currentModule, RVA fixupRva, - SIZE_T *entry); + SIZE_T *entry, + BOOL mayUsePrecompiledNDirectMethods = TRUE); // // The legacy x86 monitor helpers do not need a state argument @@ -1163,4 +1164,3 @@ FCDECL1(INT64, GetCompiledMethodCount, CLR_BOOL currentThread); FCDECL1(INT64, GetCompilationTimeInTicks, CLR_BOOL currentThread); #endif // JITINTERFACE_H - diff --git a/src/coreclr/vm/managedmdimport.cpp b/src/coreclr/vm/managedmdimport.cpp index 6bea537f1c8e1..ec2aef0cc0398 100644 --- a/src/coreclr/vm/managedmdimport.cpp +++ b/src/coreclr/vm/managedmdimport.cpp @@ -163,6 +163,7 @@ static int * EnsureResultSize(MetadataEnumResult * pResult, ULONG length) else { ZeroMemory(pResult->smallResult, sizeof(pResult->smallResult)); + pResult->largeResult = NULL; p = pResult->smallResult; } diff --git a/src/coreclr/vm/prestub.cpp b/src/coreclr/vm/prestub.cpp index 20f5cbfaf7279..75f78f55d62e3 100644 --- a/src/coreclr/vm/prestub.cpp +++ b/src/coreclr/vm/prestub.cpp @@ -426,6 +426,12 @@ PCODE MethodDesc::PrepareILBasedCode(PrepareCodeConfig* pConfig) #endif } + if (pConfig->IsForMulticoreJit() && pCode == NULL && pConfig->ReadyToRunRejectedPrecompiledCode()) + { + // Was unable to load code from r2r image in mcj thread, don't try to jit it, this method will be loaded later + return NULL; + } + if (pCode == NULL) { LOG((LF_CLASSLOADER, LL_INFO1000000, diff --git a/src/coreclr/vm/readytoruninfo.cpp b/src/coreclr/vm/readytoruninfo.cpp index cf2803dec9375..0253d59e09c22 100644 --- a/src/coreclr/vm/readytoruninfo.cpp +++ b/src/coreclr/vm/readytoruninfo.cpp @@ -978,7 +978,12 @@ PCODE ReadyToRunInfo::GetEntryPoint(MethodDesc * pMD, PrepareCodeConfig* pConfig if (fFixups) { - if (!m_pModule->FixupDelayList(dac_cast(GetImage()->GetBase()) + offset)) + BOOL mayUsePrecompiledNDirectMethods = TRUE; +#ifndef CROSSGEN_COMPILE + mayUsePrecompiledNDirectMethods = !pConfig->IsForMulticoreJit(); +#endif // CROSSGEN_COMPILE + + if (!m_pModule->FixupDelayList(dac_cast(GetImage()->GetBase()) + offset, mayUsePrecompiledNDirectMethods)) { #ifndef CROSSGEN_COMPILE pConfig->SetReadyToRunRejectedPrecompiledCode(); diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/EncryptDecrypt.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/EncryptDecrypt.cs index 80fbbace5b58a..85fb5c7691a9e 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/EncryptDecrypt.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/EncryptDecrypt.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using Test.Cryptography; +using Microsoft.DotNet.XUnitExtensions; using Xunit; namespace System.Security.Cryptography.Rsa.Tests @@ -336,11 +337,19 @@ private void RsaCryptRoundtrip(RSAEncryptionPadding paddingMode, bool expectSucc Assert.Equal(TestData.HelloBytes, output); } - [Fact] + [ConditionalFact] [SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework)] - [ActiveIssue("https://github.com/dotnet/runtime/issues/52199", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public void RoundtripEmptyArray() { + if (OperatingSystem.IsIOS() && !OperatingSystem.IsIOSVersionAtLeast(13, 6)) + { + throw new SkipTestException("iOS prior to 13.6 does not reliably support RSA encryption of empty data."); + } + if (OperatingSystem.IsTvOS() && !OperatingSystem.IsTvOSVersionAtLeast(14, 0)) + { + throw new SkipTestException("tvOS prior to 14.0 does not reliably support RSA encryption of empty data."); + } + using (RSA rsa = RSAFactory.Create(TestData.RSA2048Params)) { void RoundtripEmpty(RSAEncryptionPadding paddingMode) diff --git a/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs b/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs index c1bb1854ff1ba..d44f9bcfdd661 100644 --- a/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs +++ b/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs @@ -54,6 +54,9 @@ public static partial class PlatformDetection public static bool Is64BitProcess => IntPtr.Size == 8; public static bool IsNotWindows => !IsWindows; + public static bool IsCaseInsensitiveOS => IsWindows || IsOSX; + public static bool IsCaseSensitiveOS => !IsCaseInsensitiveOS; + public static bool IsThreadingSupported => !IsBrowser; public static bool IsBinaryFormatterSupported => IsNotMobile; diff --git a/src/libraries/Directory.Build.targets b/src/libraries/Directory.Build.targets index 2e90117f462b4..1964e8ef8b8f9 100644 --- a/src/libraries/Directory.Build.targets +++ b/src/libraries/Directory.Build.targets @@ -272,20 +272,7 @@ - - - <_intellisenseRootFolder>$(BuildOutputTargetFolder) - <_intellisenseRootFolder Condition="'$(_intellisenseRootFolder)' == ''">lib - - - - - - - IncludeAnalyzersInPackage;$(BeforePack) $(BuildProjectReferences) false @@ -296,41 +283,13 @@ so we don't apply TargetFramework filters nor do we pass in TargetFramework. When BuildProjectReferences=false we make sure to set BuildReference=false to make sure not to try to call GetTargetPath in the outerbuild of the analyzer project. --> - + - - - - - - - - - - <_TargetPathsToSymbols Include="@(_AnalyzerFile)" TargetPath="/%(_AnalyzerFile.PackagePath)" Condition="%(_AnalyzerFile.IsSymbol)" /> - - - - - - <_analyzerPath>analyzers/dotnet - <_analyzerPath Condition="'$(AnalyzerLanguage)' != ''">$(_analyzerPath)/$(AnalyzerLanguage) - - - <_AnalyzerPackFile Include="@(_BuildOutputInPackage)" IsSymbol="false" /> - <_AnalyzerPackFile Include="@(_TargetPathsToSymbols)" IsSymbol="true" /> - <_AnalyzerPackFile PackagePath="$(_analyzerPath)/%(TargetPath)" /> - - - - diff --git a/src/libraries/Microsoft.AspNetCore.Internal.Transport/pkg/Microsoft.AspNetCore.Internal.Transport.pkgproj b/src/libraries/Microsoft.AspNetCore.Internal.Transport/pkg/Microsoft.AspNetCore.Internal.Transport.pkgproj deleted file mode 100644 index 23046099e10ad..0000000000000 --- a/src/libraries/Microsoft.AspNetCore.Internal.Transport/pkg/Microsoft.AspNetCore.Internal.Transport.pkgproj +++ /dev/null @@ -1,18 +0,0 @@ - - - - true - true - false - false - Internal transport package to provide aspnetcore with the assemblies that make up the Microsoft.ASPNetCore.App shared framework. - - - <_analyzers Include="$(ASPNETCoreAppPackageRootPath)\analyzers\**\*.*" /> - - <_libDocs Include="$(ASPNETCoreAppPackageRuntimePath)\*.xml" /> - - - - - diff --git a/src/libraries/Microsoft.AspNetCore.Internal.Transport/src/Microsoft.AspNetCore.Internal.Transport.proj b/src/libraries/Microsoft.AspNetCore.Internal.Transport/src/Microsoft.AspNetCore.Internal.Transport.proj index 8d90792dd6ffe..8f8f7feae0fbb 100644 --- a/src/libraries/Microsoft.AspNetCore.Internal.Transport/src/Microsoft.AspNetCore.Internal.Transport.proj +++ b/src/libraries/Microsoft.AspNetCore.Internal.Transport/src/Microsoft.AspNetCore.Internal.Transport.proj @@ -1,6 +1,29 @@ - - + - netstandard2.0 + $(NetCoreAppCurrent) + true + false + + true + Internal transport package to provide aspnetcore with the assemblies that make up the Microsoft.ASPNetCore.App shared framework. + + $(NoWarn);NU5131 - \ No newline at end of file + + + <_analyzer Include="$(ASPNETCoreAppPackageRootPath)\analyzers\**\*.*" /> + <_libDoc Include="$(ASPNETCoreAppPackageRuntimePath)\*.xml" /> + + + + + + diff --git a/src/libraries/Microsoft.Extensions.Configuration.EnvironmentVariables/src/EnvironmentVariablesConfigurationProvider.cs b/src/libraries/Microsoft.Extensions.Configuration.EnvironmentVariables/src/EnvironmentVariablesConfigurationProvider.cs index 294956a5e737e..5ea29116ca2d9 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.EnvironmentVariables/src/EnvironmentVariablesConfigurationProvider.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.EnvironmentVariables/src/EnvironmentVariablesConfigurationProvider.cs @@ -38,6 +38,13 @@ public class EnvironmentVariablesConfigurationProvider : ConfigurationProvider public override void Load() => Load(Environment.GetEnvironmentVariables()); + /// + /// Generates a string representing this provider name and relevant details. + /// + /// The configuration name. + public override string ToString() + => $"{GetType().Name} Prefix: '{_prefix}'"; + internal void Load(IDictionary envVariables) { var data = new Dictionary(StringComparer.OrdinalIgnoreCase); diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Microsoft.Extensions.DependencyInjection.Abstractions.csproj b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Microsoft.Extensions.DependencyInjection.Abstractions.csproj index b275c71c780c7..dc32454f1759a 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Microsoft.Extensions.DependencyInjection.Abstractions.csproj +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Microsoft.Extensions.DependencyInjection.Abstractions.csproj @@ -1,4 +1,4 @@ - + $(NetCoreAppCurrent);netstandard2.1;netstandard2.0;net461 diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ILLink/ILLink.Substitutions.xml b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ILLink/ILLink.Substitutions.xml new file mode 100644 index 0000000000000..eb381de19d615 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ILLink/ILLink.Substitutions.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ILLink/ILLink.Suppressions.xml b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ILLink/ILLink.Suppressions.xml deleted file mode 100644 index 3a09880ba32d1..0000000000000 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ILLink/ILLink.Suppressions.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - ILLink - IL2055 - member - M:Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateOpenGeneric(Microsoft.Extensions.DependencyInjection.ServiceDescriptor,System.Type,Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteChain,System.Int32,System.Boolean) - - - \ No newline at end of file diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/Microsoft.Extensions.DependencyInjection.csproj b/src/libraries/Microsoft.Extensions.DependencyInjection/src/Microsoft.Extensions.DependencyInjection.csproj index b93c0a8e61e66..7ee51306d042d 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/Microsoft.Extensions.DependencyInjection.csproj +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/Microsoft.Extensions.DependencyInjection.csproj @@ -1,4 +1,4 @@ - + $(NetCoreAppCurrent);netstandard2.1;netstandard2.0;net461 @@ -19,6 +19,10 @@ $(DefineConstants);SAVE_ASSEMBLIES + + + + @@ -32,7 +36,7 @@ - + @@ -41,7 +45,6 @@ Link="Common\src\Extensions\ParameterDefaultValue\ParameterDefaultValue.cs" /> - diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/Resources/Strings.resx b/src/libraries/Microsoft.Extensions.DependencyInjection/src/Resources/Strings.resx index e76446a526b4f..efbb7cc4a7451 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/Resources/Strings.resx +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/Resources/Strings.resx @@ -174,4 +174,10 @@ Call site type {0} is not supported - \ No newline at end of file + + Generic implementation type '{0}' has a DynamicallyAccessedMembers attribute applied to a generic argument type, but the service type '{1}' doesn't have a matching DynamicallyAccessedMembers attribute on its generic argument type. + + + Generic implementation type '{0}' has a DefaultConstructorConstraint ('new()' constraint), but the generic service type '{1}' doesn't. + + diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs index a2e02ce4f5001..06bcdf632879c 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs @@ -51,11 +51,18 @@ private void Populate() SR.Format(SR.TypeCannotBeActivated, implementationType, serviceType)); } - if (serviceType.GetGenericArguments().Length != implementationType.GetGenericArguments().Length) + Type[] serviceTypeGenericArguments = serviceType.GetGenericArguments(); + Type[] implementationTypeGenericArguments = implementationType.GetGenericArguments(); + if (serviceTypeGenericArguments.Length != implementationTypeGenericArguments.Length) { throw new ArgumentException( SR.Format(SR.ArityOfOpenGenericServiceNotEqualArityOfOpenGenericImplementation, serviceType, implementationType), "descriptors"); } + + if (ServiceProvider.VerifyOpenGenericServiceTrimmability) + { + ValidateTrimmingAnnotations(serviceType, serviceTypeGenericArguments, implementationType, implementationTypeGenericArguments); + } } else if (descriptor.ImplementationInstance == null && descriptor.ImplementationFactory == null) { @@ -77,6 +84,68 @@ private void Populate() } } + /// + /// Validates that two generic type definitions have compatible trimming annotations on their generic arguments. + /// + /// + /// When open generic types are used in DI, there is an error when the concrete implementation type + /// has [DynamicallyAccessedMembers] attributes on a generic argument type, but the interface/service type + /// doesn't have matching annotations. The problem is that the trimmer doesn't see the members that need to + /// be preserved on the type being passed to the generic argument. But when the interface/service type also has + /// the annotations, the trimmer will see which members need to be preserved on the closed generic argument type. + /// + private static void ValidateTrimmingAnnotations( + Type serviceType, + Type[] serviceTypeGenericArguments, + Type implementationType, + Type[] implementationTypeGenericArguments) + { + Debug.Assert(serviceTypeGenericArguments.Length == implementationTypeGenericArguments.Length); + + for (int i = 0; i < serviceTypeGenericArguments.Length; i++) + { + Type serviceGenericType = serviceTypeGenericArguments[i]; + Type implementationGenericType = implementationTypeGenericArguments[i]; + + DynamicallyAccessedMemberTypes serviceDynamicallyAccessedMembers = GetDynamicallyAccessedMemberTypes(serviceGenericType); + DynamicallyAccessedMemberTypes implementationDynamicallyAccessedMembers = GetDynamicallyAccessedMemberTypes(implementationGenericType); + + if (!AreCompatible(serviceDynamicallyAccessedMembers, implementationDynamicallyAccessedMembers)) + { + throw new ArgumentException(SR.Format(SR.TrimmingAnnotationsDoNotMatch, implementationType.FullName, serviceType.FullName)); + } + + bool serviceHasNewConstraint = serviceGenericType.GenericParameterAttributes.HasFlag(GenericParameterAttributes.DefaultConstructorConstraint); + bool implementationHasNewConstraint = implementationGenericType.GenericParameterAttributes.HasFlag(GenericParameterAttributes.DefaultConstructorConstraint); + if (implementationHasNewConstraint && !serviceHasNewConstraint) + { + throw new ArgumentException(SR.Format(SR.TrimmingAnnotationsDoNotMatch_NewConstraint, implementationType.FullName, serviceType.FullName)); + } + } + } + + private static DynamicallyAccessedMemberTypes GetDynamicallyAccessedMemberTypes(Type serviceGenericType) + { + foreach (CustomAttributeData attributeData in serviceGenericType.GetCustomAttributesData()) + { + if (attributeData.AttributeType.FullName == "System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute" && + attributeData.ConstructorArguments.Count == 1 && + attributeData.ConstructorArguments[0].ArgumentType.FullName == "System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes") + { + return (DynamicallyAccessedMemberTypes)(int)attributeData.ConstructorArguments[0].Value; + } + } + + return DynamicallyAccessedMemberTypes.None; + } + + private static bool AreCompatible(DynamicallyAccessedMemberTypes serviceDynamicallyAccessedMembers, DynamicallyAccessedMemberTypes implementationDynamicallyAccessedMembers) + { + // The DynamicallyAccessedMemberTypes don't need to exactly match. + // The service type needs to preserve a superset of the members required by the implementation type. + return serviceDynamicallyAccessedMembers.HasFlag(implementationDynamicallyAccessedMembers); + } + // For unit testing internal int? GetSlot(ServiceDescriptor serviceDescriptor) { @@ -273,6 +342,10 @@ private ServiceCallSite TryCreateExact(ServiceDescriptor descriptor, Type servic return null; } + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2055:MakeGenericType", + Justification = "MakeGenericType here is used to create a closed generic implementation type given the closed service type. " + + "Trimming annotations on the generic types are verified when 'Microsoft.Extensions.DependencyInjection.VerifyOpenGenericServiceTrimmability' is set, which is set by default when PublishTrimmed=true. " + + "That check informs developers when these generic types don't have compatible trimming annotations.")] private ServiceCallSite TryCreateOpenGeneric(ServiceDescriptor descriptor, Type serviceType, CallSiteChain callSiteChain, int slot, bool throwOnConstraintViolation) { if (serviceType.IsConstructedGenericType && diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceProvider.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceProvider.cs index afe118acf7909..a05e82f8a4498 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceProvider.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceProvider.cs @@ -30,6 +30,9 @@ public sealed class ServiceProvider : IServiceProvider, IDisposable, IAsyncDispo internal ServiceProviderEngineScope Root { get; } + internal static bool VerifyOpenGenericServiceTrimmability { get; } = + AppContext.TryGetSwitch("Microsoft.Extensions.DependencyInjection.VerifyOpenGenericServiceTrimmability", out bool verifyOpenGenerics) ? verifyOpenGenerics : false; + internal ServiceProvider(IEnumerable serviceDescriptors, ServiceProviderOptions options) { // note that Root needs to be set before calling GetEngine(), because the engine may need to access Root diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/Microsoft.Extensions.DependencyInjection.Tests.csproj b/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/Microsoft.Extensions.DependencyInjection.Tests.csproj index 073451c2cd9f0..698e3ec3dd659 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/Microsoft.Extensions.DependencyInjection.Tests.csproj +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/Microsoft.Extensions.DependencyInjection.Tests.csproj @@ -1,8 +1,11 @@ - + $(NetCoreAppCurrent);net461 true + true + + $(NoWarn);CS0436 @@ -11,6 +14,12 @@ Link="Shared\SingleThreadedSynchronizationContext.cs" /> + + + + + + diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ServiceLookup/CallSiteFactoryTest.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ServiceLookup/CallSiteFactoryTest.cs index 8d6a78029feff..da24dca4e92cf 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ServiceLookup/CallSiteFactoryTest.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ServiceLookup/CallSiteFactoryTest.cs @@ -3,9 +3,11 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Reflection; using System.Threading.Tasks; +using Microsoft.DotNet.RemoteExecutor; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.DependencyInjection.Specification.Fakes; using Xunit; @@ -849,6 +851,51 @@ public void CallSitesAreUniquePerServiceTypeAndSlotWithOpenGenericInGraph() } } + [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + [SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework)] // RuntimeConfigurationOptions are not supported on .NET Framework (and neither is trimming) + public void VerifyOpenGenericTrimmabilityChecks() + { + RemoteInvokeOptions options = new RemoteInvokeOptions(); + options.RuntimeConfigurationOptions.Add("Microsoft.Extensions.DependencyInjection.VerifyOpenGenericServiceTrimmability", "true"); + + using RemoteInvokeHandle remoteHandle = RemoteExecutor.Invoke(() => + { + (Type, Type)[] invalidTestCases = new[] + { + (typeof(IFakeOpenGenericService<>), typeof(ClassWithNewConstraint<>)), + (typeof(IServiceWithoutTrimmingAnnotations<>), typeof(ServiceWithTrimmingAnnotations<>)), + (typeof(IServiceWithPublicConstructors<>), typeof(ServiceWithPublicProperties<>)), + (typeof(IServiceWithTwoGenerics<,>), typeof(ServiceWithTwoGenericsInvalid<,>)), + }; + foreach ((Type serviceType, Type implementationType) in invalidTestCases) + { + ServiceDescriptor[] serviceDescriptors = new[] + { + new ServiceDescriptor(serviceType, implementationType, ServiceLifetime.Singleton) + }; + + Assert.Throws(() => new CallSiteFactory(serviceDescriptors)); + } + + (Type, Type)[] validTestCases = new[] + { + (typeof(IFakeOpenGenericService<>), typeof(FakeOpenGenericService<>)), + (typeof(IServiceWithPublicConstructors<>), typeof(ServiceWithPublicConstructors<>)), + (typeof(IServiceWithTwoGenerics<,>), typeof(ServiceWithTwoGenericsValid<,>)), + (typeof(IServiceWithMoreMemberTypes<>), typeof(ServiceWithLessMemberTypes<>)), + }; + foreach ((Type serviceType, Type implementationType) in validTestCases) + { + ServiceDescriptor[] serviceDescriptors = new[] + { + new ServiceDescriptor(serviceType, implementationType, ServiceLifetime.Singleton) + }; + + Assert.NotNull(new CallSiteFactory(serviceDescriptors)); + } + }, options); + } + private static Func GetCallSiteFactory(params ServiceDescriptor[] descriptors) { var collection = new ServiceCollection(); @@ -887,5 +934,20 @@ private class ClassB { public ClassB(ClassC cc) { } } private class ClassC { } private class ClassD { public ClassD(ClassC cd) { } } private class ClassE { public ClassE(ClassB cb) { } } + + // Open generic with trimming annotations + private interface IServiceWithoutTrimmingAnnotations { } + private class ServiceWithTrimmingAnnotations<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] T> : IServiceWithoutTrimmingAnnotations { } + + private interface IServiceWithPublicConstructors<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] T> { } + private class ServiceWithPublicProperties<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] T>: IServiceWithPublicConstructors { } + private class ServiceWithPublicConstructors<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] T>: IServiceWithPublicConstructors { } + + private interface IServiceWithTwoGenerics { } + private class ServiceWithTwoGenericsInvalid : IServiceWithTwoGenerics { } + private class ServiceWithTwoGenericsValid : IServiceWithTwoGenerics { } + + private interface IServiceWithMoreMemberTypes<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.PublicProperties)] T> { } + private class ServiceWithLessMemberTypes<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] T> : IServiceWithMoreMemberTypes { } } } diff --git a/src/libraries/Microsoft.Extensions.HostFactoryResolver/src/Microsoft.Extensions.HostFactoryResolver.Sources.csproj b/src/libraries/Microsoft.Extensions.HostFactoryResolver/src/Microsoft.Extensions.HostFactoryResolver.Sources.csproj index dff90383f96cb..31cd86025ee01 100644 --- a/src/libraries/Microsoft.Extensions.HostFactoryResolver/src/Microsoft.Extensions.HostFactoryResolver.Sources.csproj +++ b/src/libraries/Microsoft.Extensions.HostFactoryResolver/src/Microsoft.Extensions.HostFactoryResolver.Sources.csproj @@ -3,8 +3,6 @@ package infra globs for .cs files. --> netstandard2.0 - - true false true diff --git a/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj b/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj index 299a8b2ceb734..9aad9681e31f9 100644 --- a/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj +++ b/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj @@ -6,8 +6,6 @@ $(MSBuildProjectName) true Microsoft.NETCore.Platforms.BuildTasks - - true false true diff --git a/src/libraries/Microsoft.Windows.Compatibility/src/Microsoft.Windows.Compatibility.csproj b/src/libraries/Microsoft.Windows.Compatibility/src/Microsoft.Windows.Compatibility.csproj new file mode 100644 index 0000000000000..86afb922f869e --- /dev/null +++ b/src/libraries/Microsoft.Windows.Compatibility/src/Microsoft.Windows.Compatibility.csproj @@ -0,0 +1,70 @@ + + + + $(NetCoreAppCurrent);netcoreapp3.1;netstandard2.1;netstandard2.0 + true + + false + + $(NoWarn);NU5128 + This Windows Compatibility Pack provides access to APIs that were previously available only for .NET Framework. It can be used from both .NET Core as well as .NET Standard. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/libraries/Native/Unix/System.Globalization.Native/pal_collation.c b/src/libraries/Native/Unix/System.Globalization.Native/pal_collation.c index 4a8d5bcd72153..0e0a46c5b1c59 100644 --- a/src/libraries/Native/Unix/System.Globalization.Native/pal_collation.c +++ b/src/libraries/Native/Unix/System.Globalization.Native/pal_collation.c @@ -839,11 +839,35 @@ int32_t GlobalizationNative_LastIndexOf( result = usearch_last(pSearch, &err); - // if the search was successful, - // we'll try to get the matched string length. - if (result != USEARCH_DONE && pMatchedLength != NULL) + // if the search was successful, we'll try to get the matched string length. + if (result != USEARCH_DONE) { - *pMatchedLength = usearch_getMatchedLength(pSearch); + int32_t matchLength = -1; + + if (pMatchedLength != NULL) + { + matchLength = usearch_getMatchedLength(pSearch); + *pMatchedLength = matchLength; + } + + // In case the search result is pointing at the last character (including Surrogate case) of the source string, we need to check if the target string + // was constructed with characters which have no sort weights. The way we do that is to check that the matched length is 0. + // We need to update the returned index to have consistent behavior with Ordinal and NLS operations, and satisfy the condition: + // index = source.LastIndexOf(value, comparisonType); + // originalString.Substring(index).StartsWith(value, comparisonType) == true. + // https://github.com/dotnet/runtime/issues/13383 + if (result >= cwSourceLength - 2) + { + if (pMatchedLength == NULL) + { + matchLength = usearch_getMatchedLength(pSearch); + } + + if (matchLength == 0) + { + result = cwSourceLength; + } + } } RestoreSearchHandle(pSortHandle, pSearch, searchCacheSlot); diff --git a/src/libraries/System.Buffers/tests/ArrayPool/CollectionTests.cs b/src/libraries/System.Buffers/tests/ArrayPool/CollectionTests.cs index 6b39f5409bdea..b4b9685ff887a 100644 --- a/src/libraries/System.Buffers/tests/ArrayPool/CollectionTests.cs +++ b/src/libraries/System.Buffers/tests/ArrayPool/CollectionTests.cs @@ -23,48 +23,51 @@ public void BuffersAreCollectedWhenStale() const int BufferCount = 8; const int BufferSize = 1025; - // Get the pool and check our trim setting - var pool = ArrayPool.Shared; - List rentedBuffers = new List(); // Rent and return a set of buffers for (int i = 0; i < BufferCount; i++) { - rentedBuffers.Add(pool.Rent(BufferSize)); + rentedBuffers.Add(ArrayPool.Shared.Rent(BufferSize)); } for (int i = 0; i < BufferCount; i++) { - pool.Return(rentedBuffers[i]); + ArrayPool.Shared.Return(rentedBuffers[i]); } // Rent what we returned and ensure they are the same for (int i = 0; i < BufferCount; i++) { - var buffer = pool.Rent(BufferSize); + var buffer = ArrayPool.Shared.Rent(BufferSize); Assert.Contains(rentedBuffers, item => ReferenceEquals(item, buffer)); } for (int i = 0; i < BufferCount; i++) { - pool.Return(rentedBuffers[i]); + ArrayPool.Shared.Return(rentedBuffers[i]); + } + + // Trigger a few Gen2 GCs to make sure the pool has appropriately time stamped buffers. + for (int i = 0; i < 2; i++) + { + GC.Collect(); + GC.WaitForPendingFinalizers(); } // Now wait a little over a minute and force a GC to get some buffers returned Console.WriteLine("Waiting a minute for buffers to go stale..."); Thread.Sleep(61 * 1000); - GC.Collect(2); + GC.Collect(); GC.WaitForPendingFinalizers(); bool foundNewBuffer = false; for (int i = 0; i < BufferCount; i++) { - var buffer = pool.Rent(BufferSize); + var buffer = ArrayPool.Shared.Rent(BufferSize); if (!rentedBuffers.Any(item => ReferenceEquals(item, buffer))) { foundNewBuffer = true; } } - // Should only have found a new buffer if we're trimming Assert.True(foundNewBuffer); }, 3 * 60 * 1000); // This test has to wait for the buffers to go stale (give it three minutes) } @@ -78,21 +81,18 @@ public unsafe void ThreadLocalIsCollectedUnderHighPressure() { RemoteInvokeWithTrimming(() => { - // Get the pool and check our trim setting - var pool = ArrayPool.Shared; - // Create our buffer, return it, re-rent it and ensure we have the same one const int BufferSize = 4097; - var buffer = pool.Rent(BufferSize); - pool.Return(buffer); - Assert.Same(buffer, pool.Rent(BufferSize)); + byte[] buffer = ArrayPool.Shared.Rent(BufferSize); + ArrayPool.Shared.Return(buffer); + Assert.Same(buffer, ArrayPool.Shared.Rent(BufferSize)); // Return it and put memory pressure on to get it cleared - pool.Return(buffer); + ArrayPool.Shared.Return(buffer); const int AllocSize = 1024 * 1024 * 64; int PageSize = Environment.SystemPageSize; - var pressureMethod = pool.GetType().GetMethod("GetMemoryPressure", BindingFlags.Static | BindingFlags.NonPublic); + var pressureMethod = ArrayPool.Shared.GetType().GetMethod("GetMemoryPressure", BindingFlags.Static | BindingFlags.NonPublic); do { Span native = new Span(Marshal.AllocHGlobal(AllocSize).ToPointer(), AllocSize); @@ -109,10 +109,45 @@ public unsafe void ThreadLocalIsCollectedUnderHighPressure() GC.WaitForPendingFinalizers(); // Should have a new buffer now - Assert.NotSame(buffer, pool.Rent(BufferSize)); + Assert.NotSame(buffer, ArrayPool.Shared.Rent(BufferSize)); }); } + // This test can cause problems for other tests run in parallel (from other assemblies) as + // it pushes the physical memory usage above 80% temporarily. + [OuterLoop("This is a long running test (over 2 minutes)")] + [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + public unsafe void ThreadLocalIsCollectedUnderNormalPressure() + { + RemoteInvokeWithTrimming(() => + { + // Create our buffer, return it, re-rent it and ensure we have the same one + const int BufferSize = 4097; + byte[] buffer = ArrayPool.Shared.Rent(BufferSize); + ArrayPool.Shared.Return(buffer); + Assert.Same(buffer, ArrayPool.Shared.Rent(BufferSize)); + + // Return it and put memory pressure on to get it cleared + ArrayPool.Shared.Return(buffer); + + // Make sure buffer gets time stamped + for (int i = 0; i < 2; i++) + { + GC.Collect(); + GC.WaitForPendingFinalizers(); + } + + // Now wait for enough time to pass and force a GC to get buffers dropped + Console.WriteLine("Waiting a minute for buffers to go stale..."); + Thread.Sleep(61 * 1000); + GC.Collect(); + GC.WaitForPendingFinalizers(); + + // Should have a new buffer now + Assert.NotSame(buffer, ArrayPool.Shared.Rent(BufferSize)); + }, 3 * 60 * 1000); // This test has to wait for the buffers to go stale (give it three minutes) + } + private static bool IsPreciseGcSupportedAndRemoteExecutorSupported => PlatformDetection.IsPreciseGcSupported && RemoteExecutor.IsSupported; [ActiveIssue("https://github.com/dotnet/runtime/issues/44037")] @@ -121,9 +156,8 @@ public void PollingEventFires() { RemoteInvokeWithTrimming(() => { - var pool = ArrayPool.Shared; bool pollEventFired = false; - var buffer = pool.Rent(10); + float[] buffer = ArrayPool.Shared.Rent(10); // Polling doesn't start until the thread locals are created for a pool. // Try before the return then after. @@ -141,7 +175,7 @@ public void PollingEventFires() }); Assert.False(pollEventFired, "collection isn't hooked up until the first item is returned"); - pool.Return(buffer); + ArrayPool.Shared.Return(buffer); RunWithListener(() => { diff --git a/src/libraries/System.Collections.Concurrent/tests/BlockingCollectionCancellationTests.cs b/src/libraries/System.Collections.Concurrent/tests/BlockingCollectionCancellationTests.cs index a3d366927137d..14fa6d8d48746 100644 --- a/src/libraries/System.Collections.Concurrent/tests/BlockingCollectionCancellationTests.cs +++ b/src/libraries/System.Collections.Concurrent/tests/BlockingCollectionCancellationTests.cs @@ -97,7 +97,6 @@ public static void ExternalCancel_Negative() } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50576", TestPlatforms.Android)] public static void ExternalCancel_AddToAny() { for (int test = 0; test < 3; test++) diff --git a/src/libraries/System.Collections/src/System/Collections/Generic/SortedDictionary.cs b/src/libraries/System.Collections/src/System/Collections/Generic/SortedDictionary.cs index 35da349f53297..c28fa0123728c 100644 --- a/src/libraries/System.Collections/src/System/Collections/Generic/SortedDictionary.cs +++ b/src/libraries/System.Collections/src/System/Collections/Generic/SortedDictionary.cs @@ -947,6 +947,21 @@ public override int Compare(KeyValuePair x, KeyValuePair Equals_TestData() [Theory] [MemberData(nameof(Equals_TestData))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50881", TestPlatforms.Android)] public void Equals_Object_ReturnsExpected(CategoryAttribute attribute, object other, bool expected) { Assert.Equal(expected, attribute.Equals(other)); @@ -90,7 +87,6 @@ public static IEnumerable Properties_TestData() [Theory] [MemberData(nameof(Properties_TestData))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50881", TestPlatforms.Android)] public void Properties_Get_ReturnsExpected(Func attributeThunk, string expectedCategory) { CategoryAttribute attribute = attributeThunk(); @@ -129,7 +125,6 @@ public void GetLocalizedString_InvokeValueExists_ReturnsNonEmpty(string value) [InlineData(null)] [InlineData("")] [InlineData("value")] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50881", TestPlatforms.Android)] public void GetLocalizedString_InvokeNoSuchValue_ReturnsNull(string value) { var attribute = new SubCategoryAttribute(); diff --git a/src/libraries/System.ComponentModel.Primitives/tests/System/ComponentModel/InvalidEnumArgumentExceptionTests.cs b/src/libraries/System.ComponentModel.Primitives/tests/System/ComponentModel/InvalidEnumArgumentExceptionTests.cs index a993c3f81d676..4b6187edc248d 100644 --- a/src/libraries/System.ComponentModel.Primitives/tests/System/ComponentModel/InvalidEnumArgumentExceptionTests.cs +++ b/src/libraries/System.ComponentModel.Primitives/tests/System/ComponentModel/InvalidEnumArgumentExceptionTests.cs @@ -88,7 +88,6 @@ public void Ctor_NullEnumClass_ThrowsArgumentNulException() } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsBinaryFormatterSupported))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50881", TestPlatforms.Android)] public void Ctor_SerializationInfo_StreamingContext() { using (var stream = new MemoryStream()) diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/LicFileLicenseProvider.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/LicFileLicenseProvider.cs index cd420c931a90f..e5ce14bcb1d31 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/LicFileLicenseProvider.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/LicFileLicenseProvider.cs @@ -3,6 +3,7 @@ using System.ComponentModel.Design; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; @@ -40,6 +41,10 @@ protected virtual string GetKey(Type type) /// /// Gets a license for the instance of the component and determines if it is valid. /// + [UnconditionalSuppressMessage("SingleFile", "IL3002:RequiresAssemblyFiles", + Justification = "Only used for when Location is non-empty")] + [UnconditionalSuppressMessage("SingleFile", "IL3000:RequiresAssemblyFiles", + Justification = "Location is checked for empty")] public override License? GetLicense(LicenseContext context, Type type, object? instance, bool allowExceptions) { LicFileLicense? lic = null; @@ -69,30 +74,33 @@ protected virtual string GetKey(Type type) } } - if (modulePath == null) + if (type.Assembly.Location.Length != 0) { - modulePath = type.Module.FullyQualifiedName; - } + if (modulePath == null) + { + modulePath = type.Module.FullyQualifiedName; + } - string? moduleDir = Path.GetDirectoryName(modulePath); - string licenseFile = moduleDir + "\\" + type.FullName + ".lic"; + string? moduleDir = Path.GetDirectoryName(modulePath); + string licenseFile = moduleDir + "\\" + type.FullName + ".lic"; - Debug.WriteLine($"Looking for license in: {licenseFile}"); - if (File.Exists(licenseFile)) - { - Stream licStream = new FileStream(licenseFile, FileMode.Open, FileAccess.Read, FileShare.Read); - StreamReader sr = new StreamReader(licStream); - string? s = sr.ReadLine(); - sr.Close(); - if (IsKeyValid(s, type)) + Debug.WriteLine($"Looking for license in: {licenseFile}"); + if (File.Exists(licenseFile)) { - lic = new LicFileLicense(this, GetKey(type)); + Stream licStream = new FileStream(licenseFile, FileMode.Open, FileAccess.Read, FileShare.Read); + StreamReader sr = new StreamReader(licStream); + string? s = sr.ReadLine(); + sr.Close(); + if (IsKeyValid(s, type)) + { + lic = new LicFileLicense(this, GetKey(type)); + } } - } - if (lic != null) - { - context!.SetSavedLicenseKey(type, lic.LicenseKey); + if (lic != null) + { + context!.SetSavedLicenseKey(type, lic.LicenseKey); + } } } } diff --git a/src/libraries/System.Composition.Hosting/tests/System/Composition/Hosting/Core/CompositionDependencyTests.cs b/src/libraries/System.Composition.Hosting/tests/System/Composition/Hosting/Core/CompositionDependencyTests.cs index cfa0fc3fc2708..eb9fb2192704d 100644 --- a/src/libraries/System.Composition.Hosting/tests/System/Composition/Hosting/Core/CompositionDependencyTests.cs +++ b/src/libraries/System.Composition.Hosting/tests/System/Composition/Hosting/Core/CompositionDependencyTests.cs @@ -37,7 +37,6 @@ public void Missing_NullSite_ThrowsArgumentNullException() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50917", TestPlatforms.Android)] public void Satisfied_Invoke_ReturnsExpected() { var contract = new CompositionContract(typeof(int)); diff --git a/src/libraries/System.Composition.Hosting/tests/System/Composition/Hosting/Core/ExportDescriptorPromiseTests.cs b/src/libraries/System.Composition.Hosting/tests/System/Composition/Hosting/Core/ExportDescriptorPromiseTests.cs index 2883082f94a70..082eca388e478 100644 --- a/src/libraries/System.Composition.Hosting/tests/System/Composition/Hosting/Core/ExportDescriptorPromiseTests.cs +++ b/src/libraries/System.Composition.Hosting/tests/System/Composition/Hosting/Core/ExportDescriptorPromiseTests.cs @@ -252,7 +252,6 @@ public void GetDescriptor_CycleMetadataBroken_HasExpectedProperties() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50917", TestPlatforms.Android)] public void ToString_Invoke_ReturnsExpected() { var promise = new ExportDescriptorPromise(new CompositionContract(typeof(int)), "Origin", true, () => Enumerable.Empty(), depdendencies => diff --git a/src/libraries/System.Composition.Runtime/tests/System/Composition/Hosting/Core/CompositionContractTests.cs b/src/libraries/System.Composition.Runtime/tests/System/Composition/Hosting/Core/CompositionContractTests.cs index 04088a747177c..7784bad7ba48f 100644 --- a/src/libraries/System.Composition.Runtime/tests/System/Composition/Hosting/Core/CompositionContractTests.cs +++ b/src/libraries/System.Composition.Runtime/tests/System/Composition/Hosting/Core/CompositionContractTests.cs @@ -279,7 +279,6 @@ public static IEnumerable ToString_TestData() [Theory] [MemberData(nameof(ToString_TestData))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50918", TestPlatforms.Android)] public void ToString_Get_ReturnsExpected(CompositionContract contract, string expected) { Assert.Equal(expected, contract.ToString()); diff --git a/src/libraries/System.Composition/tests/CardinalityTests.cs b/src/libraries/System.Composition/tests/CardinalityTests.cs index 87723ebf69acb..149287cfa8721 100644 --- a/src/libraries/System.Composition/tests/CardinalityTests.cs +++ b/src/libraries/System.Composition/tests/CardinalityTests.cs @@ -31,7 +31,6 @@ public class UsesLog } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50919", TestPlatforms.Android)] public void RequestingOneWhereMultipleArePresentFails() { var c = CreateContainer(typeof(LogA), typeof(LogB)); @@ -42,7 +41,6 @@ public void RequestingOneWhereMultipleArePresentFails() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50919", TestPlatforms.Android)] public void ImportingOneWhereMultipleArePresentFails() { var c = CreateContainer(typeof(LogA), typeof(LogB), typeof(UsesLog)); diff --git a/src/libraries/System.Composition/tests/ContractTests.cs b/src/libraries/System.Composition/tests/ContractTests.cs index b0c3fbc46f631..746cd56641f37 100644 --- a/src/libraries/System.Composition/tests/ContractTests.cs +++ b/src/libraries/System.Composition/tests/ContractTests.cs @@ -67,7 +67,6 @@ public void ConstraintsWithEquivalentKeysAndValuesHaveTheSameHashCode() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50919", TestPlatforms.Android)] public void FormattingTheContractPrintsConstraintKeysAndValues() { var mcd = new CompositionContract(typeof(AType), null, new Dictionary { { "A", 1 }, { "B", "C" } }); diff --git a/src/libraries/System.Composition/tests/DiscoveryTests.cs b/src/libraries/System.Composition/tests/DiscoveryTests.cs index 8087e3d938436..833001774e4e0 100644 --- a/src/libraries/System.Composition/tests/DiscoveryTests.cs +++ b/src/libraries/System.Composition/tests/DiscoveryTests.cs @@ -56,7 +56,6 @@ public void DiscoversCustomExportAttributesUnderConventions() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50919", TestPlatforms.Android)] public void InstanceExportsOfIncompatibleContractsAreDetected() { var x = Assert.Throws(() => CreateContainer(typeof(IncompatibleRule))); @@ -64,7 +63,6 @@ public void InstanceExportsOfIncompatibleContractsAreDetected() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50919", TestPlatforms.Android)] public void PropertyExportsOfIncompatibleContractsAreDetected() { var x = Assert.Throws(() => CreateContainer(typeof(IncompatibleRuleProperty))); @@ -124,7 +122,6 @@ public class MultipleImportsOnProperty } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50919", TestPlatforms.Android)] public void MultipleImportAttributesAreDetected() { var c = new ContainerConfiguration() diff --git a/src/libraries/System.Composition/tests/ErrorMessageQualityTests.cs b/src/libraries/System.Composition/tests/ErrorMessageQualityTests.cs index f53e79612eb10..f0918e392c29c 100644 --- a/src/libraries/System.Composition/tests/ErrorMessageQualityTests.cs +++ b/src/libraries/System.Composition/tests/ErrorMessageQualityTests.cs @@ -63,7 +63,6 @@ public class RequiresOnlyOne } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50919", TestPlatforms.Android)] public void MissingTopLevelExportMessageIsInformative() { var cc = CreateContainer(); @@ -72,7 +71,6 @@ public void MissingTopLevelExportMessageIsInformative() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50919", TestPlatforms.Android)] public void MissingTopLevelNamedExportMessageIsInformative() { var cc = CreateContainer(); @@ -81,7 +79,6 @@ public void MissingTopLevelNamedExportMessageIsInformative() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50919", TestPlatforms.Android)] public void MissingDependencyMessageIsInformative() { var cc = CreateContainer(typeof(UserOfUnregistered)); @@ -92,7 +89,6 @@ public void MissingDependencyMessageIsInformative() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50919", TestPlatforms.Android)] public void CycleMessageIsInformative() { var cc = CreateContainer(typeof(CycleA), typeof(CycleB), typeof(CycleC)); @@ -106,7 +102,6 @@ public void CycleMessageIsInformative() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50919", TestPlatforms.Android)] public void CardinalityViolationMessageIsInformative() { var cc = CreateContainer(typeof(ShouldBeOne), typeof(ButThereIsAnother), typeof(RequiresOnlyOne)); diff --git a/src/libraries/System.Composition/tests/MetadataViewGenerationTests.cs b/src/libraries/System.Composition/tests/MetadataViewGenerationTests.cs index e2561e916ee05..9786a7db1ae4f 100644 --- a/src/libraries/System.Composition/tests/MetadataViewGenerationTests.cs +++ b/src/libraries/System.Composition/tests/MetadataViewGenerationTests.cs @@ -77,7 +77,6 @@ public class InvalidConcreteView } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50919", TestPlatforms.Android)] public void AConcreteTypeWithUnsupportedConstructorsCannotBeUsedAsAMetadataView() { var cc = new ContainerConfiguration() @@ -102,7 +101,6 @@ public class ImportsWithMetadataInterface } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50919", TestPlatforms.Android)] public void UnsupportedMetadataViewMessageIsInformative() { var cc = new ContainerConfiguration().WithParts(typeof(ImportsWithMetadataInterface), typeof(ExportsWithMetadata)).CreateContainer(); diff --git a/src/libraries/System.Composition/tests/OpenGenericsTests.cs b/src/libraries/System.Composition/tests/OpenGenericsTests.cs index 8462c5aa6f67f..a7eec57c15b09 100644 --- a/src/libraries/System.Composition/tests/OpenGenericsTests.cs +++ b/src/libraries/System.Composition/tests/OpenGenericsTests.cs @@ -123,7 +123,6 @@ public void MultipleGenericExportsCanBeSpecifiedAtTheClassLevel() // In future, the set of allowable generic type mappings will be expanded (see // ignored tests above). [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50919", TestPlatforms.Android)] public void TypesWithMismatchedGenericParameterListsAreDetectedDuringDiscovery() { var x = Assert.Throws(() => CreateContainer(typeof(RepositoryWithKey<,>))); @@ -131,7 +130,6 @@ public void TypesWithMismatchedGenericParameterListsAreDetectedDuringDiscovery() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50919", TestPlatforms.Android)] public void TypesWithNonGenericExportsAreDetectedDuringDiscovery() { var x = Assert.Throws(() => CreateContainer(typeof(RepositoryWithNonGenericExport<>))); diff --git a/src/libraries/System.Composition/tests/SharingTests.cs b/src/libraries/System.Composition/tests/SharingTests.cs index 22cd14fa41713..826881f349c5d 100644 --- a/src/libraries/System.Composition/tests/SharingTests.cs +++ b/src/libraries/System.Composition/tests/SharingTests.cs @@ -318,7 +318,6 @@ public class SharingTest : ContainerTests /// we fail only when we create instance of B.. is that correct. /// [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50919", TestPlatforms.Android)] public void BoundaryExposedBoundaryButNoneImported() { try diff --git a/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ClientConfigPaths.cs b/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ClientConfigPaths.cs index a92612ca0b0f4..747815c9f6ce9 100644 --- a/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ClientConfigPaths.cs +++ b/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ClientConfigPaths.cs @@ -31,6 +31,8 @@ internal sealed class ClientConfigPaths [UnconditionalSuppressMessage("SingleFile", "IL3000: Avoid accessing Assembly file path when publishing as a single file", Justification = "Code handles single file case")] + [UnconditionalSuppressMessage("SingleFile", "IL3002: RequiresAssemblyFiles on Module.Name", + Justification = "Code handles single file case")] private ClientConfigPaths(string exePath, bool includeUserConfig) { _includesUserConfig = includeUserConfig; @@ -222,6 +224,8 @@ private static string CombineIfValid(string path1, string path2) // The evidence we use, in priority order, is Strong Name, Url and Exe Path. If one of // these is found, we compute a SHA1 hash of it and return a suffix based on that. // If none is found, we return null. + [UnconditionalSuppressMessage("SingleFile", "IL3002: RequiresAssemblyFiles on Module.Name", + Justification = "Code handles single file case")] private static string GetTypeAndHashSuffix(string exePath, bool isSingleFile) { Assembly assembly = Assembly.GetEntryAssembly(); diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/tests/TestWithConfigSwitches/ActivityTests.cs b/src/libraries/System.Diagnostics.DiagnosticSource/tests/TestWithConfigSwitches/ActivityTests.cs index 5890e43abd37b..cb848a9c1cb40 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/tests/TestWithConfigSwitches/ActivityTests.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/tests/TestWithConfigSwitches/ActivityTests.cs @@ -6,8 +6,6 @@ namespace System.Diagnostics.Tests { - [ActiveIssue("https://github.com/dotnet/runtime/issues/37073", TestPlatforms.Android)] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51376", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public class ActivityTests : IDisposable { [Fact] diff --git a/src/libraries/System.Diagnostics.Process/tests/ProcessTests.cs b/src/libraries/System.Diagnostics.Process/tests/ProcessTests.cs index f275db05e48ee..e4f52b617096a 100644 --- a/src/libraries/System.Diagnostics.Process/tests/ProcessTests.cs +++ b/src/libraries/System.Diagnostics.Process/tests/ProcessTests.cs @@ -489,7 +489,7 @@ public void TestToString_OnExitedProcess() // Ensure ToString does not throw an exception, but still returns // a representation of the object. - Assert.Equal("System.Diagnostics.Process", p.ToString()); + Assert.Contains("System.Diagnostics.Process", p.ToString()); } [Fact] diff --git a/src/libraries/System.Drawing.Common/tests/GraphicsTests.cs b/src/libraries/System.Drawing.Common/tests/GraphicsTests.cs index ba8246641c6e2..8c0f280b86361 100644 --- a/src/libraries/System.Drawing.Common/tests/GraphicsTests.cs +++ b/src/libraries/System.Drawing.Common/tests/GraphicsTests.cs @@ -98,6 +98,7 @@ public static IEnumerable FromHdc_TestData() } [ActiveIssue("https://github.com/dotnet/runtime/issues/22221", TestPlatforms.AnyUnix)] + [ActiveIssue("https://github.com/dotnet/runtime/issues/51097", typeof(PlatformDetection), nameof(PlatformDetection.IsArm64Process), nameof(PlatformDetection.IsWindows10OrLater))] [ConditionalTheory(Helpers.IsDrawingSupported)] [MemberData(nameof(FromHdc_TestData))] public void FromHdc_ValidHdc_ReturnsExpected(IntPtr hdc) @@ -110,6 +111,7 @@ public void FromHdc_ValidHdc_ReturnsExpected(IntPtr hdc) } [ActiveIssue("https://github.com/dotnet/runtime/issues/22221", TestPlatforms.AnyUnix)] + [ActiveIssue("https://github.com/dotnet/runtime/issues/51097", typeof(PlatformDetection), nameof(PlatformDetection.IsArm64Process), nameof(PlatformDetection.IsWindows10OrLater))] [ConditionalTheory(Helpers.IsDrawingSupported)] [MemberData(nameof(FromHdc_TestData))] public void FromHdc_ValidHdcWithContext_ReturnsExpected(IntPtr hdc) @@ -122,6 +124,7 @@ public void FromHdc_ValidHdcWithContext_ReturnsExpected(IntPtr hdc) } [ActiveIssue("https://github.com/dotnet/runtime/issues/22221", TestPlatforms.AnyUnix)] + [ActiveIssue("https://github.com/dotnet/runtime/issues/51097", typeof(PlatformDetection), nameof(PlatformDetection.IsArm64Process), nameof(PlatformDetection.IsWindows10OrLater))] [ConditionalTheory(Helpers.IsDrawingSupported)] [MemberData(nameof(FromHdc_TestData))] public void FromHdcInternal_GetDC_ReturnsExpected(IntPtr hdc) @@ -258,6 +261,7 @@ public static IEnumerable Hwnd_TestData() } [ActiveIssue("https://github.com/dotnet/runtime/issues/22221", TestPlatforms.AnyUnix)] + [ActiveIssue("https://github.com/dotnet/runtime/issues/51097", typeof(PlatformDetection), nameof(PlatformDetection.IsArm64Process), nameof(PlatformDetection.IsWindows10OrLater))] [ConditionalTheory(Helpers.IsDrawingSupported)] [MemberData(nameof(Hwnd_TestData))] public void FromHwnd_ValidHwnd_ReturnsExpected(IntPtr hWnd) @@ -270,6 +274,7 @@ public void FromHwnd_ValidHwnd_ReturnsExpected(IntPtr hWnd) } [ActiveIssue("https://github.com/dotnet/runtime/issues/22221", TestPlatforms.AnyUnix)] + [ActiveIssue("https://github.com/dotnet/runtime/issues/51097", typeof(PlatformDetection), nameof(PlatformDetection.IsArm64Process), nameof(PlatformDetection.IsWindows10OrLater))] [ConditionalTheory(Helpers.IsDrawingSupported)] [MemberData(nameof(Hwnd_TestData))] public void FromHwndInternal_ValidHwnd_ReturnsExpected(IntPtr hWnd) diff --git a/src/libraries/System.Globalization/tests/CompareInfo/CompareInfoTests.LastIndexOf.cs b/src/libraries/System.Globalization/tests/CompareInfo/CompareInfoTests.LastIndexOf.cs index 060648e8185b2..a400dedbdca66 100644 --- a/src/libraries/System.Globalization/tests/CompareInfo/CompareInfoTests.LastIndexOf.cs +++ b/src/libraries/System.Globalization/tests/CompareInfo/CompareInfoTests.LastIndexOf.cs @@ -92,7 +92,13 @@ public static IEnumerable LastIndexOf_TestData() // ICU matches weightless characters at 1 index prior to the end of the string yield return new object[] { s_invariantCompare, "", "\u200d", 0, 0, CompareOptions.None, 0, 0 }; yield return new object[] { s_invariantCompare, "", "\u200d", -1, 0, CompareOptions.None, 0, 0 }; - yield return new object[] { s_invariantCompare, "hello", "\u200d", 4, 5, CompareOptions.IgnoreCase, useNls ? 5 : 4 , 0}; + yield return new object[] { s_invariantCompare, "hello", "\u200d", 4, 5, CompareOptions.IgnoreCase, 5, 0}; + yield return new object[] { s_invariantCompare, "hello", "\0", 4, 5, CompareOptions.None, useNls ? -1 : 5, 0}; + + yield return new object[] { s_invariantCompare, "A\u0303", "\u200d", 1, 2, CompareOptions.None, 2, 0}; // A + ̃ = Ã + yield return new object[] { s_invariantCompare, "A\u0303\u200D", "\u200d", 2, 3, CompareOptions.None, 3, 0}; // A + ̃ = Ã + yield return new object[] { s_invariantCompare, "\u0001F601", "\u200d", 1, 2, CompareOptions.None, 2, 0}; // \u0001F601 is GRINNING FACE WITH SMILING EYES surrogate character + yield return new object[] { s_invariantCompare, "AA\u200DA", "\u200d", 3, 4, CompareOptions.None, 4, 0}; // Ignore symbols yield return new object[] { s_invariantCompare, "More Test's", "Tests", 10, 11, CompareOptions.IgnoreSymbols, 5, 6 }; diff --git a/src/libraries/System.IO.FileSystem/tests/FileStream/ReadAsync.cs b/src/libraries/System.IO.FileSystem/tests/FileStream/ReadAsync.cs index da429bbad2187..e5b8ecdfab992 100644 --- a/src/libraries/System.IO.FileSystem/tests/FileStream/ReadAsync.cs +++ b/src/libraries/System.IO.FileSystem/tests/FileStream/ReadAsync.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Linq; +using System.Security.Cryptography; using System.Threading; using System.Threading.Tasks; using Xunit; @@ -92,6 +94,38 @@ public async Task ReadAsyncCanceledFile() } } } + + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] + [InlineData(FileShare.None, FileOptions.Asynchronous)] // FileShare.None: exclusive access + [InlineData(FileShare.ReadWrite, FileOptions.Asynchronous)] // FileShare.ReadWrite: others can write to the file, the length can't be cached + [InlineData(FileShare.None, FileOptions.None)] + [InlineData(FileShare.ReadWrite, FileOptions.None)] + public async Task IncompleteReadCantSetPositionBeyondEndOfFile(FileShare fileShare, FileOptions options) + { + const int fileSize = 10_000; + string filePath = GetTestFilePath(); + byte[] content = RandomNumberGenerator.GetBytes(fileSize); + File.WriteAllBytes(filePath, content); + + byte[][] buffers = Enumerable.Repeat(Enumerable.Repeat(byte.MaxValue, fileSize * 2).ToArray(), 10).ToArray(); + + using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, fileShare, bufferSize: 0, options)) + { + Task[] reads = buffers.Select(buffer => fs.ReadAsync(buffer, 0, buffer.Length)).ToArray(); + + // the reads were not awaited, it's an anti-pattern and Position can be (0, buffersLength) now: + Assert.InRange(fs.Position, 0, buffers.Sum(buffer => buffer.Length)); + + await Task.WhenAll(reads); + // but when they are finished, the first buffer should contain valid data: + Assert.Equal(fileSize, reads.First().Result); + AssertExtensions.SequenceEqual(content, buffers.First().AsSpan(0, fileSize)); + // and other reads should return 0: + Assert.All(reads.Skip(1), read => Assert.Equal(0, read.Result)); + // and the Position must be correct: + Assert.Equal(fileSize, fs.Position); + } + } } [ActiveIssue("https://github.com/dotnet/runtime/issues/34582", TestPlatforms.Windows, TargetFrameworkMonikers.Netcoreapp, TestRuntimes.Mono)] diff --git a/src/libraries/System.IO.Pipelines/tests/FlushAsyncCompletionTests.cs b/src/libraries/System.IO.Pipelines/tests/FlushAsyncCompletionTests.cs index 6169d1e05684b..5b56222f819e5 100644 --- a/src/libraries/System.IO.Pipelines/tests/FlushAsyncCompletionTests.cs +++ b/src/libraries/System.IO.Pipelines/tests/FlushAsyncCompletionTests.cs @@ -10,7 +10,6 @@ namespace System.IO.Pipelines.Tests public class FlushAsyncCompletionTests : PipeTest { [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50927", TestPlatforms.Android)] public void AwaitingFlushAsyncAwaitableTwiceCompletesReaderWithException() { async Task Await(ValueTask a) diff --git a/src/libraries/System.IO.Pipelines/tests/FlushAsyncTests.cs b/src/libraries/System.IO.Pipelines/tests/FlushAsyncTests.cs index fa3db4c91ae4d..afa1f318937a4 100644 --- a/src/libraries/System.IO.Pipelines/tests/FlushAsyncTests.cs +++ b/src/libraries/System.IO.Pipelines/tests/FlushAsyncTests.cs @@ -71,7 +71,6 @@ public async Task CallingFlushAsyncMultipleTimesAllowsFirstToComplete() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50927", TestPlatforms.Android)] public async Task DoubleFlushAsyncThrows() { Pipe.Writer.WriteEmpty(65); diff --git a/src/libraries/System.IO.Pipelines/tests/PipeReaderWriterFacts.cs b/src/libraries/System.IO.Pipelines/tests/PipeReaderWriterFacts.cs index dc4593bfeb0db..f4b41418a6afc 100644 --- a/src/libraries/System.IO.Pipelines/tests/PipeReaderWriterFacts.cs +++ b/src/libraries/System.IO.Pipelines/tests/PipeReaderWriterFacts.cs @@ -150,7 +150,6 @@ public async Task CompleteReaderAfterFlushWithoutAdvancingDoesNotThrow() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50927", TestPlatforms.Android)] public async Task AdvanceAfterCompleteThrows() { await _pipe.Writer.WriteAsync(new byte[1]); @@ -621,7 +620,6 @@ public async Task WritingDataMakesDataReadableViaPipeline() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50927", TestPlatforms.Android)] public async Task DoubleAsyncReadThrows() { ValueTask readTask1 = _pipe.Reader.ReadAsync(); @@ -658,7 +656,6 @@ public async Task CompleteAfterAdvanceCommits() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50927", TestPlatforms.Android)] public async Task AdvanceWithoutReadThrows() { await _pipe.Writer.WriteAsync(new byte[3]); diff --git a/src/libraries/System.IO.Pipelines/tests/ReadAsyncCompletionTests.cs b/src/libraries/System.IO.Pipelines/tests/ReadAsyncCompletionTests.cs index 2abc58534071c..f15da4024d67e 100644 --- a/src/libraries/System.IO.Pipelines/tests/ReadAsyncCompletionTests.cs +++ b/src/libraries/System.IO.Pipelines/tests/ReadAsyncCompletionTests.cs @@ -9,7 +9,6 @@ namespace System.IO.Pipelines.Tests public class ReadAsyncCompletionTests : PipeTest { [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50927", TestPlatforms.Android)] public void AwaitingReadAsyncAwaitableTwiceCompletesWriterWithException() { async Task Await(ValueTask a) diff --git a/src/libraries/System.Linq.Expressions/tests/Dynamic/InvokeMemberBindingTests.cs b/src/libraries/System.Linq.Expressions/tests/Dynamic/InvokeMemberBindingTests.cs index ee4962af5ff1c..a9a77a61e7f9d 100644 --- a/src/libraries/System.Linq.Expressions/tests/Dynamic/InvokeMemberBindingTests.cs +++ b/src/libraries/System.Linq.Expressions/tests/Dynamic/InvokeMemberBindingTests.cs @@ -245,7 +245,6 @@ public void NonIndexerParameterizedDirectAccess() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/37474", TestPlatforms.Android)] public void NonIndexerParameterizedGetterAndSetterIndexAccess() { dynamic d = GetObjectWithNonIndexerParameterProperty(true, true); @@ -256,7 +255,6 @@ public void NonIndexerParameterizedGetterAndSetterIndexAccess() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/37474", TestPlatforms.Android)] public void NonIndexerParameterizedGetterOnlyIndexAccess() { dynamic d = GetObjectWithNonIndexerParameterProperty(true, false); @@ -267,7 +265,6 @@ public void NonIndexerParameterizedGetterOnlyIndexAccess() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/37474", TestPlatforms.Android)] public void NonIndexerParameterizedSetterOnlyIndexAccess() { dynamic d = GetObjectWithNonIndexerParameterProperty(false, true); diff --git a/src/libraries/System.Memory/src/System/SequencePosition.cs b/src/libraries/System.Memory/src/System/SequencePosition.cs index 117131d0ad6d3..574fb767d4ed2 100644 --- a/src/libraries/System.Memory/src/System/SequencePosition.cs +++ b/src/libraries/System.Memory/src/System/SequencePosition.cs @@ -8,7 +8,7 @@ namespace System { /// /// Represents position in non-contiguous set of memory. - /// Properties of this type should not be interpreted by anything but the type that created it. + /// Parts of this type should not be interpreted by anything but the type that created it. /// public readonly struct SequencePosition : IEquatable { diff --git a/src/libraries/System.Memory/tests/MemoryMarshal/GetArrayDataReference.cs b/src/libraries/System.Memory/tests/MemoryMarshal/GetArrayDataReference.cs index c5ed1414d6a99..ea9ab62621363 100644 --- a/src/libraries/System.Memory/tests/MemoryMarshal/GetArrayDataReference.cs +++ b/src/libraries/System.Memory/tests/MemoryMarshal/GetArrayDataReference.cs @@ -11,7 +11,6 @@ namespace System.SpanTests public static partial class MemoryMarshalTests { [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/36885", TestPlatforms.tvOS)] public static void GetArrayDataReference_NullInput_ThrowsNullRef() { Assert.Throws(() => MemoryMarshal.GetArrayDataReference((object[])null)); diff --git a/src/libraries/System.Net.Mail/tests/Functional/LoggingTest.cs b/src/libraries/System.Net.Mail/tests/Functional/LoggingTest.cs index 95f952e663536..c4c9e801fd78c 100644 --- a/src/libraries/System.Net.Mail/tests/Functional/LoggingTest.cs +++ b/src/libraries/System.Net.Mail/tests/Functional/LoggingTest.cs @@ -13,7 +13,6 @@ namespace System.Net.Mail.Tests public class LoggingTest { [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50999", TestPlatforms.Android)] public void EventSource_ExistsWithCorrectId() { Type esType = typeof(SmtpClient).Assembly.GetType("System.Net.NetEventSource", throwOnError: true, ignoreCase: false); diff --git a/src/libraries/System.Net.Mail/tests/Functional/SmtpExceptionTest.cs b/src/libraries/System.Net.Mail/tests/Functional/SmtpExceptionTest.cs index a10bed3e1684f..d97d147413cf7 100644 --- a/src/libraries/System.Net.Mail/tests/Functional/SmtpExceptionTest.cs +++ b/src/libraries/System.Net.Mail/tests/Functional/SmtpExceptionTest.cs @@ -54,7 +54,6 @@ public void TestConstructorWithStatusCodeArgument() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50999", TestPlatforms.Android)] public void TestConstructorWithStringArgument() { string msg; @@ -92,7 +91,6 @@ public void TestConstructorWithStringArgument() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50999", TestPlatforms.Android)] public void TestConstructorWithStatusCodeAndStringArgument() { string msg; diff --git a/src/libraries/System.Net.NameResolution/tests/FunctionalTests/LoggingTest.cs b/src/libraries/System.Net.NameResolution/tests/FunctionalTests/LoggingTest.cs index e4d4fcc9aa6a4..915067acffbbf 100644 --- a/src/libraries/System.Net.NameResolution/tests/FunctionalTests/LoggingTest.cs +++ b/src/libraries/System.Net.NameResolution/tests/FunctionalTests/LoggingTest.cs @@ -17,7 +17,6 @@ namespace System.Net.NameResolution.Tests public class LoggingTest { [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50928", TestPlatforms.Android)] public static void EventSource_ExistsWithCorrectId() { Type esType = typeof(Dns).Assembly.GetType("System.Net.NetEventSource", throwOnError: true, ignoreCase: false); @@ -30,7 +29,6 @@ public static void EventSource_ExistsWithCorrectId() } [ConditionalFact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50928", TestPlatforms.Android)] public void GetHostEntry_InvalidHost_LogsError() { using (var listener = new TestEventListener("Private.InternalDiagnostics.System.Net.NameResolution", EventLevel.Error)) @@ -65,7 +63,6 @@ public void GetHostEntry_InvalidHost_LogsError() } [ConditionalFact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50928", TestPlatforms.Android)] public async Task GetHostEntryAsync_InvalidHost_LogsError() { using (var listener = new TestEventListener("Private.InternalDiagnostics.System.Net.NameResolution", EventLevel.Error)) @@ -115,7 +112,6 @@ static async Task WaitForErrorEventAsync(ConcurrentQueue } [ConditionalFact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50928", TestPlatforms.Android)] public void GetHostEntry_ValidName_NoErrors() { using (var listener = new TestEventListener("Private.InternalDiagnostics.System.Net.NameResolution", EventLevel.Verbose)) diff --git a/src/libraries/System.Net.NameResolution/tests/FunctionalTests/TelemetryTest.cs b/src/libraries/System.Net.NameResolution/tests/FunctionalTests/TelemetryTest.cs index a3ee6418d903b..55d0e3ac08f36 100644 --- a/src/libraries/System.Net.NameResolution/tests/FunctionalTests/TelemetryTest.cs +++ b/src/libraries/System.Net.NameResolution/tests/FunctionalTests/TelemetryTest.cs @@ -17,7 +17,6 @@ namespace System.Net.NameResolution.Tests public class TelemetryTest { [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50928", TestPlatforms.Android)] public static void EventSource_ExistsWithCorrectId() { Type esType = typeof(Dns).Assembly.GetType("System.Net.NameResolutionTelemetry", throwOnError: true, ignoreCase: false); diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/MsQuicConnection.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/MsQuicConnection.cs index d909514ea0f82..82638fc605f6b 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/MsQuicConnection.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/MsQuicConnection.cs @@ -150,6 +150,7 @@ public MsQuicConnection(IPEndPoint localEndPoint, IPEndPoint remoteEndPoint, Saf try { + Debug.Assert(!Monitor.IsEntered(_state)); MsQuicApi.Api.SetCallbackHandlerDelegate( _state.Handle, s_connectionDelegate, @@ -184,6 +185,7 @@ public MsQuicConnection(QuicClientConnectionOptions options) _state.StateGCHandle = GCHandle.Alloc(_state); try { + Debug.Assert(!Monitor.IsEntered(_state)); uint status = MsQuicApi.Api.ConnectionOpenDelegate( MsQuicApi.Api.Registration, s_connectionDelegate, @@ -220,7 +222,7 @@ private static uint HandleEventConnected(State state, ref ConnectionEvent connec if (!state.Connected) { // Connected will already be true for connections accepted from a listener. - + Debug.Assert(!Monitor.IsEntered(state)); SOCKADDR_INET inetAddress = MsQuicParameterHelpers.GetINetParam(MsQuicApi.Api, state.Handle, QUIC_PARAM_LEVEL.CONNECTION, (uint)QUIC_PARAM_CONN.LOCAL_ADDRESS); Debug.Assert(state.Connection != null); @@ -459,6 +461,10 @@ internal override ValueTask WaitForAvailableUnidirectionalStreamsAsync(Cancellat TaskCompletionSource? tcs = _state.NewUnidirectionalStreamsAvailable; if (tcs is null) { + // We need to avoid calling MsQuic under lock. + // This is not atomic but it won't be anyway as counts can change between when task is completed + // and before somebody may try to allocate new stream. + int count = GetRemoteAvailableUnidirectionalStreamCount(); lock (_state) { if (_state.NewUnidirectionalStreamsAvailable is null) @@ -468,13 +474,14 @@ internal override ValueTask WaitForAvailableUnidirectionalStreamsAsync(Cancellat throw new QuicOperationAbortedException(); } - if (GetRemoteAvailableUnidirectionalStreamCount() > 0) + if (count > 0) { return ValueTask.CompletedTask; } _state.NewUnidirectionalStreamsAvailable = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); } + tcs = _state.NewUnidirectionalStreamsAvailable; } } @@ -487,6 +494,10 @@ internal override ValueTask WaitForAvailableBidirectionalStreamsAsync(Cancellati TaskCompletionSource? tcs = _state.NewBidirectionalStreamsAvailable; if (tcs is null) { + // We need to avoid calling MsQuic under lock. + // This is not atomic but it won't be anyway as counts can change between when task is completed + // and before somebody may try to allocate new stream. + int count = GetRemoteAvailableBidirectionalStreamCount(); lock (_state) { if (_state.NewBidirectionalStreamsAvailable is null) @@ -496,7 +507,7 @@ internal override ValueTask WaitForAvailableBidirectionalStreamsAsync(Cancellati throw new QuicOperationAbortedException(); } - if (GetRemoteAvailableBidirectionalStreamCount() > 0) + if (count > 0) { return ValueTask.CompletedTask; } @@ -526,11 +537,13 @@ internal override QuicStreamProvider OpenBidirectionalStream() internal override int GetRemoteAvailableUnidirectionalStreamCount() { + Debug.Assert(!Monitor.IsEntered(_state)); return MsQuicParameterHelpers.GetUShortParam(MsQuicApi.Api, _state.Handle, QUIC_PARAM_LEVEL.CONNECTION, (uint)QUIC_PARAM_CONN.LOCAL_UNIDI_STREAM_COUNT); } internal override int GetRemoteAvailableBidirectionalStreamCount() { + Debug.Assert(!Monitor.IsEntered(_state)); return MsQuicParameterHelpers.GetUShortParam(MsQuicApi.Api, _state.Handle, QUIC_PARAM_LEVEL.CONNECTION, (uint)QUIC_PARAM_CONN.LOCAL_BIDI_STREAM_COUNT); } @@ -563,6 +576,7 @@ internal override ValueTask ConnectAsync(CancellationToken cancellationToken = d SOCKADDR_INET address = MsQuicAddressHelpers.IPEndPointToINet((IPEndPoint)_remoteEndPoint); unsafe { + Debug.Assert(!Monitor.IsEntered(_state)); status = MsQuicApi.Api.SetParamDelegate(_state.Handle, QUIC_PARAM_LEVEL.CONNECTION, (uint)QUIC_PARAM_CONN.REMOTE_ADDRESS, (uint)sizeof(SOCKADDR_INET), (byte*)&address); QuicExceptionHelpers.ThrowIfFailed(status, "Failed to connect to peer."); } @@ -587,6 +601,7 @@ internal override ValueTask ConnectAsync(CancellationToken cancellationToken = d try { + Debug.Assert(!Monitor.IsEntered(_state)); status = MsQuicApi.Api.ConnectionStartDelegate( _state.Handle, _configuration, @@ -620,6 +635,7 @@ internal override ValueTask ConnectAsync(CancellationToken cancellationToken = d try { + Debug.Assert(!Monitor.IsEntered(_state)); MsQuicApi.Api.ConnectionShutdownDelegate( _state.Handle, Flags, @@ -747,6 +763,7 @@ private void Dispose(bool disposing) if (_state.Handle != null) { // Handle can be null if outbound constructor failed and we are called from finalizer. + Debug.Assert(!Monitor.IsEntered(_state)); MsQuicApi.Api.ConnectionShutdownDelegate( _state.Handle, QUIC_CONNECTION_SHUTDOWN_FLAGS.SILENT, diff --git a/src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.OverlappedValueTaskSource.Windows.cs b/src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.OverlappedValueTaskSource.Windows.cs index 367184e9a455e..26e17f1d161d8 100644 --- a/src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.OverlappedValueTaskSource.Windows.cs +++ b/src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.OverlappedValueTaskSource.Windows.cs @@ -5,6 +5,7 @@ using System.Buffers; using System.Diagnostics; using System.IO; +using System.IO.Strategies; using System.Threading; using System.Threading.Tasks.Sources; @@ -45,7 +46,9 @@ internal sealed unsafe class OverlappedValueTaskSource : IValueTaskSource, internal readonly PreAllocatedOverlapped _preallocatedOverlapped; internal readonly SafeFileHandle _fileHandle; + private AsyncWindowsFileStreamStrategy? _strategy; internal MemoryHandle _memoryHandle; + private int _bufferSize; internal ManualResetValueTaskSourceCore _source; // mutable struct; do not make this readonly private NativeOverlapped* _overlapped; private CancellationTokenRegistration _cancellationRegistration; @@ -74,9 +77,11 @@ internal static Exception GetIOError(int errorCode, string? path) ? ThrowHelper.CreateEndOfFileException() : Win32Marshal.GetExceptionForWin32Error(errorCode, path); - internal NativeOverlapped* PrepareForOperation(ReadOnlyMemory memory, long fileOffset) + internal NativeOverlapped* PrepareForOperation(ReadOnlyMemory memory, long fileOffset, AsyncWindowsFileStreamStrategy? strategy = null) { _result = 0; + _strategy = strategy; + _bufferSize = memory.Length; _memoryHandle = memory.Pin(); _overlapped = _fileHandle.ThreadPoolBinding!.AllocateNativeOverlapped(_preallocatedOverlapped); _overlapped->OffsetLow = (int)fileOffset; @@ -132,8 +137,9 @@ internal void RegisterForCancellation(CancellationToken cancellationToken) } } - internal void ReleaseResources() + private void ReleaseResources() { + _strategy = null; // Unpin any pinned buffer. _memoryHandle.Dispose(); @@ -187,11 +193,19 @@ private static void IOCallback(uint errorCode, uint numBytes, NativeOverlapped* internal void Complete(uint errorCode, uint numBytes) { + Debug.Assert(errorCode == Interop.Errors.ERROR_SUCCESS || numBytes == 0, $"Callback returned {errorCode} error and {numBytes} bytes"); + + AsyncWindowsFileStreamStrategy? strategy = _strategy; ReleaseResources(); + if (strategy is not null && _bufferSize != numBytes) // true only for incomplete reads + { + strategy.OnIncompleteRead(_bufferSize, (int)numBytes); + } + switch (errorCode) { - case 0: + case Interop.Errors.ERROR_SUCCESS: case Interop.Errors.ERROR_BROKEN_PIPE: case Interop.Errors.ERROR_NO_DATA: case Interop.Errors.ERROR_HANDLE_EOF: // logically success with 0 bytes read (read at end of file) diff --git a/src/libraries/System.Private.CoreLib/src/System/Buffers/TlsOverPerCoreLockedStacksArrayPool.cs b/src/libraries/System.Private.CoreLib/src/System/Buffers/TlsOverPerCoreLockedStacksArrayPool.cs index fd4d242463c32..d38bda960e752 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Buffers/TlsOverPerCoreLockedStacksArrayPool.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Buffers/TlsOverPerCoreLockedStacksArrayPool.cs @@ -21,12 +21,6 @@ namespace System.Buffers /// internal sealed partial class TlsOverPerCoreLockedStacksArrayPool : ArrayPool { - // TODO https://github.com/dotnet/coreclr/pull/7747: "Investigate optimizing ArrayPool heuristics" - // - Explore caching in TLS more than one array per size per thread, and moving stale buffers to the global queue. - // - Explore changing the size of each per-core bucket, potentially dynamically or based on other factors like array size. - // - Investigate whether false sharing is causing any issues, in particular on LockedStack's count and the contents of its array. - // ... - /// The number of buckets (array sizes) in the pool, one for each array length, starting from length 16. private const int NumBuckets = 27; // Utilities.SelectBucketIndex(1024 * 1024 * 1024 + 1) /// Maximum number of per-core stacks to use per array size. @@ -36,9 +30,9 @@ internal sealed partial class TlsOverPerCoreLockedStacksArrayPool : ArrayPool /// A per-thread array of arrays, to cache one array per array size per thread. [ThreadStatic] - private static T[]?[]? t_tlsBuckets; + private static ThreadLocalArray[]? t_tlsBuckets; /// Used to keep track of all thread local buckets for trimming if needed. - private readonly ConditionalWeakTable _allTlsBuckets = new ConditionalWeakTable(); + private readonly ConditionalWeakTable _allTlsBuckets = new ConditionalWeakTable(); /// /// An array of per-core array stacks. The slots are lazily initialized to avoid creating /// lots of overhead for unused array sizes. @@ -67,13 +61,13 @@ public override T[] Rent(int minimumLength) int bucketIndex = Utilities.SelectBucketIndex(minimumLength); // First, try to get an array from TLS if possible. - T[]?[]? tlsBuckets = t_tlsBuckets; + ThreadLocalArray[]? tlsBuckets = t_tlsBuckets; if (tlsBuckets is not null && (uint)bucketIndex < (uint)tlsBuckets.Length) { - buffer = tlsBuckets[bucketIndex]; + buffer = tlsBuckets[bucketIndex].Array; if (buffer is not null) { - tlsBuckets[bucketIndex] = null; + tlsBuckets[bucketIndex].Array = null; if (log.IsEnabled()) { log.BufferRented(buffer.GetHashCode(), buffer.Length, Id, bucketIndex); @@ -143,7 +137,7 @@ public override void Return(T[] array, bool clearArray = false) // this if the array being returned is erroneous or too large for the pool, but the // former condition is an error we don't need to optimize for, and the latter is incredibly // rare, given a max size of 1B elements. - T[]?[] tlsBuckets = t_tlsBuckets ?? InitializeTlsBucketsAndTrimming(); + ThreadLocalArray[] tlsBuckets = t_tlsBuckets ?? InitializeTlsBucketsAndTrimming(); bool haveBucket = false; bool returned = true; @@ -166,8 +160,9 @@ public override void Return(T[] array, bool clearArray = false) // Store the array into the TLS bucket. If there's already an array in it, // push that array down into the per-core stacks, preferring to keep the latest // one in TLS for better locality. - T[]? prev = tlsBuckets[bucketIndex]; - tlsBuckets[bucketIndex] = array; + ref ThreadLocalArray tla = ref tlsBuckets[bucketIndex]; + T[]? prev = tla.Array; + tla = new ThreadLocalArray(array); if (prev is not null) { PerCoreLockedStacks stackBucket = _buckets[bucketIndex] ?? CreatePerCoreLockedStacks(bucketIndex); @@ -191,58 +186,110 @@ public override void Return(T[] array, bool clearArray = false) public bool Trim() { - int milliseconds = Environment.TickCount; + int currentMilliseconds = Environment.TickCount; Utilities.MemoryPressure pressure = Utilities.GetMemoryPressure(); + // Log that we're trimming. ArrayPoolEventSource log = ArrayPoolEventSource.Log; if (log.IsEnabled()) { - log.BufferTrimPoll(milliseconds, (int)pressure); + log.BufferTrimPoll(currentMilliseconds, (int)pressure); } + // Trim each of the per-core buckets. PerCoreLockedStacks?[] perCoreBuckets = _buckets; for (int i = 0; i < perCoreBuckets.Length; i++) { - perCoreBuckets[i]?.Trim((uint)milliseconds, Id, pressure, Utilities.GetMaxSizeForBucket(i)); + perCoreBuckets[i]?.Trim(currentMilliseconds, Id, pressure, Utilities.GetMaxSizeForBucket(i)); } + // Trim each of the TLS buckets. Note that threads may be modifying their TLS slots concurrently with + // this trimming happening. We do not force synchronization with those operations, so we accept the fact + // that we may end up firing a trimming event even if an array wasn't trimmed, and potentially + // trim an array we didn't need to. Both of these should be rare occurrences. + + // Under high pressure, release all thread locals. if (pressure == Utilities.MemoryPressure.High) { - // Under high pressure, release all thread locals +#if !MONO // TODO https://github.com/mono/linker/issues/2181: Remove !MONO ifdefs in this method once is fixed if (log.IsEnabled()) { - foreach (KeyValuePair tlsBuckets in _allTlsBuckets) + foreach (KeyValuePair tlsBuckets in _allTlsBuckets) { - T[]?[] buckets = tlsBuckets.Key; + ThreadLocalArray[] buckets = tlsBuckets.Key; for (int i = 0; i < buckets.Length; i++) { - T[]? buffer = Interlocked.Exchange(ref buckets[i], null); - if (buffer is not null) + if (Interlocked.Exchange(ref buckets[i].Array, null) is T[] buffer) { - // As we don't want to take a perf hit in the rent path it - // is possible that a buffer could be rented as we "free" it. log.BufferTrimmed(buffer.GetHashCode(), buffer.Length, Id); } } } } else +#endif { - foreach (KeyValuePair tlsBuckets in _allTlsBuckets) + foreach (KeyValuePair tlsBuckets in _allTlsBuckets) { Array.Clear(tlsBuckets.Key); } } } + else + { + // Otherwise, release thread locals based on how long we've observed them to be stored. This time is + // approximate, with the time set not when the array is stored but when we see it during a Trim, so it + // takes at least two Trim calls (and thus two gen2 GCs) to drop an array, unless we're in high memory + // pressure. These values have been set arbitrarily; we could tune them in the future. + uint millisecondsThreshold = pressure switch + { + Utilities.MemoryPressure.Medium => 15_000, + _ => 30_000, + }; + + foreach (KeyValuePair tlsBuckets in _allTlsBuckets) + { + ThreadLocalArray[] buckets = tlsBuckets.Key; + for (int i = 0; i < buckets.Length; i++) + { + if (buckets[i].Array is null) + { + continue; + } + + // We treat 0 to mean it hasn't yet been seen in a Trim call. In the very rare case where Trim records 0, + // it'll take an extra Trim call to remove the array. + int lastSeen = buckets[i].MillisecondsTimeStamp; + if (lastSeen == 0) + { + buckets[i].MillisecondsTimeStamp = currentMilliseconds; + } + else if ((currentMilliseconds - lastSeen) >= millisecondsThreshold) + { + // Time noticeably wrapped, or we've surpassed the threshold. + // Clear out the array, and log its being trimmed if desired. + if (Interlocked.Exchange(ref buckets[i].Array, null) is T[] buffer) + { +#if !MONO + if (log.IsEnabled()) + { + log.BufferTrimmed(buffer.GetHashCode(), buffer.Length, Id); + } +#endif + } + } + } + } + } return true; } - private T[]?[] InitializeTlsBucketsAndTrimming() + private ThreadLocalArray[] InitializeTlsBucketsAndTrimming() { - Debug.Assert(t_tlsBuckets is null); + Debug.Assert(t_tlsBuckets is null, $"Non-null {nameof(t_tlsBuckets)}"); - T[]?[]? tlsBuckets = new T[NumBuckets][]; + var tlsBuckets = new ThreadLocalArray[NumBuckets]; t_tlsBuckets = tlsBuckets; _allTlsBuckets.Add(tlsBuckets, null); @@ -307,12 +354,12 @@ public bool TryPush(T[] array) return null; } - public void Trim(uint tickCount, int id, Utilities.MemoryPressure pressure, int bucketSize) + public void Trim(int currentMilliseconds, int id, Utilities.MemoryPressure pressure, int bucketSize) { LockedStack[] stacks = _perCoreStacks; for (int i = 0; i < stacks.Length; i++) { - stacks[i].Trim(tickCount, id, pressure, bucketSize); + stacks[i].Trim(currentMilliseconds, id, pressure, bucketSize); } } } @@ -320,9 +367,12 @@ public void Trim(uint tickCount, int id, Utilities.MemoryPressure pressure, int /// Provides a simple, bounded stack of arrays, protected by a lock. private sealed class LockedStack { + /// The arrays in the stack. private readonly T[]?[] _arrays = new T[MaxBuffersPerArraySizePerCore][]; + /// Number of arrays stored in . private int _count; - private uint _firstStackItemMS; + /// Timestamp set by Trim when it sees this as 0. + private int _millisecondsTimestamp; [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool TryPush(T[] array) @@ -335,8 +385,9 @@ public bool TryPush(T[] array) { if (count == 0) { - // Stash the time the bottom of the stack was filled - _firstStackItemMS = (uint)Environment.TickCount; + // Reset the time stamp now that we're transitioning from empty to non-empty. + // Trim will see this as 0 and initialize it to the current time when Trim is called. + _millisecondsTimestamp = 0; } arrays[count] = array; @@ -364,11 +415,10 @@ public bool TryPush(T[] array) return arr; } - public void Trim(uint tickCount, int id, Utilities.MemoryPressure pressure, int bucketSize) + public void Trim(int currentMilliseconds, int id, Utilities.MemoryPressure pressure, int bucketSize) { - const uint StackTrimAfterMS = 60 * 1000; // Trim after 60 seconds for low/moderate pressure - const uint StackHighTrimAfterMS = 10 * 1000; // Trim after 10 seconds for high pressure - const uint StackRefreshMS = StackTrimAfterMS / 4; // Time bump after trimming (1/4 trim time) + const int StackTrimAfterMS = 60 * 1000; // Trim after 60 seconds for low/moderate pressure + const int StackHighTrimAfterMS = 10 * 1000; // Trim after 10 seconds for high pressure const int StackLowTrimCount = 1; // Trim one item when pressure is low const int StackMediumTrimCount = 2; // Trim two items when pressure is moderate const int StackHighTrimCount = MaxBuffersPerArraySizePerCore; // Trim all items when pressure is high @@ -381,63 +431,88 @@ public void Trim(uint tickCount, int id, Utilities.MemoryPressure pressure, int return; } - uint trimTicks = pressure == Utilities.MemoryPressure.High ? StackHighTrimAfterMS : StackTrimAfterMS; + int trimMilliseconds = pressure == Utilities.MemoryPressure.High ? StackHighTrimAfterMS : StackTrimAfterMS; lock (this) { - if (_count > 0 && _firstStackItemMS > tickCount || (tickCount - _firstStackItemMS) > trimTicks) + if (_count == 0) { - // We've wrapped the tick count or elapsed enough time since the - // first item went into the stack. Drop the top item so it can - // be collected and make the stack look a little newer. + return; + } - ArrayPoolEventSource log = ArrayPoolEventSource.Log; - int trimCount = StackLowTrimCount; - switch (pressure) - { - case Utilities.MemoryPressure.High: - trimCount = StackHighTrimCount; + if (_millisecondsTimestamp == 0) + { + _millisecondsTimestamp = currentMilliseconds; + return; + } - // When pressure is high, aggressively trim larger arrays. - if (bucketSize > StackLargeBucket) - { - trimCount++; - } - if (Unsafe.SizeOf() > StackModerateTypeSize) - { - trimCount++; - } - if (Unsafe.SizeOf() > StackLargeTypeSize) - { - trimCount++; - } - break; + if ((currentMilliseconds - _millisecondsTimestamp) <= trimMilliseconds) + { + return; + } - case Utilities.MemoryPressure.Medium: - trimCount = StackMediumTrimCount; - break; - } + // We've elapsed enough time since the first item went into the stack. + // Drop the top item so it can be collected and make the stack look a little newer. - while (_count > 0 && trimCount-- > 0) - { - T[]? array = _arrays[--_count]; - Debug.Assert(array is not null, "No nulls should have been present in slots < _count."); - _arrays[_count] = null; + ArrayPoolEventSource log = ArrayPoolEventSource.Log; + int trimCount = StackLowTrimCount; + switch (pressure) + { + case Utilities.MemoryPressure.High: + trimCount = StackHighTrimCount; - if (log.IsEnabled()) + // When pressure is high, aggressively trim larger arrays. + if (bucketSize > StackLargeBucket) { - log.BufferTrimmed(array.GetHashCode(), array.Length, id); + trimCount++; } - } + if (Unsafe.SizeOf() > StackModerateTypeSize) + { + trimCount++; + } + if (Unsafe.SizeOf() > StackLargeTypeSize) + { + trimCount++; + } + break; + + case Utilities.MemoryPressure.Medium: + trimCount = StackMediumTrimCount; + break; + } - if (_count > 0 && _firstStackItemMS < uint.MaxValue - StackRefreshMS) + while (_count > 0 && trimCount-- > 0) + { + T[]? array = _arrays[--_count]; + Debug.Assert(array is not null, "No nulls should have been present in slots < _count."); + _arrays[_count] = null; + + if (log.IsEnabled()) { - // Give the remaining items a bit more time - _firstStackItemMS += StackRefreshMS; + log.BufferTrimmed(array.GetHashCode(), array.Length, id); } } + + _millisecondsTimestamp = _count > 0 ? + _millisecondsTimestamp + (trimMilliseconds / 4) : // Give the remaining items a bit more time + 0; } } } + + /// Wrapper for arrays stored in ThreadStatic buckets. + private struct ThreadLocalArray + { + /// The stored array. + public T[]? Array; + /// Environment.TickCount timestamp for when this array was observed by Trim. + public int MillisecondsTimeStamp; + + public ThreadLocalArray(T[] array) + { + Array = array; + MillisecondsTimeStamp = 0; + } + } } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/GlobalizationMode.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/GlobalizationMode.Unix.cs index 2cc6fd74b8201..dc5a71d3935a5 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/GlobalizationMode.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/GlobalizationMode.Unix.cs @@ -8,12 +8,15 @@ internal static partial class GlobalizationMode private static partial class Settings { /// - /// Load ICU (when not in Invariant mode) in a static cctor to ensure it is loaded early in the process. - /// Other places, e.g. CompareInfo.GetSortKey, rely on ICU already being loaded before they are called. + /// Load ICU (when not in Invariant mode) in a static cctor to ensure it is loaded as side-effect of + /// the GlobalizationMode.Invariant check. Globalization P/Invokes, e.g. in CompareInfo.GetSortKey, + /// rely on ICU already being loaded before they are called. /// static Settings() { - if (!Invariant) + // Use GlobalizationMode.Invariant to allow ICU initialization to be trimmed when Invariant=true + // and PredefinedCulturesOnly is unspecified. + if (!GlobalizationMode.Invariant) { if (TryGetAppLocalIcuSwitchValue(out string? icuSuffixAndVersion)) { diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/GlobalizationMode.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/GlobalizationMode.cs index d611ea2b5e13f..4f69f98015041 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/GlobalizationMode.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/GlobalizationMode.cs @@ -8,11 +8,12 @@ namespace System.Globalization { internal static partial class GlobalizationMode { - // split from GlobalizationMode so the whole class can be trimmed when Invariant=true. + // Split from GlobalizationMode so the whole class can be trimmed when Invariant=true. Trimming tests + // validate this implementation detail. private static partial class Settings { internal static bool Invariant { get; } = AppContextConfigHelper.GetBooleanConfig("System.Globalization.Invariant", "DOTNET_SYSTEM_GLOBALIZATION_INVARIANT"); - internal static bool PredefinedCulturesOnly { get; } = AppContextConfigHelper.GetBooleanConfig("System.Globalization.PredefinedCulturesOnly", "DOTNET_SYSTEM_GLOBALIZATION_PREDEFINED_CULTURES_ONLY", Invariant); + internal static bool PredefinedCulturesOnly { get; } = AppContextConfigHelper.GetBooleanConfig("System.Globalization.PredefinedCulturesOnly", "DOTNET_SYSTEM_GLOBALIZATION_PREDEFINED_CULTURES_ONLY", GlobalizationMode.Invariant); } // Note: Invariant=true and Invariant=false are substituted at different levels in the ILLink.Substitutions file. @@ -20,6 +21,7 @@ private static partial class Settings // static cctor (on Unix) to be preserved when Invariant=false. internal static bool Invariant => Settings.Invariant; internal static bool PredefinedCulturesOnly => Settings.PredefinedCulturesOnly; + private static bool TryGetAppLocalIcuSwitchValue([NotNullWhen(true)] out string? value) => TryGetStringValue("System.Globalization.AppLocalIcu", "DOTNET_SYSTEM_GLOBALIZATION_APPLOCALICU", out value); private static bool TryGetStringValue(string switchName, string envVariable, [NotNullWhen(true)] out string? value) diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/FileStream.cs b/src/libraries/System.Private.CoreLib/src/System/IO/FileStream.cs index a2be26fa23103..6a94ad202fa19 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/FileStream.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/FileStream.cs @@ -280,9 +280,14 @@ public override Task ReadAsync(byte[] buffer, int offset, int count, Cancel { return Task.FromCanceled(cancellationToken); } - else if (_strategy.IsClosed) + else if (!_strategy.CanRead) { - ThrowHelper.ThrowObjectDisposedException_FileClosed(); + if (_strategy.IsClosed) + { + ThrowHelper.ThrowObjectDisposedException_FileClosed(); + } + + ThrowHelper.ThrowNotSupportedException_UnreadableStream(); } return _strategy.ReadAsync(buffer, offset, count, cancellationToken); @@ -294,9 +299,14 @@ public override ValueTask ReadAsync(Memory buffer, CancellationToken { return ValueTask.FromCanceled(cancellationToken); } - else if (_strategy.IsClosed) + else if (!_strategy.CanRead) { - ThrowHelper.ThrowObjectDisposedException_FileClosed(); + if (_strategy.IsClosed) + { + ThrowHelper.ThrowObjectDisposedException_FileClosed(); + } + + ThrowHelper.ThrowNotSupportedException_UnreadableStream(); } return _strategy.ReadAsync(buffer, cancellationToken); @@ -319,9 +329,14 @@ public override Task WriteAsync(byte[] buffer, int offset, int count, Cancellati { return Task.FromCanceled(cancellationToken); } - else if (_strategy.IsClosed) + else if (!_strategy.CanWrite) { - ThrowHelper.ThrowObjectDisposedException_FileClosed(); + if (_strategy.IsClosed) + { + ThrowHelper.ThrowObjectDisposedException_FileClosed(); + } + + ThrowHelper.ThrowNotSupportedException_UnwritableStream(); } return _strategy.WriteAsync(buffer, offset, count, cancellationToken); @@ -333,9 +348,14 @@ public override ValueTask WriteAsync(ReadOnlyMemory buffer, CancellationTo { return ValueTask.FromCanceled(cancellationToken); } - else if (_strategy.IsClosed) + else if (!_strategy.CanWrite) { - ThrowHelper.ThrowObjectDisposedException_FileClosed(); + if (_strategy.IsClosed) + { + ThrowHelper.ThrowObjectDisposedException_FileClosed(); + } + + ThrowHelper.ThrowNotSupportedException_UnwritableStream(); } return _strategy.WriteAsync(buffer, cancellationToken); diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/RandomAccess.Windows.cs b/src/libraries/System.Private.CoreLib/src/System/IO/RandomAccess.Windows.cs index 8711ce23e9d2c..09f7a69552ef2 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/RandomAccess.Windows.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/RandomAccess.Windows.cs @@ -242,21 +242,23 @@ internal static ValueTask ReadAtOffsetAsync(SafeFileHandle handle, Memory buffer, long fileOffset, CancellationToken cancellationToken) + internal static unsafe (SafeFileHandle.OverlappedValueTaskSource? vts, int errorCode) QueueAsyncReadFile(SafeFileHandle handle, Memory buffer, long fileOffset, + CancellationToken cancellationToken, AsyncWindowsFileStreamStrategy? strategy = null) { handle.EnsureThreadPoolBindingInitialized(); SafeFileHandle.OverlappedValueTaskSource vts = handle.GetOverlappedValueTaskSource(); + int errorCode = 0; try { - NativeOverlapped* nativeOverlapped = vts.PrepareForOperation(buffer, fileOffset); + NativeOverlapped* nativeOverlapped = vts.PrepareForOperation(buffer, fileOffset, strategy); Debug.Assert(vts._memoryHandle.Pointer != null); // Queue an async ReadFile operation. if (Interop.Kernel32.ReadFile(handle, (byte*)vts._memoryHandle.Pointer, buffer.Length, IntPtr.Zero, nativeOverlapped) == 0) { // The operation failed, or it's pending. - int errorCode = FileStreamHelpers.GetLastWin32ErrorAndDisposeHandleIfInvalid(handle); + errorCode = FileStreamHelpers.GetLastWin32ErrorAndDisposeHandleIfInvalid(handle); switch (errorCode) { case Interop.Errors.ERROR_IO_PENDING: @@ -286,6 +288,13 @@ internal static unsafe (SafeFileHandle.OverlappedValueTaskSource? vts, int error vts.Dispose(); throw; } + finally + { + if (errorCode != Interop.Errors.ERROR_IO_PENDING && errorCode != Interop.Errors.ERROR_SUCCESS) + { + strategy?.OnIncompleteRead(buffer.Length, 0); + } + } // Completion handled by callback. vts.FinishedScheduling(); @@ -686,8 +695,11 @@ private static NativeOverlapped GetNativeOverlappedForSyncHandle(SafeFileHandle Debug.Assert(!handle.IsAsync); NativeOverlapped result = default; - result.OffsetLow = unchecked((int)fileOffset); - result.OffsetHigh = (int)(fileOffset >> 32); + if (handle.CanSeek) + { + result.OffsetLow = unchecked((int)fileOffset); + result.OffsetHigh = (int)(fileOffset >> 32); + } return result; } diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/AsyncWindowsFileStreamStrategy.cs b/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/AsyncWindowsFileStreamStrategy.cs index 913ce597be00a..12af993b617f6 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/AsyncWindowsFileStreamStrategy.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/AsyncWindowsFileStreamStrategy.cs @@ -21,83 +21,47 @@ internal AsyncWindowsFileStreamStrategy(string path, FileMode mode, FileAccess a internal override bool IsAsync => true; - public override Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) - => ReadAsyncInternal(new Memory(buffer, offset, count), cancellationToken).AsTask(); - public override ValueTask ReadAsync(Memory destination, CancellationToken cancellationToken = default) - => ReadAsyncInternal(destination, cancellationToken); - - private unsafe ValueTask ReadAsyncInternal(Memory destination, CancellationToken cancellationToken) { - if (!CanRead) + if (!CanSeek) { - ThrowHelper.ThrowNotSupportedException_UnreadableStream(); + return RandomAccess.ReadAtOffsetAsync(_fileHandle, destination, fileOffset: -1, cancellationToken); } - long positionBefore = _filePosition; - if (CanSeek) + if (LengthCachingSupported && _length >= 0 && Volatile.Read(ref _filePosition) >= _length) { - long len = Length; - if (positionBefore + destination.Length > len) - { - destination = positionBefore <= len ? - destination.Slice(0, (int)(len - positionBefore)) : - default; - } - - // When using overlapped IO, the OS is not supposed to - // touch the file pointer location at all. We will adjust it - // ourselves, but only in memory. This isn't threadsafe. - _filePosition += destination.Length; - - // We know for sure that there is nothing to read, so we just return here and avoid a sys-call. - if (destination.IsEmpty && LengthCachingSupported) - { - return ValueTask.FromResult(0); - } + // We know for sure that the file length can be safely cached and it has already been obtained. + // If we have reached EOF we just return here and avoid a sys-call. + return ValueTask.FromResult(0); } - (SafeFileHandle.OverlappedValueTaskSource? vts, int errorCode) = RandomAccess.QueueAsyncReadFile(_fileHandle, destination, positionBefore, cancellationToken); + // This implementation updates the file position before the operation starts and updates it after incomplete read. + // This is done to keep backward compatibility for concurrent reads. + // It uses Interlocked as there can be multiple concurrent incomplete reads updating position at the same time. + long readOffset = Interlocked.Add(ref _filePosition, destination.Length) - destination.Length; + + (SafeFileHandle.OverlappedValueTaskSource? vts, int errorCode) = RandomAccess.QueueAsyncReadFile(_fileHandle, destination, readOffset, cancellationToken, this); return vts != null ? new ValueTask(vts, vts.Version) - : (errorCode == 0) ? ValueTask.FromResult(0) : ValueTask.FromException(HandleIOError(positionBefore, errorCode)); + : (errorCode == 0) ? ValueTask.FromResult(0) : ValueTask.FromException(HandleIOError(readOffset, errorCode)); } - public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) - => WriteAsyncInternal(new ReadOnlyMemory(buffer, offset, count), cancellationToken).AsTask(); - public override ValueTask WriteAsync(ReadOnlyMemory buffer, CancellationToken cancellationToken = default) - => WriteAsyncInternal(buffer, cancellationToken); - - private unsafe ValueTask WriteAsyncInternal(ReadOnlyMemory source, CancellationToken cancellationToken) { - if (!CanWrite) - { - ThrowHelper.ThrowNotSupportedException_UnwritableStream(); - } + long writeOffset = CanSeek ? Interlocked.Add(ref _filePosition, buffer.Length) - buffer.Length : -1; - long positionBefore = _filePosition; - if (CanSeek) - { - // When using overlapped IO, the OS is not supposed to - // touch the file pointer location at all. We will adjust it - // ourselves, but only in memory. This isn't threadsafe. - _filePosition += source.Length; - UpdateLengthOnChangePosition(); - } - - (SafeFileHandle.OverlappedValueTaskSource? vts, int errorCode) = RandomAccess.QueueAsyncWriteFile(_fileHandle, source, positionBefore, cancellationToken); + (SafeFileHandle.OverlappedValueTaskSource? vts, int errorCode) = RandomAccess.QueueAsyncWriteFile(_fileHandle, buffer, writeOffset, cancellationToken); return vts != null ? new ValueTask(vts, vts.Version) - : (errorCode == 0) ? ValueTask.CompletedTask : ValueTask.FromException(HandleIOError(positionBefore, errorCode)); + : (errorCode == 0) ? ValueTask.CompletedTask : ValueTask.FromException(HandleIOError(writeOffset, errorCode)); } private Exception HandleIOError(long positionBefore, int errorCode) { - if (!_fileHandle.IsClosed && CanSeek) + if (_fileHandle.CanSeek) { // Update Position... it could be anywhere. - _filePosition = positionBefore; + Interlocked.Exchange(ref _filePosition, positionBefore); } return SafeFileHandle.OverlappedValueTaskSource.GetIOError(errorCode, _fileHandle.Path); @@ -144,15 +108,5 @@ await FileStreamHelpers } } } - - public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback? callback, object? state) => - TaskToApm.Begin(ReadAsync(buffer, offset, count), callback, state); - - public override int EndRead(IAsyncResult asyncResult) => TaskToApm.End(asyncResult); - - public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback? callback, object? state) => - TaskToApm.Begin(WriteAsync(buffer, offset, count), callback, state); - - public override void EndWrite(IAsyncResult asyncResult) => TaskToApm.End(asyncResult); } } diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/OSFileStreamStrategy.cs b/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/OSFileStreamStrategy.cs index 226765ff8f0ee..260624bf93416 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/OSFileStreamStrategy.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/OSFileStreamStrategy.cs @@ -4,6 +4,7 @@ using System.Diagnostics; using System.Threading; using System.Threading.Tasks; +using System.Threading.Tasks.Sources; using Microsoft.Win32.SafeHandles; namespace System.IO.Strategies @@ -13,11 +14,12 @@ internal abstract class OSFileStreamStrategy : FileStreamStrategy { protected readonly SafeFileHandle _fileHandle; // only ever null if ctor throws private readonly FileAccess _access; // What file was opened for. + private ReadAsyncTaskSource? _readAsyncTaskSource; // Cached IValueTaskSource used for async-over-sync reads protected long _filePosition; + protected long _length = -1; // negative means that hasn't been fetched. private long _appendStart; // When appending, prevent overwriting file. - private long _length = -1; // When the file is locked for writes on Windows ((share & FileShare.Write) == 0) cache file length in-memory, negative means that hasn't been fetched. - private bool _lengthCanBeCached; // SafeFileHandle hasn't been exposed and FileShare.Write was not specified when the handle was opened. + private bool _lengthCanBeCached; // SafeFileHandle hasn't been exposed, file has been opened for reading and not shared for writing. internal OSFileStreamStrategy(SafeFileHandle handle, FileAccess access) { @@ -44,7 +46,7 @@ internal OSFileStreamStrategy(string path, FileMode mode, FileAccess access, Fil string fullPath = Path.GetFullPath(path); _access = access; - _lengthCanBeCached = (share & FileShare.Write) == 0; + _lengthCanBeCached = (share & FileShare.Write) == 0 && (access & FileAccess.Write) == 0; _fileHandle = SafeFileHandle.Open(fullPath, mode, access, share, options, preallocationSize); @@ -69,6 +71,8 @@ internal OSFileStreamStrategy(string path, FileMode mode, FileAccess access, Fil } } + internal override bool IsAsync => _fileHandle.IsAsync; + public sealed override bool CanSeek => _fileHandle.CanSeek; public sealed override bool CanRead => !_fileHandle.IsClosed && (_access & FileAccess.Read) != 0; @@ -96,21 +100,9 @@ public unsafe sealed override long Length } } - protected void UpdateLengthOnChangePosition() - { - // Do not update the cached length if the file is not locked - // or if the length hasn't been fetched. - if (!LengthCachingSupported || _length < 0) - { - Debug.Assert(_length < 0); - return; - } - - if (_filePosition > _length) - { - _length = _filePosition; - } - } + // in case of concurrent incomplete reads, there can be multiple threads trying to update the position + // at the same time. That is why we are using Interlocked here. + internal void OnIncompleteRead(int expectedBytesRead, int actualBytesRead) => Interlocked.Add(ref _filePosition, actualBytesRead - expectedBytesRead); protected bool LengthCachingSupported => OperatingSystem.IsWindows() && _lengthCanBeCached; @@ -287,18 +279,148 @@ public sealed override void Write(ReadOnlySpan buffer) ThrowHelper.ThrowNotSupportedException_UnwritableStream(); } - try + RandomAccess.WriteAtOffset(_fileHandle, buffer, _filePosition); + _filePosition += buffer.Length; + } + + public sealed override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback? callback, object? state) => + TaskToApm.Begin(WriteAsync(buffer, offset, count), callback, state); + + public sealed override void EndWrite(IAsyncResult asyncResult) => + TaskToApm.End(asyncResult); + + public sealed override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) => + WriteAsync(new ReadOnlyMemory(buffer, offset, count), cancellationToken).AsTask(); + + public override ValueTask WriteAsync(ReadOnlyMemory source, CancellationToken cancellationToken) + { + long writeOffset = CanSeek ? Interlocked.Add(ref _filePosition, source.Length) - source.Length : -1; + return RandomAccess.WriteAtOffsetAsync(_fileHandle, source, writeOffset, cancellationToken); + } + + public sealed override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback? callback, object? state) => + TaskToApm.Begin(ReadAsync(buffer, offset, count), callback, state); + + public sealed override int EndRead(IAsyncResult asyncResult) => + TaskToApm.End(asyncResult); + + public sealed override Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) => + ReadAsync(new Memory(buffer, offset, count), cancellationToken).AsTask(); + + public override ValueTask ReadAsync(Memory destination, CancellationToken cancellationToken) + { + if (!CanSeek) { - RandomAccess.WriteAtOffset(_fileHandle, buffer, _filePosition); + return RandomAccess.ReadAtOffsetAsync(_fileHandle, destination, fileOffset: -1, cancellationToken); } - catch + + // This implementation updates the file position before the operation starts and updates it after incomplete read. + // Also, unlike the Net5CompatFileStreamStrategy implementation, this implementation doesn't serialize operations. + long readOffset = Interlocked.Add(ref _filePosition, destination.Length) - destination.Length; + ReadAsyncTaskSource rats = Interlocked.Exchange(ref _readAsyncTaskSource, null) ?? new ReadAsyncTaskSource(this); + return rats.QueueRead(destination, readOffset, cancellationToken); + } + + /// Provides a reusable ValueTask-backing object for implementing ReadAsync. + private sealed class ReadAsyncTaskSource : IValueTaskSource, IThreadPoolWorkItem + { + private readonly OSFileStreamStrategy _stream; + private ManualResetValueTaskSourceCore _source; + + private Memory _destination; + private long _readOffset; + private ExecutionContext? _context; + private CancellationToken _cancellationToken; + + public ReadAsyncTaskSource(OSFileStreamStrategy stream) => _stream = stream; + + public ValueTask QueueRead(Memory destination, long readOffset, CancellationToken cancellationToken) { - _length = -1; // invalidate cached length - throw; + _destination = destination; + _readOffset = readOffset; + _cancellationToken = cancellationToken; + _context = ExecutionContext.Capture(); + + ThreadPool.UnsafeQueueUserWorkItem(this, preferLocal: true); + return new ValueTask(this, _source.Version); } - _filePosition += buffer.Length; - UpdateLengthOnChangePosition(); + void IThreadPoolWorkItem.Execute() + { + if (_context is null || _context.IsDefault) + { + Read(); + } + else + { + ExecutionContext.RunForThreadPoolUnsafe(_context, static x => x.Read(), this); + } + } + + private void Read() + { + Exception? error = null; + int result = 0; + + try + { + if (_cancellationToken.IsCancellationRequested) + { + error = new OperationCanceledException(_cancellationToken); + } + else + { + result = RandomAccess.ReadAtOffset(_stream._fileHandle, _destination.Span, _readOffset); + } + } + catch (Exception e) + { + error = e; + } + finally + { + // if the read was incomplete, we need to update the file position: + if (result != _destination.Length) + { + _stream.OnIncompleteRead(_destination.Length, result); + } + + _destination = default; + _readOffset = -1; + _cancellationToken = default; + _context = null; + } + + if (error is not null) + { + _source.SetException(error); + } + else + { + _source.SetResult(result); + } + } + + int IValueTaskSource.GetResult(short token) + { + try + { + return _source.GetResult(token); + } + finally + { + _source.Reset(); +#pragma warning disable CS0197 + Volatile.Write(ref _stream._readAsyncTaskSource, this); +#pragma warning restore CS0197 + } + } + + ValueTaskSourceStatus IValueTaskSource.GetStatus(short token) => + _source.GetStatus(token); + + void IValueTaskSource.OnCompleted(Action continuation, object? state, short token, ValueTaskSourceOnCompletedFlags flags) => + _source.OnCompleted(continuation, state, token, flags); } } } diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/SyncWindowsFileStreamStrategy.cs b/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/SyncWindowsFileStreamStrategy.cs index d25fcd65db3df..5e2513252a510 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/SyncWindowsFileStreamStrategy.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/SyncWindowsFileStreamStrategy.cs @@ -1,9 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Runtime.InteropServices; -using System.Threading; -using System.Threading.Tasks; using Microsoft.Win32.SafeHandles; namespace System.IO.Strategies @@ -20,45 +17,5 @@ internal SyncWindowsFileStreamStrategy(string path, FileMode mode, FileAccess ac } internal override bool IsAsync => false; - - public override Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) - { - // If we weren't opened for asynchronous I/O, we still call to the base implementation so that - // Read is invoked asynchronously. But we can do so using the base Stream's internal helper - // that bypasses delegating to BeginRead, since we already know this is FileStream rather - // than something derived from it and what our BeginRead implementation is going to do. - return BeginReadInternal(buffer, offset, count, null, null, serializeAsynchronously: true, apm: false); - } - - public override ValueTask ReadAsync(Memory buffer, CancellationToken cancellationToken = default) - { - // If we weren't opened for asynchronous I/O, we still call to the base implementation so that - // Read is invoked asynchronously. But if we have a byte[], we can do so using the base Stream's - // internal helper that bypasses delegating to BeginRead, since we already know this is FileStream - // rather than something derived from it and what our BeginRead implementation is going to do. - return MemoryMarshal.TryGetArray(buffer, out ArraySegment segment) ? - new ValueTask(BeginReadInternal(segment.Array!, segment.Offset, segment.Count, null, null, serializeAsynchronously: true, apm: false)) : - base.ReadAsync(buffer, cancellationToken); - } - - public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) - { - // If we weren't opened for asynchronous I/O, we still call to the base implementation so that - // Write is invoked asynchronously. But we can do so using the base Stream's internal helper - // that bypasses delegating to BeginWrite, since we already know this is FileStream rather - // than something derived from it and what our BeginWrite implementation is going to do. - return BeginWriteInternal(buffer, offset, count, null, null, serializeAsynchronously: true, apm: false); - } - - public override ValueTask WriteAsync(ReadOnlyMemory buffer, CancellationToken cancellationToken = default) - { - // If we weren't opened for asynchronous I/O, we still call to the base implementation so that - // Write is invoked asynchronously. But if we have a byte[], we can do so using the base Stream's - // internal helper that bypasses delegating to BeginWrite, since we already know this is FileStream - // rather than something derived from it and what our BeginWrite implementation is going to do. - return MemoryMarshal.TryGetArray(buffer, out ArraySegment segment) ? - new ValueTask(BeginWriteInternal(segment.Array!, segment.Offset, segment.Count, null, null, serializeAsynchronously: true, apm: false)) : - base.WriteAsync(buffer, cancellationToken); - } } } diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/UnixFileStreamStrategy.cs b/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/UnixFileStreamStrategy.cs index e9f00f254ad29..3c54f1b23a476 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/UnixFileStreamStrategy.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/UnixFileStreamStrategy.cs @@ -1,17 +1,12 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Threading; -using System.Threading.Tasks; -using System.Threading.Tasks.Sources; using Microsoft.Win32.SafeHandles; namespace System.IO.Strategies { internal sealed partial class UnixFileStreamStrategy : OSFileStreamStrategy { - private ReadAsyncTaskSource? _readAsyncTaskSource; - internal UnixFileStreamStrategy(SafeFileHandle handle, FileAccess access) : base(handle, access) { } @@ -20,153 +15,5 @@ internal UnixFileStreamStrategy(SafeFileHandle handle, FileAccess access) : base base(path, mode, access, share, options, preallocationSize) { } - - internal override bool IsAsync => _fileHandle.IsAsync; - - public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback? callback, object? state) => - TaskToApm.Begin(ReadAsync(buffer, offset, count), callback, state); - - public override int EndRead(IAsyncResult asyncResult) => - TaskToApm.End(asyncResult); - - public override Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) => - ReadAsync(new Memory(buffer, offset, count), cancellationToken).AsTask(); - - public override ValueTask ReadAsync(Memory destination, CancellationToken cancellationToken) - { - if (!CanRead) - { - ThrowHelper.ThrowNotSupportedException_UnreadableStream(); - } - - if (CanSeek) - { - // This implementation updates the file position after the operation completes, rather than before. - // Also, unlike the Net5CompatFileStreamStrategy implementation, this implementation doesn't serialize operations. - ReadAsyncTaskSource rats = Interlocked.Exchange(ref _readAsyncTaskSource, null) ?? new ReadAsyncTaskSource(this); - return rats.QueueRead(destination, cancellationToken); - } - - return RandomAccess.ReadAtOffsetAsync(_fileHandle, destination, fileOffset: -1, cancellationToken); - } - - public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback? callback, object? state) => - TaskToApm.Begin(WriteAsync(buffer, offset, count), callback, state); - - public override void EndWrite(IAsyncResult asyncResult) => - TaskToApm.End(asyncResult); - - public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) => - WriteAsync(new ReadOnlyMemory(buffer, offset, count), cancellationToken).AsTask(); - - public override ValueTask WriteAsync(ReadOnlyMemory source, CancellationToken cancellationToken) - { - if (!CanWrite) - { - ThrowHelper.ThrowNotSupportedException_UnwritableStream(); - } - - long filePositionBefore = -1; - if (CanSeek) - { - filePositionBefore = _filePosition; - _filePosition += source.Length; - } - - return RandomAccess.WriteAtOffsetAsync(_fileHandle, source, filePositionBefore, cancellationToken); - } - - /// Provides a reusable ValueTask-backing object for implementing ReadAsync. - private sealed class ReadAsyncTaskSource : IValueTaskSource, IThreadPoolWorkItem - { - private readonly UnixFileStreamStrategy _stream; - private ManualResetValueTaskSourceCore _source; - - private Memory _destination; - private ExecutionContext? _context; - private CancellationToken _cancellationToken; - - public ReadAsyncTaskSource(UnixFileStreamStrategy stream) => _stream = stream; - - public ValueTask QueueRead(Memory destination, CancellationToken cancellationToken) - { - _destination = destination; - _cancellationToken = cancellationToken; - _context = ExecutionContext.Capture(); - - ThreadPool.UnsafeQueueUserWorkItem(this, preferLocal: true); - return new ValueTask(this, _source.Version); - } - - void IThreadPoolWorkItem.Execute() - { - if (_context is null || _context.IsDefault) - { - Read(); - } - else - { - ExecutionContext.RunForThreadPoolUnsafe(_context, static x => x.Read(), this); - } - } - - private void Read() - { - Exception? error = null; - int result = 0; - - try - { - if (_cancellationToken.IsCancellationRequested) - { - error = new OperationCanceledException(_cancellationToken); - } - else - { - result = _stream.Read(_destination.Span); - } - } - catch (Exception e) - { - error = e; - } - finally - { - _destination = default; - _cancellationToken = default; - _context = null; - } - - if (error is not null) - { - _source.SetException(error); - } - else - { - _source.SetResult(result); - } - } - - int IValueTaskSource.GetResult(short token) - { - try - { - return _source.GetResult(token); - } - finally - { - _source.Reset(); -#pragma warning disable CS0197 - Volatile.Write(ref _stream._readAsyncTaskSource, this); -#pragma warning restore CS0197 - } - } - - ValueTaskSourceStatus IValueTaskSource.GetStatus(short token) => - _source.GetStatus(token); - - void IValueTaskSource.OnCompleted(Action continuation, object? state, short token, ValueTaskSourceOnCompletedFlags flags) => - _source.OnCompleted(continuation, state, token, flags); - } } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/Assembly.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/Assembly.cs index 5b5035b272062..3612e751aee28 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/Assembly.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/Assembly.cs @@ -81,7 +81,9 @@ public virtual IEnumerable ExportedTypes [RequiresUnreferencedCode("Types might be removed")] public virtual Type[] GetForwardedTypes() { throw NotImplemented.ByDesign; } - [RequiresAssemblyFiles("The code will throw for assemblies embedded in a single-file app")] + internal const string ThrowingMessageInRAF = "This member throws an exception for assemblies embedded in a single-file app"; + + [RequiresAssemblyFiles(ThrowingMessageInRAF)] public virtual string? CodeBase => throw NotImplemented.ByDesign; public virtual MethodInfo? EntryPoint => throw NotImplemented.ByDesign; public virtual string? FullName => throw NotImplemented.ByDesign; @@ -116,7 +118,7 @@ public virtual IEnumerable ExportedTypes public virtual object[] GetCustomAttributes(bool inherit) { throw NotImplemented.ByDesign; } public virtual object[] GetCustomAttributes(Type attributeType, bool inherit) { throw NotImplemented.ByDesign; } - [RequiresAssemblyFiles("The code will throw for assemblies embedded in a single-file app")] + [RequiresAssemblyFiles(ThrowingMessageInRAF)] public virtual string EscapedCodeBase => AssemblyName.EscapeCodeBase(CodeBase); [RequiresUnreferencedCode("Assembly.CreateInstance is not supported with trimming. Use Type.GetType instead.")] @@ -153,9 +155,11 @@ public virtual IEnumerable ExportedTypes public virtual Assembly GetSatelliteAssembly(CultureInfo culture) { throw NotImplemented.ByDesign; } public virtual Assembly GetSatelliteAssembly(CultureInfo culture, Version? version) { throw NotImplemented.ByDesign; } + [RequiresAssemblyFiles(ThrowingMessageInRAF)] public virtual FileStream? GetFile(string name) { throw NotImplemented.ByDesign; } - [RequiresAssemblyFiles("The code will throw for assemblies embedded in a single-file app")] + [RequiresAssemblyFiles(ThrowingMessageInRAF)] public virtual FileStream[] GetFiles() => GetFiles(getResourceModules: false); + [RequiresAssemblyFiles(ThrowingMessageInRAF)] public virtual FileStream[] GetFiles(bool getResourceModules) { throw NotImplemented.ByDesign; } public virtual void GetObjectData(SerializationInfo info, StreamingContext context) { throw NotImplemented.ByDesign; } diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/AssemblyBuilder.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/AssemblyBuilder.cs index dc77c941297f3..631b6ea927ede 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/AssemblyBuilder.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/AssemblyBuilder.cs @@ -8,7 +8,7 @@ namespace System.Reflection.Emit { public sealed partial class AssemblyBuilder : Assembly { - [RequiresAssemblyFiles("The code will throw for assemblies embedded in a single-file app")] + [RequiresAssemblyFiles(ThrowingMessageInRAF)] public override string? CodeBase => throw new NotSupportedException(SR.NotSupported_DynamicAssembly); public override string Location => throw new NotSupportedException(SR.NotSupported_DynamicAssembly); public override MethodInfo? EntryPoint => null; @@ -18,9 +18,11 @@ public sealed partial class AssemblyBuilder : Assembly public override Type[] GetExportedTypes() => throw new NotSupportedException(SR.NotSupported_DynamicAssembly); + [RequiresAssemblyFiles(ThrowingMessageInRAF)] public override FileStream GetFile(string name) => throw new NotSupportedException(SR.NotSupported_DynamicAssembly); + [RequiresAssemblyFiles(ThrowingMessageInRAF)] public override FileStream[] GetFiles(bool getResourceModules) => throw new NotSupportedException(SR.NotSupported_DynamicAssembly); diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/Module.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/Module.cs index 4fe3b9ad74747..fc762fee94977 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/Module.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/Module.cs @@ -13,7 +13,11 @@ public abstract partial class Module : ICustomAttributeProvider, ISerializable protected Module() { } public virtual Assembly Assembly => throw NotImplemented.ByDesign; + + internal const string UnknownStringMessageInRAF = "Returns for modules with no file path"; + [RequiresAssemblyFiles(UnknownStringMessageInRAF)] public virtual string FullyQualifiedName => throw NotImplemented.ByDesign; + [RequiresAssemblyFiles(UnknownStringMessageInRAF)] public virtual string Name => throw NotImplemented.ByDesign; public virtual int MDStreamVersion => throw NotImplemented.ByDesign; diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.PlatformNotSupported.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.PlatformNotSupported.cs index 2cfac1e1919e9..f2701035b93ab 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.PlatformNotSupported.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.PlatformNotSupported.cs @@ -41,6 +41,7 @@ public static void RegisterForTrackerSupport(ComWrappers instance) throw new PlatformNotSupportedException(); } + [SupportedOSPlatform("windows")] public static void RegisterForMarshalling(ComWrappers instance) { throw new PlatformNotSupportedException(); diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.cs index 72019f3d833cc..ff16e14d4e39d 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.cs @@ -69,7 +69,11 @@ public enum CreateObjectFlags /// /// Class for managing wrappers of COM IUnknown types. /// - [SupportedOSPlatform("windows")] + [UnsupportedOSPlatform("android")] + [UnsupportedOSPlatform("browser")] + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("maccatalyst")] + [UnsupportedOSPlatform("tvos")] [CLSCompliant(false)] public abstract partial class ComWrappers { diff --git a/src/libraries/System.Private.Xml.Linq/tests/xNodeBuilder/CommonTests.cs b/src/libraries/System.Private.Xml.Linq/tests/xNodeBuilder/CommonTests.cs index 86f7320662620..772f9b87ab908 100644 --- a/src/libraries/System.Private.Xml.Linq/tests/xNodeBuilder/CommonTests.cs +++ b/src/libraries/System.Private.Xml.Linq/tests/xNodeBuilder/CommonTests.cs @@ -3403,7 +3403,6 @@ private void CData_4() //[Variation(Id = 5, Desc = "WriteCData with ]]>", Priority = 1)] [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50944", TestPlatforms.Android)] public void WriteCDataWithTwoClosingBrackets_5() { XDocument doc = new XDocument(); @@ -3599,7 +3598,6 @@ private void comment_5() //[Variation(Id = 6, Desc = "WriteComment with -- in value", Priority = 1)] [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50944", TestPlatforms.Android)] public void WriteCommentWithDoubleHyphensInValue() { XDocument doc = new XDocument(); @@ -4205,7 +4203,6 @@ private void pi_10() //[Variation(Id = 11, Desc = "Include PI end tag ?> as part of the text value", Priority = 1)] [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50944", TestPlatforms.Android)] public void IncludePIEndTagAsPartOfTextValue() { XDocument doc = new XDocument(); diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Serialization/XmlSerializer.cs b/src/libraries/System.Private.Xml/src/System/Xml/Serialization/XmlSerializer.cs index 049836211d752..de4eb5155bdd3 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Serialization/XmlSerializer.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Serialization/XmlSerializer.cs @@ -9,6 +9,7 @@ using System.Globalization; using System.IO; using System.Reflection; +using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Text; @@ -109,7 +110,13 @@ internal enum SerializationMode public class XmlSerializer { - internal static SerializationMode Mode { get; set; } = SerializationMode.ReflectionAsBackup; + private static SerializationMode s_mode = SerializationMode.ReflectionAsBackup; + + internal static SerializationMode Mode + { + get => RuntimeFeature.IsDynamicCodeSupported ? s_mode : SerializationMode.ReflectionOnly; + set => s_mode = value; + } private static bool ReflectionMethodEnabled { diff --git a/src/libraries/System.Private.Xml/tests/XmlReader/Tests/ReaderEncodingTests.cs b/src/libraries/System.Private.Xml/tests/XmlReader/Tests/ReaderEncodingTests.cs index c89b48447c37a..0c91c2b2e27b3 100644 --- a/src/libraries/System.Private.Xml/tests/XmlReader/Tests/ReaderEncodingTests.cs +++ b/src/libraries/System.Private.Xml/tests/XmlReader/Tests/ReaderEncodingTests.cs @@ -17,7 +17,6 @@ public class ReaderEncodingTests private static string _invalidCharInThisEncoding = "Invalid character in the given encoding"; [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50945", TestPlatforms.Android)] public static void ReadWithSurrogateCharAndInvalidChar() { // {60, 0, 0, 0} is a normal char, {0, 34, 1, 0} is a surrogate char {62, 100, 60, 47} is an invalid char @@ -30,7 +29,6 @@ public static void ReadWithSurrogateCharAndInvalidChar() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50945", TestPlatforms.Android)] public static void ReadWithNormalCharAndInvalidChar() { // {60, 0, 0, 0, 65, 0, 0, 0} are normal chars, {62, 100, 60, 47} is an invalid char, similar bytes used below tests @@ -43,7 +41,6 @@ public static void ReadWithNormalCharAndInvalidChar() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50945", TestPlatforms.Android)] public static void ReadWithSurrogateCharAndInvalidChar_ValidXmlStructure() { var bytes = new byte[] { 60, 0, 0, 0, 97, 0, 0, 0, 62, 0, 0, 0, 0, 34, 1, 0, 62, 100, 60, 47, 60, 0, 0, 0, 47, 0, 0, 0, 97, 0, 0, 0, 62, 0, 0, 0 }; @@ -55,7 +52,6 @@ public static void ReadWithSurrogateCharAndInvalidChar_ValidXmlStructure() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50945", TestPlatforms.Android)] public static void ReadWithSurrogateCharAsElementName() { var bytes = new byte[] { 60, 0, 0, 0, 0, 34, 1, 0, 65, 0, 0, 0, 97, 0, 0, 0 }; @@ -88,7 +84,6 @@ public static void BytesEndingWithSurrogateChar() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50945", TestPlatforms.Android)] public static void BytesStartingWithInvalidChar() { var bytes = new byte[] { 62, 100, 60, 47, 60, 0, 0, 0, 0, 34, 1, 0, 65, 0, 0, 0, 97, 0, 0, 0 }; @@ -99,7 +94,6 @@ public static void BytesStartingWithInvalidChar() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50945", TestPlatforms.Android)] public static void BytesEndingWithInvalidChar() { var bytes = new byte[] { 60, 0, 0, 0, 97, 0, 0, 0, 62, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 97, 0, 0, 0, 62, 100, 60, 47}; @@ -120,7 +114,6 @@ public static void ReadWithSurrogateChar_ValidXmlStructure() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50945", TestPlatforms.Android)] public static void ReadWithIncompleteBytes() { var bytes = new byte[] { 60, 0, 0, 0, 97, 0, 0, 0, 65, 0, 0, 0, 97, 62, 10}; diff --git a/src/libraries/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/XslCompiledTransform.cs b/src/libraries/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/XslCompiledTransform.cs index 568072314f34c..e8cf2496e07ae 100644 --- a/src/libraries/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/XslCompiledTransform.cs +++ b/src/libraries/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/XslCompiledTransform.cs @@ -544,7 +544,6 @@ public void XmlResolver2(XslInputType xslInputType, ReaderType readerType) } //[Variation(id = 3, Desc = "Default XmlResolver, load style sheet with document function, should resolve during transform", Pri = 1, Param = "DefaultResolver.txt")] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51911", typeof(PlatformDetection), nameof(PlatformDetection.IsBuiltWithAggressiveTrimming), nameof(PlatformDetection.IsBrowser))] [InlineData("DefaultResolver.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)] [InlineData("DefaultResolver.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)] [InlineData("DefaultResolver.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)] @@ -2409,7 +2408,6 @@ public void XmlResolver1(XslInputType xslInputType , ReaderType readerType, Outp } //[Variation("Pass null XmlResolver, load style sheet with document function, should not resolve during transform", Param = "xmlResolver_document_function.txt")] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51911", typeof(PlatformDetection), nameof(PlatformDetection.IsBuiltWithAggressiveTrimming), nameof(PlatformDetection.IsBrowser))] [InlineData("xmlResolver_document_function.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)] [InlineData("xmlResolver_document_function.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)] [InlineData("xmlResolver_document_function.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)] @@ -2445,7 +2443,6 @@ public void XmlResolver2(object param, XslInputType xslInputType, ReaderType rea } //[Variation("Default XmlResolver, load style sheet with document function, should resolve during transform", Param = "DefaultResolver.txt")] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51911", typeof(PlatformDetection), nameof(PlatformDetection.IsBuiltWithAggressiveTrimming), nameof(PlatformDetection.IsBrowser))] [InlineData("DefaultResolver.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)] [InlineData("DefaultResolver.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)] [InlineData("DefaultResolver.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)] @@ -2973,7 +2970,6 @@ public void TransformStrStrResolver1(XslInputType xslInputType, ReaderType reade } //[Variation("Pass null XmlResolver, load style sheet with document function, should not resolve during transform")] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51911", typeof(PlatformDetection), nameof(PlatformDetection.IsBuiltWithAggressiveTrimming), nameof(PlatformDetection.IsBrowser))] [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader)] [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader)] [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader)] @@ -3336,7 +3332,6 @@ public CTransformRegressionTest(ITestOutputHelper output) : base(output) } //[Variation("Bug398968 - Globalization is broken for document() function")] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51244", typeof(PlatformDetection), nameof(PlatformDetection.IsBuiltWithAggressiveTrimming), nameof(PlatformDetection.IsBrowser))] [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)] [Theory] public void RegressionTest1(XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType) diff --git a/src/libraries/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/XsltSettings.cs b/src/libraries/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/XsltSettings.cs index 5074facbfc0d0..c736fe09811fb 100644 --- a/src/libraries/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/XsltSettings.cs +++ b/src/libraries/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/XsltSettings.cs @@ -78,7 +78,6 @@ public void XsltSettings1_2_ContainsScript(object param0, object param1, object } //[Variation(id = 5, Desc = "Test the document function with EnableDocumentFunction, should work", Pri = 0, Params = new object[] { "XsltSettings.xml", "XsltSettings2.xsl", true, false })] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51911", typeof(PlatformDetection), nameof(PlatformDetection.IsBuiltWithAggressiveTrimming), nameof(PlatformDetection.IsBrowser))] [InlineData(5, "XsltSettings.xml", "XsltSettings2.xsl", true, false)] //[Variation(id = 8, Desc = "Test the document function with TrustedXslt, should work", Pri = 1, Params = new object[] { "XsltSettings.xml", "XsltSettings2.xsl", true, true })] [InlineData(8, "XsltSettings.xml", "XsltSettings2.xsl", true, true)] @@ -91,7 +90,6 @@ public void XsltSettings1_1_ExternalURI(object param0, object param1, object par } //[Variation(id = 18, Desc = "Test 6 with EnableDocumentFunction override, should work", Pri = 1, Params = new object[] { "XsltSettings.xml", "XsltSettings2.xsl", false, false, true, false })] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51911", typeof(PlatformDetection), nameof(PlatformDetection.IsBuiltWithAggressiveTrimming), nameof(PlatformDetection.IsBrowser))] [InlineData(18, "XsltSettings.xml", "XsltSettings2.xsl", false, false, true, false)] [Theory] public void XsltSettings1_2_ExternalURI(object param0, object param1, object param2, object param3, object param4, object param5, object param6) diff --git a/src/libraries/System.Reflection.Context/src/System/Reflection/Context/Delegation/DelegatingModule.cs b/src/libraries/System.Reflection.Context/src/System/Reflection/Context/Delegation/DelegatingModule.cs index c1f11fcc4ba1e..0c34b67b4cf4e 100644 --- a/src/libraries/System.Reflection.Context/src/System/Reflection/Context/Delegation/DelegatingModule.cs +++ b/src/libraries/System.Reflection.Context/src/System/Reflection/Context/Delegation/DelegatingModule.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; namespace System.Reflection.Context.Delegation { @@ -22,6 +23,11 @@ public override Assembly Assembly get { return UnderlyingModule.Assembly; } } + internal const string UnknownStringMessageInRAF = "Returns for modules with no file path"; + +#if NET5_0_OR_GREATER + [RequiresAssemblyFiles(UnknownStringMessageInRAF)] +#endif public override string FullyQualifiedName { get { return UnderlyingModule.FullyQualifiedName; } @@ -42,6 +48,9 @@ public override Guid ModuleVersionId get { return UnderlyingModule.ModuleVersionId; } } +#if NET5_0_OR_GREATER + [RequiresAssemblyFiles(UnknownStringMessageInRAF)] +#endif public override string Name { get { return UnderlyingModule.Name; } diff --git a/src/libraries/System.Reflection.Emit/ref/System.Reflection.Emit.cs b/src/libraries/System.Reflection.Emit/ref/System.Reflection.Emit.cs index e823c6a25c3c0..cbbcaa28059a5 100644 --- a/src/libraries/System.Reflection.Emit/ref/System.Reflection.Emit.cs +++ b/src/libraries/System.Reflection.Emit/ref/System.Reflection.Emit.cs @@ -29,7 +29,9 @@ public sealed partial class AssemblyBuilder : System.Reflection.Assembly public System.Reflection.Emit.ModuleBuilder? GetDynamicModule(string name) { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Types might be removed")] public override System.Type[] GetExportedTypes() { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresAssemblyFilesAttribute("This member throws an exception for assemblies embedded in a single-file app")] public override System.IO.FileStream GetFile(string name) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresAssemblyFilesAttribute("This member throws an exception for assemblies embedded in a single-file app")] public override System.IO.FileStream[] GetFiles(bool getResourceModules) { throw null; } public override int GetHashCode() { throw null; } public override System.Reflection.Module[] GetLoadedModules(bool getResourceModules) { throw null; } diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/Ecma/EcmaAssembly.ManifestResources.cs b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/Ecma/EcmaAssembly.ManifestResources.cs index 976d002039ae2..9cfdf5b19d935 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/Ecma/EcmaAssembly.ManifestResources.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/Ecma/EcmaAssembly.ManifestResources.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Reflection.Metadata; @@ -11,7 +12,7 @@ namespace System.Reflection.TypeLoading.Ecma /// internal sealed partial class EcmaAssembly { - public sealed override ManifestResourceInfo GetManifestResourceInfo(string resourceName) + public sealed override ManifestResourceInfo? GetManifestResourceInfo(string resourceName) { if (resourceName == null) throw new ArgumentNullException(nameof(resourceName)); @@ -20,6 +21,11 @@ public sealed override ManifestResourceInfo GetManifestResourceInfo(string resou InternalManifestResourceInfo internalManifestResourceInfo = GetEcmaManifestModule().GetInternalManifestResourceInfo(resourceName); + if (!internalManifestResourceInfo.Found) + { + return null; + } + if (internalManifestResourceInfo.ResourceLocation == ResourceLocation.ContainedInAnotherAssembly) { // Must get resource info from other assembly, and OR in the contained in another assembly information @@ -51,6 +57,8 @@ public sealed override string[] GetManifestResourceNames() return resourceNames; } + [UnconditionalSuppressMessage("SingleFile", "IL3002:RequiresAssemblyFiles on Module.GetFile", + Justification = "ResourceLocation should never be ContainedInAnotherAssembly if embedded in a single-file")] public sealed override Stream? GetManifestResourceStream(string name) { if (name == null) @@ -59,6 +67,12 @@ public sealed override string[] GetManifestResourceNames() throw new ArgumentException(nameof(name)); InternalManifestResourceInfo internalManifestResourceInfo = GetEcmaManifestModule().GetInternalManifestResourceInfo(name); + + if (!internalManifestResourceInfo.Found) + { + return null; + } + if ((internalManifestResourceInfo.ResourceLocation & ResourceLocation.Embedded) != 0) { unsafe diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/RoAssembly.Modules.cs b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/RoAssembly.Modules.cs index fe92aa504f05a..d141c710af2e8 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/RoAssembly.Modules.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/RoAssembly.Modules.cs @@ -4,6 +4,7 @@ using System.IO; using System.Threading; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Collections.Generic; namespace System.Reflection.TypeLoading @@ -16,6 +17,9 @@ internal abstract partial class RoAssembly public sealed override Module? GetModule(string name) => GetRoModule(name); public sealed override Module[] GetModules(bool getResourceModules) => ComputeRoModules(getResourceModules).CloneArray(); +#if NET5_0_OR_GREATER + [RequiresAssemblyFiles(ThrowingMessageInRAF)] +#endif public sealed override FileStream? GetFile(string name) { Module? m = GetModule(name); @@ -24,6 +28,9 @@ internal abstract partial class RoAssembly return new FileStream(m.FullyQualifiedName, FileMode.Open, FileAccess.Read, FileShare.Read); } +#if NET5_0_OR_GREATER + [RequiresAssemblyFiles(ThrowingMessageInRAF)] +#endif public sealed override FileStream[] GetFiles(bool getResourceModules) { Module[] m = GetModules(getResourceModules); diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/RoAssembly.cs b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/RoAssembly.cs index 114f581d06954..43609a2f3eb86 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/RoAssembly.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/RoAssembly.cs @@ -40,16 +40,18 @@ protected RoAssembly(MetadataLoadContext loader, int assemblyFileCount) public sealed override string FullName => _lazyFullName ?? (_lazyFullName = GetName().FullName); private volatile string? _lazyFullName; + internal const string ThrowingMessageInRAF = "This member throws an exception for assemblies embedded in a single-file app"; + // Location and codebase public abstract override string Location { get; } #if NET5_0_OR_GREATER [Obsolete(Obsoletions.CodeBaseMessage, DiagnosticId = Obsoletions.CodeBaseDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] - [RequiresAssemblyFiles("The code will throw for assemblies embedded in a single-file app")] + [RequiresAssemblyFiles(ThrowingMessageInRAF)] #endif public sealed override string CodeBase => throw new NotSupportedException(SR.NotSupported_AssemblyCodeBase); #if NET5_0_OR_GREATER [Obsolete(Obsoletions.CodeBaseMessage, DiagnosticId = Obsoletions.CodeBaseDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] - [RequiresAssemblyFiles("The code will throw for assemblies embedded in a single-file app")] + [RequiresAssemblyFiles(ThrowingMessageInRAF)] #endif public sealed override string EscapedCodeBase => throw new NotSupportedException(SR.NotSupported_AssemblyCodeBase); @@ -164,7 +166,7 @@ public sealed override AssemblyName[] GetReferencedAssemblies() public abstract override MethodInfo? EntryPoint { get; } // Manifest resource support. - public abstract override ManifestResourceInfo GetManifestResourceInfo(string resourceName); + public abstract override ManifestResourceInfo? GetManifestResourceInfo(string resourceName); public abstract override string[] GetManifestResourceNames(); public abstract override Stream? GetManifestResourceStream(string name); public sealed override Stream? GetManifestResourceStream(Type type, string name) diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/RoStubAssembly.cs b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/RoStubAssembly.cs index 3807a905adbf4..315efba1b9849 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/RoStubAssembly.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/RoStubAssembly.cs @@ -17,7 +17,7 @@ internal abstract class RoStubAssembly : RoAssembly public sealed override bool IsDynamic => throw null!; public sealed override event ModuleResolveEventHandler? ModuleResolve { add { throw null!; } remove { throw null!; } } public sealed override IEnumerable CustomAttributes => throw null!; - public sealed override ManifestResourceInfo GetManifestResourceInfo(string resourceName) => throw null!; + public sealed override ManifestResourceInfo? GetManifestResourceInfo(string resourceName) => throw null!; public sealed override string[] GetManifestResourceNames() => throw null!; public sealed override Stream GetManifestResourceStream(string name) => throw null!; protected sealed override AssemblyNameData[] ComputeAssemblyReferences() => throw null!; diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Modules/Ecma/EcmaModule.GetTypeCore.cs b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Modules/Ecma/EcmaModule.GetTypeCore.cs index 78f4d92757b4a..cba523452ffdb 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Modules/Ecma/EcmaModule.GetTypeCore.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Modules/Ecma/EcmaModule.GetTypeCore.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; using System.Reflection.Metadata; namespace System.Reflection.TypeLoading.Ecma @@ -16,6 +17,8 @@ internal sealed partial class EcmaModule /// If a type is not contained or forwarded from the assembly, this method returns null (does not throw.) /// This supports the "throwOnError: false" behavior of Module.GetType(string, bool). /// + [UnconditionalSuppressMessage("SingleFile", "IL3002:RequiresAssemblyFiles on FullyQualifiedName", + Justification = "FullyQualifiedName is only used for exception message")] protected sealed override RoDefinitionType? GetTypeCoreNoCache(ReadOnlySpan ns, ReadOnlySpan name, out Exception? e) { MetadataReader reader = Reader; diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Modules/RoModule.cs b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Modules/RoModule.cs index e9727f2db0bba..4ddd4427edbb1 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Modules/RoModule.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Modules/RoModule.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Runtime.Serialization; @@ -15,7 +16,7 @@ internal abstract partial class RoModule : Module { private readonly string _fullyQualifiedName; - internal const string FullyQualifiedNameForModulesLoadedFromByteArrays = ""; + internal const string FullyQualifiedNameForModulesLoadedFromByteArrays = ""; internal RoModule(string fullyQualifiedName) : base() @@ -30,11 +31,19 @@ internal RoModule(string fullyQualifiedName) public sealed override Assembly Assembly => GetRoAssembly(); internal abstract RoAssembly GetRoAssembly(); + internal const string UnknownStringMessageInRAF = "Returns for modules with no file path"; + +#if NET5_0_OR_GREATER + [RequiresAssemblyFiles(UnknownStringMessageInRAF)] +#endif public sealed override string FullyQualifiedName => _fullyQualifiedName; public abstract override int MDStreamVersion { get; } public abstract override int MetadataToken { get; } public abstract override Guid ModuleVersionId { get; } +#if NET5_0_OR_GREATER + [RequiresAssemblyFiles(UnknownStringMessageInRAF)] +#endif public sealed override string Name { get diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Modules/RoResourceModule.cs b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Modules/RoResourceModule.cs index 9bff8aba7a8f1..7e2adb511c662 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Modules/RoResourceModule.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Modules/RoResourceModule.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; namespace System.Reflection.TypeLoading { @@ -30,6 +31,9 @@ internal RoResourceModule(RoAssembly assembly, string fullyQualifiedName) public sealed override int MDStreamVersion => throw new InvalidOperationException(SR.ResourceOnlyModule); public sealed override int MetadataToken => 0x00000000; public sealed override Guid ModuleVersionId => throw new InvalidOperationException(SR.ResourceOnlyModule); + + [UnconditionalSuppressMessage("SingleFile", "IL3002:RequiresAssemblyFiles on Name", + Justification = "https://github.com/dotnet/runtime/issues/56519")] public sealed override string ScopeName => Name; public sealed override void GetPEKind(out PortableExecutableKinds peKind, out ImageFileMachine machine) { diff --git a/src/libraries/System.Reflection.MetadataLoadContext/tests/src/Tests/Assembly/AssemblyTests.cs b/src/libraries/System.Reflection.MetadataLoadContext/tests/src/Tests/Assembly/AssemblyTests.cs index 43179d98a0a56..2dc40fa00d1c9 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/tests/src/Tests/Assembly/AssemblyTests.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/tests/src/Tests/Assembly/AssemblyTests.cs @@ -602,5 +602,27 @@ public static void CrossAssemblyTypeRefToNestedType() Assert.Equal(expected, bt); } } + + [Fact] + public static void ResourceDoesNotExist_GetManifestResourceInfo_ReturnsNull() + { + using (MetadataLoadContext lc = new MetadataLoadContext(new SimpleAssemblyResolver())) + { + Assembly a = lc.LoadFromByteArray(TestData.s_AssemblyWithEmbeddedResourcesImage); + ManifestResourceInfo? r = a.GetManifestResourceInfo("ResourceThatDoesNotExist"); + Assert.Null(r); + } + } + + [Fact] + public static void ResourceDoesNotExist_GetManifestResourceStream_ReturnsNull() + { + using (MetadataLoadContext lc = new MetadataLoadContext(new SimpleAssemblyResolver())) + { + Assembly a = lc.LoadFromByteArray(TestData.s_AssemblyWithEmbeddedResourcesImage); + Stream? r = a.GetManifestResourceStream("ResourceThatDoesNotExist"); + Assert.Null(r); + } + } } } diff --git a/src/libraries/System.Reflection.MetadataLoadContext/tests/src/Tests/Module/MultiModuleTests.cs b/src/libraries/System.Reflection.MetadataLoadContext/tests/src/Tests/Module/MultiModuleTests.cs index 578d04f8d51b5..569cc33aa7031 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/tests/src/Tests/Module/MultiModuleTests.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/tests/src/Tests/Module/MultiModuleTests.cs @@ -234,8 +234,8 @@ public static void LoadModule(string moduleName) Assert.Equal(m, m1); Assert.Equal(a, m.Assembly); - Assert.Equal("", m.FullyQualifiedName); - Assert.Equal("", m.Name); + Assert.Equal("", m.FullyQualifiedName); + Assert.Equal("", m.Name); Assert.Equal("Joe.netmodule", m.ScopeName); Assert.Equal(TestData.s_JoeNetModuleMvid, m.ModuleVersionId); } diff --git a/src/libraries/System.Runtime.Extensions/tests/System/AppDomainTests.cs b/src/libraries/System.Runtime.Extensions/tests/System/AppDomainTests.cs index 7360975078aba..ce88bd7162300 100644 --- a/src/libraries/System.Runtime.Extensions/tests/System/AppDomainTests.cs +++ b/src/libraries/System.Runtime.Extensions/tests/System/AppDomainTests.cs @@ -44,9 +44,7 @@ public void RelativeSearchPath_Is_Null() } [Fact] - [SkipOnPlatform(TestPlatforms.Browser, "throws pNSE")] - [ActiveIssue("https://github.com/dotnet/runtime/issues/49868", TestPlatforms.Android)] - [ActiveIssue("https://github.com/dotnet/runtime/issues/36896", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] + [SkipOnPlatform(TestPlatforms.Browser | TestPlatforms.Android | TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst, "The dotnet sdk will not be available on these platforms")] public void TargetFrameworkTest() { const int ExpectedExitCode = 0; @@ -800,9 +798,9 @@ public static void GetPermissionSet() } [Theory] - [ActiveIssue("https://github.com/dotnet/runtime/issues/34030", TestPlatforms.Linux | TestPlatforms.Browser | TestPlatforms.Android, TargetFrameworkMonikers.Netcoreapp, TestRuntimes.Mono)] - [MemberData(nameof(TestingCreateInstanceFromObjectHandleData))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/34030", TestPlatforms.Linux | TestPlatforms.Browser, TargetFrameworkMonikers.Netcoreapp, TestRuntimes.Mono)] [ActiveIssue("https://github.com/dotnet/runtime/issues/36896", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] + [MemberData(nameof(TestingCreateInstanceFromObjectHandleData))] public static void TestingCreateInstanceFromObjectHandle(string physicalFileName, string assemblyFile, string type, string returnedFullNameType, Type exceptionType) { ObjectHandle oh = null; @@ -838,18 +836,29 @@ public static void TestingCreateInstanceFromObjectHandle(string physicalFileName Assert.True(File.Exists(physicalFileName)); } - public static TheoryData TestingCreateInstanceFromObjectHandleData => new TheoryData + public static IEnumerable TestingCreateInstanceFromObjectHandleData() { + Type exceptionType; + + if (PlatformDetection.IsCaseSensitiveOS && PlatformDetection.IsMonoRuntime) + { + exceptionType = typeof(FileNotFoundException); + } + else + { + exceptionType = typeof(TypeLoadException); + } + // string physicalFileName, string assemblyFile, string typeName, returnedFullNameType, expectedException - { "AssemblyResolveTestApp.dll", "AssemblyResolveTestApp.dll", "AssemblyResolveTestApp.PublicClassSample", "AssemblyResolveTestApp.PublicClassSample", null }, - { "AssemblyResolveTestApp.dll", "assemblyresolvetestapp.dll", "assemblyresolvetestapp.publicclasssample", "AssemblyResolveTestApp.PublicClassSample", typeof(TypeLoadException) }, + yield return new object[] { "AssemblyResolveTestApp.dll", "AssemblyResolveTestApp.dll", "AssemblyResolveTestApp.PublicClassSample", "AssemblyResolveTestApp.PublicClassSample", null }; + yield return new object[] { "AssemblyResolveTestApp.dll", "assemblyresolvetestapp.dll", "assemblyresolvetestapp.publicclasssample", "AssemblyResolveTestApp.PublicClassSample", exceptionType }; - { "AssemblyResolveTestApp.dll", "AssemblyResolveTestApp.dll", "AssemblyResolveTestApp.PrivateClassSample", "AssemblyResolveTestApp.PrivateClassSample", null }, - { "AssemblyResolveTestApp.dll", "assemblyresolvetestapp.dll", "assemblyresolvetestapp.privateclasssample", "AssemblyResolveTestApp.PrivateClassSample", typeof(TypeLoadException) }, + yield return new object[] { "AssemblyResolveTestApp.dll", "AssemblyResolveTestApp.dll", "AssemblyResolveTestApp.PrivateClassSample", "AssemblyResolveTestApp.PrivateClassSample", null }; + yield return new object[] { "AssemblyResolveTestApp.dll", "assemblyresolvetestapp.dll", "assemblyresolvetestapp.privateclasssample", "AssemblyResolveTestApp.PrivateClassSample", exceptionType }; - { "AssemblyResolveTestApp.dll", "AssemblyResolveTestApp.dll", "AssemblyResolveTestApp.PublicClassNoDefaultConstructorSample", "AssemblyResolveTestApp.PublicClassNoDefaultConstructorSample", typeof(MissingMethodException) }, - { "AssemblyResolveTestApp.dll", "assemblyresolvetestapp.dll", "assemblyresolvetestapp.publicclassnodefaultconstructorsample", "AssemblyResolveTestApp.PublicClassNoDefaultConstructorSample", typeof(TypeLoadException) } - }; + yield return new object[] { "AssemblyResolveTestApp.dll", "AssemblyResolveTestApp.dll", "AssemblyResolveTestApp.PublicClassNoDefaultConstructorSample", "AssemblyResolveTestApp.PublicClassNoDefaultConstructorSample", typeof(MissingMethodException) }; + yield return new object[] { "AssemblyResolveTestApp.dll", "assemblyresolvetestapp.dll", "assemblyresolvetestapp.publicclassnodefaultconstructorsample", "AssemblyResolveTestApp.PublicClassNoDefaultConstructorSample", exceptionType }; + } [Theory] [MemberData(nameof(TestingCreateInstanceObjectHandleData))] @@ -901,7 +910,7 @@ public static void TestingCreateInstanceObjectHandle(string assemblyName, string }; [Theory] - [ActiveIssue("https://github.com/dotnet/runtime/issues/34030", TestPlatforms.Linux | TestPlatforms.Browser | TestPlatforms.Android, TargetFrameworkMonikers.Netcoreapp, TestRuntimes.Mono)] + [ActiveIssue("https://github.com/dotnet/runtime/issues/34030", TestPlatforms.Linux | TestPlatforms.Browser, TargetFrameworkMonikers.Netcoreapp, TestRuntimes.Mono)] [MemberData(nameof(TestingCreateInstanceFromObjectHandleFullSignatureData))] [ActiveIssue("https://github.com/dotnet/runtime/issues/36896", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public static void TestingCreateInstanceFromObjectHandleFullSignature(string physicalFileName, string assemblyFile, string type, bool ignoreCase, BindingFlags bindingAttr, Binder binder, object[] args, CultureInfo culture, object[] activationAttributes, string returnedFullNameType) @@ -919,14 +928,17 @@ public static IEnumerable TestingCreateInstanceFromObjectHandleFullSig { // string physicalFileName, string assemblyFile, string typeName, bool ignoreCase, BindingFlags bindingAttr, Binder binder, object[] args, CultureInfo culture, object[] activationAttributes, returnedFullNameType yield return new object[] { "AssemblyResolveTestApp.dll", "AssemblyResolveTestApp.dll", "AssemblyResolveTestApp.PublicClassSample", false, BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[0], CultureInfo.InvariantCulture, null, "AssemblyResolveTestApp.PublicClassSample" }; - yield return new object[] { "AssemblyResolveTestApp.dll", "assemblyresolvetestapp.dll", "assemblyresolvetestapp.publicclasssample", true, BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[0], CultureInfo.InvariantCulture, null, "AssemblyResolveTestApp.PublicClassSample" }; yield return new object[] { "AssemblyResolveTestApp.dll", "AssemblyResolveTestApp.dll", "AssemblyResolveTestApp.PublicClassSample", false, BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[1] { 1 }, CultureInfo.InvariantCulture, null, "AssemblyResolveTestApp.PublicClassSample" }; - yield return new object[] { "AssemblyResolveTestApp.dll", "assemblyresolvetestapp.dll", "assemblyresolvetestapp.publicclasssample", true, BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[1] { 1 }, CultureInfo.InvariantCulture, null, "AssemblyResolveTestApp.PublicClassSample" }; - yield return new object[] { "AssemblyResolveTestApp.dll", "AssemblyResolveTestApp.dll", "AssemblyResolveTestApp.PrivateClassSample", false, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[0], CultureInfo.InvariantCulture, null, "AssemblyResolveTestApp.PrivateClassSample" }; - yield return new object[] { "AssemblyResolveTestApp.dll", "assemblyresolvetestapp.dll", "assemblyresolvetestapp.privateclasssample", true, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[0], CultureInfo.InvariantCulture, null, "AssemblyResolveTestApp.PrivateClassSample" }; yield return new object[] { "AssemblyResolveTestApp.dll", "AssemblyResolveTestApp.dll", "AssemblyResolveTestApp.PrivateClassSample", false, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[1] { 1 }, CultureInfo.InvariantCulture, null, "AssemblyResolveTestApp.PrivateClassSample" }; - yield return new object[] { "AssemblyResolveTestApp.dll", "assemblyresolvetestapp.dll", "assemblyresolvetestapp.privateclasssample", true, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[1] { 1 }, CultureInfo.InvariantCulture, null, "AssemblyResolveTestApp.PrivateClassSample" }; + + if (PlatformDetection.IsCaseInsensitiveOS) + { + yield return new object[] { "AssemblyResolveTestApp.dll", "assemblyresolvetestapp.dll", "assemblyresolvetestapp.publicclasssample", true, BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[0], CultureInfo.InvariantCulture, null, "AssemblyResolveTestApp.PublicClassSample" }; + yield return new object[] { "AssemblyResolveTestApp.dll", "assemblyresolvetestapp.dll", "assemblyresolvetestapp.publicclasssample", true, BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[1] { 1 }, CultureInfo.InvariantCulture, null, "AssemblyResolveTestApp.PublicClassSample" }; + yield return new object[] { "AssemblyResolveTestApp.dll", "assemblyresolvetestapp.dll", "assemblyresolvetestapp.privateclasssample", true, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[0], CultureInfo.InvariantCulture, null, "AssemblyResolveTestApp.PrivateClassSample" }; + yield return new object[] { "AssemblyResolveTestApp.dll", "assemblyresolvetestapp.dll", "assemblyresolvetestapp.privateclasssample", true, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[1] { 1 }, CultureInfo.InvariantCulture, null, "AssemblyResolveTestApp.PrivateClassSample" }; + } } [Theory] diff --git a/src/libraries/System.Runtime.Extensions/tests/System/Environment.Exit.cs b/src/libraries/System.Runtime.Extensions/tests/System/Environment.Exit.cs index f6ef6cef9f463..ed187de932e90 100644 --- a/src/libraries/System.Runtime.Extensions/tests/System/Environment.Exit.cs +++ b/src/libraries/System.Runtime.Extensions/tests/System/Environment.Exit.cs @@ -41,8 +41,7 @@ public static void ExitCode_Roundtrips(int exitCode) [InlineData(1)] // setting ExitCode and exiting Main [InlineData(2)] // setting ExitCode both from Main and from an Unloading event handler. [InlineData(3)] // using Exit(exitCode) - [SkipOnPlatform(TestPlatforms.Browser | TestPlatforms.iOS | TestPlatforms.MacCatalyst | TestPlatforms.tvOS, "Not supported on Browser, iOS, MacCatalyst, or tvOS.")] - [ActiveIssue("https://github.com/dotnet/runtime/issues/49868", TestPlatforms.Android)] + [SkipOnPlatform(TestPlatforms.Android | TestPlatforms.Browser | TestPlatforms.iOS | TestPlatforms.MacCatalyst | TestPlatforms.tvOS, "Not supported on Android, Browser, iOS, MacCatalyst, or tvOS.")] public static void ExitCode_VoidMainAppReturnsSetValue(int mode) { int expectedExitCode = 123; diff --git a/src/libraries/System.Runtime.Extensions/tests/System/StringComparer.cs b/src/libraries/System.Runtime.Extensions/tests/System/StringComparer.cs index ef8cd8945e38e..f4e28a34b8dfb 100644 --- a/src/libraries/System.Runtime.Extensions/tests/System/StringComparer.cs +++ b/src/libraries/System.Runtime.Extensions/tests/System/StringComparer.cs @@ -87,7 +87,7 @@ public static IEnumerable UpperLowerCasing_TestData() yield return new object[] { "abcd", "ABCD", "en-US" }; yield return new object[] { "latin i", "LATIN I", "en-US" }; - if (PlatformDetection.IsNotInvariantGlobalization) + if (PlatformDetection.IsNotInvariantGlobalization && !PlatformDetection.IsAndroid) { yield return new object[] { "turky \u0131", "TURKY I", "tr-TR" }; yield return new object[] { "turky i", "TURKY \u0130", "tr-TR" }; @@ -96,7 +96,6 @@ public static IEnumerable UpperLowerCasing_TestData() [Theory] [MemberData(nameof(UpperLowerCasing_TestData))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/49868", TestPlatforms.Android)] public static void CreateWithCulturesTest(string lowerForm, string upperForm, string cultureName) { CultureInfo ci = CultureInfo.GetCultureInfo(cultureName); @@ -164,28 +163,33 @@ public static void FromComparisonInvalidTest() AssertExtensions.Throws("comparisonType", () => StringComparer.FromComparison(maxInvalid)); } - public static TheoryData CreateFromCultureAndOptionsData => - new TheoryData + public static IEnumerable CreateFromCultureAndOptionsData() + { + yield return new object[] { "abcd", "ABCD", "en-US", CompareOptions.None, false}; + yield return new object[] { "latin i", "LATIN I", "en-US", CompareOptions.None, false}; + yield return new object[] { "turky \u0131", "TURKY I", "tr-TR", CompareOptions.None, false}; + yield return new object[] { "turky i", "TURKY \u0130", "tr-TR", CompareOptions.None, false}; + yield return new object[] { "abcd", "ABCD", "en-US", CompareOptions.IgnoreCase, true}; + yield return new object[] { "latin i", "LATIN I", "en-US", CompareOptions.IgnoreCase, true}; + + // Android has its own ICU, which doesn't work well with tr + if (!PlatformDetection.IsAndroid) { - { "abcd", "ABCD", "en-US", CompareOptions.None, false}, - { "latin i", "LATIN I", "en-US", CompareOptions.None, false}, - { "turky \u0131", "TURKY I", "tr-TR", CompareOptions.None, false}, - { "turky i", "TURKY \u0130", "tr-TR", CompareOptions.None, false}, - { "abcd", "ABCD", "en-US", CompareOptions.IgnoreCase, true}, - { "latin i", "LATIN I", "en-US", CompareOptions.IgnoreCase, true}, - { "turky \u0131", "TURKY I", "tr-TR", CompareOptions.IgnoreCase, true}, - { "turky i", "TURKY \u0130", "tr-TR", CompareOptions.IgnoreCase, true}, - { "abcd", "ab cd", "en-US", CompareOptions.IgnoreSymbols, true }, - { "abcd", "ab+cd", "en-US", CompareOptions.IgnoreSymbols, true }, - { "abcd", "ab%cd", "en-US", CompareOptions.IgnoreSymbols, true }, - { "abcd", "ab&cd", "en-US", CompareOptions.IgnoreSymbols, true }, - { "abcd", "ab$cd", "en-US", CompareOptions.IgnoreSymbols, true }, - { "abcd", "ab$cd", "en-US", CompareOptions.IgnoreSymbols, true }, - { "a-bcd", "ab$cd", "en-US", CompareOptions.IgnoreSymbols, true }, - { "abcd*", "ab$cd", "en-US", CompareOptions.IgnoreSymbols, true }, - { "ab$dd", "ab$cd", "en-US", CompareOptions.IgnoreSymbols, false }, - { "abcd", "ab$cd", "en-US", CompareOptions.IgnoreSymbols, true }, - }; + yield return new object[] { "turky \u0131", "TURKY I", "tr-TR", CompareOptions.IgnoreCase, true}; + yield return new object[] { "turky i", "TURKY \u0130", "tr-TR", CompareOptions.IgnoreCase, true}; + } + + yield return new object[] { "abcd", "ab cd", "en-US", CompareOptions.IgnoreSymbols, true }; + yield return new object[] { "abcd", "ab+cd", "en-US", CompareOptions.IgnoreSymbols, true }; + yield return new object[] { "abcd", "ab%cd", "en-US", CompareOptions.IgnoreSymbols, true }; + yield return new object[] { "abcd", "ab&cd", "en-US", CompareOptions.IgnoreSymbols, true }; + yield return new object[] { "abcd", "ab$cd", "en-US", CompareOptions.IgnoreSymbols, true }; + yield return new object[] { "abcd", "ab$cd", "en-US", CompareOptions.IgnoreSymbols, true }; + yield return new object[] { "a-bcd", "ab$cd", "en-US", CompareOptions.IgnoreSymbols, true }; + yield return new object[] { "abcd*", "ab$cd", "en-US", CompareOptions.IgnoreSymbols, true }; + yield return new object[] { "ab$dd", "ab$cd", "en-US", CompareOptions.IgnoreSymbols, false }; + yield return new object[] { "abcd", "ab$cd", "en-US", CompareOptions.IgnoreSymbols, true }; + } public static TheoryData CreateFromCultureAndOptionsStringSortData => new TheoryData { @@ -196,7 +200,6 @@ public static void FromComparisonInvalidTest() [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsNotInvariantGlobalization))] [MemberData(nameof(CreateFromCultureAndOptionsData))] [MemberData(nameof(CreateFromCultureAndOptionsStringSortData))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/49868", TestPlatforms.Android)] public static void CreateFromCultureAndOptions(string actualString, string expectedString, string cultureName, CompareOptions options, bool result) { CultureInfo ci = CultureInfo.GetCultureInfo(cultureName); @@ -208,7 +211,6 @@ public static void CreateFromCultureAndOptions(string actualString, string expec [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsNotInvariantGlobalization))] [MemberData(nameof(CreateFromCultureAndOptionsData))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/49868", TestPlatforms.Android)] public static void CreateFromCultureAndOptionsStringSort(string actualString, string expectedString, string cultureName, CompareOptions options, bool result) { CultureInfo ci = CultureInfo.GetCultureInfo(cultureName); diff --git a/src/libraries/System.Runtime.InteropServices/ref/System.Runtime.InteropServices.cs b/src/libraries/System.Runtime.InteropServices/ref/System.Runtime.InteropServices.cs index e6c03d03d2418..feb8ae7135abb 100644 --- a/src/libraries/System.Runtime.InteropServices/ref/System.Runtime.InteropServices.cs +++ b/src/libraries/System.Runtime.InteropServices/ref/System.Runtime.InteropServices.cs @@ -1125,7 +1125,11 @@ public enum CreateObjectFlags Aggregation = 4, Unwrap = 8, } - [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] + [System.Runtime.Versioning.UnsupportedOSPlatform("browser")] + [System.Runtime.Versioning.UnsupportedOSPlatform("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatform("maccatalyst")] + [System.Runtime.Versioning.UnsupportedOSPlatform("tvos")] [System.CLSCompliantAttribute(false)] public abstract class ComWrappers { @@ -1147,6 +1151,7 @@ public struct ComInterfaceDispatch public object GetOrRegisterObjectForComInstance(System.IntPtr externalComObject, CreateObjectFlags flags, object wrapper, System.IntPtr inner) { throw null; } protected abstract void ReleaseObjects(System.Collections.IEnumerable objects); public static void RegisterForTrackerSupport(ComWrappers instance) { } + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] public static void RegisterForMarshalling(ComWrappers instance) { } protected static void GetIUnknownImpl(out System.IntPtr fpQueryInterface, out System.IntPtr fpAddRef, out System.IntPtr fpRelease) { throw null; } } diff --git a/src/libraries/System.Runtime.InteropServices/src/MatchingRefApiCompatBaseline.txt b/src/libraries/System.Runtime.InteropServices/src/MatchingRefApiCompatBaseline.txt index 8a50ec864714b..dd2e06b69c3c2 100644 --- a/src/libraries/System.Runtime.InteropServices/src/MatchingRefApiCompatBaseline.txt +++ b/src/libraries/System.Runtime.InteropServices/src/MatchingRefApiCompatBaseline.txt @@ -1,5 +1,6 @@ Compat issues with assembly System.Runtime.InteropServices: TypesMustExist : Type 'System.Runtime.InteropServices.AssemblyRegistrationFlags' does not exist in the reference but it does exist in the implementation. +CannotChangeAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' on 'System.Runtime.InteropServices.ComWrappers' changed from '[UnsupportedOSPlatformAttribute("android")]' in the implementation to '[UnsupportedOSPlatformAttribute("android")]' in the reference. TypesMustExist : Type 'System.Runtime.InteropServices.ExporterEventKind' does not exist in the reference but it does exist in the implementation. TypesMustExist : Type 'System.Runtime.InteropServices.IDispatchImplAttribute' does not exist in the reference but it does exist in the implementation. TypesMustExist : Type 'System.Runtime.InteropServices.IDispatchImplType' does not exist in the reference but it does exist in the implementation. @@ -7,5 +8,4 @@ TypesMustExist : Type 'System.Runtime.InteropServices.RegistrationClassContext' TypesMustExist : Type 'System.Runtime.InteropServices.RegistrationConnectionType' does not exist in the reference but it does exist in the implementation. TypesMustExist : Type 'System.Runtime.InteropServices.SetWin32ContextInIDispatchAttribute' does not exist in the reference but it does exist in the implementation. MembersMustExist : Member 'public void System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute..ctor()' does not exist in the reference but it does exist in the implementation. -CannotRemoveAttribute : Attribute 'System.CLSCompliantAttribute' exists on 'System.Runtime.InteropServices.ComTypes.IDataObject' in the implementation but not the reference. Total Issues: 9 diff --git a/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.Tests.csproj b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.Tests.csproj index f0ffe70d47c31..5235b8023a63d 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.Tests.csproj +++ b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.Tests.csproj @@ -137,6 +137,7 @@ + diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/AddRefTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/AddRefTests.cs index c8cd89168b352..ec5ae351bc79c 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/AddRefTests.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/AddRefTests.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Runtime.InteropServices.Tests.Common; using Xunit; namespace System.Runtime.InteropServices.Tests @@ -8,10 +9,11 @@ namespace System.Runtime.InteropServices.Tests public class AddRefTests { [Fact] - [PlatformSpecific(TestPlatforms.Windows)] + [SkipOnMono("ComWrappers are not supported on Mono")] public void AddRef_ValidPointer_Success() { - IntPtr iUnknown = Marshal.GetIUnknownForObject(new object()); + var cw = new ComWrappersImpl(); + IntPtr iUnknown = cw.GetOrCreateComInterfaceForObject(new object(), CreateComInterfaceFlags.None); try { Assert.Equal(2, Marshal.AddRef(iUnknown)); diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/Common/COMWrappersImpl.cs b/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/Common/COMWrappersImpl.cs new file mode 100644 index 0000000000000..f6b7180c299e3 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/Common/COMWrappersImpl.cs @@ -0,0 +1,43 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections; +using System.Runtime.CompilerServices; +using Xunit; + +namespace System.Runtime.InteropServices.Tests.Common +{ + public class ComWrappersImpl : ComWrappers + { + // Doesn't represent a real interface. The value is only used to support a call to QueryInterface for testing. + public const string IID_TestQueryInterface = "1F906666-B388-4729-B78C-826BC5FD4245"; + + protected unsafe override ComInterfaceEntry* ComputeVtables(object obj, CreateComInterfaceFlags flags, out int count) + { + Assert.Equal(CreateComInterfaceFlags.None, flags); + + IntPtr fpQueryInterface = default; + IntPtr fpAddRef = default; + IntPtr fpRelease = default; + ComWrappers.GetIUnknownImpl(out fpQueryInterface, out fpAddRef, out fpRelease); + + var vtblRaw = (IntPtr*)RuntimeHelpers.AllocateTypeAssociatedMemory(typeof(ComWrappersImpl), IntPtr.Size * 3); + vtblRaw[0] = fpQueryInterface; + vtblRaw[1] = fpAddRef; + vtblRaw[2] = fpRelease; + + var entryRaw = (ComInterfaceEntry*)RuntimeHelpers.AllocateTypeAssociatedMemory(typeof(ComWrappersImpl), sizeof(ComInterfaceEntry)); + entryRaw->IID = new Guid(IID_TestQueryInterface); + entryRaw->Vtable = (IntPtr)vtblRaw; + + count = 1; + return entryRaw; + } + + protected override object CreateObject(IntPtr externalComObject, CreateObjectFlags flag) + => throw new NotImplementedException(); + + protected override void ReleaseObjects(IEnumerable objects) + => throw new NotImplementedException(); + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/QueryInterfaceTests.Windows.cs b/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/QueryInterfaceTests.Windows.cs index 30657253cc824..74ffdaad3b2db 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/QueryInterfaceTests.Windows.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/QueryInterfaceTests.Windows.cs @@ -9,6 +9,7 @@ namespace System.Runtime.InteropServices.Tests { public partial class QueryInterfaceTests { + public const string IID_IDISPATCH = "00020400-0000-0000-C000-000000000046"; public const string IID_IINSPECTABLE = "AF86E2E0-B12D-4c6a-9C5A-D7AA65101E90"; public static IEnumerable QueryInterface_ValidComObjectInterface_TestData() @@ -45,7 +46,25 @@ public static IEnumerable QueryInterface_ValidComObjectInterface_TestD [MemberData(nameof(QueryInterface_ValidComObjectInterface_TestData))] public void QueryInterface_ValidComObjectInterface_Success(object o, string iidString) { - QueryInterface_ValidInterface_Success(o, iidString); + IntPtr ptr = Marshal.GetIUnknownForObject(o); + try + { + Guid guid = new Guid(iidString); + Assert.Equal(0, Marshal.QueryInterface(ptr, ref guid, out IntPtr ppv)); + Assert.NotEqual(IntPtr.Zero, ppv); + try + { + Assert.Equal(new Guid(iidString), guid); + } + finally + { + Marshal.Release(ppv); + } + } + finally + { + Marshal.Release(ptr); + } } public static IEnumerable QueryInterface_NoSuchComObjectInterface_TestData() @@ -83,7 +102,18 @@ public static IEnumerable QueryInterface_NoSuchComObjectInterface_Test [MemberData(nameof(QueryInterface_NoSuchComObjectInterface_TestData))] public void QueryInterface_NoSuchComObjectInterface_Success(object o, string iidString) { - QueryInterface_NoSuchInterface_Success(o, iidString); + IntPtr ptr = Marshal.GetIUnknownForObject(o); + try + { + Guid iid = new Guid(iidString); + Assert.Equal(E_NOINTERFACE, Marshal.QueryInterface(ptr, ref iid, out IntPtr ppv)); + Assert.Equal(IntPtr.Zero, ppv); + Assert.Equal(new Guid(iidString), iid); + } + finally + { + Marshal.Release(ptr); + } } } } diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/QueryInterfaceTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/QueryInterfaceTests.cs index fbb7ca8c0fa6b..a52f710abf576 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/QueryInterfaceTests.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/QueryInterfaceTests.cs @@ -12,71 +12,28 @@ public partial class QueryInterfaceTests { public const int E_NOINTERFACE = unchecked((int)0x80004002); public const string IID_IUNKNOWN = "00000000-0000-0000-C000-000000000046"; - public const string IID_IDISPATCH = "00020400-0000-0000-C000-000000000046"; public static IEnumerable QueryInterface_ValidInterface_TestData() { yield return new object[] { new object(), IID_IUNKNOWN }; - yield return new object[] { new object(), IID_IDISPATCH }; - - yield return new object[] { 10, IID_IUNKNOWN }; - if (!PlatformDetection.IsNetCore) - { - yield return new object[] { 10, IID_IDISPATCH }; - } - - yield return new object[] { "string", IID_IUNKNOWN }; - if (!PlatformDetection.IsNetCore) - { - yield return new object[] { "string", IID_IDISPATCH }; - } - - yield return new object[] { new NonGenericClass(), IID_IUNKNOWN }; - if (!PlatformDetection.IsNetCore) - { - yield return new object[] { new NonGenericClass(), IID_IDISPATCH }; - } - yield return new object[] { new GenericClass(), IID_IUNKNOWN }; - - yield return new object[] { new NonGenericStruct(), IID_IUNKNOWN }; - if (!PlatformDetection.IsNetCore) - { - yield return new object[] { new NonGenericStruct(), IID_IDISPATCH }; - } - yield return new object[] { new GenericStruct(), IID_IUNKNOWN }; - - yield return new object[] { Int32Enum.Value1, IID_IUNKNOWN }; - if (!PlatformDetection.IsNetCore) - { - yield return new object[] { Int32Enum.Value1, IID_IDISPATCH }; - } - - yield return new object[] { new int[] { 10 }, IID_IUNKNOWN }; - yield return new object[] { new int[][] { new int[] { 10 } }, IID_IUNKNOWN }; - yield return new object[] { new int[,] { { 10 } }, IID_IUNKNOWN }; - - MethodInfo method = typeof(GetObjectForIUnknownTests).GetMethod(nameof(NonGenericMethod), BindingFlags.NonPublic | BindingFlags.Static); - Delegate d = method.CreateDelegate(typeof(NonGenericDelegate)); - yield return new object[] { d, IID_IUNKNOWN }; - yield return new object[] { d, IID_IDISPATCH }; - - yield return new object[] { new KeyValuePair("key", 10), IID_IUNKNOWN }; + yield return new object[] { new object(), ComWrappersImpl.IID_TestQueryInterface }; } [Theory] [MemberData(nameof(QueryInterface_ValidInterface_TestData))] - [PlatformSpecific(TestPlatforms.Windows)] - public void QueryInterface_ValidInterface_Success(object o, string guid) + [SkipOnMono("ComWrappers are not supported on Mono")] + public void QueryInterface_ValidInterface_Success(object o, string iidString) { - IntPtr ptr = Marshal.GetIUnknownForObject(o); + var cw = new ComWrappersImpl(); + IntPtr ptr = cw.GetOrCreateComInterfaceForObject(o, CreateComInterfaceFlags.None); try { - Guid iidString = new Guid(guid); - Assert.Equal(0, Marshal.QueryInterface(ptr, ref iidString, out IntPtr ppv)); + Guid guid = new Guid(iidString); + Assert.Equal(0, Marshal.QueryInterface(ptr, ref guid, out IntPtr ppv)); Assert.NotEqual(IntPtr.Zero, ppv); try { - Assert.Equal(new Guid(guid), iidString); + Assert.Equal(new Guid(iidString), guid); } finally { @@ -93,23 +50,15 @@ public static IEnumerable QueryInterface_NoSuchInterface_TestData() { yield return new object[] { new object(), Guid.Empty.ToString() }; yield return new object[] { new object(), "927971f5-0939-11d1-8be1-00c04fd8d503" }; - - yield return new object[] { new int[] { 10 }, IID_IDISPATCH }; - yield return new object[] { new int[][] { new int[] { 10 } }, IID_IDISPATCH }; - yield return new object[] { new int[,] { { 10 } }, IID_IDISPATCH }; - - yield return new object[] { new GenericClass(), IID_IDISPATCH }; - yield return new object[] { new Dictionary(), IID_IDISPATCH }; - yield return new object[] { new GenericStruct(), IID_IDISPATCH }; - yield return new object[] { new KeyValuePair(), IID_IDISPATCH }; } [Theory] [MemberData(nameof(QueryInterface_NoSuchInterface_TestData))] - [PlatformSpecific(TestPlatforms.Windows)] + [SkipOnMono("ComWrappers are not supported on Mono")] public void QueryInterface_NoSuchInterface_Success(object o, string iidString) { - IntPtr ptr = Marshal.GetIUnknownForObject(o); + var cw = new ComWrappersImpl(); + IntPtr ptr = cw.GetOrCreateComInterfaceForObject(o, CreateComInterfaceFlags.None); try { Guid iid = new Guid(iidString); @@ -129,10 +78,5 @@ public void QueryInterface_ZeroPointer_ThrowsArgumentNullException() Guid iid = Guid.Empty; AssertExtensions.Throws("pUnk", () => Marshal.QueryInterface(IntPtr.Zero, ref iid, out IntPtr ppv)); } - - private static void NonGenericMethod(int i) { } - public delegate void NonGenericDelegate(int i); - - public enum Int32Enum : int { Value1, Value2 } } } diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/ReleaseTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/ReleaseTests.cs index 211270c699578..3ef69cfc0920f 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/ReleaseTests.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/ReleaseTests.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Runtime.InteropServices.Tests.Common; using Xunit; namespace System.Runtime.InteropServices.Tests @@ -8,10 +9,11 @@ namespace System.Runtime.InteropServices.Tests public class ReleaseTests { [Fact] - [PlatformSpecific(TestPlatforms.Windows)] + [SkipOnMono("ComWrappers are not supported on Mono")] public void Release_ValidPointer_Success() { - IntPtr iUnknown = Marshal.GetIUnknownForObject(new object()); + var cw = new ComWrappersImpl(); + IntPtr iUnknown = cw.GetOrCreateComInterfaceForObject(new object(), CreateComInterfaceFlags.None); try { Marshal.AddRef(iUnknown); diff --git a/src/libraries/System.Runtime.Loader/System.Runtime.Loader.sln b/src/libraries/System.Runtime.Loader/System.Runtime.Loader.sln index 7a8d6cf736121..f9468b7e1fd66 100644 --- a/src/libraries/System.Runtime.Loader/System.Runtime.Loader.sln +++ b/src/libraries/System.Runtime.Loader/System.Runtime.Loader.sln @@ -1,4 +1,8 @@ -Microsoft Visual Studio Solution File, Format Version 12.00 + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.31515.178 +MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Private.CoreLib", "..\..\coreclr\System.Private.CoreLib\System.Private.CoreLib.csproj", "{64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestUtilities", "..\Common\tests\TestUtilities\TestUtilities.csproj", "{D6D16FFD-FD76-4700-B456-1DC4D093D1B5}" @@ -47,55 +51,102 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ref", "ref", "{C75ECE17-3CF EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{6963C709-FD2F-45A7-9A9D-431B1E9A4796}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Reflection.Metadata.ApplyUpdate.Test.CustomAttributeDelete", "tests\ApplyUpdate\System.Reflection.Metadata.ApplyUpdate.Test.CustomAttributeDelete\System.Reflection.Metadata.ApplyUpdate.Test.CustomAttributeDelete.csproj", "{EEAE2A15-E2AE-4421-8D30-AAB17AC805F8}" +EndProject Global + GlobalSection(SharedMSBuildProjectFiles) = preSolution + ..\System.Private.CoreLib\src\System.Private.CoreLib.Shared.projitems*{64ddd2af-bf90-4dd8-ac24-d2084db8d558}*SharedItemsImports = 5 + EndGlobalSection GlobalSection(SolutionConfigurationPlatforms) = preSolution + Checked|Any CPU = Checked|Any CPU + Checked|x64 = Checked|x64 + Checked|x86 = Checked|x86 Debug|Any CPU = Debug|Any CPU Debug|x64 = Debug|x64 Debug|x86 = Debug|x86 Release|Any CPU = Release|Any CPU Release|x64 = Release|x64 Release|x86 = Release|x86 - Checked|Any CPU = Checked|Any CPU - Checked|x64 = Checked|x64 - Checked|x86 = Checked|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {29E02AA9-E3D5-400C-B2C5-970B6E6D8562}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {29E02AA9-E3D5-400C-B2C5-970B6E6D8562}.Debug|Any CPU.Build.0 = Debug|Any CPU - {29E02AA9-E3D5-400C-B2C5-970B6E6D8562}.Debug|x64.ActiveCfg = Debug|Any CPU - {29E02AA9-E3D5-400C-B2C5-970B6E6D8562}.Debug|x64.Build.0 = Debug|Any CPU - {29E02AA9-E3D5-400C-B2C5-970B6E6D8562}.Debug|x86.ActiveCfg = Debug|Any CPU - {29E02AA9-E3D5-400C-B2C5-970B6E6D8562}.Debug|x86.Build.0 = Debug|Any CPU - {29E02AA9-E3D5-400C-B2C5-970B6E6D8562}.Release|Any CPU.ActiveCfg = Release|Any CPU - {29E02AA9-E3D5-400C-B2C5-970B6E6D8562}.Release|Any CPU.Build.0 = Release|Any CPU - {29E02AA9-E3D5-400C-B2C5-970B6E6D8562}.Release|x64.ActiveCfg = Release|Any CPU - {29E02AA9-E3D5-400C-B2C5-970B6E6D8562}.Release|x64.Build.0 = Release|Any CPU - {29E02AA9-E3D5-400C-B2C5-970B6E6D8562}.Release|x86.ActiveCfg = Release|Any CPU - {29E02AA9-E3D5-400C-B2C5-970B6E6D8562}.Release|x86.Build.0 = Release|Any CPU - {29E02AA9-E3D5-400C-B2C5-970B6E6D8562}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {29E02AA9-E3D5-400C-B2C5-970B6E6D8562}.Checked|Any CPU.Build.0 = Debug|Any CPU - {29E02AA9-E3D5-400C-B2C5-970B6E6D8562}.Checked|x64.ActiveCfg = Debug|Any CPU - {29E02AA9-E3D5-400C-B2C5-970B6E6D8562}.Checked|x64.Build.0 = Debug|Any CPU - {29E02AA9-E3D5-400C-B2C5-970B6E6D8562}.Checked|x86.ActiveCfg = Debug|Any CPU - {29E02AA9-E3D5-400C-B2C5-970B6E6D8562}.Checked|x86.Build.0 = Debug|Any CPU - {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159}.Debug|x64.ActiveCfg = Debug|Any CPU - {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159}.Debug|x64.Build.0 = Debug|Any CPU - {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159}.Debug|x86.ActiveCfg = Debug|Any CPU - {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159}.Debug|x86.Build.0 = Debug|Any CPU - {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159}.Release|Any CPU.Build.0 = Release|Any CPU - {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159}.Release|x64.ActiveCfg = Release|Any CPU - {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159}.Release|x64.Build.0 = Release|Any CPU - {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159}.Release|x86.ActiveCfg = Release|Any CPU - {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159}.Release|x86.Build.0 = Release|Any CPU - {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159}.Checked|Any CPU.Build.0 = Debug|Any CPU - {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159}.Checked|x64.ActiveCfg = Debug|Any CPU - {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159}.Checked|x64.Build.0 = Debug|Any CPU - {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159}.Checked|x86.ActiveCfg = Debug|Any CPU - {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159}.Checked|x86.Build.0 = Debug|Any CPU + {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}.Checked|Any CPU.ActiveCfg = Checked|x64 + {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}.Checked|Any CPU.Build.0 = Checked|x64 + {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}.Checked|x64.ActiveCfg = Checked|x64 + {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}.Checked|x64.Build.0 = Checked|x64 + {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}.Checked|x86.ActiveCfg = Checked|x86 + {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}.Checked|x86.Build.0 = Checked|x86 + {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}.Debug|Any CPU.ActiveCfg = Debug|x64 + {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}.Debug|Any CPU.Build.0 = Debug|x64 + {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}.Debug|x64.ActiveCfg = Debug|x64 + {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}.Debug|x64.Build.0 = Debug|x64 + {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}.Debug|x86.ActiveCfg = Debug|x86 + {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}.Debug|x86.Build.0 = Debug|x86 + {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}.Release|Any CPU.ActiveCfg = Release|x64 + {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}.Release|Any CPU.Build.0 = Release|x64 + {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}.Release|x64.ActiveCfg = Release|x64 + {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}.Release|x64.Build.0 = Release|x64 + {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}.Release|x86.ActiveCfg = Release|x86 + {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}.Release|x86.Build.0 = Release|x86 + {D6D16FFD-FD76-4700-B456-1DC4D093D1B5}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {D6D16FFD-FD76-4700-B456-1DC4D093D1B5}.Checked|Any CPU.Build.0 = Debug|Any CPU + {D6D16FFD-FD76-4700-B456-1DC4D093D1B5}.Checked|x64.ActiveCfg = Debug|Any CPU + {D6D16FFD-FD76-4700-B456-1DC4D093D1B5}.Checked|x64.Build.0 = Debug|Any CPU + {D6D16FFD-FD76-4700-B456-1DC4D093D1B5}.Checked|x86.ActiveCfg = Debug|Any CPU + {D6D16FFD-FD76-4700-B456-1DC4D093D1B5}.Checked|x86.Build.0 = Debug|Any CPU + {D6D16FFD-FD76-4700-B456-1DC4D093D1B5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D6D16FFD-FD76-4700-B456-1DC4D093D1B5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D6D16FFD-FD76-4700-B456-1DC4D093D1B5}.Debug|x64.ActiveCfg = Debug|Any CPU + {D6D16FFD-FD76-4700-B456-1DC4D093D1B5}.Debug|x64.Build.0 = Debug|Any CPU + {D6D16FFD-FD76-4700-B456-1DC4D093D1B5}.Debug|x86.ActiveCfg = Debug|Any CPU + {D6D16FFD-FD76-4700-B456-1DC4D093D1B5}.Debug|x86.Build.0 = Debug|Any CPU + {D6D16FFD-FD76-4700-B456-1DC4D093D1B5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D6D16FFD-FD76-4700-B456-1DC4D093D1B5}.Release|Any CPU.Build.0 = Release|Any CPU + {D6D16FFD-FD76-4700-B456-1DC4D093D1B5}.Release|x64.ActiveCfg = Release|Any CPU + {D6D16FFD-FD76-4700-B456-1DC4D093D1B5}.Release|x64.Build.0 = Release|Any CPU + {D6D16FFD-FD76-4700-B456-1DC4D093D1B5}.Release|x86.ActiveCfg = Release|Any CPU + {D6D16FFD-FD76-4700-B456-1DC4D093D1B5}.Release|x86.Build.0 = Release|Any CPU + {8D19CD03-08EE-4574-B798-C658502C0A42}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {8D19CD03-08EE-4574-B798-C658502C0A42}.Checked|Any CPU.Build.0 = Debug|Any CPU + {8D19CD03-08EE-4574-B798-C658502C0A42}.Checked|x64.ActiveCfg = Debug|Any CPU + {8D19CD03-08EE-4574-B798-C658502C0A42}.Checked|x64.Build.0 = Debug|Any CPU + {8D19CD03-08EE-4574-B798-C658502C0A42}.Checked|x86.ActiveCfg = Debug|Any CPU + {8D19CD03-08EE-4574-B798-C658502C0A42}.Checked|x86.Build.0 = Debug|Any CPU + {8D19CD03-08EE-4574-B798-C658502C0A42}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8D19CD03-08EE-4574-B798-C658502C0A42}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8D19CD03-08EE-4574-B798-C658502C0A42}.Debug|x64.ActiveCfg = Debug|Any CPU + {8D19CD03-08EE-4574-B798-C658502C0A42}.Debug|x64.Build.0 = Debug|Any CPU + {8D19CD03-08EE-4574-B798-C658502C0A42}.Debug|x86.ActiveCfg = Debug|Any CPU + {8D19CD03-08EE-4574-B798-C658502C0A42}.Debug|x86.Build.0 = Debug|Any CPU + {8D19CD03-08EE-4574-B798-C658502C0A42}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8D19CD03-08EE-4574-B798-C658502C0A42}.Release|Any CPU.Build.0 = Release|Any CPU + {8D19CD03-08EE-4574-B798-C658502C0A42}.Release|x64.ActiveCfg = Release|Any CPU + {8D19CD03-08EE-4574-B798-C658502C0A42}.Release|x64.Build.0 = Release|Any CPU + {8D19CD03-08EE-4574-B798-C658502C0A42}.Release|x86.ActiveCfg = Release|Any CPU + {8D19CD03-08EE-4574-B798-C658502C0A42}.Release|x86.Build.0 = Release|Any CPU + {04BA3E3C-6979-4792-B19E-C797AD607F42}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {04BA3E3C-6979-4792-B19E-C797AD607F42}.Checked|Any CPU.Build.0 = Debug|Any CPU + {04BA3E3C-6979-4792-B19E-C797AD607F42}.Checked|x64.ActiveCfg = Debug|Any CPU + {04BA3E3C-6979-4792-B19E-C797AD607F42}.Checked|x64.Build.0 = Debug|Any CPU + {04BA3E3C-6979-4792-B19E-C797AD607F42}.Checked|x86.ActiveCfg = Debug|Any CPU + {04BA3E3C-6979-4792-B19E-C797AD607F42}.Checked|x86.Build.0 = Debug|Any CPU + {04BA3E3C-6979-4792-B19E-C797AD607F42}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {04BA3E3C-6979-4792-B19E-C797AD607F42}.Debug|Any CPU.Build.0 = Debug|Any CPU + {04BA3E3C-6979-4792-B19E-C797AD607F42}.Debug|x64.ActiveCfg = Debug|Any CPU + {04BA3E3C-6979-4792-B19E-C797AD607F42}.Debug|x64.Build.0 = Debug|Any CPU + {04BA3E3C-6979-4792-B19E-C797AD607F42}.Debug|x86.ActiveCfg = Debug|Any CPU + {04BA3E3C-6979-4792-B19E-C797AD607F42}.Debug|x86.Build.0 = Debug|Any CPU + {04BA3E3C-6979-4792-B19E-C797AD607F42}.Release|Any CPU.ActiveCfg = Release|Any CPU + {04BA3E3C-6979-4792-B19E-C797AD607F42}.Release|Any CPU.Build.0 = Release|Any CPU + {04BA3E3C-6979-4792-B19E-C797AD607F42}.Release|x64.ActiveCfg = Release|Any CPU + {04BA3E3C-6979-4792-B19E-C797AD607F42}.Release|x64.Build.0 = Release|Any CPU + {04BA3E3C-6979-4792-B19E-C797AD607F42}.Release|x86.ActiveCfg = Release|Any CPU + {04BA3E3C-6979-4792-B19E-C797AD607F42}.Release|x86.Build.0 = Release|Any CPU + {95B66B14-BCC7-407A-930C-4B34D4F7EC98}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {95B66B14-BCC7-407A-930C-4B34D4F7EC98}.Checked|Any CPU.Build.0 = Debug|Any CPU + {95B66B14-BCC7-407A-930C-4B34D4F7EC98}.Checked|x64.ActiveCfg = Debug|Any CPU + {95B66B14-BCC7-407A-930C-4B34D4F7EC98}.Checked|x64.Build.0 = Debug|Any CPU + {95B66B14-BCC7-407A-930C-4B34D4F7EC98}.Checked|x86.ActiveCfg = Debug|Any CPU + {95B66B14-BCC7-407A-930C-4B34D4F7EC98}.Checked|x86.Build.0 = Debug|Any CPU {95B66B14-BCC7-407A-930C-4B34D4F7EC98}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {95B66B14-BCC7-407A-930C-4B34D4F7EC98}.Debug|Any CPU.Build.0 = Debug|Any CPU {95B66B14-BCC7-407A-930C-4B34D4F7EC98}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -108,30 +159,12 @@ Global {95B66B14-BCC7-407A-930C-4B34D4F7EC98}.Release|x64.Build.0 = Release|Any CPU {95B66B14-BCC7-407A-930C-4B34D4F7EC98}.Release|x86.ActiveCfg = Release|Any CPU {95B66B14-BCC7-407A-930C-4B34D4F7EC98}.Release|x86.Build.0 = Release|Any CPU - {95B66B14-BCC7-407A-930C-4B34D4F7EC98}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {95B66B14-BCC7-407A-930C-4B34D4F7EC98}.Checked|Any CPU.Build.0 = Debug|Any CPU - {95B66B14-BCC7-407A-930C-4B34D4F7EC98}.Checked|x64.ActiveCfg = Debug|Any CPU - {95B66B14-BCC7-407A-930C-4B34D4F7EC98}.Checked|x64.Build.0 = Debug|Any CPU - {95B66B14-BCC7-407A-930C-4B34D4F7EC98}.Checked|x86.ActiveCfg = Debug|Any CPU - {95B66B14-BCC7-407A-930C-4B34D4F7EC98}.Checked|x86.Build.0 = Debug|Any CPU - {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902}.Debug|x64.ActiveCfg = Debug|Any CPU - {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902}.Debug|x64.Build.0 = Debug|Any CPU - {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902}.Debug|x86.ActiveCfg = Debug|Any CPU - {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902}.Debug|x86.Build.0 = Debug|Any CPU - {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902}.Release|Any CPU.Build.0 = Release|Any CPU - {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902}.Release|x64.ActiveCfg = Release|Any CPU - {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902}.Release|x64.Build.0 = Release|Any CPU - {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902}.Release|x86.ActiveCfg = Release|Any CPU - {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902}.Release|x86.Build.0 = Release|Any CPU - {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902}.Checked|Any CPU.Build.0 = Debug|Any CPU - {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902}.Checked|x64.ActiveCfg = Debug|Any CPU - {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902}.Checked|x64.Build.0 = Debug|Any CPU - {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902}.Checked|x86.ActiveCfg = Debug|Any CPU - {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902}.Checked|x86.Build.0 = Debug|Any CPU + {B8F22D73-B183-4F17-9D5E-04B80699E56A}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {B8F22D73-B183-4F17-9D5E-04B80699E56A}.Checked|Any CPU.Build.0 = Debug|Any CPU + {B8F22D73-B183-4F17-9D5E-04B80699E56A}.Checked|x64.ActiveCfg = Debug|Any CPU + {B8F22D73-B183-4F17-9D5E-04B80699E56A}.Checked|x64.Build.0 = Debug|Any CPU + {B8F22D73-B183-4F17-9D5E-04B80699E56A}.Checked|x86.ActiveCfg = Debug|Any CPU + {B8F22D73-B183-4F17-9D5E-04B80699E56A}.Checked|x86.Build.0 = Debug|Any CPU {B8F22D73-B183-4F17-9D5E-04B80699E56A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {B8F22D73-B183-4F17-9D5E-04B80699E56A}.Debug|Any CPU.Build.0 = Debug|Any CPU {B8F22D73-B183-4F17-9D5E-04B80699E56A}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -144,156 +177,102 @@ Global {B8F22D73-B183-4F17-9D5E-04B80699E56A}.Release|x64.Build.0 = Release|Any CPU {B8F22D73-B183-4F17-9D5E-04B80699E56A}.Release|x86.ActiveCfg = Release|Any CPU {B8F22D73-B183-4F17-9D5E-04B80699E56A}.Release|x86.Build.0 = Release|Any CPU - {B8F22D73-B183-4F17-9D5E-04B80699E56A}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {B8F22D73-B183-4F17-9D5E-04B80699E56A}.Checked|Any CPU.Build.0 = Debug|Any CPU - {B8F22D73-B183-4F17-9D5E-04B80699E56A}.Checked|x64.ActiveCfg = Debug|Any CPU - {B8F22D73-B183-4F17-9D5E-04B80699E56A}.Checked|x64.Build.0 = Debug|Any CPU - {B8F22D73-B183-4F17-9D5E-04B80699E56A}.Checked|x86.ActiveCfg = Debug|Any CPU - {B8F22D73-B183-4F17-9D5E-04B80699E56A}.Checked|x86.Build.0 = Debug|Any CPU - {49B0A873-5834-45A4-9495-E1063005CB82}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {49B0A873-5834-45A4-9495-E1063005CB82}.Debug|Any CPU.Build.0 = Debug|Any CPU - {49B0A873-5834-45A4-9495-E1063005CB82}.Debug|x64.ActiveCfg = Debug|Any CPU - {49B0A873-5834-45A4-9495-E1063005CB82}.Debug|x64.Build.0 = Debug|Any CPU - {49B0A873-5834-45A4-9495-E1063005CB82}.Debug|x86.ActiveCfg = Debug|Any CPU - {49B0A873-5834-45A4-9495-E1063005CB82}.Debug|x86.Build.0 = Debug|Any CPU - {49B0A873-5834-45A4-9495-E1063005CB82}.Release|Any CPU.ActiveCfg = Release|Any CPU - {49B0A873-5834-45A4-9495-E1063005CB82}.Release|Any CPU.Build.0 = Release|Any CPU - {49B0A873-5834-45A4-9495-E1063005CB82}.Release|x64.ActiveCfg = Release|Any CPU - {49B0A873-5834-45A4-9495-E1063005CB82}.Release|x64.Build.0 = Release|Any CPU - {49B0A873-5834-45A4-9495-E1063005CB82}.Release|x86.ActiveCfg = Release|Any CPU - {49B0A873-5834-45A4-9495-E1063005CB82}.Release|x86.Build.0 = Release|Any CPU - {49B0A873-5834-45A4-9495-E1063005CB82}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {49B0A873-5834-45A4-9495-E1063005CB82}.Checked|Any CPU.Build.0 = Debug|Any CPU - {49B0A873-5834-45A4-9495-E1063005CB82}.Checked|x64.ActiveCfg = Debug|Any CPU - {49B0A873-5834-45A4-9495-E1063005CB82}.Checked|x64.Build.0 = Debug|Any CPU - {49B0A873-5834-45A4-9495-E1063005CB82}.Checked|x86.ActiveCfg = Debug|Any CPU - {49B0A873-5834-45A4-9495-E1063005CB82}.Checked|x86.Build.0 = Debug|Any CPU - {D6D16FFD-FD76-4700-B456-1DC4D093D1B5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D6D16FFD-FD76-4700-B456-1DC4D093D1B5}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D6D16FFD-FD76-4700-B456-1DC4D093D1B5}.Debug|x64.ActiveCfg = Debug|Any CPU - {D6D16FFD-FD76-4700-B456-1DC4D093D1B5}.Debug|x64.Build.0 = Debug|Any CPU - {D6D16FFD-FD76-4700-B456-1DC4D093D1B5}.Debug|x86.ActiveCfg = Debug|Any CPU - {D6D16FFD-FD76-4700-B456-1DC4D093D1B5}.Debug|x86.Build.0 = Debug|Any CPU - {D6D16FFD-FD76-4700-B456-1DC4D093D1B5}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D6D16FFD-FD76-4700-B456-1DC4D093D1B5}.Release|Any CPU.Build.0 = Release|Any CPU - {D6D16FFD-FD76-4700-B456-1DC4D093D1B5}.Release|x64.ActiveCfg = Release|Any CPU - {D6D16FFD-FD76-4700-B456-1DC4D093D1B5}.Release|x64.Build.0 = Release|Any CPU - {D6D16FFD-FD76-4700-B456-1DC4D093D1B5}.Release|x86.ActiveCfg = Release|Any CPU - {D6D16FFD-FD76-4700-B456-1DC4D093D1B5}.Release|x86.Build.0 = Release|Any CPU - {D6D16FFD-FD76-4700-B456-1DC4D093D1B5}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {D6D16FFD-FD76-4700-B456-1DC4D093D1B5}.Checked|Any CPU.Build.0 = Debug|Any CPU - {D6D16FFD-FD76-4700-B456-1DC4D093D1B5}.Checked|x64.ActiveCfg = Debug|Any CPU - {D6D16FFD-FD76-4700-B456-1DC4D093D1B5}.Checked|x64.Build.0 = Debug|Any CPU - {D6D16FFD-FD76-4700-B456-1DC4D093D1B5}.Checked|x86.ActiveCfg = Debug|Any CPU - {D6D16FFD-FD76-4700-B456-1DC4D093D1B5}.Checked|x86.Build.0 = Debug|Any CPU - {E60DD367-D1D7-4F6C-919B-DC68E8445E97}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E60DD367-D1D7-4F6C-919B-DC68E8445E97}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E60DD367-D1D7-4F6C-919B-DC68E8445E97}.Debug|x64.ActiveCfg = Debug|Any CPU - {E60DD367-D1D7-4F6C-919B-DC68E8445E97}.Debug|x64.Build.0 = Debug|Any CPU - {E60DD367-D1D7-4F6C-919B-DC68E8445E97}.Debug|x86.ActiveCfg = Debug|Any CPU - {E60DD367-D1D7-4F6C-919B-DC68E8445E97}.Debug|x86.Build.0 = Debug|Any CPU - {E60DD367-D1D7-4F6C-919B-DC68E8445E97}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E60DD367-D1D7-4F6C-919B-DC68E8445E97}.Release|Any CPU.Build.0 = Release|Any CPU - {E60DD367-D1D7-4F6C-919B-DC68E8445E97}.Release|x64.ActiveCfg = Release|Any CPU - {E60DD367-D1D7-4F6C-919B-DC68E8445E97}.Release|x64.Build.0 = Release|Any CPU - {E60DD367-D1D7-4F6C-919B-DC68E8445E97}.Release|x86.ActiveCfg = Release|Any CPU - {E60DD367-D1D7-4F6C-919B-DC68E8445E97}.Release|x86.Build.0 = Release|Any CPU - {E60DD367-D1D7-4F6C-919B-DC68E8445E97}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {E60DD367-D1D7-4F6C-919B-DC68E8445E97}.Checked|Any CPU.Build.0 = Debug|Any CPU - {E60DD367-D1D7-4F6C-919B-DC68E8445E97}.Checked|x64.ActiveCfg = Debug|Any CPU - {E60DD367-D1D7-4F6C-919B-DC68E8445E97}.Checked|x64.Build.0 = Debug|Any CPU - {E60DD367-D1D7-4F6C-919B-DC68E8445E97}.Checked|x86.ActiveCfg = Debug|Any CPU - {E60DD367-D1D7-4F6C-919B-DC68E8445E97}.Checked|x86.Build.0 = Debug|Any CPU - {9AD657ED-396B-4BE7-BCB6-BCA130825418}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {9AD657ED-396B-4BE7-BCB6-BCA130825418}.Debug|Any CPU.Build.0 = Debug|Any CPU - {9AD657ED-396B-4BE7-BCB6-BCA130825418}.Debug|x64.ActiveCfg = Debug|Any CPU - {9AD657ED-396B-4BE7-BCB6-BCA130825418}.Debug|x64.Build.0 = Debug|Any CPU - {9AD657ED-396B-4BE7-BCB6-BCA130825418}.Debug|x86.ActiveCfg = Debug|Any CPU - {9AD657ED-396B-4BE7-BCB6-BCA130825418}.Debug|x86.Build.0 = Debug|Any CPU - {9AD657ED-396B-4BE7-BCB6-BCA130825418}.Release|Any CPU.ActiveCfg = Release|Any CPU - {9AD657ED-396B-4BE7-BCB6-BCA130825418}.Release|Any CPU.Build.0 = Release|Any CPU - {9AD657ED-396B-4BE7-BCB6-BCA130825418}.Release|x64.ActiveCfg = Release|Any CPU - {9AD657ED-396B-4BE7-BCB6-BCA130825418}.Release|x64.Build.0 = Release|Any CPU - {9AD657ED-396B-4BE7-BCB6-BCA130825418}.Release|x86.ActiveCfg = Release|Any CPU - {9AD657ED-396B-4BE7-BCB6-BCA130825418}.Release|x86.Build.0 = Release|Any CPU - {9AD657ED-396B-4BE7-BCB6-BCA130825418}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {9AD657ED-396B-4BE7-BCB6-BCA130825418}.Checked|Any CPU.Build.0 = Debug|Any CPU - {9AD657ED-396B-4BE7-BCB6-BCA130825418}.Checked|x64.ActiveCfg = Debug|Any CPU - {9AD657ED-396B-4BE7-BCB6-BCA130825418}.Checked|x64.Build.0 = Debug|Any CPU - {9AD657ED-396B-4BE7-BCB6-BCA130825418}.Checked|x86.ActiveCfg = Debug|Any CPU - {9AD657ED-396B-4BE7-BCB6-BCA130825418}.Checked|x86.Build.0 = Debug|Any CPU - {44B22827-B9F0-4ADC-969C-7EC647D0B82A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {44B22827-B9F0-4ADC-969C-7EC647D0B82A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {44B22827-B9F0-4ADC-969C-7EC647D0B82A}.Debug|x64.ActiveCfg = Debug|Any CPU - {44B22827-B9F0-4ADC-969C-7EC647D0B82A}.Debug|x64.Build.0 = Debug|Any CPU - {44B22827-B9F0-4ADC-969C-7EC647D0B82A}.Debug|x86.ActiveCfg = Debug|Any CPU - {44B22827-B9F0-4ADC-969C-7EC647D0B82A}.Debug|x86.Build.0 = Debug|Any CPU - {44B22827-B9F0-4ADC-969C-7EC647D0B82A}.Release|Any CPU.ActiveCfg = Release|Any CPU - {44B22827-B9F0-4ADC-969C-7EC647D0B82A}.Release|Any CPU.Build.0 = Release|Any CPU - {44B22827-B9F0-4ADC-969C-7EC647D0B82A}.Release|x64.ActiveCfg = Release|Any CPU - {44B22827-B9F0-4ADC-969C-7EC647D0B82A}.Release|x64.Build.0 = Release|Any CPU - {44B22827-B9F0-4ADC-969C-7EC647D0B82A}.Release|x86.ActiveCfg = Release|Any CPU - {44B22827-B9F0-4ADC-969C-7EC647D0B82A}.Release|x86.Build.0 = Release|Any CPU - {44B22827-B9F0-4ADC-969C-7EC647D0B82A}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {44B22827-B9F0-4ADC-969C-7EC647D0B82A}.Checked|Any CPU.Build.0 = Debug|Any CPU - {44B22827-B9F0-4ADC-969C-7EC647D0B82A}.Checked|x64.ActiveCfg = Debug|Any CPU - {44B22827-B9F0-4ADC-969C-7EC647D0B82A}.Checked|x64.Build.0 = Debug|Any CPU - {44B22827-B9F0-4ADC-969C-7EC647D0B82A}.Checked|x86.ActiveCfg = Debug|Any CPU - {44B22827-B9F0-4ADC-969C-7EC647D0B82A}.Checked|x86.Build.0 = Debug|Any CPU - {76BE0621-CDAD-4808-8537-ADC9F028286B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {76BE0621-CDAD-4808-8537-ADC9F028286B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {76BE0621-CDAD-4808-8537-ADC9F028286B}.Debug|x64.ActiveCfg = Debug|Any CPU - {76BE0621-CDAD-4808-8537-ADC9F028286B}.Debug|x64.Build.0 = Debug|Any CPU - {76BE0621-CDAD-4808-8537-ADC9F028286B}.Debug|x86.ActiveCfg = Debug|Any CPU - {76BE0621-CDAD-4808-8537-ADC9F028286B}.Debug|x86.Build.0 = Debug|Any CPU - {76BE0621-CDAD-4808-8537-ADC9F028286B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {76BE0621-CDAD-4808-8537-ADC9F028286B}.Release|Any CPU.Build.0 = Release|Any CPU - {76BE0621-CDAD-4808-8537-ADC9F028286B}.Release|x64.ActiveCfg = Release|Any CPU - {76BE0621-CDAD-4808-8537-ADC9F028286B}.Release|x64.Build.0 = Release|Any CPU - {76BE0621-CDAD-4808-8537-ADC9F028286B}.Release|x86.ActiveCfg = Release|Any CPU - {76BE0621-CDAD-4808-8537-ADC9F028286B}.Release|x86.Build.0 = Release|Any CPU + {BCE10255-8B2B-4F66-914D-7B685BC98198}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {BCE10255-8B2B-4F66-914D-7B685BC98198}.Checked|Any CPU.Build.0 = Debug|Any CPU + {BCE10255-8B2B-4F66-914D-7B685BC98198}.Checked|x64.ActiveCfg = Debug|Any CPU + {BCE10255-8B2B-4F66-914D-7B685BC98198}.Checked|x64.Build.0 = Debug|Any CPU + {BCE10255-8B2B-4F66-914D-7B685BC98198}.Checked|x86.ActiveCfg = Debug|Any CPU + {BCE10255-8B2B-4F66-914D-7B685BC98198}.Checked|x86.Build.0 = Debug|Any CPU + {BCE10255-8B2B-4F66-914D-7B685BC98198}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BCE10255-8B2B-4F66-914D-7B685BC98198}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BCE10255-8B2B-4F66-914D-7B685BC98198}.Debug|x64.ActiveCfg = Debug|Any CPU + {BCE10255-8B2B-4F66-914D-7B685BC98198}.Debug|x64.Build.0 = Debug|Any CPU + {BCE10255-8B2B-4F66-914D-7B685BC98198}.Debug|x86.ActiveCfg = Debug|Any CPU + {BCE10255-8B2B-4F66-914D-7B685BC98198}.Debug|x86.Build.0 = Debug|Any CPU + {BCE10255-8B2B-4F66-914D-7B685BC98198}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BCE10255-8B2B-4F66-914D-7B685BC98198}.Release|Any CPU.Build.0 = Release|Any CPU + {BCE10255-8B2B-4F66-914D-7B685BC98198}.Release|x64.ActiveCfg = Release|Any CPU + {BCE10255-8B2B-4F66-914D-7B685BC98198}.Release|x64.Build.0 = Release|Any CPU + {BCE10255-8B2B-4F66-914D-7B685BC98198}.Release|x86.ActiveCfg = Release|Any CPU + {BCE10255-8B2B-4F66-914D-7B685BC98198}.Release|x86.Build.0 = Release|Any CPU + {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5}.Checked|Any CPU.Build.0 = Debug|Any CPU + {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5}.Checked|x64.ActiveCfg = Debug|Any CPU + {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5}.Checked|x64.Build.0 = Debug|Any CPU + {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5}.Checked|x86.ActiveCfg = Debug|Any CPU + {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5}.Checked|x86.Build.0 = Debug|Any CPU + {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5}.Debug|x64.ActiveCfg = Debug|Any CPU + {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5}.Debug|x64.Build.0 = Debug|Any CPU + {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5}.Debug|x86.ActiveCfg = Debug|Any CPU + {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5}.Debug|x86.Build.0 = Debug|Any CPU + {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5}.Release|Any CPU.Build.0 = Release|Any CPU + {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5}.Release|x64.ActiveCfg = Release|Any CPU + {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5}.Release|x64.Build.0 = Release|Any CPU + {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5}.Release|x86.ActiveCfg = Release|Any CPU + {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5}.Release|x86.Build.0 = Release|Any CPU + {71B8CD61-839D-445C-8E7D-F0F67CE00527}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {71B8CD61-839D-445C-8E7D-F0F67CE00527}.Checked|Any CPU.Build.0 = Debug|Any CPU + {71B8CD61-839D-445C-8E7D-F0F67CE00527}.Checked|x64.ActiveCfg = Debug|Any CPU + {71B8CD61-839D-445C-8E7D-F0F67CE00527}.Checked|x64.Build.0 = Debug|Any CPU + {71B8CD61-839D-445C-8E7D-F0F67CE00527}.Checked|x86.ActiveCfg = Debug|Any CPU + {71B8CD61-839D-445C-8E7D-F0F67CE00527}.Checked|x86.Build.0 = Debug|Any CPU + {71B8CD61-839D-445C-8E7D-F0F67CE00527}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {71B8CD61-839D-445C-8E7D-F0F67CE00527}.Debug|Any CPU.Build.0 = Debug|Any CPU + {71B8CD61-839D-445C-8E7D-F0F67CE00527}.Debug|x64.ActiveCfg = Debug|Any CPU + {71B8CD61-839D-445C-8E7D-F0F67CE00527}.Debug|x64.Build.0 = Debug|Any CPU + {71B8CD61-839D-445C-8E7D-F0F67CE00527}.Debug|x86.ActiveCfg = Debug|Any CPU + {71B8CD61-839D-445C-8E7D-F0F67CE00527}.Debug|x86.Build.0 = Debug|Any CPU + {71B8CD61-839D-445C-8E7D-F0F67CE00527}.Release|Any CPU.ActiveCfg = Release|Any CPU + {71B8CD61-839D-445C-8E7D-F0F67CE00527}.Release|Any CPU.Build.0 = Release|Any CPU + {71B8CD61-839D-445C-8E7D-F0F67CE00527}.Release|x64.ActiveCfg = Release|Any CPU + {71B8CD61-839D-445C-8E7D-F0F67CE00527}.Release|x64.Build.0 = Release|Any CPU + {71B8CD61-839D-445C-8E7D-F0F67CE00527}.Release|x86.ActiveCfg = Release|Any CPU + {71B8CD61-839D-445C-8E7D-F0F67CE00527}.Release|x86.Build.0 = Release|Any CPU {76BE0621-CDAD-4808-8537-ADC9F028286B}.Checked|Any CPU.ActiveCfg = Debug|Any CPU {76BE0621-CDAD-4808-8537-ADC9F028286B}.Checked|Any CPU.Build.0 = Debug|Any CPU {76BE0621-CDAD-4808-8537-ADC9F028286B}.Checked|x64.ActiveCfg = Debug|Any CPU {76BE0621-CDAD-4808-8537-ADC9F028286B}.Checked|x64.Build.0 = Debug|Any CPU {76BE0621-CDAD-4808-8537-ADC9F028286B}.Checked|x86.ActiveCfg = Debug|Any CPU {76BE0621-CDAD-4808-8537-ADC9F028286B}.Checked|x86.Build.0 = Debug|Any CPU - {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD}.Debug|Any CPU.Build.0 = Debug|Any CPU - {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD}.Debug|x64.ActiveCfg = Debug|Any CPU - {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD}.Debug|x64.Build.0 = Debug|Any CPU - {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD}.Debug|x86.ActiveCfg = Debug|Any CPU - {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD}.Debug|x86.Build.0 = Debug|Any CPU - {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD}.Release|Any CPU.ActiveCfg = Release|Any CPU - {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD}.Release|Any CPU.Build.0 = Release|Any CPU - {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD}.Release|x64.ActiveCfg = Release|Any CPU - {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD}.Release|x64.Build.0 = Release|Any CPU - {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD}.Release|x86.ActiveCfg = Release|Any CPU - {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD}.Release|x86.Build.0 = Release|Any CPU - {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD}.Checked|Any CPU.Build.0 = Debug|Any CPU - {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD}.Checked|x64.ActiveCfg = Debug|Any CPU - {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD}.Checked|x64.Build.0 = Debug|Any CPU - {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD}.Checked|x86.ActiveCfg = Debug|Any CPU - {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD}.Checked|x86.Build.0 = Debug|Any CPU - {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD}.Debug|Any CPU.Build.0 = Debug|Any CPU - {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD}.Debug|x64.ActiveCfg = Debug|Any CPU - {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD}.Debug|x64.Build.0 = Debug|Any CPU - {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD}.Debug|x86.ActiveCfg = Debug|Any CPU - {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD}.Debug|x86.Build.0 = Debug|Any CPU - {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD}.Release|Any CPU.ActiveCfg = Release|Any CPU - {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD}.Release|Any CPU.Build.0 = Release|Any CPU - {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD}.Release|x64.ActiveCfg = Release|Any CPU - {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD}.Release|x64.Build.0 = Release|Any CPU - {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD}.Release|x86.ActiveCfg = Release|Any CPU - {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD}.Release|x86.Build.0 = Release|Any CPU - {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD}.Checked|Any CPU.Build.0 = Debug|Any CPU - {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD}.Checked|x64.ActiveCfg = Debug|Any CPU - {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD}.Checked|x64.Build.0 = Debug|Any CPU - {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD}.Checked|x86.ActiveCfg = Debug|Any CPU - {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD}.Checked|x86.Build.0 = Debug|Any CPU + {76BE0621-CDAD-4808-8537-ADC9F028286B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {76BE0621-CDAD-4808-8537-ADC9F028286B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {76BE0621-CDAD-4808-8537-ADC9F028286B}.Debug|x64.ActiveCfg = Debug|Any CPU + {76BE0621-CDAD-4808-8537-ADC9F028286B}.Debug|x64.Build.0 = Debug|Any CPU + {76BE0621-CDAD-4808-8537-ADC9F028286B}.Debug|x86.ActiveCfg = Debug|Any CPU + {76BE0621-CDAD-4808-8537-ADC9F028286B}.Debug|x86.Build.0 = Debug|Any CPU + {76BE0621-CDAD-4808-8537-ADC9F028286B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {76BE0621-CDAD-4808-8537-ADC9F028286B}.Release|Any CPU.Build.0 = Release|Any CPU + {76BE0621-CDAD-4808-8537-ADC9F028286B}.Release|x64.ActiveCfg = Release|Any CPU + {76BE0621-CDAD-4808-8537-ADC9F028286B}.Release|x64.Build.0 = Release|Any CPU + {76BE0621-CDAD-4808-8537-ADC9F028286B}.Release|x86.ActiveCfg = Release|Any CPU + {76BE0621-CDAD-4808-8537-ADC9F028286B}.Release|x86.Build.0 = Release|Any CPU + {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159}.Checked|Any CPU.Build.0 = Debug|Any CPU + {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159}.Checked|x64.ActiveCfg = Debug|Any CPU + {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159}.Checked|x64.Build.0 = Debug|Any CPU + {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159}.Checked|x86.ActiveCfg = Debug|Any CPU + {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159}.Checked|x86.Build.0 = Debug|Any CPU + {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159}.Debug|x64.ActiveCfg = Debug|Any CPU + {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159}.Debug|x64.Build.0 = Debug|Any CPU + {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159}.Debug|x86.ActiveCfg = Debug|Any CPU + {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159}.Debug|x86.Build.0 = Debug|Any CPU + {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159}.Release|Any CPU.Build.0 = Release|Any CPU + {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159}.Release|x64.ActiveCfg = Release|Any CPU + {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159}.Release|x64.Build.0 = Release|Any CPU + {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159}.Release|x86.ActiveCfg = Release|Any CPU + {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159}.Release|x86.Build.0 = Release|Any CPU + {78BC94E5-2E23-40EF-863E-52AFCE838C96}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {78BC94E5-2E23-40EF-863E-52AFCE838C96}.Checked|Any CPU.Build.0 = Debug|Any CPU + {78BC94E5-2E23-40EF-863E-52AFCE838C96}.Checked|x64.ActiveCfg = Debug|Any CPU + {78BC94E5-2E23-40EF-863E-52AFCE838C96}.Checked|x64.Build.0 = Debug|Any CPU + {78BC94E5-2E23-40EF-863E-52AFCE838C96}.Checked|x86.ActiveCfg = Debug|Any CPU + {78BC94E5-2E23-40EF-863E-52AFCE838C96}.Checked|x86.Build.0 = Debug|Any CPU {78BC94E5-2E23-40EF-863E-52AFCE838C96}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {78BC94E5-2E23-40EF-863E-52AFCE838C96}.Debug|Any CPU.Build.0 = Debug|Any CPU {78BC94E5-2E23-40EF-863E-52AFCE838C96}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -306,12 +285,12 @@ Global {78BC94E5-2E23-40EF-863E-52AFCE838C96}.Release|x64.Build.0 = Release|Any CPU {78BC94E5-2E23-40EF-863E-52AFCE838C96}.Release|x86.ActiveCfg = Release|Any CPU {78BC94E5-2E23-40EF-863E-52AFCE838C96}.Release|x86.Build.0 = Release|Any CPU - {78BC94E5-2E23-40EF-863E-52AFCE838C96}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {78BC94E5-2E23-40EF-863E-52AFCE838C96}.Checked|Any CPU.Build.0 = Debug|Any CPU - {78BC94E5-2E23-40EF-863E-52AFCE838C96}.Checked|x64.ActiveCfg = Debug|Any CPU - {78BC94E5-2E23-40EF-863E-52AFCE838C96}.Checked|x64.Build.0 = Debug|Any CPU - {78BC94E5-2E23-40EF-863E-52AFCE838C96}.Checked|x86.ActiveCfg = Debug|Any CPU - {78BC94E5-2E23-40EF-863E-52AFCE838C96}.Checked|x86.Build.0 = Debug|Any CPU + {7E785A7B-6ED6-4459-A07D-28DE1830C186}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {7E785A7B-6ED6-4459-A07D-28DE1830C186}.Checked|Any CPU.Build.0 = Debug|Any CPU + {7E785A7B-6ED6-4459-A07D-28DE1830C186}.Checked|x64.ActiveCfg = Debug|Any CPU + {7E785A7B-6ED6-4459-A07D-28DE1830C186}.Checked|x64.Build.0 = Debug|Any CPU + {7E785A7B-6ED6-4459-A07D-28DE1830C186}.Checked|x86.ActiveCfg = Debug|Any CPU + {7E785A7B-6ED6-4459-A07D-28DE1830C186}.Checked|x86.Build.0 = Debug|Any CPU {7E785A7B-6ED6-4459-A07D-28DE1830C186}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {7E785A7B-6ED6-4459-A07D-28DE1830C186}.Debug|Any CPU.Build.0 = Debug|Any CPU {7E785A7B-6ED6-4459-A07D-28DE1830C186}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -324,146 +303,195 @@ Global {7E785A7B-6ED6-4459-A07D-28DE1830C186}.Release|x64.Build.0 = Release|Any CPU {7E785A7B-6ED6-4459-A07D-28DE1830C186}.Release|x86.ActiveCfg = Release|Any CPU {7E785A7B-6ED6-4459-A07D-28DE1830C186}.Release|x86.Build.0 = Release|Any CPU - {7E785A7B-6ED6-4459-A07D-28DE1830C186}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {7E785A7B-6ED6-4459-A07D-28DE1830C186}.Checked|Any CPU.Build.0 = Debug|Any CPU - {7E785A7B-6ED6-4459-A07D-28DE1830C186}.Checked|x64.ActiveCfg = Debug|Any CPU - {7E785A7B-6ED6-4459-A07D-28DE1830C186}.Checked|x64.Build.0 = Debug|Any CPU - {7E785A7B-6ED6-4459-A07D-28DE1830C186}.Checked|x86.ActiveCfg = Debug|Any CPU - {7E785A7B-6ED6-4459-A07D-28DE1830C186}.Checked|x86.Build.0 = Debug|Any CPU - {71B8CD61-839D-445C-8E7D-F0F67CE00527}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {71B8CD61-839D-445C-8E7D-F0F67CE00527}.Debug|Any CPU.Build.0 = Debug|Any CPU - {71B8CD61-839D-445C-8E7D-F0F67CE00527}.Debug|x64.ActiveCfg = Debug|Any CPU - {71B8CD61-839D-445C-8E7D-F0F67CE00527}.Debug|x64.Build.0 = Debug|Any CPU - {71B8CD61-839D-445C-8E7D-F0F67CE00527}.Debug|x86.ActiveCfg = Debug|Any CPU - {71B8CD61-839D-445C-8E7D-F0F67CE00527}.Debug|x86.Build.0 = Debug|Any CPU - {71B8CD61-839D-445C-8E7D-F0F67CE00527}.Release|Any CPU.ActiveCfg = Release|Any CPU - {71B8CD61-839D-445C-8E7D-F0F67CE00527}.Release|Any CPU.Build.0 = Release|Any CPU - {71B8CD61-839D-445C-8E7D-F0F67CE00527}.Release|x64.ActiveCfg = Release|Any CPU - {71B8CD61-839D-445C-8E7D-F0F67CE00527}.Release|x64.Build.0 = Release|Any CPU - {71B8CD61-839D-445C-8E7D-F0F67CE00527}.Release|x86.ActiveCfg = Release|Any CPU - {71B8CD61-839D-445C-8E7D-F0F67CE00527}.Release|x86.Build.0 = Release|Any CPU - {71B8CD61-839D-445C-8E7D-F0F67CE00527}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {71B8CD61-839D-445C-8E7D-F0F67CE00527}.Checked|Any CPU.Build.0 = Debug|Any CPU - {71B8CD61-839D-445C-8E7D-F0F67CE00527}.Checked|x64.ActiveCfg = Debug|Any CPU - {71B8CD61-839D-445C-8E7D-F0F67CE00527}.Checked|x64.Build.0 = Debug|Any CPU - {71B8CD61-839D-445C-8E7D-F0F67CE00527}.Checked|x86.ActiveCfg = Debug|Any CPU - {71B8CD61-839D-445C-8E7D-F0F67CE00527}.Checked|x86.Build.0 = Debug|Any CPU - {BCE10255-8B2B-4F66-914D-7B685BC98198}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {BCE10255-8B2B-4F66-914D-7B685BC98198}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BCE10255-8B2B-4F66-914D-7B685BC98198}.Debug|x64.ActiveCfg = Debug|Any CPU - {BCE10255-8B2B-4F66-914D-7B685BC98198}.Debug|x64.Build.0 = Debug|Any CPU - {BCE10255-8B2B-4F66-914D-7B685BC98198}.Debug|x86.ActiveCfg = Debug|Any CPU - {BCE10255-8B2B-4F66-914D-7B685BC98198}.Debug|x86.Build.0 = Debug|Any CPU - {BCE10255-8B2B-4F66-914D-7B685BC98198}.Release|Any CPU.ActiveCfg = Release|Any CPU - {BCE10255-8B2B-4F66-914D-7B685BC98198}.Release|Any CPU.Build.0 = Release|Any CPU - {BCE10255-8B2B-4F66-914D-7B685BC98198}.Release|x64.ActiveCfg = Release|Any CPU - {BCE10255-8B2B-4F66-914D-7B685BC98198}.Release|x64.Build.0 = Release|Any CPU - {BCE10255-8B2B-4F66-914D-7B685BC98198}.Release|x86.ActiveCfg = Release|Any CPU - {BCE10255-8B2B-4F66-914D-7B685BC98198}.Release|x86.Build.0 = Release|Any CPU - {BCE10255-8B2B-4F66-914D-7B685BC98198}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {BCE10255-8B2B-4F66-914D-7B685BC98198}.Checked|Any CPU.Build.0 = Debug|Any CPU - {BCE10255-8B2B-4F66-914D-7B685BC98198}.Checked|x64.ActiveCfg = Debug|Any CPU - {BCE10255-8B2B-4F66-914D-7B685BC98198}.Checked|x64.Build.0 = Debug|Any CPU - {BCE10255-8B2B-4F66-914D-7B685BC98198}.Checked|x86.ActiveCfg = Debug|Any CPU - {BCE10255-8B2B-4F66-914D-7B685BC98198}.Checked|x86.Build.0 = Debug|Any CPU - {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5}.Debug|Any CPU.Build.0 = Debug|Any CPU - {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5}.Debug|x64.ActiveCfg = Debug|Any CPU - {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5}.Debug|x64.Build.0 = Debug|Any CPU - {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5}.Debug|x86.ActiveCfg = Debug|Any CPU - {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5}.Debug|x86.Build.0 = Debug|Any CPU - {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5}.Release|Any CPU.ActiveCfg = Release|Any CPU - {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5}.Release|Any CPU.Build.0 = Release|Any CPU - {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5}.Release|x64.ActiveCfg = Release|Any CPU - {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5}.Release|x64.Build.0 = Release|Any CPU - {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5}.Release|x86.ActiveCfg = Release|Any CPU - {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5}.Release|x86.Build.0 = Release|Any CPU - {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5}.Checked|Any CPU.Build.0 = Debug|Any CPU - {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5}.Checked|x64.ActiveCfg = Debug|Any CPU - {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5}.Checked|x64.Build.0 = Debug|Any CPU - {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5}.Checked|x86.ActiveCfg = Debug|Any CPU - {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5}.Checked|x86.Build.0 = Debug|Any CPU - {04BA3E3C-6979-4792-B19E-C797AD607F42}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {04BA3E3C-6979-4792-B19E-C797AD607F42}.Debug|Any CPU.Build.0 = Debug|Any CPU - {04BA3E3C-6979-4792-B19E-C797AD607F42}.Debug|x64.ActiveCfg = Debug|Any CPU - {04BA3E3C-6979-4792-B19E-C797AD607F42}.Debug|x64.Build.0 = Debug|Any CPU - {04BA3E3C-6979-4792-B19E-C797AD607F42}.Debug|x86.ActiveCfg = Debug|Any CPU - {04BA3E3C-6979-4792-B19E-C797AD607F42}.Debug|x86.Build.0 = Debug|Any CPU - {04BA3E3C-6979-4792-B19E-C797AD607F42}.Release|Any CPU.ActiveCfg = Release|Any CPU - {04BA3E3C-6979-4792-B19E-C797AD607F42}.Release|Any CPU.Build.0 = Release|Any CPU - {04BA3E3C-6979-4792-B19E-C797AD607F42}.Release|x64.ActiveCfg = Release|Any CPU - {04BA3E3C-6979-4792-B19E-C797AD607F42}.Release|x64.Build.0 = Release|Any CPU - {04BA3E3C-6979-4792-B19E-C797AD607F42}.Release|x86.ActiveCfg = Release|Any CPU - {04BA3E3C-6979-4792-B19E-C797AD607F42}.Release|x86.Build.0 = Release|Any CPU - {04BA3E3C-6979-4792-B19E-C797AD607F42}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {04BA3E3C-6979-4792-B19E-C797AD607F42}.Checked|Any CPU.Build.0 = Debug|Any CPU - {04BA3E3C-6979-4792-B19E-C797AD607F42}.Checked|x64.ActiveCfg = Debug|Any CPU - {04BA3E3C-6979-4792-B19E-C797AD607F42}.Checked|x64.Build.0 = Debug|Any CPU - {04BA3E3C-6979-4792-B19E-C797AD607F42}.Checked|x86.ActiveCfg = Debug|Any CPU - {04BA3E3C-6979-4792-B19E-C797AD607F42}.Checked|x86.Build.0 = Debug|Any CPU - {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}.Debug|Any CPU.ActiveCfg = Debug|x64 - {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}.Debug|Any CPU.Build.0 = Debug|x64 - {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}.Debug|x64.ActiveCfg = Debug|x64 - {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}.Debug|x64.Build.0 = Debug|x64 - {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}.Debug|x86.ActiveCfg = Debug|x86 - {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}.Debug|x86.Build.0 = Debug|x86 - {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}.Release|Any CPU.ActiveCfg = Release|x64 - {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}.Release|Any CPU.Build.0 = Release|x64 - {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}.Release|x64.ActiveCfg = Release|x64 - {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}.Release|x64.Build.0 = Release|x64 - {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}.Release|x86.ActiveCfg = Release|x86 - {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}.Release|x86.Build.0 = Release|x86 - {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}.Checked|Any CPU.ActiveCfg = Checked|x64 - {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}.Checked|Any CPU.Build.0 = Checked|x64 - {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}.Checked|x64.ActiveCfg = Checked|x64 - {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}.Checked|x64.Build.0 = Checked|x64 - {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}.Checked|x86.ActiveCfg = Checked|x86 - {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}.Checked|x86.Build.0 = Checked|x86 - {8D19CD03-08EE-4574-B798-C658502C0A42}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8D19CD03-08EE-4574-B798-C658502C0A42}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8D19CD03-08EE-4574-B798-C658502C0A42}.Debug|x64.ActiveCfg = Debug|Any CPU - {8D19CD03-08EE-4574-B798-C658502C0A42}.Debug|x64.Build.0 = Debug|Any CPU - {8D19CD03-08EE-4574-B798-C658502C0A42}.Debug|x86.ActiveCfg = Debug|Any CPU - {8D19CD03-08EE-4574-B798-C658502C0A42}.Debug|x86.Build.0 = Debug|Any CPU - {8D19CD03-08EE-4574-B798-C658502C0A42}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8D19CD03-08EE-4574-B798-C658502C0A42}.Release|Any CPU.Build.0 = Release|Any CPU - {8D19CD03-08EE-4574-B798-C658502C0A42}.Release|x64.ActiveCfg = Release|Any CPU - {8D19CD03-08EE-4574-B798-C658502C0A42}.Release|x64.Build.0 = Release|Any CPU - {8D19CD03-08EE-4574-B798-C658502C0A42}.Release|x86.ActiveCfg = Release|Any CPU - {8D19CD03-08EE-4574-B798-C658502C0A42}.Release|x86.Build.0 = Release|Any CPU - {8D19CD03-08EE-4574-B798-C658502C0A42}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {8D19CD03-08EE-4574-B798-C658502C0A42}.Checked|Any CPU.Build.0 = Debug|Any CPU - {8D19CD03-08EE-4574-B798-C658502C0A42}.Checked|x64.ActiveCfg = Debug|Any CPU - {8D19CD03-08EE-4574-B798-C658502C0A42}.Checked|x64.Build.0 = Debug|Any CPU - {8D19CD03-08EE-4574-B798-C658502C0A42}.Checked|x86.ActiveCfg = Debug|Any CPU - {8D19CD03-08EE-4574-B798-C658502C0A42}.Checked|x86.Build.0 = Debug|Any CPU + {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902}.Checked|Any CPU.Build.0 = Debug|Any CPU + {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902}.Checked|x64.ActiveCfg = Debug|Any CPU + {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902}.Checked|x64.Build.0 = Debug|Any CPU + {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902}.Checked|x86.ActiveCfg = Debug|Any CPU + {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902}.Checked|x86.Build.0 = Debug|Any CPU + {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902}.Debug|x64.ActiveCfg = Debug|Any CPU + {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902}.Debug|x64.Build.0 = Debug|Any CPU + {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902}.Debug|x86.ActiveCfg = Debug|Any CPU + {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902}.Debug|x86.Build.0 = Debug|Any CPU + {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902}.Release|Any CPU.Build.0 = Release|Any CPU + {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902}.Release|x64.ActiveCfg = Release|Any CPU + {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902}.Release|x64.Build.0 = Release|Any CPU + {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902}.Release|x86.ActiveCfg = Release|Any CPU + {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902}.Release|x86.Build.0 = Release|Any CPU + {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD}.Checked|Any CPU.Build.0 = Debug|Any CPU + {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD}.Checked|x64.ActiveCfg = Debug|Any CPU + {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD}.Checked|x64.Build.0 = Debug|Any CPU + {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD}.Checked|x86.ActiveCfg = Debug|Any CPU + {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD}.Checked|x86.Build.0 = Debug|Any CPU + {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD}.Debug|x64.ActiveCfg = Debug|Any CPU + {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD}.Debug|x64.Build.0 = Debug|Any CPU + {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD}.Debug|x86.ActiveCfg = Debug|Any CPU + {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD}.Debug|x86.Build.0 = Debug|Any CPU + {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD}.Release|Any CPU.Build.0 = Release|Any CPU + {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD}.Release|x64.ActiveCfg = Release|Any CPU + {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD}.Release|x64.Build.0 = Release|Any CPU + {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD}.Release|x86.ActiveCfg = Release|Any CPU + {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD}.Release|x86.Build.0 = Release|Any CPU + {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD}.Checked|Any CPU.Build.0 = Debug|Any CPU + {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD}.Checked|x64.ActiveCfg = Debug|Any CPU + {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD}.Checked|x64.Build.0 = Debug|Any CPU + {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD}.Checked|x86.ActiveCfg = Debug|Any CPU + {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD}.Checked|x86.Build.0 = Debug|Any CPU + {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD}.Debug|x64.ActiveCfg = Debug|Any CPU + {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD}.Debug|x64.Build.0 = Debug|Any CPU + {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD}.Debug|x86.ActiveCfg = Debug|Any CPU + {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD}.Debug|x86.Build.0 = Debug|Any CPU + {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD}.Release|Any CPU.Build.0 = Release|Any CPU + {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD}.Release|x64.ActiveCfg = Release|Any CPU + {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD}.Release|x64.Build.0 = Release|Any CPU + {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD}.Release|x86.ActiveCfg = Release|Any CPU + {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD}.Release|x86.Build.0 = Release|Any CPU + {44B22827-B9F0-4ADC-969C-7EC647D0B82A}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {44B22827-B9F0-4ADC-969C-7EC647D0B82A}.Checked|Any CPU.Build.0 = Debug|Any CPU + {44B22827-B9F0-4ADC-969C-7EC647D0B82A}.Checked|x64.ActiveCfg = Debug|Any CPU + {44B22827-B9F0-4ADC-969C-7EC647D0B82A}.Checked|x64.Build.0 = Debug|Any CPU + {44B22827-B9F0-4ADC-969C-7EC647D0B82A}.Checked|x86.ActiveCfg = Debug|Any CPU + {44B22827-B9F0-4ADC-969C-7EC647D0B82A}.Checked|x86.Build.0 = Debug|Any CPU + {44B22827-B9F0-4ADC-969C-7EC647D0B82A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {44B22827-B9F0-4ADC-969C-7EC647D0B82A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {44B22827-B9F0-4ADC-969C-7EC647D0B82A}.Debug|x64.ActiveCfg = Debug|Any CPU + {44B22827-B9F0-4ADC-969C-7EC647D0B82A}.Debug|x64.Build.0 = Debug|Any CPU + {44B22827-B9F0-4ADC-969C-7EC647D0B82A}.Debug|x86.ActiveCfg = Debug|Any CPU + {44B22827-B9F0-4ADC-969C-7EC647D0B82A}.Debug|x86.Build.0 = Debug|Any CPU + {44B22827-B9F0-4ADC-969C-7EC647D0B82A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {44B22827-B9F0-4ADC-969C-7EC647D0B82A}.Release|Any CPU.Build.0 = Release|Any CPU + {44B22827-B9F0-4ADC-969C-7EC647D0B82A}.Release|x64.ActiveCfg = Release|Any CPU + {44B22827-B9F0-4ADC-969C-7EC647D0B82A}.Release|x64.Build.0 = Release|Any CPU + {44B22827-B9F0-4ADC-969C-7EC647D0B82A}.Release|x86.ActiveCfg = Release|Any CPU + {44B22827-B9F0-4ADC-969C-7EC647D0B82A}.Release|x86.Build.0 = Release|Any CPU + {49B0A873-5834-45A4-9495-E1063005CB82}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {49B0A873-5834-45A4-9495-E1063005CB82}.Checked|Any CPU.Build.0 = Debug|Any CPU + {49B0A873-5834-45A4-9495-E1063005CB82}.Checked|x64.ActiveCfg = Debug|Any CPU + {49B0A873-5834-45A4-9495-E1063005CB82}.Checked|x64.Build.0 = Debug|Any CPU + {49B0A873-5834-45A4-9495-E1063005CB82}.Checked|x86.ActiveCfg = Debug|Any CPU + {49B0A873-5834-45A4-9495-E1063005CB82}.Checked|x86.Build.0 = Debug|Any CPU + {49B0A873-5834-45A4-9495-E1063005CB82}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {49B0A873-5834-45A4-9495-E1063005CB82}.Debug|Any CPU.Build.0 = Debug|Any CPU + {49B0A873-5834-45A4-9495-E1063005CB82}.Debug|x64.ActiveCfg = Debug|Any CPU + {49B0A873-5834-45A4-9495-E1063005CB82}.Debug|x64.Build.0 = Debug|Any CPU + {49B0A873-5834-45A4-9495-E1063005CB82}.Debug|x86.ActiveCfg = Debug|Any CPU + {49B0A873-5834-45A4-9495-E1063005CB82}.Debug|x86.Build.0 = Debug|Any CPU + {49B0A873-5834-45A4-9495-E1063005CB82}.Release|Any CPU.ActiveCfg = Release|Any CPU + {49B0A873-5834-45A4-9495-E1063005CB82}.Release|Any CPU.Build.0 = Release|Any CPU + {49B0A873-5834-45A4-9495-E1063005CB82}.Release|x64.ActiveCfg = Release|Any CPU + {49B0A873-5834-45A4-9495-E1063005CB82}.Release|x64.Build.0 = Release|Any CPU + {49B0A873-5834-45A4-9495-E1063005CB82}.Release|x86.ActiveCfg = Release|Any CPU + {49B0A873-5834-45A4-9495-E1063005CB82}.Release|x86.Build.0 = Release|Any CPU + {E60DD367-D1D7-4F6C-919B-DC68E8445E97}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {E60DD367-D1D7-4F6C-919B-DC68E8445E97}.Checked|Any CPU.Build.0 = Debug|Any CPU + {E60DD367-D1D7-4F6C-919B-DC68E8445E97}.Checked|x64.ActiveCfg = Debug|Any CPU + {E60DD367-D1D7-4F6C-919B-DC68E8445E97}.Checked|x64.Build.0 = Debug|Any CPU + {E60DD367-D1D7-4F6C-919B-DC68E8445E97}.Checked|x86.ActiveCfg = Debug|Any CPU + {E60DD367-D1D7-4F6C-919B-DC68E8445E97}.Checked|x86.Build.0 = Debug|Any CPU + {E60DD367-D1D7-4F6C-919B-DC68E8445E97}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E60DD367-D1D7-4F6C-919B-DC68E8445E97}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E60DD367-D1D7-4F6C-919B-DC68E8445E97}.Debug|x64.ActiveCfg = Debug|Any CPU + {E60DD367-D1D7-4F6C-919B-DC68E8445E97}.Debug|x64.Build.0 = Debug|Any CPU + {E60DD367-D1D7-4F6C-919B-DC68E8445E97}.Debug|x86.ActiveCfg = Debug|Any CPU + {E60DD367-D1D7-4F6C-919B-DC68E8445E97}.Debug|x86.Build.0 = Debug|Any CPU + {E60DD367-D1D7-4F6C-919B-DC68E8445E97}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E60DD367-D1D7-4F6C-919B-DC68E8445E97}.Release|Any CPU.Build.0 = Release|Any CPU + {E60DD367-D1D7-4F6C-919B-DC68E8445E97}.Release|x64.ActiveCfg = Release|Any CPU + {E60DD367-D1D7-4F6C-919B-DC68E8445E97}.Release|x64.Build.0 = Release|Any CPU + {E60DD367-D1D7-4F6C-919B-DC68E8445E97}.Release|x86.ActiveCfg = Release|Any CPU + {E60DD367-D1D7-4F6C-919B-DC68E8445E97}.Release|x86.Build.0 = Release|Any CPU + {9AD657ED-396B-4BE7-BCB6-BCA130825418}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {9AD657ED-396B-4BE7-BCB6-BCA130825418}.Checked|Any CPU.Build.0 = Debug|Any CPU + {9AD657ED-396B-4BE7-BCB6-BCA130825418}.Checked|x64.ActiveCfg = Debug|Any CPU + {9AD657ED-396B-4BE7-BCB6-BCA130825418}.Checked|x64.Build.0 = Debug|Any CPU + {9AD657ED-396B-4BE7-BCB6-BCA130825418}.Checked|x86.ActiveCfg = Debug|Any CPU + {9AD657ED-396B-4BE7-BCB6-BCA130825418}.Checked|x86.Build.0 = Debug|Any CPU + {9AD657ED-396B-4BE7-BCB6-BCA130825418}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9AD657ED-396B-4BE7-BCB6-BCA130825418}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9AD657ED-396B-4BE7-BCB6-BCA130825418}.Debug|x64.ActiveCfg = Debug|Any CPU + {9AD657ED-396B-4BE7-BCB6-BCA130825418}.Debug|x64.Build.0 = Debug|Any CPU + {9AD657ED-396B-4BE7-BCB6-BCA130825418}.Debug|x86.ActiveCfg = Debug|Any CPU + {9AD657ED-396B-4BE7-BCB6-BCA130825418}.Debug|x86.Build.0 = Debug|Any CPU + {9AD657ED-396B-4BE7-BCB6-BCA130825418}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9AD657ED-396B-4BE7-BCB6-BCA130825418}.Release|Any CPU.Build.0 = Release|Any CPU + {9AD657ED-396B-4BE7-BCB6-BCA130825418}.Release|x64.ActiveCfg = Release|Any CPU + {9AD657ED-396B-4BE7-BCB6-BCA130825418}.Release|x64.Build.0 = Release|Any CPU + {9AD657ED-396B-4BE7-BCB6-BCA130825418}.Release|x86.ActiveCfg = Release|Any CPU + {9AD657ED-396B-4BE7-BCB6-BCA130825418}.Release|x86.Build.0 = Release|Any CPU + {29E02AA9-E3D5-400C-B2C5-970B6E6D8562}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {29E02AA9-E3D5-400C-B2C5-970B6E6D8562}.Checked|Any CPU.Build.0 = Debug|Any CPU + {29E02AA9-E3D5-400C-B2C5-970B6E6D8562}.Checked|x64.ActiveCfg = Debug|Any CPU + {29E02AA9-E3D5-400C-B2C5-970B6E6D8562}.Checked|x64.Build.0 = Debug|Any CPU + {29E02AA9-E3D5-400C-B2C5-970B6E6D8562}.Checked|x86.ActiveCfg = Debug|Any CPU + {29E02AA9-E3D5-400C-B2C5-970B6E6D8562}.Checked|x86.Build.0 = Debug|Any CPU + {29E02AA9-E3D5-400C-B2C5-970B6E6D8562}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {29E02AA9-E3D5-400C-B2C5-970B6E6D8562}.Debug|Any CPU.Build.0 = Debug|Any CPU + {29E02AA9-E3D5-400C-B2C5-970B6E6D8562}.Debug|x64.ActiveCfg = Debug|Any CPU + {29E02AA9-E3D5-400C-B2C5-970B6E6D8562}.Debug|x64.Build.0 = Debug|Any CPU + {29E02AA9-E3D5-400C-B2C5-970B6E6D8562}.Debug|x86.ActiveCfg = Debug|Any CPU + {29E02AA9-E3D5-400C-B2C5-970B6E6D8562}.Debug|x86.Build.0 = Debug|Any CPU + {29E02AA9-E3D5-400C-B2C5-970B6E6D8562}.Release|Any CPU.ActiveCfg = Release|Any CPU + {29E02AA9-E3D5-400C-B2C5-970B6E6D8562}.Release|Any CPU.Build.0 = Release|Any CPU + {29E02AA9-E3D5-400C-B2C5-970B6E6D8562}.Release|x64.ActiveCfg = Release|Any CPU + {29E02AA9-E3D5-400C-B2C5-970B6E6D8562}.Release|x64.Build.0 = Release|Any CPU + {29E02AA9-E3D5-400C-B2C5-970B6E6D8562}.Release|x86.ActiveCfg = Release|Any CPU + {29E02AA9-E3D5-400C-B2C5-970B6E6D8562}.Release|x86.Build.0 = Release|Any CPU + {EEAE2A15-E2AE-4421-8D30-AAB17AC805F8}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {EEAE2A15-E2AE-4421-8D30-AAB17AC805F8}.Checked|Any CPU.Build.0 = Debug|Any CPU + {EEAE2A15-E2AE-4421-8D30-AAB17AC805F8}.Checked|x64.ActiveCfg = Debug|Any CPU + {EEAE2A15-E2AE-4421-8D30-AAB17AC805F8}.Checked|x64.Build.0 = Debug|Any CPU + {EEAE2A15-E2AE-4421-8D30-AAB17AC805F8}.Checked|x86.ActiveCfg = Debug|Any CPU + {EEAE2A15-E2AE-4421-8D30-AAB17AC805F8}.Checked|x86.Build.0 = Debug|Any CPU + {EEAE2A15-E2AE-4421-8D30-AAB17AC805F8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EEAE2A15-E2AE-4421-8D30-AAB17AC805F8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EEAE2A15-E2AE-4421-8D30-AAB17AC805F8}.Debug|x64.ActiveCfg = Debug|Any CPU + {EEAE2A15-E2AE-4421-8D30-AAB17AC805F8}.Debug|x64.Build.0 = Debug|Any CPU + {EEAE2A15-E2AE-4421-8D30-AAB17AC805F8}.Debug|x86.ActiveCfg = Debug|Any CPU + {EEAE2A15-E2AE-4421-8D30-AAB17AC805F8}.Debug|x86.Build.0 = Debug|Any CPU + {EEAE2A15-E2AE-4421-8D30-AAB17AC805F8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EEAE2A15-E2AE-4421-8D30-AAB17AC805F8}.Release|Any CPU.Build.0 = Release|Any CPU + {EEAE2A15-E2AE-4421-8D30-AAB17AC805F8}.Release|x64.ActiveCfg = Release|Any CPU + {EEAE2A15-E2AE-4421-8D30-AAB17AC805F8}.Release|x64.Build.0 = Release|Any CPU + {EEAE2A15-E2AE-4421-8D30-AAB17AC805F8}.Release|x86.ActiveCfg = Release|Any CPU + {EEAE2A15-E2AE-4421-8D30-AAB17AC805F8}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution - {29E02AA9-E3D5-400C-B2C5-970B6E6D8562} = {F36F0790-5CF7-4CAD-B903-4A3EE0DC1345} + {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558} = {6963C709-FD2F-45A7-9A9D-431B1E9A4796} + {D6D16FFD-FD76-4700-B456-1DC4D093D1B5} = {F36F0790-5CF7-4CAD-B903-4A3EE0DC1345} + {8D19CD03-08EE-4574-B798-C658502C0A42} = {C75ECE17-3CF5-409D-B26F-E2F5053DD5B9} + {04BA3E3C-6979-4792-B19E-C797AD607F42} = {6963C709-FD2F-45A7-9A9D-431B1E9A4796} + {95B66B14-BCC7-407A-930C-4B34D4F7EC98} = {C75ECE17-3CF5-409D-B26F-E2F5053DD5B9} + {B8F22D73-B183-4F17-9D5E-04B80699E56A} = {6963C709-FD2F-45A7-9A9D-431B1E9A4796} + {BCE10255-8B2B-4F66-914D-7B685BC98198} = {F36F0790-5CF7-4CAD-B903-4A3EE0DC1345} + {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5} = {F36F0790-5CF7-4CAD-B903-4A3EE0DC1345} + {71B8CD61-839D-445C-8E7D-F0F67CE00527} = {F36F0790-5CF7-4CAD-B903-4A3EE0DC1345} + {76BE0621-CDAD-4808-8537-ADC9F028286B} = {F36F0790-5CF7-4CAD-B903-4A3EE0DC1345} {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159} = {F36F0790-5CF7-4CAD-B903-4A3EE0DC1345} + {78BC94E5-2E23-40EF-863E-52AFCE838C96} = {F36F0790-5CF7-4CAD-B903-4A3EE0DC1345} + {7E785A7B-6ED6-4459-A07D-28DE1830C186} = {F36F0790-5CF7-4CAD-B903-4A3EE0DC1345} {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902} = {F36F0790-5CF7-4CAD-B903-4A3EE0DC1345} + {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD} = {F36F0790-5CF7-4CAD-B903-4A3EE0DC1345} + {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD} = {F36F0790-5CF7-4CAD-B903-4A3EE0DC1345} + {44B22827-B9F0-4ADC-969C-7EC647D0B82A} = {F36F0790-5CF7-4CAD-B903-4A3EE0DC1345} {49B0A873-5834-45A4-9495-E1063005CB82} = {F36F0790-5CF7-4CAD-B903-4A3EE0DC1345} - {D6D16FFD-FD76-4700-B456-1DC4D093D1B5} = {F36F0790-5CF7-4CAD-B903-4A3EE0DC1345} {E60DD367-D1D7-4F6C-919B-DC68E8445E97} = {F36F0790-5CF7-4CAD-B903-4A3EE0DC1345} {9AD657ED-396B-4BE7-BCB6-BCA130825418} = {F36F0790-5CF7-4CAD-B903-4A3EE0DC1345} - {44B22827-B9F0-4ADC-969C-7EC647D0B82A} = {F36F0790-5CF7-4CAD-B903-4A3EE0DC1345} - {76BE0621-CDAD-4808-8537-ADC9F028286B} = {F36F0790-5CF7-4CAD-B903-4A3EE0DC1345} - {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD} = {F36F0790-5CF7-4CAD-B903-4A3EE0DC1345} - {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD} = {F36F0790-5CF7-4CAD-B903-4A3EE0DC1345} - {78BC94E5-2E23-40EF-863E-52AFCE838C96} = {F36F0790-5CF7-4CAD-B903-4A3EE0DC1345} - {7E785A7B-6ED6-4459-A07D-28DE1830C186} = {F36F0790-5CF7-4CAD-B903-4A3EE0DC1345} - {71B8CD61-839D-445C-8E7D-F0F67CE00527} = {F36F0790-5CF7-4CAD-B903-4A3EE0DC1345} - {BCE10255-8B2B-4F66-914D-7B685BC98198} = {F36F0790-5CF7-4CAD-B903-4A3EE0DC1345} - {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5} = {F36F0790-5CF7-4CAD-B903-4A3EE0DC1345} - {95B66B14-BCC7-407A-930C-4B34D4F7EC98} = {C75ECE17-3CF5-409D-B26F-E2F5053DD5B9} - {8D19CD03-08EE-4574-B798-C658502C0A42} = {C75ECE17-3CF5-409D-B26F-E2F5053DD5B9} - {B8F22D73-B183-4F17-9D5E-04B80699E56A} = {6963C709-FD2F-45A7-9A9D-431B1E9A4796} - {04BA3E3C-6979-4792-B19E-C797AD607F42} = {6963C709-FD2F-45A7-9A9D-431B1E9A4796} - {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558} = {6963C709-FD2F-45A7-9A9D-431B1E9A4796} + {29E02AA9-E3D5-400C-B2C5-970B6E6D8562} = {F36F0790-5CF7-4CAD-B903-4A3EE0DC1345} + {EEAE2A15-E2AE-4421-8D30-AAB17AC805F8} = {F36F0790-5CF7-4CAD-B903-4A3EE0DC1345} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {73D0667D-A181-41CA-B57B-DD177166E019} diff --git a/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.CustomAttributeDelete/CustomAttributeDelete.cs b/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.CustomAttributeDelete/CustomAttributeDelete.cs new file mode 100644 index 0000000000000..1781dcfe3db18 --- /dev/null +++ b/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.CustomAttributeDelete/CustomAttributeDelete.cs @@ -0,0 +1,35 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +using System; + + +namespace System.Reflection.Metadata.ApplyUpdate.Test +{ + [AttributeUsage (AttributeTargets.Method, AllowMultiple=true)] + public class MyDeleteAttribute : Attribute + { + public MyDeleteAttribute (string stringValue) { StringValue = stringValue; } + + public MyDeleteAttribute (Type typeValue) { TypeValue = typeValue; } + + public MyDeleteAttribute (int x) { IntValue = x; } + + public string StringValue { get; set; } + public Type TypeValue {get; set; } + public int IntValue {get; set; } + } + + public class ClassWithCustomAttributeDelete + { + [MyDeleteAttribute ("abcd")] + public static string Method1 () => null; + + [MyDeleteAttribute (typeof(Exception))] + public static string Method2 () => null; + + [MyDeleteAttribute (42, StringValue = "hijkl", TypeValue = typeof(Type))] + [MyDeleteAttribute (17, StringValue = "", TypeValue = typeof(object))] + public static string Method3 () => null; + + } +} diff --git a/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.CustomAttributeDelete/CustomAttributeDelete_v1.cs b/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.CustomAttributeDelete/CustomAttributeDelete_v1.cs new file mode 100644 index 0000000000000..db85640bb538d --- /dev/null +++ b/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.CustomAttributeDelete/CustomAttributeDelete_v1.cs @@ -0,0 +1,31 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +using System; + + +namespace System.Reflection.Metadata.ApplyUpdate.Test +{ + [AttributeUsage (AttributeTargets.Method, AllowMultiple=true)] + public class MyDeleteAttribute : Attribute + { + public MyDeleteAttribute (string stringValue) { StringValue = stringValue; } + + public MyDeleteAttribute (Type typeValue) { TypeValue = typeValue; } + + public MyDeleteAttribute (int x) { IntValue = x; } + + public string StringValue { get; set; } + public Type TypeValue {get; set; } + public int IntValue {get; set; } + } + + public class ClassWithCustomAttributeDelete + { + public static string Method1 () => null; + + public static string Method2 () => null; + + [MyDeleteAttribute (17, StringValue = "Not Deleted", TypeValue = typeof(object))] + public static string Method3 () => null; + } +} diff --git a/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.CustomAttributeDelete/System.Reflection.Metadata.ApplyUpdate.Test.CustomAttributeDelete.csproj b/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.CustomAttributeDelete/System.Reflection.Metadata.ApplyUpdate.Test.CustomAttributeDelete.csproj new file mode 100644 index 0000000000000..fa4dec5c554d7 --- /dev/null +++ b/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.CustomAttributeDelete/System.Reflection.Metadata.ApplyUpdate.Test.CustomAttributeDelete.csproj @@ -0,0 +1,11 @@ + + + System.Runtime.Loader.Tests + $(NetCoreAppCurrent) + true + deltascript.json + + + + + diff --git a/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.CustomAttributeDelete/deltascript.json b/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.CustomAttributeDelete/deltascript.json new file mode 100644 index 0000000000000..ffddaad9069e3 --- /dev/null +++ b/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.CustomAttributeDelete/deltascript.json @@ -0,0 +1,6 @@ +{ + "changes": [ + {"document": "CustomAttributeDelete.cs", "update": "CustomAttributeDelete_v1.cs"}, + ] +} + diff --git a/src/libraries/System.Runtime.Loader/tests/ApplyUpdateTest.cs b/src/libraries/System.Runtime.Loader/tests/ApplyUpdateTest.cs index 6976f8a6f7772..c8cf4b47e5e28 100644 --- a/src/libraries/System.Runtime.Loader/tests/ApplyUpdateTest.cs +++ b/src/libraries/System.Runtime.Loader/tests/ApplyUpdateTest.cs @@ -112,6 +112,46 @@ public void CustomAttributeUpdates() }); } + [ActiveIssue("https://github.com/dotnet/runtime/issues/52993", TestRuntimes.Mono)] + [ConditionalFact(typeof(ApplyUpdateUtil), nameof (ApplyUpdateUtil.IsSupported))] + public void CustomAttributeDelete() + { + // Test that deleting custom attribute on constructor/property works as expected. + ApplyUpdateUtil.TestCase(static () => + { + var assm = typeof(System.Reflection.Metadata.ApplyUpdate.Test.ClassWithCustomAttributeDelete).Assembly; + + ApplyUpdateUtil.ApplyUpdate(assm); + ApplyUpdateUtil.ClearAllReflectionCaches(); + + // Just check the updated value on one method + + Type attrType = typeof(System.Reflection.Metadata.ApplyUpdate.Test.MyDeleteAttribute); + Type ty = assm.GetType("System.Reflection.Metadata.ApplyUpdate.Test.ClassWithCustomAttributeDelete"); + Assert.NotNull(ty); + + MethodInfo mi1 = ty.GetMethod(nameof(System.Reflection.Metadata.ApplyUpdate.Test.ClassWithCustomAttributeDelete.Method1), BindingFlags.Public | BindingFlags.Static); + Assert.NotNull(mi1); + Attribute[] cattrs = Attribute.GetCustomAttributes(mi1, attrType); + Assert.NotNull(cattrs); + Assert.Equal(0, cattrs.Length); + + MethodInfo mi2 = ty.GetMethod(nameof(System.Reflection.Metadata.ApplyUpdate.Test.ClassWithCustomAttributeDelete.Method2), BindingFlags.Public | BindingFlags.Static); + Assert.NotNull(mi2); + cattrs = Attribute.GetCustomAttributes(mi2, attrType); + Assert.NotNull(cattrs); + Assert.Equal(0, cattrs.Length); + + MethodInfo mi3 = ty.GetMethod(nameof(System.Reflection.Metadata.ApplyUpdate.Test.ClassWithCustomAttributeDelete.Method3), BindingFlags.Public | BindingFlags.Static); + Assert.NotNull(mi3); + cattrs = Attribute.GetCustomAttributes(mi3, attrType); + Assert.NotNull(cattrs); + Assert.Equal(1, cattrs.Length); + string p = (cattrs[0] as System.Reflection.Metadata.ApplyUpdate.Test.MyDeleteAttribute).StringValue; + Assert.Equal("Not Deleted", p); + }); + } + class NonRuntimeAssembly : Assembly { } diff --git a/src/libraries/System.Runtime.Loader/tests/System.Runtime.Loader.Tests.csproj b/src/libraries/System.Runtime.Loader/tests/System.Runtime.Loader.Tests.csproj index a5f2b3b0cce7b..714d83d65fabe 100644 --- a/src/libraries/System.Runtime.Loader/tests/System.Runtime.Loader.Tests.csproj +++ b/src/libraries/System.Runtime.Loader/tests/System.Runtime.Loader.Tests.csproj @@ -23,15 +23,10 @@ - - - + + + + @@ -48,35 +43,22 @@ - + - - - + + + - + - - - + + + diff --git a/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigInteger.cs b/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigInteger.cs index ffee155326a5f..fbb8ab78b3a63 100644 --- a/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigInteger.cs +++ b/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigInteger.cs @@ -4,6 +4,7 @@ using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; +using System.Runtime.InteropServices; namespace System.Numerics { @@ -263,7 +264,7 @@ public BigInteger(ReadOnlySpan value, bool isUnsigned = false, bool isBigE bool isNegative; if (byteCount > 0) { - byte mostSignificantByte = isBigEndian ? value[0] : value[byteCount - 1]; + byte mostSignificantByte = isBigEndian ? value[0] : value[^1]; isNegative = (mostSignificantByte & 0x80) != 0 && !isUnsigned; if (mostSignificantByte == 0) @@ -639,12 +640,12 @@ public bool IsPowerOfTwo AssertValid(); if (_bits == null) - return (_sign & (_sign - 1)) == 0 && _sign != 0; + return BitOperations.IsPow2(_sign); if (_sign != 1) return false; int iu = _bits.Length - 1; - if ((_bits[iu] & (_bits[iu] - 1)) != 0) + if (!BitOperations.IsPow2(_bits[iu])) return false; while (--iu >= 0) { @@ -818,12 +819,12 @@ public static double Log(BigInteger value, double baseValue) if (value._bits == null) return Math.Log(value._sign, baseValue); - ulong h = value._bits[value._bits.Length - 1]; - ulong m = value._bits.Length > 1 ? value._bits[value._bits.Length - 2] : 0; - ulong l = value._bits.Length > 2 ? value._bits[value._bits.Length - 3] : 0; + ulong h = value._bits[^1]; + ulong m = value._bits.Length > 1 ? value._bits[^2] : 0; + ulong l = value._bits.Length > 2 ? value._bits[^3] : 0; // Measure the exact bit count - int c = NumericsHelpers.CbitHighZero((uint)h); + int c = BitOperations.LeadingZeroCount((uint)h); long b = (long)value._bits.Length * 32 - c; // Extract most significant bits @@ -989,19 +990,17 @@ public override int GetHashCode() if (_bits == null) return _sign; - int hash = _sign; - for (int iv = _bits.Length; --iv >= 0;) - hash = NumericsHelpers.CombineHash(hash, unchecked((int)_bits[iv])); - return hash; + + HashCode hash = default; + hash.Add(_sign); + hash.AddBytes(MemoryMarshal.AsBytes(_bits.AsSpan())); + return hash.ToHashCode(); } public override bool Equals([NotNullWhen(true)] object? obj) { AssertValid(); - - if (!(obj is BigInteger)) - return false; - return Equals((BigInteger)obj); + return obj is BigInteger other && Equals(other); } public bool Equals(long other) @@ -1124,9 +1123,9 @@ public int CompareTo(object? obj) { if (obj == null) return 1; - if (!(obj is BigInteger)) + if (obj is not BigInteger bigInt) throw new ArgumentException(SR.Argument_MustBeBigInt, nameof(obj)); - return CompareTo((BigInteger)obj); + return CompareTo(bigInt); } /// @@ -1294,13 +1293,13 @@ private enum GetBytesMode { AllocateArray, Count, Span } // because a bits array of all zeros would represent 0, and this case // would be encoded as _bits = null and _sign = 0. Debug.Assert(bits.Length > 0); - Debug.Assert(bits[bits.Length - 1] != 0); + Debug.Assert(bits[^1] != 0); while (bits[nonZeroDwordIndex] == 0U) { nonZeroDwordIndex++; } - highDword = ~bits[bits.Length - 1]; + highDword = ~bits[^1]; if (bits.Length - 1 == nonZeroDwordIndex) { // This will not overflow because highDword is less than or equal to uint.MaxValue - 1. @@ -1312,7 +1311,7 @@ private enum GetBytesMode { AllocateArray, Count, Span } { Debug.Assert(sign == 1); highByte = 0x00; - highDword = bits[bits.Length - 1]; + highDword = bits[^1]; } byte msb; @@ -1470,15 +1469,18 @@ private ReadOnlySpan ToUInt32Span(Span scratch) } // Find highest significant byte and ensure high bit is 0 if positive, 1 if negative - int msb; - for (msb = dwords.Length - 1; msb > 0 && dwords[msb] == highDWord; msb--); + int msb = dwords.Length - 1; + while (msb > 0 && dwords[msb] == highDWord) + { + msb--; + } bool needExtraByte = (dwords[msb] & 0x80000000) != (highDWord & 0x80000000); int length = msb + 1 + (needExtraByte ? 1 : 0); bool copyDwordsToScratch = true; if (length <= scratch.Length) { - scratch = scratch.Slice(0, length); + scratch = scratch[..length]; copyDwordsToScratch = !dwordsIsScratch; } else @@ -1488,7 +1490,7 @@ private ReadOnlySpan ToUInt32Span(Span scratch) if (copyDwordsToScratch) { - dwords.Slice(0, msb + 1).CopyTo(scratch); + dwords[..(msb + 1)].CopyTo(scratch); } if (needExtraByte) @@ -1818,11 +1820,11 @@ private static BigInteger Subtract(uint[]? leftBits, int leftSign, uint[]? right return double.NegativeInfinity; } - ulong h = bits[length - 1]; - ulong m = length > 1 ? bits[length - 2] : 0; - ulong l = length > 2 ? bits[length - 3] : 0; + ulong h = bits[^1]; + ulong m = length > 1 ? bits[^2] : 0; + ulong l = length > 2 ? bits[^3] : 0; - int z = NumericsHelpers.CbitHighZero((uint)h); + int z = BitOperations.LeadingZeroCount((uint)h); int exp = (length - 2) * 32 - z; ulong man = (h << 32 + z) | (m << z) | (l >> 32 - z); @@ -2416,7 +2418,7 @@ public long GetBitLength() else { bitsArrayLength = bits.Length; - highValue = bits[bitsArrayLength - 1]; + highValue = bits[^1]; } long bitLength = bitsArrayLength * 32L - BitOperations.LeadingZeroCount(highValue); @@ -2493,7 +2495,7 @@ private void AssertValid() // Wasted space: _bits[0] could have been packed into _sign Debug.Assert(_bits.Length > 1 || _bits[0] >= kuMaskHighBit); // Wasted space: leading zeros could have been truncated - Debug.Assert(_bits[_bits.Length - 1] != 0); + Debug.Assert(_bits[^1] != 0); } else { diff --git a/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.DivRem.cs b/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.DivRem.cs index bb75e77a228d0..de1001d7f4f38 100644 --- a/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.DivRem.cs +++ b/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.DivRem.cs @@ -173,7 +173,7 @@ public static unsafe uint[] Remainder(uint[] left, uint[] right) uint divLo = rightLength > 1 ? right[rightLength - 2] : 0; // We measure the leading zeros of the divisor - int shift = LeadingZeros(divHi); + int shift = BitOperations.LeadingZeroCount(divHi); int backShift = 32 - shift; // And, we make sure the most significant bit is set @@ -316,39 +316,5 @@ public static unsafe uint[] Remainder(uint[] left, uint[] right) return false; } - - private static int LeadingZeros(uint value) - { - if (value == 0) - return 32; - - int count = 0; - if ((value & 0xFFFF0000) == 0) - { - count += 16; - value = value << 16; - } - if ((value & 0xFF000000) == 0) - { - count += 8; - value = value << 8; - } - if ((value & 0xF0000000) == 0) - { - count += 4; - value = value << 4; - } - if ((value & 0xC0000000) == 0) - { - count += 2; - value = value << 2; - } - if ((value & 0x80000000) == 0) - { - count += 1; - } - - return count; - } } } diff --git a/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.GcdInv.cs b/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.GcdInv.cs index d984912ec6246..9368891c0428e 100644 --- a/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.GcdInv.cs +++ b/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.GcdInv.cs @@ -238,7 +238,7 @@ private static void Gcd(ref BitsBuffer left, ref BitsBuffer right) } // Use all the bits but one, see [hac] 14.58 (ii) - int z = LeadingZeros((uint)xh); + int z = BitOperations.LeadingZeroCount((uint)xh); x = ((xh << 32 + z) | (xm << z) | (xl >> 32 - z)) >> 1; y = ((yh << 32 + z) | (ym << z) | (yl >> 32 - z)) >> 1; diff --git a/src/libraries/System.Runtime.Numerics/src/System/Numerics/Complex.cs b/src/libraries/System.Runtime.Numerics/src/System/Numerics/Complex.cs index 9325be0d806c2..8ec356e6dc215 100644 --- a/src/libraries/System.Runtime.Numerics/src/System/Numerics/Complex.cs +++ b/src/libraries/System.Runtime.Numerics/src/System/Numerics/Complex.cs @@ -370,8 +370,7 @@ public static Complex Reciprocal(Complex value) public override bool Equals([NotNullWhen(true)] object? obj) { - if (!(obj is Complex)) return false; - return Equals((Complex)obj); + return obj is Complex other && Equals(other); } public bool Equals(Complex value) @@ -379,14 +378,7 @@ public bool Equals(Complex value) return m_real.Equals(value.m_real) && m_imaginary.Equals(value.m_imaginary); } - public override int GetHashCode() - { - int n1 = 99999997; - int realHash = m_real.GetHashCode() % n1; - int imaginaryHash = m_imaginary.GetHashCode(); - int finalHash = realHash ^ imaginaryHash; - return finalHash; - } + public override int GetHashCode() => HashCode.Combine(m_real, m_imaginary); public override string ToString() => $"({m_real}, {m_imaginary})"; diff --git a/src/libraries/System.Runtime.Numerics/src/System/Numerics/NumericsHelpers.cs b/src/libraries/System.Runtime.Numerics/src/System/Numerics/NumericsHelpers.cs index e89bc4acd13e8..0926f69e2ba68 100644 --- a/src/libraries/System.Runtime.Numerics/src/System/Numerics/NumericsHelpers.cs +++ b/src/libraries/System.Runtime.Numerics/src/System/Numerics/NumericsHelpers.cs @@ -2,32 +2,20 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; -using System.Runtime.InteropServices; namespace System.Numerics { - [StructLayout(LayoutKind.Explicit)] - internal struct DoubleUlong - { - [FieldOffset(0)] - public double dbl; - [FieldOffset(0)] - public ulong uu; - } - internal static class NumericsHelpers { private const int kcbitUint = 32; public static void GetDoubleParts(double dbl, out int sign, out int exp, out ulong man, out bool fFinite) { - DoubleUlong du; - du.uu = 0; - du.dbl = dbl; + ulong bits = BitConverter.DoubleToUInt64Bits(dbl); - sign = 1 - ((int)(du.uu >> 62) & 2); - man = du.uu & 0x000FFFFFFFFFFFFF; - exp = (int)(du.uu >> 52) & 0x7FF; + sign = 1 - ((int)(bits >> 62) & 2); + man = bits & 0x000FFFFFFFFFFFFF; + exp = (int)(bits >> 52) & 0x7FF; if (exp == 0) { // Denormalized number. @@ -51,15 +39,14 @@ public static void GetDoubleParts(double dbl, out int sign, out int exp, out ulo public static double GetDoubleFromParts(int sign, int exp, ulong man) { - DoubleUlong du; - du.dbl = 0; + ulong bits; if (man == 0) - du.uu = 0; + bits = 0; else { // Normalize so that 0x0010 0000 0000 0000 is the highest bit set. - int cbitShift = CbitHighZero(man) - 11; + int cbitShift = BitOperations.LeadingZeroCount(man) - 11; if (cbitShift < 0) man >>= -cbitShift; else @@ -74,7 +61,7 @@ public static double GetDoubleFromParts(int sign, int exp, ulong man) if (exp >= 0x7FF) { // Infinity. - du.uu = 0x7FF0000000000000; + bits = 0x7FF0000000000000; } else if (exp <= 0) { @@ -83,25 +70,25 @@ public static double GetDoubleFromParts(int sign, int exp, ulong man) if (exp < -52) { // Underflow to zero. - du.uu = 0; + bits = 0; } else { - du.uu = man >> -exp; - Debug.Assert(du.uu != 0); + bits = man >> -exp; + Debug.Assert(bits != 0); } } else { // Mask off the implicit high bit. - du.uu = (man & 0x000FFFFFFFFFFFFF) | ((ulong)exp << 52); + bits = (man & 0x000FFFFFFFFFFFFF) | ((ulong)exp << 52); } } if (sign < 0) - du.uu |= 0x8000000000000000; + bits |= 0x8000000000000000; - return du.dbl; + return BitConverter.UInt64BitsToDouble(bits); } // Do an in-place two's complement. "Dangerous" because it causes @@ -139,53 +126,5 @@ public static uint Abs(int a) return ((uint)a ^ mask) - mask; } } - - public static uint CombineHash(uint u1, uint u2) - { - return ((u1 << 7) | (u1 >> 25)) ^ u2; - } - - public static int CombineHash(int n1, int n2) - { - return unchecked((int)CombineHash((uint)n1, (uint)n2)); - } - - public static int CbitHighZero(uint u) - { - if (u == 0) - return 32; - - int cbit = 0; - if ((u & 0xFFFF0000) == 0) - { - cbit += 16; - u <<= 16; - } - if ((u & 0xFF000000) == 0) - { - cbit += 8; - u <<= 8; - } - if ((u & 0xF0000000) == 0) - { - cbit += 4; - u <<= 4; - } - if ((u & 0xC0000000) == 0) - { - cbit += 2; - u <<= 2; - } - if ((u & 0x80000000) == 0) - cbit += 1; - return cbit; - } - - public static int CbitHighZero(ulong uu) - { - if ((uu & 0xFFFFFFFF00000000) == 0) - return 32 + CbitHighZero((uint)uu); - return CbitHighZero((uint)(uu >> 32)); - } } } diff --git a/src/libraries/System.Runtime/ref/System.Runtime.cs b/src/libraries/System.Runtime/ref/System.Runtime.cs index a94b40b28eec0..380e0a2e7f100 100644 --- a/src/libraries/System.Runtime/ref/System.Runtime.cs +++ b/src/libraries/System.Runtime/ref/System.Runtime.cs @@ -11060,13 +11060,13 @@ public abstract partial class Assembly : System.Reflection.ICustomAttributeProvi { protected Assembly() { } [System.ObsoleteAttribute("Assembly.CodeBase and Assembly.EscapedCodeBase are only included for .NET Framework compatibility. Use Assembly.Location instead.", DiagnosticId = "SYSLIB0012", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] - [System.Diagnostics.CodeAnalysis.RequiresAssemblyFilesAttribute("The code will throw for assemblies embedded in a single-file app")] + [System.Diagnostics.CodeAnalysis.RequiresAssemblyFilesAttribute("This member throws an exception for assemblies embedded in a single-file app")] public virtual string? CodeBase { get { throw null; } } public virtual System.Collections.Generic.IEnumerable CustomAttributes { get { throw null; } } public virtual System.Collections.Generic.IEnumerable DefinedTypes { [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Types might be removed")] get { throw null; } } public virtual System.Reflection.MethodInfo? EntryPoint { get { throw null; } } [System.ObsoleteAttribute("Assembly.CodeBase and Assembly.EscapedCodeBase are only included for .NET Framework compatibility. Use Assembly.Location instead.", DiagnosticId = "SYSLIB0012", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] - [System.Diagnostics.CodeAnalysis.RequiresAssemblyFilesAttribute("The code will throw for assemblies embedded in a single-file app")] + [System.Diagnostics.CodeAnalysis.RequiresAssemblyFilesAttribute("This member throws an exception for assemblies embedded in a single-file app")] public virtual string EscapedCodeBase { get { throw null; } } public virtual System.Collections.Generic.IEnumerable ExportedTypes { [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Types might be removed")] get { throw null; } } public virtual string? FullName { get { throw null; } } @@ -11100,9 +11100,11 @@ public abstract partial class Assembly : System.Reflection.ICustomAttributeProvi public static System.Reflection.Assembly GetExecutingAssembly() { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Types might be removed")] public virtual System.Type[] GetExportedTypes() { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresAssemblyFilesAttribute("This member throws an exception for assemblies embedded in a single-file app")] public virtual System.IO.FileStream? GetFile(string name) { throw null; } - [System.Diagnostics.CodeAnalysis.RequiresAssemblyFiles("The code will throw for assemblies embedded in a single-file app")] + [System.Diagnostics.CodeAnalysis.RequiresAssemblyFilesAttribute("This member throws an exception for assemblies embedded in a single-file app")] public virtual System.IO.FileStream[] GetFiles() { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresAssemblyFilesAttribute("This member throws an exception for assemblies embedded in a single-file app")] public virtual System.IO.FileStream[] GetFiles(bool getResourceModules) { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Types might be removed")] public virtual System.Type[] GetForwardedTypes() { throw null; } @@ -11867,11 +11869,13 @@ public abstract partial class Module : System.Reflection.ICustomAttributeProvide protected Module() { } public virtual System.Reflection.Assembly Assembly { get { throw null; } } public virtual System.Collections.Generic.IEnumerable CustomAttributes { get { throw null; } } + [System.Diagnostics.CodeAnalysis.RequiresAssemblyFilesAttribute("Returns for modules with no file path")] public virtual string FullyQualifiedName { get { throw null; } } public virtual int MDStreamVersion { get { throw null; } } public virtual int MetadataToken { get { throw null; } } public System.ModuleHandle ModuleHandle { get { throw null; } } public virtual System.Guid ModuleVersionId { get { throw null; } } + [System.Diagnostics.CodeAnalysis.RequiresAssemblyFilesAttribute("Returns for modules with no file path")] public virtual string Name { get { throw null; } } public virtual string ScopeName { get { throw null; } } public override bool Equals(object? o) { throw null; } diff --git a/src/libraries/System.Text.Json/ref/System.Text.Json.cs b/src/libraries/System.Text.Json/ref/System.Text.Json.cs index 99a987c579291..757d8d63d5133 100644 --- a/src/libraries/System.Text.Json/ref/System.Text.Json.cs +++ b/src/libraries/System.Text.Json/ref/System.Text.Json.cs @@ -595,7 +595,7 @@ public abstract partial class JsonNode public System.Text.Json.Nodes.JsonObject AsObject() { throw null; } public System.Text.Json.Nodes.JsonValue AsValue() { throw null; } public string GetPath() { throw null; } - public virtual TValue GetValue() { throw null; } + public virtual T GetValue() { throw null; } public static explicit operator bool (System.Text.Json.Nodes.JsonNode value) { throw null; } public static explicit operator byte (System.Text.Json.Nodes.JsonNode value) { throw null; } public static explicit operator char (System.Text.Json.Nodes.JsonNode value) { throw null; } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Nodes/JsonNode.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Nodes/JsonNode.cs index 6de74aef8ec3b..71ccc3f4b24b3 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Nodes/JsonNode.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Nodes/JsonNode.cs @@ -2,7 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; namespace System.Text.Json.Nodes { @@ -165,14 +164,23 @@ public JsonNode Root /// /// Gets the value for the current . /// + /// + /// {T} can be the type or base type of the underlying value. + /// If the underlying value is a then {T} can also be the type of any primitive + /// value supported by current . + /// Specifying the type for {T} will always succeed and return the underlying value as .
+ /// The underlying value of a after deserialization is an instance of , + /// otherwise it's the value specified when the was created. + ///
+ /// /// - /// The current cannot be represented as a {TValue}. + /// The current cannot be represented as a {T}. /// /// /// The current is not a or - /// is not compatible with {TValue}. + /// is not compatible with {T}. /// - public virtual TValue GetValue() => + public virtual T GetValue() => throw new InvalidOperationException(SR.Format(SR.NodeWrongType, nameof(JsonValue))); /// diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Nodes/JsonValue.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Nodes/JsonValue.cs index 1d0eb05631c47..87b6953f46765 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Nodes/JsonValue.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Nodes/JsonValue.cs @@ -99,6 +99,15 @@ internal override void GetPath(List path, JsonNode? child) /// /// Tries to obtain the current JSON value and returns a value that indicates whether the operation succeeded. /// + /// + /// {T} can be the type or base type of the underlying value. + /// If the underlying value is a then {T} can also be the type of any primitive + /// value supported by current . + /// Specifying the type for {T} will always succeed and return the underlying value as .
+ /// The underlying value of a after deserialization is an instance of , + /// otherwise it's the value specified when the was created. + ///
+ /// /// The type of value to obtain. /// When this method returns, contains the parsed value. /// if the value can be successfully obtained; otherwise, . diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/EnumConverter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/EnumConverter.cs index 64e891b5b0f1f..b4e666bc96b8a 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/EnumConverter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/EnumConverter.cs @@ -25,6 +25,8 @@ internal sealed class EnumConverter : JsonConverter private readonly ConcurrentDictionary _nameCache; + private ConcurrentDictionary? _dictionaryKeyPolicyCache; + // This is used to prevent flooding the cache due to exponential bitwise combinations of flags. // Since multiple threads can add to the cache, a few more values might be added. private const int NameCacheSizeSoftLimit = 64; @@ -325,35 +327,82 @@ internal override void WriteWithQuotes(Utf8JsonWriter writer, T value, JsonSeria ulong key = ConvertToUInt64(value); - if (_nameCache.TryGetValue(key, out JsonEncodedText formatted)) + // Try to obtain values from caches + if (options.DictionaryKeyPolicy != null) + { + Debug.Assert(!state.Current.IgnoreDictionaryKeyPolicy); + + if (_dictionaryKeyPolicyCache != null && _dictionaryKeyPolicyCache.TryGetValue(key, out JsonEncodedText formatted)) + { + writer.WritePropertyName(formatted); + return; + } + } + else if (_nameCache.TryGetValue(key, out JsonEncodedText formatted)) { writer.WritePropertyName(formatted); return; } + + // if there are not cached values string original = value.ToString(); if (IsValidIdentifier(original)) { - // We are dealing with a combination of flag constants since - // all constant values were cached during warm-up. - JavaScriptEncoder? encoder = options.Encoder; - - if (_nameCache.Count < NameCacheSizeSoftLimit) + if (options.DictionaryKeyPolicy != null) { - formatted = JsonEncodedText.Encode(original, encoder); + original = options.DictionaryKeyPolicy.ConvertName(original); - writer.WritePropertyName(formatted); + if (original == null) + { + ThrowHelper.ThrowInvalidOperationException_NamingPolicyReturnNull(options.DictionaryKeyPolicy); + } + + _dictionaryKeyPolicyCache ??= new ConcurrentDictionary(); + + if (_dictionaryKeyPolicyCache.Count < NameCacheSizeSoftLimit) + { + JavaScriptEncoder? encoder = options.Encoder; + + JsonEncodedText formatted = JsonEncodedText.Encode(original, encoder); + + writer.WritePropertyName(formatted); + + _dictionaryKeyPolicyCache.TryAdd(key, formatted); + } + else + { + // We also do not create a JsonEncodedText instance here because passing the string + // directly to the writer is cheaper than creating one and not caching it for reuse. + writer.WritePropertyName(original); + } - _nameCache.TryAdd(key, formatted); + return; } else { - // We also do not create a JsonEncodedText instance here because passing the string - // directly to the writer is cheaper than creating one and not caching it for reuse. - writer.WritePropertyName(original); - } + // We might be dealing with a combination of flag constants since all constant values were + // likely cached during warm - up(assuming the number of constants <= NameCacheSizeSoftLimit). - return; + JavaScriptEncoder? encoder = options.Encoder; + + if (_nameCache.Count < NameCacheSizeSoftLimit) + { + JsonEncodedText formatted = JsonEncodedText.Encode(original, encoder); + + writer.WritePropertyName(formatted); + + _nameCache.TryAdd(key, formatted); + } + else + { + // We also do not create a JsonEncodedText instance here because passing the string + // directly to the writer is cheaper than creating one and not caching it for reuse. + writer.WritePropertyName(original); + } + + return; + } } switch (s_enumTypeCode) diff --git a/src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.Dictionary.KeyPolicy.cs b/src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.Dictionary.KeyPolicy.cs index 1a90f20a2744c..bb00474f510fa 100644 --- a/src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.Dictionary.KeyPolicy.cs +++ b/src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.Dictionary.KeyPolicy.cs @@ -188,6 +188,101 @@ public async Task CustomNameSerialize() Assert.Equal(JsonCustomKey, json); } + public enum ETestEnum + { + TestValue1 = 1, + TestValue2 = 2, + } + + [Fact] + public static void EnumSerialization_DictionaryPolicy_Honored_CamelCase() + { + var options = new JsonSerializerOptions + { + DictionaryKeyPolicy = JsonNamingPolicy.CamelCase, + }; + + Dictionary dict = new Dictionary { [ETestEnum.TestValue1] = ETestEnum.TestValue1 }; + string value = JsonSerializer.Serialize(dict, options); + Assert.Equal("{\"testValue1\":1}", value); + + dict = new Dictionary { [ETestEnum.TestValue2] = ETestEnum.TestValue2 }; + value = JsonSerializer.Serialize(dict, options); + Assert.Equal("{\"testValue2\":2}", value); + + dict = new Dictionary { [ETestEnum.TestValue1] = ETestEnum.TestValue1, [ETestEnum.TestValue2] = ETestEnum.TestValue2 }; + value = JsonSerializer.Serialize(dict, options); + Assert.Equal("{\"testValue1\":1,\"testValue2\":2}", value); + } + + [Fact] + public static void EnumSerializationAsDictKey_NoDictionaryKeyPolicy() + { + Dictionary dict = new Dictionary { [ETestEnum.TestValue1] = ETestEnum.TestValue1 }; + string value = JsonSerializer.Serialize(dict); + Assert.Equal("{\"TestValue1\":1}", value); + + dict = new Dictionary { [ETestEnum.TestValue2] = ETestEnum.TestValue2 }; + value = JsonSerializer.Serialize(dict); + Assert.Equal("{\"TestValue2\":2}", value); + + dict = new Dictionary { [ETestEnum.TestValue1] = ETestEnum.TestValue1, [ETestEnum.TestValue2] = ETestEnum.TestValue2 }; + value = JsonSerializer.Serialize(dict); + Assert.Equal("{\"TestValue1\":1,\"TestValue2\":2}", value); + } + + public class ClassWithEnumProperties + { + public ETestEnum TestEnumProperty1 { get; } = ETestEnum.TestValue2; + public DayOfWeek TestEnumProperty2 { get; } = DayOfWeek.Monday; + } + + [Fact] + public static void EnumSerialization_DictionaryPolicy_NotApplied_WhenEnumsAreSerialized() + { + var options = new JsonSerializerOptions + { + DictionaryKeyPolicy = JsonNamingPolicy.CamelCase, + }; + + string value = JsonSerializer.Serialize(DayOfWeek.Friday, options); + + Assert.Equal("5", value); + + value = JsonSerializer.Serialize(ETestEnum.TestValue2, options); + + Assert.Equal("2", value); + + + value = JsonSerializer.Serialize(new ClassWithEnumProperties(), options); + + Assert.Equal("{\"TestEnumProperty1\":2,\"TestEnumProperty2\":1}", value); + + value = JsonSerializer.Serialize(new List { DayOfWeek.Sunday, DayOfWeek.Monday, DayOfWeek.Tuesday, DayOfWeek.Wednesday, DayOfWeek.Thursday, DayOfWeek.Friday, DayOfWeek.Saturday}, options); + + Assert.Equal("[0,1,2,3,4,5,6]", value); + } + + public class CustomJsonNamingPolicy : JsonNamingPolicy + { + public override string ConvertName(string name) => null; + } + + [Fact] + public static void EnumSerialization_DictionaryPolicy_ThrowsException_WhenNamingPolicyReturnsNull() + { + var options = new JsonSerializerOptions + { + DictionaryKeyPolicy = new CustomJsonNamingPolicy(), + }; + + Dictionary dict = new Dictionary { [ETestEnum.TestValue1] = ETestEnum.TestValue1 }; + + InvalidOperationException ex = Assert.Throws(() => JsonSerializer.Serialize(dict, options)); + + Assert.Contains(typeof(CustomJsonNamingPolicy).ToString(), ex.Message); + } + [Fact] public async Task NullNamePolicy() { diff --git a/src/libraries/System.Threading.Tasks/tests/System.Runtime.CompilerServices/AsyncTaskMethodBuilderTests.cs b/src/libraries/System.Threading.Tasks/tests/System.Runtime.CompilerServices/AsyncTaskMethodBuilderTests.cs index d762f2b639fc9..d90c0685451f3 100644 --- a/src/libraries/System.Threading.Tasks/tests/System.Runtime.CompilerServices/AsyncTaskMethodBuilderTests.cs +++ b/src/libraries/System.Threading.Tasks/tests/System.Runtime.CompilerServices/AsyncTaskMethodBuilderTests.cs @@ -560,6 +560,7 @@ async Task YieldOnceAsync(object s) { GC.Collect(); GC.WaitForPendingFinalizers(); + await Task.Yield(); } if (!Volatile.Read(ref finalized)) diff --git a/src/libraries/libraries-packages.proj b/src/libraries/libraries-packages.proj index f67803e79972b..0bc55ebbffd53 100644 --- a/src/libraries/libraries-packages.proj +++ b/src/libraries/libraries-packages.proj @@ -2,13 +2,13 @@ + - + + + Exclude="$(MSBuildThisFileDirectory)*\src\**\*.shproj" /> diff --git a/src/libraries/pkg/Microsoft.Windows.Compatibility/Microsoft.Windows.Compatibility.pkgproj b/src/libraries/pkg/Microsoft.Windows.Compatibility/Microsoft.Windows.Compatibility.pkgproj deleted file mode 100644 index c1a3f16e19ec1..0000000000000 --- a/src/libraries/pkg/Microsoft.Windows.Compatibility/Microsoft.Windows.Compatibility.pkgproj +++ /dev/null @@ -1,98 +0,0 @@ - - - - - false - This Windows Compatibility Pack provides access to APIs that were previously available only for .NET Framework. It can be used from both .NET Core as well as .NET Standard. - - - - $(PackageVersion) - - - $(PackageVersion) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/libraries/pkg/Microsoft.Windows.Compatibility/Microsoft.Windows.Compatibility.proj b/src/libraries/pkg/Microsoft.Windows.Compatibility/Microsoft.Windows.Compatibility.proj deleted file mode 100644 index 17a7f16890297..0000000000000 --- a/src/libraries/pkg/Microsoft.Windows.Compatibility/Microsoft.Windows.Compatibility.proj +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/src/libraries/pkg/baseline/packageIndex.json b/src/libraries/pkg/baseline/packageIndex.json index 6c24d93bbb486..09f1be0796e39 100644 --- a/src/libraries/pkg/baseline/packageIndex.json +++ b/src/libraries/pkg/baseline/packageIndex.json @@ -1439,25 +1439,6 @@ "6.0.0.0": "6.0.0" } }, - "Microsoft.Windows.Compatibility": { - "StableVersions": [ - "2.0.0", - "2.0.1", - "2.1.0", - "2.1.1", - "3.0.0", - "3.0.1", - "5.0.0" - ], - "InboxOn": {} - }, - "Microsoft.Windows.Compatibility.Shims": { - "StableVersions": [ - "2.0.0", - "2.0.1" - ], - "InboxOn": {} - }, "Microsoft.XmlSerializer.Generator": { "StableVersions": [ "1.0.0", diff --git a/src/libraries/pkg/runtime.native.System.IO.Ports/runtime.native.System.IO.Ports.proj b/src/libraries/pkg/runtime.native.System.IO.Ports/runtime.native.System.IO.Ports.proj index a1ec1ea4bd1c9..4cccee8eede3c 100644 --- a/src/libraries/pkg/runtime.native.System.IO.Ports/runtime.native.System.IO.Ports.proj +++ b/src/libraries/pkg/runtime.native.System.IO.Ports/runtime.native.System.IO.Ports.proj @@ -1,7 +1,7 @@ - + diff --git a/src/libraries/pkg/test/build/packageTest.targets b/src/libraries/pkg/test/build/packageTest.targets index 8bffafc8e918d..022944a2e0e02 100644 --- a/src/libraries/pkg/test/build/packageTest.targets +++ b/src/libraries/pkg/test/build/packageTest.targets @@ -1,16 +1,17 @@ - - <_targetFrameworkIdentifier>$(TargetFrameworkIdentifier.Substring(1).ToLower()) - - + <_targetFrameworkIdentifier Condition="'$(TargetFrameworkIdentifier)' != ''">$(TargetFrameworkIdentifier.Substring(1).ToLower()) true true - + + + + + @@ -28,7 +29,6 @@ - diff --git a/src/libraries/pkg/test/frameworkSettings/netcore50/settings.targets b/src/libraries/pkg/test/frameworkSettings/netcore50/settings.targets deleted file mode 100644 index b54cf42617011..0000000000000 --- a/src/libraries/pkg/test/frameworkSettings/netcore50/settings.targets +++ /dev/null @@ -1,5 +0,0 @@ - - - 10.0.0 - - \ No newline at end of file diff --git a/src/libraries/pkg/test/packageSettings/Microsoft.NETCore.Platforms/netcoreapp2.2/settings.targets b/src/libraries/pkg/test/packageSettings/Microsoft.NETCore.Platforms/netcoreapp2.2/settings.targets deleted file mode 100644 index 46711d0993657..0000000000000 --- a/src/libraries/pkg/test/packageSettings/Microsoft.NETCore.Platforms/netcoreapp2.2/settings.targets +++ /dev/null @@ -1,8 +0,0 @@ - - - - $(NoWarn);NU1605 - - \ No newline at end of file diff --git a/src/libraries/pkg/test/project.csproj.template b/src/libraries/pkg/test/project.csproj.template index b2c4858b1e1f4..e0baba921e330 100644 --- a/src/libraries/pkg/test/project.csproj.template +++ b/src/libraries/pkg/test/project.csproj.template @@ -14,8 +14,6 @@ {MicrosoftNetCoreAppFrameworkName} {MicrosoftNetCoreAppRefPackDir} - - false $(NetCoreAppCurrentVersion) diff --git a/src/libraries/pkg/test/testPackages.proj b/src/libraries/pkg/test/testPackages.proj index e4080b6116eb2..544ebe1b25f33 100644 --- a/src/libraries/pkg/test/testPackages.proj +++ b/src/libraries/pkg/test/testPackages.proj @@ -1,13 +1,7 @@ - - - - @@ -38,11 +32,6 @@ - - - - - @@ -59,9 +48,6 @@ build\Directory.Build.props; build\Directory.Build.targets" DestinationFolder="$(TestDir)" /> - @@ -77,7 +63,14 @@ - + + + + + + @@ -98,7 +91,7 @@ <_supportedPackageByTargetFrameworkToRemove Include="@(_supportedPackageByTargetFramework)" Exclude="@(TargetFrameworksToInclude)" Condition="'@(TargetFrameworksToInclude)' != ''" /> - <_filteredSupportedPackageByTargetFramework Include="@(_supportedPackageByTargetFramework)" Exclude="@(TargetFrameworksToExclude);@(_supportedPackageByTargetFrameworkToRemove)" /> + <_filteredSupportedPackageByTargetFramework Include="@(_supportedPackageByTargetFramework)" Exclude="@(_supportedPackageByTargetFrameworkToRemove)" /> diff --git a/src/libraries/shims/ApiCompat.proj b/src/libraries/shims/ApiCompat.proj index 9885f574fc6d8..4ade3e1c90441 100644 --- a/src/libraries/shims/ApiCompat.proj +++ b/src/libraries/shims/ApiCompat.proj @@ -107,7 +107,7 @@ - + diff --git a/src/libraries/shims/ApiCompatBaseline.PreviousNetCoreApp.txt b/src/libraries/shims/ApiCompatBaseline.PreviousNetCoreApp.txt index 54945167821c8..69f17447741d8 100644 --- a/src/libraries/shims/ApiCompatBaseline.PreviousNetCoreApp.txt +++ b/src/libraries/shims/ApiCompatBaseline.PreviousNetCoreApp.txt @@ -89,6 +89,8 @@ CannotChangeAttribute : Attribute 'System.AttributeUsageAttribute' on 'System.Ru CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.SupportedOSPlatformAttribute' exists on 'System.Runtime.InteropServices.Marshal.AddRef(System.IntPtr)' in the contract but not the implementation. CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.SupportedOSPlatformAttribute' exists on 'System.Runtime.InteropServices.Marshal.QueryInterface(System.IntPtr, System.Guid, System.IntPtr)' in the contract but not the implementation. CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.SupportedOSPlatformAttribute' exists on 'System.Runtime.InteropServices.Marshal.Release(System.IntPtr)' in the contract but not the implementation. +CannotChangeAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' on 'System.Security.Cryptography.AesCcm' changed from '[UnsupportedOSPlatformAttribute("browser")]' in the contract to '[UnsupportedOSPlatformAttribute("browser")]' in the implementation. +CannotChangeAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' on 'System.Security.Cryptography.AesGcm' changed from '[UnsupportedOSPlatformAttribute("browser")]' in the contract to '[UnsupportedOSPlatformAttribute("browser")]' in the implementation. CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' exists on 'System.Security.Cryptography.CryptoConfig' in the contract but not the implementation. Compat issues with assembly System: CannotChangeAttribute : Attribute 'System.ComponentModel.DesignerAttribute' on 'System.ComponentModel.IComponent' changed from '[DesignerAttribute("System.ComponentModel.Design.ComponentDesigner, System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")]' in the contract to '[DesignerAttribute("System.ComponentModel.Design.ComponentDesigner, System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")]' in the implementation. @@ -164,13 +166,14 @@ CannotChangeAttribute : Attribute 'System.AttributeUsageAttribute' on 'System.Ru CannotChangeAttribute : Attribute 'System.AttributeUsageAttribute' on 'System.Runtime.Versioning.SupportedOSPlatformAttribute' changed from '[AttributeUsageAttribute(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Constructor | AttributeTargets.Enum | AttributeTargets.Event | AttributeTargets.Field | AttributeTargets.Method | AttributeTargets.Module | AttributeTargets.Property | AttributeTargets.Struct, AllowMultiple=true, Inherited=false)]' in the contract to '[AttributeUsageAttribute(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Constructor | AttributeTargets.Enum | AttributeTargets.Event | AttributeTargets.Field | AttributeTargets.Interface | AttributeTargets.Method | AttributeTargets.Module | AttributeTargets.Property | AttributeTargets.Struct, AllowMultiple=true, Inherited=false)]' in the implementation. CannotChangeAttribute : Attribute 'System.AttributeUsageAttribute' on 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' changed from '[AttributeUsageAttribute(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Constructor | AttributeTargets.Enum | AttributeTargets.Event | AttributeTargets.Field | AttributeTargets.Method | AttributeTargets.Module | AttributeTargets.Property | AttributeTargets.Struct, AllowMultiple=true, Inherited=false)]' in the contract to '[AttributeUsageAttribute(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Constructor | AttributeTargets.Enum | AttributeTargets.Event | AttributeTargets.Field | AttributeTargets.Interface | AttributeTargets.Method | AttributeTargets.Module | AttributeTargets.Property | AttributeTargets.Struct, AllowMultiple=true, Inherited=false)]' in the implementation. Compat issues with assembly System.Runtime.InteropServices: +CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.SupportedOSPlatformAttribute' exists on 'System.Runtime.InteropServices.ComWrappers' in the contract but not the implementation. CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.SupportedOSPlatformAttribute' exists on 'System.Runtime.InteropServices.Marshal.AddRef(System.IntPtr)' in the contract but not the implementation. CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.SupportedOSPlatformAttribute' exists on 'System.Runtime.InteropServices.Marshal.QueryInterface(System.IntPtr, System.Guid, System.IntPtr)' in the contract but not the implementation. CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.SupportedOSPlatformAttribute' exists on 'System.Runtime.InteropServices.Marshal.Release(System.IntPtr)' in the contract but not the implementation. Compat issues with assembly System.Security.Cryptography.Algorithms: +CannotChangeAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' on 'System.Security.Cryptography.AesCcm' changed from '[UnsupportedOSPlatformAttribute("browser")]' in the contract to '[UnsupportedOSPlatformAttribute("browser")]' in the implementation. +CannotChangeAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' on 'System.Security.Cryptography.AesGcm' changed from '[UnsupportedOSPlatformAttribute("browser")]' in the contract to '[UnsupportedOSPlatformAttribute("browser")]' in the implementation. CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' exists on 'System.Security.Cryptography.CryptoConfig' in the contract but not the implementation. -Compat issues with assembly System.Threading.Tasks.Extensions: -CannotChangeAttribute : Attribute 'System.AttributeUsageAttribute' on 'System.Runtime.CompilerServices.AsyncMethodBuilderAttribute' changed from '[AttributeUsageAttribute(AttributeTargets.Class | AttributeTargets.Delegate | AttributeTargets.Enum | AttributeTargets.Interface | AttributeTargets.Struct, Inherited=false, AllowMultiple=false)]' in the contract to '[AttributeUsageAttribute(AttributeTargets.Class | AttributeTargets.Delegate | AttributeTargets.Enum | AttributeTargets.Interface | AttributeTargets.Method | AttributeTargets.Struct, Inherited=false, AllowMultiple=false)]' in the implementation. Compat issues with assembly System.Text.Json: CannotRemoveAttribute : Attribute 'System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute' exists on parameter 'returnType' on member 'System.Text.Json.JsonSerializer.Deserialize(System.ReadOnlySpan, System.Type, System.Text.Json.JsonSerializerOptions)' in the contract but not the implementation. CannotRemoveAttribute : Attribute 'System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute' exists on parameter 'returnType' on member 'System.Text.Json.JsonSerializer.Deserialize(System.String, System.Type, System.Text.Json.JsonSerializerOptions)' in the contract but not the implementation. @@ -180,9 +183,7 @@ CannotRemoveAttribute : Attribute 'System.Diagnostics.CodeAnalysis.DynamicallyAc CannotRemoveAttribute : Attribute 'System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute' exists on parameter 'inputType' on member 'System.Text.Json.JsonSerializer.Serialize(System.Text.Json.Utf8JsonWriter, System.Object, System.Type, System.Text.Json.JsonSerializerOptions)' in the contract but not the implementation. CannotRemoveAttribute : Attribute 'System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute' exists on parameter 'inputType' on member 'System.Text.Json.JsonSerializer.SerializeAsync(System.IO.Stream, System.Object, System.Type, System.Text.Json.JsonSerializerOptions, System.Threading.CancellationToken)' in the contract but not the implementation. CannotRemoveAttribute : Attribute 'System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute' exists on parameter 'inputType' on member 'System.Text.Json.JsonSerializer.SerializeToUtf8Bytes(System.Object, System.Type, System.Text.Json.JsonSerializerOptions)' in the contract but not the implementation. -CannotChangeAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' on 'System.Security.Cryptography.AesCcm' changed from '[UnsupportedOSPlatformAttribute("browser")]' in the contract to '[UnsupportedOSPlatformAttribute("browser")]' in the implementation. -CannotChangeAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' on 'System.Security.Cryptography.AesGcm' changed from '[UnsupportedOSPlatformAttribute("browser")]' in the contract to '[UnsupportedOSPlatformAttribute("browser")]' in the implementation. -CannotChangeAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' on 'System.Security.Cryptography.AesCcm' changed from '[UnsupportedOSPlatformAttribute("browser")]' in the contract to '[UnsupportedOSPlatformAttribute("browser")]' in the implementation. -CannotChangeAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' on 'System.Security.Cryptography.AesGcm' changed from '[UnsupportedOSPlatformAttribute("browser")]' in the contract to '[UnsupportedOSPlatformAttribute("browser")]' in the implementation. CannotChangeAttribute : Attribute 'System.AttributeUsageAttribute' on 'System.Text.Json.Serialization.JsonConverterAttribute' changed from '[AttributeUsageAttribute(AttributeTargets.Class | AttributeTargets.Enum | AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Struct, AllowMultiple=false)]' in the contract to '[AttributeUsageAttribute(AttributeTargets.Class | AttributeTargets.Enum | AttributeTargets.Field | AttributeTargets.Interface | AttributeTargets.Property | AttributeTargets.Struct, AllowMultiple=false)]' in the implementation. -Total Issues: 171 +Compat issues with assembly System.Threading.Tasks.Extensions: +CannotChangeAttribute : Attribute 'System.AttributeUsageAttribute' on 'System.Runtime.CompilerServices.AsyncMethodBuilderAttribute' changed from '[AttributeUsageAttribute(AttributeTargets.Class | AttributeTargets.Delegate | AttributeTargets.Enum | AttributeTargets.Interface | AttributeTargets.Struct, Inherited=false, AllowMultiple=false)]' in the contract to '[AttributeUsageAttribute(AttributeTargets.Class | AttributeTargets.Delegate | AttributeTargets.Enum | AttributeTargets.Interface | AttributeTargets.Method | AttributeTargets.Struct, Inherited=false, AllowMultiple=false)]' in the implementation. +Total Issues: 172 diff --git a/src/libraries/src.proj b/src/libraries/src.proj index 5862082f7e3ef..0faa26075e2d7 100644 --- a/src/libraries/src.proj +++ b/src/libraries/src.proj @@ -7,6 +7,12 @@ <_allSrc Include="$(MSBuildThisFileDirectory)*\src\*.csproj" Exclude="@(ProjectExclusions)" /> + + <_allSrc Update="$(MSBuildThisFileDirectory)Microsoft.Windows.Compatibility\src\Microsoft.Windows.Compatibility.csproj" + AdditionalProperties="BuildProjectReferences=false" /> + + <_allSrc Remove="$(MSBuildThisFileDirectory)Microsoft.Windows.Compatibility\src\Microsoft.Windows.Compatibility.csproj" + Condition="'$(BuildAllConfigurations)' != 'true'" /> - - - @@ -86,18 +83,6 @@ - - - - - - - - - - - - diff --git a/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/ModuleBuilder.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/ModuleBuilder.Mono.cs index 86ba437fa1028..427767a5fbc5d 100644 --- a/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/ModuleBuilder.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/ModuleBuilder.Mono.cs @@ -106,6 +106,7 @@ internal ModuleBuilder(AssemblyBuilder assb, string name, bool emitSymbolInfo) set_wrappers_type(this, type); } + [RequiresAssemblyFiles(UnknownStringMessageInRAF)] public override string FullyQualifiedName { get @@ -816,6 +817,7 @@ public override Assembly Assembly get { return assemblyb; } } + [RequiresAssemblyFiles(UnknownStringMessageInRAF)] public override string Name { get { return name; } @@ -874,7 +876,7 @@ internal MemberInfo ResolveOrGetRegisteredToken(int metadataToken, Type[] generi m = GetRegisteredToken(metadataToken) as MemberInfo; if (m == null) - throw RuntimeModule.resolve_token_exception(Name, metadataToken, error, "MemberInfo"); + throw RuntimeModule.resolve_token_exception(this, metadataToken, error, "MemberInfo"); else return m; } diff --git a/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs b/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs index d5fa9e4e31d83..95aed378b1707 100644 --- a/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs +++ b/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs @@ -74,7 +74,7 @@ public unsafe UnmanagedMemoryStreamForModule(byte* pointer, long length, Module public override bool ReflectionOnly => false; - [RequiresAssemblyFiles("The code will throw for assemblies embedded in a single-file app")] + [RequiresAssemblyFiles(ThrowingMessageInRAF)] public override string? CodeBase { get @@ -410,6 +410,7 @@ public override Assembly GetSatelliteAssembly(CultureInfo culture, Version? vers return res; } + [RequiresAssemblyFiles(ThrowingMessageInRAF)] public override FileStream? GetFile(string name) { if (name == null) @@ -430,6 +431,7 @@ public override Assembly GetSatelliteAssembly(CultureInfo culture, Version? vers return null; } + [RequiresAssemblyFiles(ThrowingMessageInRAF)] public override FileStream[] GetFiles(bool getResourceModules) { if (Location.Length == 0) diff --git a/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeModule.cs b/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeModule.cs index 692d7ff29926c..9b92b126780d8 100644 --- a/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeModule.cs +++ b/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeModule.cs @@ -56,6 +56,7 @@ Assembly Assembly get { return assembly; } } + [RequiresAssemblyFiles(UnknownStringMessageInRAF)] public override // Note: we do not ask for PathDiscovery because no path is returned here. @@ -94,6 +95,7 @@ Guid ModuleVersionId } } + [RequiresAssemblyFiles(UnknownStringMessageInRAF)] public override string FullyQualifiedName { @@ -232,7 +234,7 @@ internal static FieldInfo ResolveField(Module module, IntPtr monoModule, int met IntPtr handle = ResolveFieldToken(monoModule, metadataToken, ptrs_from_types(genericTypeArguments), ptrs_from_types(genericMethodArguments), out error); if (handle == IntPtr.Zero) - throw resolve_token_exception(module.Name, metadataToken, error, "Field"); + throw resolve_token_exception(module, metadataToken, error, "Field"); else return FieldInfo.GetFieldFromHandle(new RuntimeFieldHandle(handle)); } @@ -251,7 +253,7 @@ internal static MemberInfo ResolveMember(Module module, IntPtr monoModule, int m MemberInfo m = ResolveMemberToken(monoModule, metadataToken, ptrs_from_types(genericTypeArguments), ptrs_from_types(genericMethodArguments), out error); if (m == null) - throw resolve_token_exception(module.Name, metadataToken, error, "MemberInfo"); + throw resolve_token_exception(module, metadataToken, error, "MemberInfo"); else return m; } @@ -270,7 +272,7 @@ internal static MethodBase ResolveMethod(Module module, IntPtr monoModule, int m IntPtr handle = ResolveMethodToken(monoModule, metadataToken, ptrs_from_types(genericTypeArguments), ptrs_from_types(genericMethodArguments), out error); if (handle == IntPtr.Zero) - throw resolve_token_exception(module.Name, metadataToken, error, "MethodBase"); + throw resolve_token_exception(module, metadataToken, error, "MethodBase"); else return RuntimeMethodInfo.GetMethodFromHandleNoGenericCheck(new RuntimeMethodHandle(handle)); } @@ -289,7 +291,7 @@ internal static string ResolveString(Module module, IntPtr monoModule, int metad string s = ResolveStringToken(monoModule, metadataToken, out error); if (s == null) - throw resolve_token_exception(module.Name, metadataToken, error, "string"); + throw resolve_token_exception(module, metadataToken, error, "string"); else return s; } @@ -308,7 +310,7 @@ internal static Type ResolveType(Module module, IntPtr monoModule, int metadataT IntPtr handle = ResolveTypeToken(monoModule, metadataToken, ptrs_from_types(genericTypeArguments), ptrs_from_types(genericMethodArguments), out error); if (handle == IntPtr.Zero) - throw resolve_token_exception(module.Name, metadataToken, error, "Type"); + throw resolve_token_exception(module, metadataToken, error, "Type"); else return Type.GetTypeFromHandle(new RuntimeTypeHandle(handle)); } @@ -327,7 +329,7 @@ internal static byte[] ResolveSignature(Module module, IntPtr monoModule, int me byte[] res = ResolveSignature(monoModule, metadataToken, out error); if (res == null) - throw resolve_token_exception(module.Name, metadataToken, error, "signature"); + throw resolve_token_exception(module, metadataToken, error, "signature"); else return res; } @@ -364,6 +366,11 @@ internal Guid GetModuleVersionId() return new Guid(guid); } + [UnconditionalSuppressMessage("SingleFile", "IL3002:RequiresAssemblyFiles", + Justification = "Module Name is used only for diagnostic reporting message")] + internal static Exception resolve_token_exception(Module module, int metadataToken, ResolveTokenError error, string tokenType) + => resolve_token_exception(module.Name, metadataToken, error, tokenType); + internal static Exception resolve_token_exception(string name, int metadataToken, ResolveTokenError error, string tokenType) { if (error == ResolveTokenError.OutOfRange) diff --git a/src/mono/mono/component/debugger-agent.c b/src/mono/mono/component/debugger-agent.c index 91de21bee9b78..2b6842c11fea6 100644 --- a/src/mono/mono/component/debugger-agent.c +++ b/src/mono/mono/component/debugger-agent.c @@ -7617,67 +7617,67 @@ assembly_commands (int command, guint8 *p, guint8 *end, Buffer *buf) g_free (name); break; } - case CMD_ASSEMBLY_GET_METADATA_BLOB: { - MonoImage* image = ass->image; - if (ass->dynamic) { - return ERR_NOT_IMPLEMENTED; - } - buffer_add_byte_array (buf, (guint8*)image->raw_data, image->raw_data_len); - break; - } - case CMD_ASSEMBLY_GET_IS_DYNAMIC: { - buffer_add_byte (buf, ass->dynamic); - break; - } - case CMD_ASSEMBLY_GET_PDB_BLOB: { - MonoImage* image = ass->image; - MonoDebugHandle* handle = mono_debug_get_handle (image); - if (!handle) { - return ERR_INVALID_ARGUMENT; - } - MonoPPDBFile* ppdb = handle->ppdb; - if (ppdb) { - image = mono_ppdb_get_image (ppdb); - buffer_add_byte_array (buf, (guint8*)image->raw_data, image->raw_data_len); - } else { - buffer_add_byte_array (buf, NULL, 0); - } - break; - } - case CMD_ASSEMBLY_GET_TYPE_FROM_TOKEN: { - if (ass->dynamic) { - return ERR_NOT_IMPLEMENTED; - } - guint32 token = decode_int (p, &p, end); - ERROR_DECL (error); - error_init (error); - MonoClass* mono_class = mono_class_get_checked (ass->image, token, error); - if (!is_ok (error)) { - add_error_string (buf, mono_error_get_message (error)); - mono_error_cleanup (error); - return ERR_INVALID_ARGUMENT; - } - buffer_add_typeid (buf, domain, mono_class); - mono_error_cleanup (error); - break; - } - case CMD_ASSEMBLY_GET_METHOD_FROM_TOKEN: { - if (ass->dynamic) { - return ERR_NOT_IMPLEMENTED; - } - guint32 token = decode_int (p, &p, end); - ERROR_DECL (error); - error_init (error); - MonoMethod* mono_method = mono_get_method_checked (ass->image, token, NULL, NULL, error); - if (!is_ok (error)) { - add_error_string (buf, mono_error_get_message (error)); - mono_error_cleanup (error); - return ERR_INVALID_ARGUMENT; - } - buffer_add_methodid (buf, domain, mono_method); - mono_error_cleanup (error); - break; - } + case CMD_ASSEMBLY_GET_METADATA_BLOB: { + MonoImage* image = ass->image; + if (ass->dynamic) { + return ERR_NOT_IMPLEMENTED; + } + buffer_add_byte_array (buf, (guint8*)image->raw_data, image->raw_data_len); + break; + } + case CMD_ASSEMBLY_GET_IS_DYNAMIC: { + buffer_add_byte (buf, ass->dynamic); + break; + } + case CMD_ASSEMBLY_GET_PDB_BLOB: { + MonoImage* image = ass->image; + MonoDebugHandle* handle = mono_debug_get_handle (image); + if (!handle) { + return ERR_INVALID_ARGUMENT; + } + MonoPPDBFile* ppdb = handle->ppdb; + if (ppdb) { + image = mono_ppdb_get_image (ppdb); + buffer_add_byte_array (buf, (guint8*)image->raw_data, image->raw_data_len); + } else { + buffer_add_byte_array (buf, NULL, 0); + } + break; + } + case CMD_ASSEMBLY_GET_TYPE_FROM_TOKEN: { + if (ass->dynamic) { + return ERR_NOT_IMPLEMENTED; + } + guint32 token = decode_int (p, &p, end); + ERROR_DECL (error); + error_init (error); + MonoClass* mono_class = mono_class_get_checked (ass->image, token, error); + if (!is_ok (error)) { + add_error_string (buf, mono_error_get_message (error)); + mono_error_cleanup (error); + return ERR_INVALID_ARGUMENT; + } + buffer_add_typeid (buf, domain, mono_class); + mono_error_cleanup (error); + break; + } + case CMD_ASSEMBLY_GET_METHOD_FROM_TOKEN: { + if (ass->dynamic) { + return ERR_NOT_IMPLEMENTED; + } + guint32 token = decode_int (p, &p, end); + ERROR_DECL (error); + error_init (error); + MonoMethod* mono_method = mono_get_method_checked (ass->image, token, NULL, NULL, error); + if (!is_ok (error)) { + add_error_string (buf, mono_error_get_message (error)); + mono_error_cleanup (error); + return ERR_INVALID_ARGUMENT; + } + buffer_add_methodid (buf, domain, mono_method); + mono_error_cleanup (error); + break; + } case CMD_ASSEMBLY_HAS_DEBUG_INFO: { buffer_add_byte (buf, !ass->dynamic && mono_debug_image_has_debug_info (ass->image)); break; @@ -8379,6 +8379,13 @@ type_commands_internal (int command, MonoClass *klass, MonoDomain *domain, guint } break; } + case MDBGPROT_CMD_TYPE_INITIALIZE: { + MonoVTable *vtable = mono_class_vtable_checked (klass, error); + goto_if_nok (error, loader_error); + mono_runtime_class_init_full (vtable, error); + goto_if_nok (error, loader_error); + break; + } default: err = ERR_NOT_IMPLEMENTED; goto exit; diff --git a/src/mono/mono/component/debugger-protocol.h b/src/mono/mono/component/debugger-protocol.h index 292b723cc351b..6bce7c5ff2ec1 100644 --- a/src/mono/mono/component/debugger-protocol.h +++ b/src/mono/mono/component/debugger-protocol.h @@ -201,7 +201,8 @@ typedef enum { MDBGPROT_CMD_TYPE_CREATE_INSTANCE = 19, MDBGPROT_CMD_TYPE_GET_VALUE_SIZE = 20, MDBGPROT_CMD_TYPE_GET_VALUES_ICORDBG = 21, - MDBGPROT_CMD_TYPE_GET_PARENTS = 22 + MDBGPROT_CMD_TYPE_GET_PARENTS = 22, + MDBGPROT_CMD_TYPE_INITIALIZE = 23 } MdbgProtCmdType; typedef enum { diff --git a/src/mono/mono/metadata/object-internals.h b/src/mono/mono/metadata/object-internals.h index d87ab17fdab75..9702920b3c26e 100644 --- a/src/mono/mono/metadata/object-internals.h +++ b/src/mono/mono/metadata/object-internals.h @@ -1599,7 +1599,7 @@ mono_class_try_get_vtable (MonoClass *klass); gboolean mono_runtime_run_module_cctor (MonoImage *image, MonoError *error); -gboolean +MONO_COMPONENT_API gboolean mono_runtime_class_init_full (MonoVTable *vtable, MonoError *error); void diff --git a/src/mono/mono/mini/CMakeLists.txt b/src/mono/mono/mini/CMakeLists.txt index b07e58569160c..3e9ca497336ab 100644 --- a/src/mono/mono/mini/CMakeLists.txt +++ b/src/mono/mono/mini/CMakeLists.txt @@ -144,7 +144,6 @@ set(mini_common_sources dwarfwriter.c mini-gc.h mini-gc.c - xdebug.c mini-llvm.h mini-llvm-cpp.h llvm-jit.h diff --git a/src/mono/mono/mini/aot-compiler.c b/src/mono/mono/mini/aot-compiler.c index ba1c7ea043c7e..369016e11892d 100644 --- a/src/mono/mono/mini/aot-compiler.c +++ b/src/mono/mono/mini/aot-compiler.c @@ -14299,7 +14299,7 @@ emit_aot_image (MonoAotCompile *acfg) return 1; } if (acfg->fp) - acfg->w = mono_img_writer_create (acfg->fp, FALSE); + acfg->w = mono_img_writer_create (acfg->fp); /* Compute symbols for methods */ for (i = 0; i < acfg->nmethods; ++i) { diff --git a/src/mono/mono/mini/driver.c b/src/mono/mono/mini/driver.c index f2792e4e6a4e4..3e7a07c17c674 100644 --- a/src/mono/mono/mini/driver.c +++ b/src/mono/mono/mini/driver.c @@ -216,9 +216,6 @@ parse_debug_options (const char* p) } else if (!strncmp (p, "mdb-optimizations", 17)) { opt->mdb_optimizations = TRUE; p += 17; - } else if (!strncmp (p, "gdb", 3)) { - opt->gdb = TRUE; - p += 3; } else if (!strncmp (p, "ignore", 6)) { opt->enabled = FALSE; p += 6; diff --git a/src/mono/mono/mini/image-writer.c b/src/mono/mono/mini/image-writer.c index 97d1a042c0fd8..cc81ac7b070dc 100644 --- a/src/mono/mono/mini/image-writer.c +++ b/src/mono/mono/mini/image-writer.c @@ -22,33 +22,13 @@ #include #include #include -#ifndef HOST_WIN32 -#include -#else -#include -#include -#endif - #include #include -#include /* for PAGESIZE */ -#ifndef PAGESIZE -#define PAGESIZE 4096 -#endif #include "image-writer.h" -#ifndef HOST_WIN32 -#include -#include -#endif - #include "mini.h" -#define TV_DECLARE(name) gint64 name -#define TV_GETTIME(tv) tv = mono_100ns_ticks () -#define TV_ELAPSED(start,end) (((end) - (start)) / 10) - /* * The used assembler dialect * TARGET_ASM_APPLE == apple assembler on OSX @@ -122,14 +102,6 @@ #define ROUND_DOWN(VALUE,SIZE) ((VALUE) & ~((SIZE) - 1)) -#ifdef USE_BIN_WRITER - -typedef struct _BinSymbol BinSymbol; -typedef struct _BinReloc BinReloc; -typedef struct _BinSection BinSection; - -#endif - /* emit mode */ enum { EMIT_NONE, @@ -141,24 +113,12 @@ enum { struct _MonoImageWriter { MonoMemPool *mempool; char *outfile; - gboolean use_bin_writer; const char *current_section; int current_subsection; const char *section_stack [16]; int subsection_stack [16]; int stack_pos; FILE *fp; - /* Bin writer */ -#ifdef USE_BIN_WRITER - BinSymbol *symbols; - BinSection *sections; - BinSection *cur_section; - BinReloc *relocations; - GHashTable *labels; - int num_relocs; - guint8 *out_buf; - int out_buf_size, out_buf_pos; -#endif /* Asm writer */ char *tmpfname; int mode; /* emit mode */ @@ -175,1482 +135,6 @@ ilog2(int value) return count; } -#ifdef USE_BIN_WRITER - -typedef struct _BinLabel BinLabel; -struct _BinLabel { - char *name; - BinSection *section; - int offset; -}; - -struct _BinReloc { - BinReloc *next; - char *val1; - char *val2; - BinSection *val2_section; - int val2_offset; - int offset; - BinSection *section; - int section_offset; - int reloc_type; -}; - -struct _BinSymbol { - BinSymbol *next; - char *name; - BinSection *section; - int offset; - gboolean is_function; - gboolean is_global; - char *end_label; -}; - -struct _BinSection { - BinSection *next; - BinSection *parent; - char *name; - int subsection; - guint8 *data; - int data_len; - int cur_offset; - int file_offset; - int virt_offset; - int shidx; - guint64 addr; - gboolean has_addr; -}; - -static void -bin_writer_emit_start (MonoImageWriter *acfg) -{ - acfg->labels = g_hash_table_new (g_str_hash, g_str_equal); -} - -static void -bin_writer_emit_section_change (MonoImageWriter *acfg, const char *section_name, int subsection_index) -{ - BinSection *section; - - if (acfg->cur_section && acfg->cur_section->subsection == subsection_index - && strcmp (acfg->cur_section->name, section_name) == 0) - return; - for (section = acfg->sections; section; section = section->next) { - if (section->subsection == subsection_index && strcmp (section->name, section_name) == 0) { - acfg->cur_section = section; - return; - } - } - if (!section) { - section = g_new0 (BinSection, 1); - section->name = g_strdup (section_name); - section->subsection = subsection_index; - section->next = acfg->sections; - acfg->sections = section; - acfg->cur_section = section; - } -} - -static void -bin_writer_set_section_addr (MonoImageWriter *acfg, guint64 addr) -{ - acfg->cur_section->addr = addr; - acfg->cur_section->has_addr = TRUE; -} - -static void -bin_writer_emit_symbol_inner (MonoImageWriter *acfg, const char *name, const char *end_label, gboolean is_global, gboolean func) -{ - BinSymbol *symbol = g_new0 (BinSymbol, 1); - symbol->name = g_strdup (name); - if (end_label) - symbol->end_label = g_strdup (end_label); - symbol->is_function = func; - symbol->is_global = is_global; - symbol->section = acfg->cur_section; - /* FIXME: we align after this call... */ - symbol->offset = symbol->section->cur_offset; - symbol->next = acfg->symbols; - acfg->symbols = symbol; -} - -static void -bin_writer_emit_global (MonoImageWriter *acfg, const char *name, gboolean func) -{ - bin_writer_emit_symbol_inner (acfg, name, NULL, TRUE, func); -} - -static void -bin_writer_emit_local_symbol (MonoImageWriter *acfg, const char *name, const char *end_label, gboolean func) -{ - bin_writer_emit_symbol_inner (acfg, name, end_label, FALSE, func); -} - -static void -bin_writer_emit_label (MonoImageWriter *acfg, const char *name) -{ - BinLabel *label = g_new0 (BinLabel, 1); - label->name = g_strdup (name); - label->section = acfg->cur_section; - label->offset = acfg->cur_section->cur_offset; - g_hash_table_insert (acfg->labels, label->name, label); -} - -static void -bin_writer_emit_ensure_buffer (BinSection *section, int size) -{ - int new_offset = section->cur_offset + size; - if (new_offset >= section->data_len) { - int new_size = section->data_len? section->data_len * 2: 256; - guint8 *data; - while (new_size <= new_offset) - new_size *= 2; - data = (guint8 *)g_malloc0 (new_size); - memcpy (data, section->data, section->data_len); - g_free (section->data); - section->data = data; - section->data_len = new_size; - } -} - -static void -bin_writer_emit_bytes (MonoImageWriter *acfg, const guint8* buf, int size) -{ - bin_writer_emit_ensure_buffer (acfg->cur_section, size); - memcpy (acfg->cur_section->data + acfg->cur_section->cur_offset, buf, size); - acfg->cur_section->cur_offset += size; -} - -static void -bin_writer_emit_string (MonoImageWriter *acfg, const char *value) -{ - int size = strlen (value) + 1; - bin_writer_emit_bytes (acfg, (const guint8*)value, size); -} - -static void -bin_writer_emit_line (MonoImageWriter *acfg) -{ - /* Nothing to do in binary writer */ -} - -static void -bin_writer_emit_alignment (MonoImageWriter *acfg, int size) -{ - int offset = acfg->cur_section->cur_offset; - int add; - offset += (size - 1); - offset &= ~(size - 1); - add = offset - acfg->cur_section->cur_offset; - if (add) { - bin_writer_emit_ensure_buffer (acfg->cur_section, add); - acfg->cur_section->cur_offset += add; - } -} - -static void -bin_writer_emit_pointer_unaligned (MonoImageWriter *acfg, const char *target) -{ - BinReloc *reloc; - - if (!target) { - acfg->cur_section->cur_offset += sizeof (gpointer); - return; - } - - reloc = g_new0 (BinReloc, 1); - reloc->val1 = g_strdup (target); - reloc->section = acfg->cur_section; - reloc->section_offset = acfg->cur_section->cur_offset; - reloc->next = acfg->relocations; - acfg->relocations = reloc; - if (strcmp (reloc->section->name, ".data") == 0) { - acfg->num_relocs++; - //g_print ("reloc: %s at %d\n", target, acfg->cur_section->cur_offset); - } - acfg->cur_section->cur_offset += sizeof (gpointer); -} - -static void -bin_writer_emit_pointer (MonoImageWriter *acfg, const char *target) -{ - bin_writer_emit_alignment (acfg, sizeof (gpointer)); - bin_writer_emit_pointer_unaligned (acfg, target); -} - -static void -bin_writer_emit_int16 (MonoImageWriter *acfg, int value) -{ - guint8 *data; - bin_writer_emit_ensure_buffer (acfg->cur_section, 2); - data = acfg->cur_section->data + acfg->cur_section->cur_offset; - acfg->cur_section->cur_offset += 2; - /* FIXME: little endian */ - data [0] = value; - data [1] = value >> 8; -} - -static void -bin_writer_emit_int32 (MonoImageWriter *acfg, int value) -{ - guint8 *data; - bin_writer_emit_ensure_buffer (acfg->cur_section, 4); - data = acfg->cur_section->data + acfg->cur_section->cur_offset; - acfg->cur_section->cur_offset += 4; - /* FIXME: little endian */ - data [0] = value; - data [1] = value >> 8; - data [2] = value >> 16; - data [3] = value >> 24; -} - -static BinReloc* -create_reloc (MonoImageWriter *acfg, const char *end, const char* start, int offset) -{ - BinReloc *reloc; - reloc = (BinReloc *)mono_mempool_alloc0 (acfg->mempool, sizeof (BinReloc)); - reloc->val1 = mono_mempool_strdup (acfg->mempool, end); - if (start) - { - if (strcmp (start, ".") == 0) { - reloc->val2_section = acfg->cur_section; - reloc->val2_offset = acfg->cur_section->cur_offset; - } else { - reloc->val2 = mono_mempool_strdup (acfg->mempool, start); - } - } - reloc->offset = offset; - reloc->section = acfg->cur_section; - reloc->section_offset = acfg->cur_section->cur_offset; - reloc->next = acfg->relocations; - acfg->relocations = reloc; - return reloc; -} - -static void -bin_writer_emit_symbol (MonoImageWriter *acfg, const char *symbol) -{ - create_reloc (acfg, symbol, NULL, 0); - acfg->cur_section->cur_offset += 4; -} - -static void -bin_writer_emit_symbol_diff (MonoImageWriter *acfg, const char *end, const char* start, int offset) -{ - create_reloc (acfg, end, start, offset); - acfg->cur_section->cur_offset += 4; - /*if (strcmp (reloc->section->name, ".data") == 0) { - acfg->num_relocs++; - g_print ("reloc: %s - %s + %d at %d\n", end, start, offset, acfg->cur_section->cur_offset - 4); - }*/ -} - -/* - * Emit a relocation entry of type RELOC_TYPE against symbol SYMBOL at the current PC. - * Do not advance PC. - */ -static G_GNUC_UNUSED void -bin_writer_emit_reloc (MonoImageWriter *acfg, int reloc_type, const char *symbol, int addend) -{ - BinReloc *reloc = create_reloc (acfg, symbol, ".", addend); - reloc->reloc_type = reloc_type; -} - -static void -bin_writer_emit_zero_bytes (MonoImageWriter *acfg, int num) -{ - bin_writer_emit_ensure_buffer (acfg->cur_section, num); - acfg->cur_section->cur_offset += num; -} - -static void -bin_writer_fwrite (MonoImageWriter *acfg, void *val, size_t size, size_t nmemb) -{ - if (acfg->fp) - fwrite (val, size, nmemb, acfg->fp); - else { - g_assert (acfg->out_buf_pos + (size * nmemb) <= acfg->out_buf_size); - memcpy (acfg->out_buf + acfg->out_buf_pos, val, size * nmemb); - acfg->out_buf_pos += (size * nmemb); - } -} - -static void -bin_writer_fseek (MonoImageWriter *acfg, int offset) -{ - if (acfg->fp) - fseek (acfg->fp, offset, SEEK_SET); - else - acfg->out_buf_pos = offset; -} - -#ifdef USE_MACH_WRITER - -/* - * This is a minimal implementation designed to support xdebug on 32 bit osx - * FIXME: 64 bit support - */ - -#include - -static gsize -get_label_addr (MonoImageWriter *acfg, const char *name) -{ - int offset; - BinLabel *lab; - BinSection *section; - gsize value; - - lab = g_hash_table_lookup (acfg->labels, name); - if (!lab) - g_error ("Undefined label: '%s'.\n", name); - section = lab->section; - offset = lab->offset; - if (section->parent) { - value = section->parent->virt_offset + section->cur_offset + offset; - } else { - value = section->virt_offset + offset; - } - return value; -} - - -static void -resolve_reloc (MonoImageWriter *acfg, BinReloc *reloc, guint8 **out_data, gsize *out_vaddr, gsize *out_start_val, gsize *out_end_val) -{ - guint8 *data; - gssize end_val, start_val; - gsize vaddr; - - end_val = get_label_addr (acfg, reloc->val1); - if (reloc->val2) { - start_val = get_label_addr (acfg, reloc->val2); - } else if (reloc->val2_section) { - start_val = reloc->val2_offset; - if (reloc->val2_section->parent) - start_val += reloc->val2_section->parent->virt_offset + reloc->val2_section->cur_offset; - else - start_val += reloc->val2_section->virt_offset; - } else { - start_val = 0; - } - end_val = end_val - start_val + reloc->offset; - if (reloc->section->parent) { - data = reloc->section->parent->data; - data += reloc->section->cur_offset; - data += reloc->section_offset; - vaddr = reloc->section->parent->virt_offset; - vaddr += reloc->section->cur_offset; - vaddr += reloc->section_offset; - } else { - data = reloc->section->data; - data += reloc->section_offset; - vaddr = reloc->section->virt_offset; - vaddr += reloc->section_offset; - } - - *out_start_val = start_val; - *out_end_val = end_val; - *out_data = data; - *out_vaddr = vaddr; -} - -static void -resolve_relocations (MonoImageWriter *acfg) -{ - BinReloc *reloc; - guint8 *data; - gsize end_val, start_val; - gsize vaddr; - - /* Only resolve static relocations */ - for (reloc = acfg->relocations; reloc; reloc = reloc->next) { - resolve_reloc (acfg, reloc, &data, &vaddr, &start_val, &end_val); - data [0] = end_val; - data [1] = end_val >> 8; - data [2] = end_val >> 16; - data [3] = end_val >> 24; - } -} - -static int -bin_writer_emit_writeout (MonoImageWriter *acfg) -{ - BinSection *s; - int sindex, file_size, nsections, file_offset, vmaddr; - struct mach_header header; - struct segment_command segment; - struct section *sections; - - /* Assing vm addresses to sections */ - nsections = 0; - vmaddr = 0; - for (s = acfg->sections; s; s = s->next) { - s->virt_offset = vmaddr; - vmaddr += s->cur_offset; - nsections ++; - } - - resolve_relocations (acfg); - - file_offset = 0; - - memset (&header, 0, sizeof (header)); - header.magic = MH_MAGIC; - header.cputype = CPU_TYPE_X86; - header.cpusubtype = CPU_SUBTYPE_X86_ALL; - header.filetype = MH_OBJECT; - header.ncmds = 0; - header.sizeofcmds = 0; - header.flags = 0; - - file_offset += sizeof (header); - - memset (&segment, 0, sizeof (segment)); - segment.cmd = LC_SEGMENT; - segment.cmdsize = sizeof (segment); - segment.maxprot = VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE; - segment.initprot = VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE; - - file_offset += sizeof (segment); - file_offset += nsections * sizeof (struct section); - - sections = g_new0 (struct section, nsections); - sindex = 0; - for (s = acfg->sections; s; s = s->next) { - s->file_offset = file_offset; - - /* .debug_line -> __debug_line */ - sprintf (sections [sindex].sectname, "__%s", s->name + 1); - sprintf (sections [sindex].segname, "%s", "__DWARF"); - sections [sindex].addr = s->virt_offset; - sections [sindex].size = s->cur_offset; - sections [sindex].offset = s->file_offset; - - file_offset += s->cur_offset; - - segment.nsects ++; - segment.cmdsize += sizeof (struct section); - - sindex ++; - } - - header.ncmds ++; - header.sizeofcmds += segment.cmdsize; - - /* Emit data */ - file_size = file_offset; - - if (!acfg->fp) { - acfg->out_buf_size = file_size; - acfg->out_buf = g_malloc (acfg->out_buf_size); - } - - bin_writer_fwrite (acfg, &header, sizeof (header), 1); - bin_writer_fwrite (acfg, &segment, sizeof (segment), 1); - bin_writer_fwrite (acfg, sections, sizeof (struct section), nsections); - for (s = acfg->sections; s; s = s->next) { - if (!acfg->fp) - g_assert (acfg->out_buf_pos == s->file_offset); - bin_writer_fwrite (acfg, s->data, s->cur_offset, 1); - } - - if (acfg->fp) - fclose (acfg->fp); - - return 0; -} - -#endif - -#ifdef USE_ELF_WRITER - -enum { - SECT_NULL, - SECT_HASH, - SECT_DYNSYM, - SECT_DYNSTR, - SECT_REL_DYN, - SECT_RELA_DYN, - SECT_TEXT, - SECT_RODATA, - SECT_DYNAMIC, - SECT_GOT_PLT, - SECT_DATA, - SECT_BSS, - SECT_DEBUG_FRAME, - SECT_DEBUG_INFO, - SECT_DEBUG_ABBREV, - SECT_DEBUG_LINE, - SECT_DEBUG_LOC, - SECT_SHSTRTAB, - SECT_SYMTAB, - SECT_STRTAB, - SECT_NUM -}; - -#if TARGET_SIZEOF_VOID_P == 4 - -typedef Elf32_Ehdr ElfHeader; -typedef Elf32_Shdr ElfSectHeader; -typedef Elf32_Phdr ElfProgHeader; -typedef Elf32_Sym ElfSymbol; -typedef Elf32_Rel ElfReloc; -typedef Elf32_Rela ElfRelocA; -typedef Elf32_Dyn ElfDynamic; - -#else - -typedef Elf64_Ehdr ElfHeader; -typedef Elf64_Shdr ElfSectHeader; -typedef Elf64_Phdr ElfProgHeader; -typedef Elf64_Sym ElfSymbol; -typedef Elf64_Rel ElfReloc; -typedef Elf64_Rela ElfRelocA; -typedef Elf64_Dyn ElfDynamic; - -#endif - -typedef struct { - const char *name; - int type; - int esize; - int flags; - int align; -} SectInfo; - -static SectInfo section_info [] = { - {"", 0, 0, 0, 0}, - {".hash", SHT_HASH, 4, 2, TARGET_SIZEOF_VOID_P}, - {".dynsym", SHT_DYNSYM, sizeof (ElfSymbol), 2, TARGET_SIZEOF_VOID_P}, - {".dynstr", SHT_STRTAB, 0, 2, 1}, - {".rel.dyn", SHT_REL, sizeof (ElfReloc), 2, TARGET_SIZEOF_VOID_P}, - {".rela.dyn", SHT_RELA, sizeof (ElfRelocA), 2, TARGET_SIZEOF_VOID_P}, - {".text", SHT_PROGBITS, 0, 6, 4096}, - {".rodata", SHT_PROGBITS, 0, SHF_ALLOC, 4096}, - {".dynamic", SHT_DYNAMIC, sizeof (ElfDynamic), 3, TARGET_SIZEOF_VOID_P}, - {".got.plt", SHT_PROGBITS, TARGET_SIZEOF_VOID_P, 3, TARGET_SIZEOF_VOID_P}, - {".data", SHT_PROGBITS, 0, 3, 8}, - {".bss", SHT_NOBITS, 0, 3, 8}, - {".debug_frame", SHT_PROGBITS, 0, 0, 8}, - {".debug_info", SHT_PROGBITS, 0, 0, 1}, - {".debug_abbrev", SHT_PROGBITS, 0, 0, 1}, - {".debug_line", SHT_PROGBITS, 0, 0, 1}, - {".debug_loc", SHT_PROGBITS, 0, 0, 1}, - {".shstrtab", SHT_STRTAB, 0, 0, 1}, - {".symtab", SHT_SYMTAB, sizeof (ElfSymbol), 0, TARGET_SIZEOF_VOID_P}, - {".strtab", SHT_STRTAB, 0, 0, 1} -}; - -typedef struct { - GString *data; - GHashTable *hash; -} ElfStrTable; - -static int -str_table_add (ElfStrTable *table, const char* value) -{ - int idx; - if (!table->data) { - table->data = g_string_new_len ("", 1); - table->hash = g_hash_table_new (g_str_hash, g_str_equal); - } - idx = GPOINTER_TO_UINT (g_hash_table_lookup (table->hash, value)); - if (idx) - return idx; - idx = table->data->len; - g_string_append (table->data, value); - g_string_append_c (table->data, 0); - g_hash_table_insert (table->hash, (void*)value, GUINT_TO_POINTER (idx)); - return idx; -} - -static void -append_subsection (MonoImageWriter *acfg, ElfSectHeader *sheaders, BinSection *sect, BinSection *add) -{ - int offset = sect->cur_offset; - /*offset += (sheaders [sect->shidx].sh_addralign - 1); - offset &= ~(sheaders [sect->shidx].sh_addralign - 1);*/ - /* - * FIXME: we shouldn't align subsections at all, but if we don't then the - * stuff inside the subsections which is aligned won't get aligned. - */ - if (strcmp (sect->name, ".debug_line") != 0) { - offset += (8 - 1); - offset &= ~(8 - 1); - } - bin_writer_emit_ensure_buffer (sect, offset); - //g_print ("section %s aligned to %d from %d\n", sect->name, offset, sect->cur_offset); - sect->cur_offset = offset; - - bin_writer_emit_ensure_buffer (sect, add->cur_offset); - memcpy (sect->data + sect->cur_offset, add->data, add->cur_offset); - add->parent = sect; - sect->cur_offset += add->cur_offset; - add->cur_offset = offset; /* it becomes the offset in the parent section */ - //g_print ("subsection %d of %s added at offset %d (align: %d)\n", add->subsection, sect->name, add->cur_offset, (int)sheaders [sect->shidx].sh_addralign); - add->data = NULL; - add->data_len = 0; -} - -/* merge the subsections */ -static int -collect_sections (MonoImageWriter *acfg, ElfSectHeader *sheaders, BinSection **out, int num) -{ - int i, j, maxs, num_sections; - BinSection *sect; - - num_sections = 0; - maxs = 0; - for (sect = acfg->sections; sect; sect = sect->next) { - if (sect->subsection == 0) { - out [num_sections++] = sect; - g_assert (num_sections < num); - } - maxs = MAX (maxs, sect->subsection); - } - for (i = 0; i < num_sections; i++) { - for (j = 1; j <= maxs; ++j) { - for (sect = acfg->sections; sect; sect = sect->next) { - if (sect->subsection == j && strcmp (out [i]->name, sect->name) == 0) { - append_subsection (acfg, sheaders, out [i], sect); - } - } - } - } - return num_sections; -} - -static unsigned long -elf_hash (const unsigned char *name) -{ - unsigned long h = 0, g; - while (*name) { - h = (h << 4) + *name++; - if ((g = h & 0xf0000000)) - h ^= g >> 24; - h &= ~g; - } - return h; -} - -#define NUM_BUCKETS 17 - -static int* -build_hash (MonoImageWriter *acfg, int num_sections, ElfStrTable *dynstr) -{ - int *data; - int num_symbols = 1 + num_sections + 3; - BinSymbol *symbol; - - for (symbol = acfg->symbols; symbol; symbol = symbol->next) { - if (!symbol->is_global) - continue; - num_symbols++; - str_table_add (dynstr, symbol->name); - /*g_print ("adding sym: %s\n", symbol->name);*/ - } - str_table_add (dynstr, "__bss_start"); - str_table_add (dynstr, "_edata"); - str_table_add (dynstr, "_end"); - - data = g_new0 (int, num_symbols + 2 + NUM_BUCKETS); - data [0] = NUM_BUCKETS; - data [1] = num_symbols; - - return data; -} - -static gsize -get_label_addr (MonoImageWriter *acfg, const char *name) -{ - int offset; - BinLabel *lab; - BinSection *section; - gsize value; - - lab = (BinLabel *)g_hash_table_lookup (acfg->labels, name); - if (!lab) - g_error ("Undefined label: '%s'.\n", name); - section = lab->section; - offset = lab->offset; - if (section->parent) { - value = section->parent->virt_offset + section->cur_offset + offset; - } else { - value = section->virt_offset + offset; - } - return value; -} - -static ElfSymbol* -collect_syms (MonoImageWriter *acfg, int *hash, ElfStrTable *strtab, ElfSectHeader *sheaders, int *num_syms) -{ - ElfSymbol *symbols; - BinSymbol *symbol; - BinSection *section; - int i; - int *bucket; - int *chain; - unsigned long hashc; - - if (hash) - symbols = g_new0 (ElfSymbol, hash [1]); - else { - i = 0; - for (symbol = acfg->symbols; symbol; symbol = symbol->next) - i ++; - - symbols = g_new0 (ElfSymbol, i + SECT_NUM + 10); /* FIXME */ - } - - /* the first symbol is undef, all zeroes */ - i = 1; - if (sheaders) { - int j; - for (j = 1; j < SECT_NUM; ++j) { - symbols [i].st_info = ELF32_ST_INFO (STB_LOCAL, STT_SECTION); - symbols [i].st_shndx = j; - symbols [i].st_value = sheaders [j].sh_addr; - ++i; - } - } else { - for (section = acfg->sections; section; section = section->next) { - if (section->parent) - continue; - symbols [i].st_info = ELF32_ST_INFO (STB_LOCAL, STT_SECTION); - if (strcmp (section->name, ".text") == 0) { - symbols [i].st_shndx = SECT_TEXT; - section->shidx = SECT_TEXT; - section->file_offset = 4096; - symbols [i].st_value = section->virt_offset; - } else if (strcmp (section->name, ".rodata") == 0) { - symbols [i].st_shndx = SECT_RODATA; - section->shidx = SECT_RODATA; - section->file_offset = 4096; - symbols [i].st_value = section->virt_offset; - } else if (strcmp (section->name, ".data") == 0) { - symbols [i].st_shndx = SECT_DATA; - section->shidx = SECT_DATA; - section->file_offset = 4096 + 28; /* FIXME */ - symbols [i].st_value = section->virt_offset; - } else if (strcmp (section->name, ".bss") == 0) { - symbols [i].st_shndx = SECT_BSS; - section->shidx = SECT_BSS; - section->file_offset = 4096 + 28 + 8; /* FIXME */ - symbols [i].st_value = section->virt_offset; - } - ++i; - } - } - for (symbol = acfg->symbols; symbol; symbol = symbol->next) { - int offset; - BinLabel *lab; - if (!symbol->is_global && hash) - continue; - symbols [i].st_info = ELF32_ST_INFO (symbol->is_global ? STB_GLOBAL : STB_LOCAL, symbol->is_function? STT_FUNC : STT_OBJECT); - symbols [i].st_name = str_table_add (strtab, symbol->name); - /*g_print ("sym name %s tabled to %d\n", symbol->name, symbols [i].st_name);*/ - section = symbol->section; - symbols [i].st_shndx = section->parent? section->parent->shidx: section->shidx; - lab = (BinLabel *)g_hash_table_lookup (acfg->labels, symbol->name); - offset = lab->offset; - if (section->parent) { - symbols [i].st_value = section->parent->virt_offset + section->cur_offset + offset; - } else { - symbols [i].st_value = section->virt_offset + offset; - } - - if (symbol->end_label) { - BinLabel *elab = (BinLabel *)g_hash_table_lookup (acfg->labels, symbol->end_label); - g_assert (elab); - symbols [i].st_size = elab->offset - lab->offset; - } - ++i; - } - /* add special symbols */ - symbols [i].st_name = str_table_add (strtab, "__bss_start"); - symbols [i].st_shndx = 0xfff1; - symbols [i].st_info = ELF32_ST_INFO (STB_GLOBAL, 0); - ++i; - symbols [i].st_name = str_table_add (strtab, "_edata"); - symbols [i].st_shndx = 0xfff1; - symbols [i].st_info = ELF32_ST_INFO (STB_GLOBAL, 0); - ++i; - symbols [i].st_name = str_table_add (strtab, "_end"); - symbols [i].st_shndx = 0xfff1; - symbols [i].st_info = ELF32_ST_INFO (STB_GLOBAL, 0); - ++i; - - if (num_syms) - *num_syms = i; - - /* add to hash table */ - if (hash) { - bucket = hash + 2; - chain = hash + 2 + hash [0]; - for (i = 0; i < hash [1]; ++i) { - int slot; - /*g_print ("checking %d '%s' (sym %d)\n", symbols [i].st_name, strtab->data->str + symbols [i].st_name, i);*/ - if (!symbols [i].st_name) - continue; - hashc = elf_hash ((guint8*)strtab->data->str + symbols [i].st_name); - slot = hashc % hash [0]; - /*g_print ("hashing '%s' at slot %d (sym %d)\n", strtab->data->str + symbols [i].st_name, slot, i);*/ - if (bucket [slot]) { - chain [i] = bucket [slot]; - bucket [slot] = i; - } else { - bucket [slot] = i; - } - } - } - return symbols; -} - -static void -reloc_symbols (MonoImageWriter *acfg, ElfSymbol *symbols, ElfSectHeader *sheaders, ElfStrTable *strtab, gboolean dynamic) -{ - BinSection *section; - BinSymbol *symbol; - int i; - - i = 1; - if (dynamic) { - for (section = acfg->sections; section; section = section->next) { - if (section->parent) - continue; - symbols [i].st_value = sheaders [section->shidx].sh_addr; - ++i; - } - } else { - for (i = 1; i < SECT_NUM; ++i) { - symbols [i].st_value = sheaders [i].sh_addr; - } - } - for (symbol = acfg->symbols; symbol; symbol = symbol->next) { - int offset; - BinLabel *lab; - if (dynamic && !symbol->is_global) - continue; - section = symbol->section; - lab = (BinLabel *)g_hash_table_lookup (acfg->labels, symbol->name); - offset = lab->offset; - if (section->parent) { - symbols [i].st_value = sheaders [section->parent->shidx].sh_addr + section->cur_offset + offset; - } else { - symbols [i].st_value = sheaders [section->shidx].sh_addr + offset; - } - ++i; - } - /* __bss_start */ - symbols [i].st_value = sheaders [SECT_BSS].sh_addr; - ++i; - /* _edata */ - symbols [i].st_value = sheaders [SECT_DATA].sh_addr + sheaders [SECT_DATA].sh_size; - ++i; - /* _end */ - symbols [i].st_value = sheaders [SECT_BSS].sh_addr + sheaders [SECT_BSS].sh_size; - ++i; -} - -static void -resolve_reloc (MonoImageWriter *acfg, BinReloc *reloc, guint8 **out_data, gsize *out_vaddr, gsize *out_start_val, gsize *out_end_val) -{ - guint8 *data; - gssize end_val, start_val; - gsize vaddr; - - end_val = get_label_addr (acfg, reloc->val1); - if (reloc->val2) { - start_val = get_label_addr (acfg, reloc->val2); - } else if (reloc->val2_section) { - start_val = reloc->val2_offset; - if (reloc->val2_section->parent) - start_val += reloc->val2_section->parent->virt_offset + reloc->val2_section->cur_offset; - else - start_val += reloc->val2_section->virt_offset; - } else { - start_val = 0; - } - end_val = end_val - start_val + reloc->offset; - if (reloc->section->parent) { - data = reloc->section->parent->data; - data += reloc->section->cur_offset; - data += reloc->section_offset; - vaddr = reloc->section->parent->virt_offset; - vaddr += reloc->section->cur_offset; - vaddr += reloc->section_offset; - } else { - data = reloc->section->data; - data += reloc->section_offset; - vaddr = reloc->section->virt_offset; - vaddr += reloc->section_offset; - } - - *out_start_val = start_val; - *out_end_val = end_val; - *out_data = data; - *out_vaddr = vaddr; -} - -#ifdef USE_ELF_RELA - -static ElfRelocA* -resolve_relocations (MonoImageWriter *acfg) -{ - BinReloc *reloc; - guint8 *data; - gsize end_val, start_val; - ElfRelocA *rr; - int i; - gsize vaddr; - - rr = g_new0 (ElfRelocA, acfg->num_relocs); - i = 0; - - for (reloc = acfg->relocations; reloc; reloc = reloc->next) { - resolve_reloc (acfg, reloc, &data, &vaddr, &start_val, &end_val); - /* FIXME: little endian */ - data [0] = end_val; - data [1] = end_val >> 8; - data [2] = end_val >> 16; - data [3] = end_val >> 24; - // FIXME: - if (start_val == 0 && reloc->val1 [0] != '.') { - rr [i].r_offset = vaddr; - rr [i].r_info = R_X86_64_RELATIVE; - rr [i].r_addend = end_val; - ++i; - g_assert (i <= acfg->num_relocs); - } - } - return rr; -} - -#else /* USE_ELF_RELA */ - -static void -do_reloc (MonoImageWriter *acfg, BinReloc *reloc, guint8 *data, gssize addr) -{ -#ifdef TARGET_ARM - /* - * We use the official ARM relocation types, but implement only the stuff actually - * needed by the code we generate. - */ - switch (reloc->reloc_type) { - case R_ARM_CALL: - case R_ARM_JUMP24: { - guint32 *code = (guint32*)(gpointer)data; - guint32 ins = *code; - int diff = addr; - - if (reloc->reloc_type == R_ARM_CALL) - /* bl */ - g_assert (data [3] == 0xeb); - else - /* b */ - g_assert (data [3] == 0xea); - if (diff >= 0 && diff <= 33554431) { - diff >>= 2; - ins = (ins & 0xff000000) | diff; - *code = ins; - } else if (diff <= 0 && diff >= -33554432) { - diff >>= 2; - ins = (ins & 0xff000000) | (diff & ~0xff000000); - *code = ins; - } else { - g_assert_not_reached (); - } - break; - } - case R_ARM_ALU_PC_G0_NC: { - /* Generated by emit_plt () */ - guint8 *code = data; - guint32 val = addr; - - g_assert (val <= 0xffffff); - if (val & 0xff0000) - ARM_ADD_REG_IMM (code, ARMREG_IP, ARMREG_PC, (val & 0xFF0000) >> 16, 16); - else - ARM_ADD_REG_IMM (code, ARMREG_IP, ARMREG_PC, 0, 0); - ARM_ADD_REG_IMM (code, ARMREG_IP, ARMREG_IP, (val & 0xFF00) >> 8, 24); - ARM_LDR_IMM (code, ARMREG_PC, ARMREG_IP, val & 0xFF); - break; - } - default: - g_assert_not_reached (); - } -#else - g_assert_not_reached (); -#endif -} - -static ElfReloc* -resolve_relocations (MonoImageWriter *acfg) -{ - BinReloc *reloc; - guint8 *data; - gsize end_val, start_val; - ElfReloc *rr; - int i; - gsize vaddr; - - rr = g_new0 (ElfReloc, acfg->num_relocs); - i = 0; - - for (reloc = acfg->relocations; reloc; reloc = reloc->next) { - resolve_reloc (acfg, reloc, &data, &vaddr, &start_val, &end_val); - /* FIXME: little endian */ - if (reloc->reloc_type) { - /* Must be static */ - g_assert (start_val > 0); - do_reloc (acfg, reloc, data, end_val); - } else { - data [0] = end_val; - data [1] = end_val >> 8; - data [2] = end_val >> 16; - data [3] = end_val >> 24; - } - // FIXME: - if (start_val == 0 && reloc->val1 [0] != '.') { - rr [i].r_offset = vaddr; - rr [i].r_info = R_386_RELATIVE; - ++i; - g_assert (i <= acfg->num_relocs); - } - } - return rr; -} - -#endif /* USE_ELF_RELA */ - -static int normal_sections [] = { SECT_DATA, SECT_DEBUG_FRAME, SECT_DEBUG_INFO, SECT_DEBUG_ABBREV, SECT_DEBUG_LINE, SECT_DEBUG_LOC }; - -static int -bin_writer_emit_writeout (MonoImageWriter *acfg) -{ - ElfHeader header; - ElfProgHeader progh [4]; - ElfSectHeader secth [SECT_NUM]; -#ifdef USE_ELF_RELA - ElfRelocA *relocs; -#else - ElfReloc *relocs; -#endif - ElfStrTable str_table = {NULL, NULL}; - ElfStrTable sh_str_table = {NULL, NULL}; - ElfStrTable dyn_str_table = {NULL, NULL}; - BinSection* all_sections [32]; - BinSection* sections [SECT_NUM]; - ElfSymbol *dynsym; - ElfSymbol *symtab; - ElfDynamic dynamic [14]; - int *hash; - int i, num_sections, file_offset, virt_offset, size; - int num_local_syms; - - /* Section headers */ - memset (§h, 0, sizeof (secth)); - memset (&dynamic, 0, sizeof (dynamic)); - memset (&header, 0, sizeof (header)); - - for (i = 1; i < SECT_NUM; ++i) { - secth [i].sh_name = str_table_add (&sh_str_table, section_info [i].name); - secth [i].sh_type = section_info [i].type; - secth [i].sh_addralign = section_info [i].align; - secth [i].sh_flags = section_info [i].flags; - secth [i].sh_entsize = section_info [i].esize; - } - secth [SECT_DYNSYM].sh_info = TARGET_SIZEOF_VOID_P == 4 ? 4 : 2; - secth [SECT_SYMTAB].sh_info = TARGET_SIZEOF_VOID_P == 4 ? 20 : 17; - secth [SECT_HASH].sh_link = SECT_DYNSYM; - secth [SECT_DYNSYM].sh_link = SECT_DYNSTR; - secth [SECT_REL_DYN].sh_link = SECT_DYNSYM; - secth [SECT_RELA_DYN].sh_link = SECT_DYNSYM; - secth [SECT_DYNAMIC].sh_link = SECT_DYNSTR; - secth [SECT_SYMTAB].sh_link = SECT_STRTAB; - - num_sections = collect_sections (acfg, secth, all_sections, 16); - hash = build_hash (acfg, num_sections, &dyn_str_table); -#if 0 - g_print ("num_sections: %d\n", num_sections); - g_print ("dynsym: %d, dynstr size: %d\n", hash [1], (int)dyn_str_table.data->len); - for (i = 0; i < num_sections; ++i) { - g_print ("section %s, size: %d, %x\n", all_sections [i]->name, all_sections [i]->cur_offset, all_sections [i]->cur_offset); - } -#endif - /* Associate the bin sections with the ELF sections */ - memset (sections, 0, sizeof (sections)); - for (i = 0; i < num_sections; ++i) { - BinSection *sect = all_sections [i]; - int j; - - for (j = 0; j < SECT_NUM; ++j) { - if (strcmp (sect->name, section_info [j].name) == 0) { - sect->shidx = j; - break; - } - } - - sections [all_sections [i]->shidx] = sect; - } - - /* at this point we know where in the file the first segment sections go */ - dynsym = collect_syms (acfg, hash, &dyn_str_table, NULL, NULL); - num_local_syms = hash [1]; - symtab = collect_syms (acfg, NULL, &str_table, secth, &num_local_syms); - - file_offset = virt_offset = sizeof (header) + sizeof (progh); - secth [SECT_HASH].sh_addr = secth [SECT_HASH].sh_offset = file_offset; - size = sizeof (int) * (2 + hash [0] + hash [1]); - virt_offset = (file_offset += size); - secth [SECT_HASH].sh_size = size; - secth [SECT_DYNSYM].sh_addr = secth [SECT_DYNSYM].sh_offset = file_offset; - size = sizeof (ElfSymbol) * hash [1]; - virt_offset = (file_offset += size); - secth [SECT_DYNSYM].sh_size = size; - secth [SECT_DYNSTR].sh_addr = secth [SECT_DYNSTR].sh_offset = file_offset; - size = dyn_str_table.data->len; - virt_offset = (file_offset += size); - secth [SECT_DYNSTR].sh_size = size; - file_offset += 4-1; - file_offset &= ~(4-1); - secth [SECT_REL_DYN].sh_addr = secth [SECT_REL_DYN].sh_offset = file_offset; -#ifndef USE_ELF_RELA - size = sizeof (ElfReloc) * acfg->num_relocs; -#else - size = 0; -#endif - virt_offset = (file_offset += size); - secth [SECT_REL_DYN].sh_size = size; - secth [SECT_RELA_DYN].sh_addr = secth [SECT_RELA_DYN].sh_offset = file_offset; -#ifdef USE_ELF_RELA - size = sizeof (ElfRelocA) * acfg->num_relocs; -#else - size = 0; -#endif - virt_offset = (file_offset += size); - secth [SECT_RELA_DYN].sh_size = size; - - file_offset = ALIGN_TO (file_offset, secth [SECT_TEXT].sh_addralign); - virt_offset = file_offset; - secth [SECT_TEXT].sh_addr = secth [SECT_TEXT].sh_offset = file_offset; - if (sections [SECT_TEXT]) { - if (sections [SECT_TEXT]->has_addr) { - secth [SECT_TEXT].sh_addr = sections [SECT_TEXT]->addr; - secth [SECT_TEXT].sh_flags &= ~SHF_ALLOC; - } - size = sections [SECT_TEXT]->cur_offset; - secth [SECT_TEXT].sh_size = size; - file_offset += size; - } - - file_offset = ALIGN_TO (file_offset, secth [SECT_RODATA].sh_addralign); - virt_offset = file_offset; - secth [SECT_RODATA].sh_addr = virt_offset; - secth [SECT_RODATA].sh_offset = file_offset; - if (sections [SECT_RODATA]) { - size = sections [SECT_RODATA]->cur_offset; - secth [SECT_RODATA].sh_size = size; - file_offset += size; - virt_offset += size; - } - - file_offset = ALIGN_TO (file_offset, secth [SECT_DYNAMIC].sh_addralign); - virt_offset = file_offset; - - /* .dynamic, .got.plt, .data, .bss here */ - /* Have to increase the virt offset since these go to a separate segment */ - virt_offset += PAGESIZE; - secth [SECT_DYNAMIC].sh_addr = virt_offset; - secth [SECT_DYNAMIC].sh_offset = file_offset; - size = sizeof (dynamic); - secth [SECT_DYNAMIC].sh_size = size; - file_offset += size; - virt_offset += size; - - file_offset = ALIGN_TO (file_offset, secth [SECT_GOT_PLT].sh_addralign); - virt_offset = ALIGN_TO (virt_offset, secth [SECT_GOT_PLT].sh_addralign); - secth [SECT_GOT_PLT].sh_addr = virt_offset; - secth [SECT_GOT_PLT].sh_offset = file_offset; - size = 3 * TARGET_SIZEOF_VOID_P; - secth [SECT_GOT_PLT].sh_size = size; - file_offset += size; - virt_offset += size; - - file_offset = ALIGN_TO (file_offset, secth [SECT_DATA].sh_addralign); - virt_offset = ALIGN_TO (virt_offset, secth [SECT_DATA].sh_addralign); - secth [SECT_DATA].sh_addr = virt_offset; - secth [SECT_DATA].sh_offset = file_offset; - if (sections [SECT_DATA]) { - size = sections [SECT_DATA]->cur_offset; - secth [SECT_DATA].sh_size = size; - file_offset += size; - virt_offset += size; - } - - file_offset = ALIGN_TO (file_offset, secth [SECT_BSS].sh_addralign); - virt_offset = ALIGN_TO (virt_offset, secth [SECT_BSS].sh_addralign); - secth [SECT_BSS].sh_addr = virt_offset; - secth [SECT_BSS].sh_offset = file_offset; - if (sections [SECT_BSS]) { - size = sections [SECT_BSS]->cur_offset; - secth [SECT_BSS].sh_size = size; - } - - /* virtual doesn't matter anymore */ - file_offset = ALIGN_TO (file_offset, secth [SECT_DEBUG_FRAME].sh_addralign); - secth [SECT_DEBUG_FRAME].sh_offset = file_offset; - if (sections [SECT_DEBUG_FRAME]) - size = sections [SECT_DEBUG_FRAME]->cur_offset; - else - size = 0; - secth [SECT_DEBUG_FRAME].sh_size = size; - file_offset += size; - - secth [SECT_DEBUG_INFO].sh_offset = file_offset; - if (sections [SECT_DEBUG_INFO]) - size = sections [SECT_DEBUG_INFO]->cur_offset; - else - size = 0; - secth [SECT_DEBUG_INFO].sh_size = size; - file_offset += size; - - secth [SECT_DEBUG_ABBREV].sh_offset = file_offset; - if (sections [SECT_DEBUG_ABBREV]) - size = sections [SECT_DEBUG_ABBREV]->cur_offset; - else - size = 0; - secth [SECT_DEBUG_ABBREV].sh_size = size; - file_offset += size; - - secth [SECT_DEBUG_LINE].sh_offset = file_offset; - if (sections [SECT_DEBUG_LINE]) - size = sections [SECT_DEBUG_LINE]->cur_offset; - else - size = 0; - secth [SECT_DEBUG_LINE].sh_size = size; - file_offset += size; - - secth [SECT_DEBUG_LOC].sh_offset = file_offset; - if (sections [SECT_DEBUG_LOC]) - size = sections [SECT_DEBUG_LOC]->cur_offset; - else - size = 0; - secth [SECT_DEBUG_LOC].sh_size = size; - file_offset += size; - - file_offset = ALIGN_TO (file_offset, secth [SECT_SHSTRTAB].sh_addralign); - secth [SECT_SHSTRTAB].sh_offset = file_offset; - size = sh_str_table.data->len; - secth [SECT_SHSTRTAB].sh_size = size; - file_offset += size; - - file_offset = ALIGN_TO (file_offset, secth [SECT_SYMTAB].sh_addralign); - secth [SECT_SYMTAB].sh_offset = file_offset; - size = sizeof (ElfSymbol) * num_local_syms; - secth [SECT_SYMTAB].sh_size = size; - file_offset += size; - - file_offset = ALIGN_TO (file_offset, secth [SECT_STRTAB].sh_addralign); - secth [SECT_STRTAB].sh_offset = file_offset; - size = str_table.data->len; - secth [SECT_STRTAB].sh_size = size; - file_offset += size; - - for (i = 1; i < SECT_NUM; ++i) { - if (section_info [i].esize != 0) - g_assert (secth [i].sh_size % section_info [i].esize == 0); - } - - file_offset += 4-1; - file_offset &= ~(4-1); - - header.e_ident [EI_MAG0] = ELFMAG0; - header.e_ident [EI_MAG1] = ELFMAG1; - header.e_ident [EI_MAG2] = ELFMAG2; - header.e_ident [EI_MAG3] = ELFMAG3; - header.e_ident [EI_CLASS] = TARGET_SIZEOF_VOID_P == 4 ? ELFCLASS32 : ELFCLASS64; - header.e_ident [EI_DATA] = ELFDATA2LSB; - header.e_ident [EI_VERSION] = EV_CURRENT; - header.e_ident [EI_OSABI] = ELFOSABI_NONE; - header.e_ident [EI_ABIVERSION] = 0; - for (i = EI_PAD; i < EI_NIDENT; ++i) - header.e_ident [i] = 0; - - header.e_type = ET_DYN; -#if defined(TARGET_X86) - header.e_machine = EM_386; -#elif defined(TARGET_AMD64) - header.e_machine = EM_X86_64; -#elif defined(TARGET_ARM) - header.e_machine = EM_ARM; -#else - g_assert_not_reached (); -#endif - header.e_version = 1; - - header.e_phoff = sizeof (header); - header.e_ehsize = sizeof (header); - header.e_phentsize = sizeof (ElfProgHeader); - header.e_phnum = 4; - header.e_entry = secth [SECT_TEXT].sh_addr; - header.e_shstrndx = SECT_SHSTRTAB; - header.e_shentsize = sizeof (ElfSectHeader); - header.e_shnum = SECT_NUM; - header.e_shoff = file_offset; - - /* dynamic data */ - i = 0; - dynamic [i].d_tag = DT_HASH; - dynamic [i].d_un.d_val = secth [SECT_HASH].sh_offset; - ++i; - dynamic [i].d_tag = DT_STRTAB; - dynamic [i].d_un.d_val = secth [SECT_DYNSTR].sh_offset; - ++i; - dynamic [i].d_tag = DT_SYMTAB; - dynamic [i].d_un.d_val = secth [SECT_DYNSYM].sh_offset; - ++i; - dynamic [i].d_tag = DT_STRSZ; - dynamic [i].d_un.d_val = dyn_str_table.data->len; - ++i; - dynamic [i].d_tag = DT_SYMENT; - dynamic [i].d_un.d_val = sizeof (ElfSymbol); - ++i; -#ifdef USE_ELF_RELA - dynamic [i].d_tag = DT_RELA; - dynamic [i].d_un.d_val = secth [SECT_RELA_DYN].sh_offset; - ++i; - dynamic [i].d_tag = DT_RELASZ; - dynamic [i].d_un.d_val = secth [SECT_RELA_DYN].sh_size; - ++i; - dynamic [i].d_tag = DT_RELAENT; - dynamic [i].d_un.d_val = sizeof (ElfRelocA); - ++i; -#else - dynamic [i].d_tag = DT_REL; - dynamic [i].d_un.d_val = secth [SECT_REL_DYN].sh_offset; - ++i; - dynamic [i].d_tag = DT_RELSZ; - dynamic [i].d_un.d_val = secth [SECT_REL_DYN].sh_size; - ++i; - dynamic [i].d_tag = DT_RELENT; - dynamic [i].d_un.d_val = sizeof (ElfReloc); - ++i; -#endif - dynamic [i].d_tag = DT_RELCOUNT; - dynamic [i].d_un.d_val = acfg->num_relocs; - ++i; - - /* Program header */ - memset (&progh, 0, sizeof (progh)); - progh [0].p_type = PT_LOAD; - progh [0].p_filesz = progh [0].p_memsz = secth [SECT_DYNAMIC].sh_offset; - progh [0].p_align = 4096; - progh [0].p_flags = 5; - - progh [1].p_type = PT_LOAD; - progh [1].p_offset = secth [SECT_DYNAMIC].sh_offset; - progh [1].p_vaddr = progh [1].p_paddr = secth [SECT_DYNAMIC].sh_addr; - progh [1].p_filesz = secth [SECT_BSS].sh_offset - secth [SECT_DYNAMIC].sh_offset; - progh [1].p_memsz = secth [SECT_BSS].sh_addr + secth [SECT_BSS].sh_size - secth [SECT_DYNAMIC].sh_addr; - progh [1].p_align = 4096; - progh [1].p_flags = 6; - - progh [2].p_type = PT_DYNAMIC; - progh [2].p_offset = secth [SECT_DYNAMIC].sh_offset; - progh [2].p_vaddr = progh [2].p_paddr = secth [SECT_DYNAMIC].sh_addr; - progh [2].p_filesz = progh [2].p_memsz = secth [SECT_DYNAMIC].sh_size; - progh [2].p_align = TARGET_SIZEOF_VOID_P; - progh [2].p_flags = 6; - - progh [3].p_type = PT_GNU_STACK; - progh [3].p_offset = secth [SECT_DYNAMIC].sh_offset; - progh [3].p_vaddr = progh [3].p_paddr = secth [SECT_DYNAMIC].sh_addr; - progh [3].p_filesz = progh [3].p_memsz = secth [SECT_DYNAMIC].sh_size; - progh [3].p_align = TARGET_SIZEOF_VOID_P; - progh [3].p_flags = 6; - - /* Compute the addresses of the bin sections, so relocation can be done */ - for (i = 0; i < SECT_NUM; ++i) { - if (sections [i]) { - sections [i]->file_offset = secth [i].sh_offset; - sections [i]->virt_offset = secth [i].sh_addr; - } - } - - reloc_symbols (acfg, dynsym, secth, &dyn_str_table, TRUE); - reloc_symbols (acfg, symtab, secth, &str_table, FALSE); - relocs = resolve_relocations (acfg); - - if (!acfg->fp) { - acfg->out_buf_size = file_offset + sizeof (secth); - acfg->out_buf = (guint8 *)g_malloc (acfg->out_buf_size); - } - - bin_writer_fwrite (acfg, &header, sizeof (header), 1); - bin_writer_fwrite (acfg, &progh, sizeof (progh), 1); - bin_writer_fwrite (acfg, hash, sizeof (int) * (hash [0] + hash [1] + 2), 1); - bin_writer_fwrite (acfg, dynsym, sizeof (ElfSymbol) * hash [1], 1); - bin_writer_fwrite (acfg, dyn_str_table.data->str, dyn_str_table.data->len, 1); - /* .rel.dyn */ - bin_writer_fseek (acfg, secth [SECT_REL_DYN].sh_offset); - bin_writer_fwrite (acfg, relocs, sizeof (ElfReloc), acfg->num_relocs); - - /* .rela.dyn */ - bin_writer_fseek (acfg, secth [SECT_RELA_DYN].sh_offset); - bin_writer_fwrite (acfg, relocs, secth [SECT_RELA_DYN].sh_size, 1); - - /* .text */ - if (sections [SECT_TEXT]) { - bin_writer_fseek (acfg, secth [SECT_TEXT].sh_offset); - bin_writer_fwrite (acfg, sections [SECT_TEXT]->data, sections [SECT_TEXT]->cur_offset, 1); - } - /* .rodata */ - if (sections [SECT_RODATA]) { - bin_writer_fseek (acfg, secth [SECT_RODATA].sh_offset); - bin_writer_fwrite (acfg, sections [SECT_RODATA]->data, sections [SECT_RODATA]->cur_offset, 1); - } - /* .dynamic */ - bin_writer_fseek (acfg, secth [SECT_DYNAMIC].sh_offset); - bin_writer_fwrite (acfg, dynamic, sizeof (dynamic), 1); - - /* .got.plt */ - size = secth [SECT_DYNAMIC].sh_addr; - bin_writer_fseek (acfg, secth [SECT_GOT_PLT].sh_offset); - bin_writer_fwrite (acfg, &size, sizeof (size), 1); - - /* normal sections */ - for (i = 0; i < sizeof (normal_sections) / sizeof (normal_sections [0]); ++i) { - int sect = normal_sections [i]; - - if (sections [sect]) { - bin_writer_fseek (acfg, secth [sect].sh_offset); - bin_writer_fwrite (acfg, sections [sect]->data, sections [sect]->cur_offset, 1); - } - } - - bin_writer_fseek (acfg, secth [SECT_SHSTRTAB].sh_offset); - bin_writer_fwrite (acfg, sh_str_table.data->str, sh_str_table.data->len, 1); - bin_writer_fseek (acfg, secth [SECT_SYMTAB].sh_offset); - bin_writer_fwrite (acfg, symtab, sizeof (ElfSymbol) * num_local_syms, 1); - bin_writer_fseek (acfg, secth [SECT_STRTAB].sh_offset); - bin_writer_fwrite (acfg, str_table.data->str, str_table.data->len, 1); - /*g_print ("file_offset %d vs %d\n", file_offset, ftell (file));*/ - /*g_assert (file_offset >= ftell (file));*/ - bin_writer_fseek (acfg, file_offset); - bin_writer_fwrite (acfg, §h, sizeof (secth), 1); - - if (acfg->fp) - fclose (acfg->fp); - - return 0; -} - -#endif /* USE_ELF_WRITER */ - -#endif /* USE_BIN_WRITER */ - /* ASM WRITER */ static void @@ -1852,7 +336,6 @@ asm_writer_emit_alignment (MonoImageWriter *acfg, int size) #endif } -#ifndef USE_BIN_WRITER static void asm_writer_emit_alignment_fill (MonoImageWriter *acfg, int size, int fill) { @@ -1863,7 +346,6 @@ asm_writer_emit_alignment_fill (MonoImageWriter *acfg, int size, int fill) asm_writer_emit_alignment (acfg, size); #endif } -#endif static void asm_writer_emit_pointer_unaligned (MonoImageWriter *acfg, const char *target) @@ -2019,27 +501,13 @@ asm_writer_emit_zero_bytes (MonoImageWriter *acfg, int num) void mono_img_writer_emit_start (MonoImageWriter *acfg) { -#ifdef USE_BIN_WRITER - if (acfg->use_bin_writer) - bin_writer_emit_start (acfg); - else - asm_writer_emit_start (acfg); -#else asm_writer_emit_start (acfg); -#endif } void mono_img_writer_emit_section_change (MonoImageWriter *acfg, const char *section_name, int subsection_index) { -#ifdef USE_BIN_WRITER - if (acfg->use_bin_writer) - bin_writer_emit_section_change (acfg, section_name, subsection_index); - else - asm_writer_emit_section_change (acfg, section_name, subsection_index); -#else asm_writer_emit_section_change (acfg, section_name, subsection_index); -#endif acfg->current_section = section_name; acfg->current_subsection = subsection_index; @@ -2067,229 +535,109 @@ mono_img_writer_emit_pop_section (MonoImageWriter *acfg) void mono_img_writer_set_section_addr (MonoImageWriter *acfg, guint64 addr) { -#ifdef USE_BIN_WRITER - if (!acfg->use_bin_writer) - NOT_IMPLEMENTED; - else - bin_writer_set_section_addr (acfg, addr); -#else NOT_IMPLEMENTED; -#endif } void mono_img_writer_emit_global (MonoImageWriter *acfg, const char *name, gboolean func) { -#ifdef USE_BIN_WRITER - if (acfg->use_bin_writer) - bin_writer_emit_global (acfg, name, func); - else - asm_writer_emit_global (acfg, name, func); -#else asm_writer_emit_global (acfg, name, func); -#endif } void mono_img_writer_emit_local_symbol (MonoImageWriter *acfg, const char *name, const char *end_label, gboolean func) { -#ifdef USE_BIN_WRITER - if (acfg->use_bin_writer) - bin_writer_emit_local_symbol (acfg, name, end_label, func); - else - asm_writer_emit_local_symbol (acfg, name, end_label, func); -#else asm_writer_emit_local_symbol (acfg, name, end_label, func); -#endif } void mono_img_writer_emit_symbol_size (MonoImageWriter *acfg, const char *name, const char *end_label) { - if (!acfg->use_bin_writer) - asm_writer_emit_symbol_size (acfg, name, end_label); + asm_writer_emit_symbol_size (acfg, name, end_label); } void mono_img_writer_emit_label (MonoImageWriter *acfg, const char *name) { -#ifdef USE_BIN_WRITER - if (acfg->use_bin_writer) - bin_writer_emit_label (acfg, name); - else - asm_writer_emit_label (acfg, name); -#else asm_writer_emit_label (acfg, name); -#endif } void mono_img_writer_emit_bytes (MonoImageWriter *acfg, const guint8* buf, int size) { -#ifdef USE_BIN_WRITER - if (acfg->use_bin_writer) - bin_writer_emit_bytes (acfg, buf, size); - else - asm_writer_emit_bytes (acfg, buf, size); -#else asm_writer_emit_bytes (acfg, buf, size); -#endif } void mono_img_writer_emit_string (MonoImageWriter *acfg, const char *value) { -#ifdef USE_BIN_WRITER - if (acfg->use_bin_writer) - bin_writer_emit_string (acfg, value); - else - asm_writer_emit_string (acfg, value); -#else asm_writer_emit_string (acfg, value); -#endif } void mono_img_writer_emit_line (MonoImageWriter *acfg) { -#ifdef USE_BIN_WRITER - if (acfg->use_bin_writer) - bin_writer_emit_line (acfg); - else - asm_writer_emit_line (acfg); -#else - asm_writer_emit_line (acfg); -#endif + asm_writer_emit_line (acfg); } void mono_img_writer_emit_alignment (MonoImageWriter *acfg, int size) { -#ifdef USE_BIN_WRITER - if (acfg->use_bin_writer) - bin_writer_emit_alignment (acfg, size); - else - asm_writer_emit_alignment (acfg, size); -#else asm_writer_emit_alignment (acfg, size); -#endif } void mono_img_writer_emit_alignment_fill (MonoImageWriter *acfg, int size, int fill) { -#ifdef USE_BIN_WRITER - if (acfg->use_bin_writer) - bin_writer_emit_alignment (acfg, size); - else - asm_writer_emit_alignment (acfg, size); -#else asm_writer_emit_alignment_fill (acfg, size, fill); -#endif } void mono_img_writer_emit_pointer_unaligned (MonoImageWriter *acfg, const char *target) { -#ifdef USE_BIN_WRITER - if (acfg->use_bin_writer) - bin_writer_emit_pointer_unaligned (acfg, target); - else - asm_writer_emit_pointer_unaligned (acfg, target); -#else asm_writer_emit_pointer_unaligned (acfg, target); -#endif } void mono_img_writer_emit_pointer (MonoImageWriter *acfg, const char *target) { -#ifdef USE_BIN_WRITER - if (acfg->use_bin_writer) - bin_writer_emit_pointer (acfg, target); - else - asm_writer_emit_pointer (acfg, target); -#else asm_writer_emit_pointer (acfg, target); -#endif } void mono_img_writer_emit_int16 (MonoImageWriter *acfg, int value) { -#ifdef USE_BIN_WRITER - if (acfg->use_bin_writer) - bin_writer_emit_int16 (acfg, value); - else - asm_writer_emit_int16 (acfg, value); -#else asm_writer_emit_int16 (acfg, value); -#endif } void mono_img_writer_emit_int32 (MonoImageWriter *acfg, int value) { -#ifdef USE_BIN_WRITER - if (acfg->use_bin_writer) - bin_writer_emit_int32 (acfg, value); - else - asm_writer_emit_int32 (acfg, value); -#else asm_writer_emit_int32 (acfg, value); -#endif } void mono_img_writer_emit_symbol (MonoImageWriter *acfg, const char *symbol) { -#ifdef USE_BIN_WRITER - if (acfg->use_bin_writer) - bin_writer_emit_symbol (acfg, symbol); - else - asm_writer_emit_symbol (acfg, symbol); -#else asm_writer_emit_symbol (acfg, symbol); -#endif } void mono_img_writer_emit_symbol_diff (MonoImageWriter *acfg, const char *end, const char* start, int offset) { -#ifdef USE_BIN_WRITER - if (acfg->use_bin_writer) - bin_writer_emit_symbol_diff (acfg, end, start, offset); - else - asm_writer_emit_symbol_diff (acfg, end, start, offset); -#else asm_writer_emit_symbol_diff (acfg, end, start, offset); -#endif } void mono_img_writer_emit_zero_bytes (MonoImageWriter *acfg, int num) { -#ifdef USE_BIN_WRITER - if (acfg->use_bin_writer) - bin_writer_emit_zero_bytes (acfg, num); - else - asm_writer_emit_zero_bytes (acfg, num); -#else asm_writer_emit_zero_bytes (acfg, num); -#endif } int mono_img_writer_emit_writeout (MonoImageWriter *acfg) { -#ifdef USE_BIN_WRITER - if (acfg->use_bin_writer) - return bin_writer_emit_writeout (acfg); - else - return asm_writer_emit_writeout (acfg); -#else - return asm_writer_emit_writeout (acfg); -#endif + return asm_writer_emit_writeout (acfg); } void @@ -2305,15 +653,7 @@ mono_img_writer_emit_byte (MonoImageWriter *acfg, guint8 val) void mono_img_writer_emit_reloc (MonoImageWriter *acfg, int reloc_type, const char *symbol, int addend) { - /* This is only supported by the bin writer */ -#ifdef USE_BIN_WRITER - if (acfg->use_bin_writer) - bin_writer_emit_reloc (acfg, reloc_type, symbol, addend); - else - g_assert_not_reached (); -#else - g_assert_not_reached (); -#endif + g_assert_not_reached (); } /* @@ -2325,8 +665,7 @@ mono_img_writer_emit_reloc (MonoImageWriter *acfg, int reloc_type, const char *s void mono_img_writer_emit_unset_mode (MonoImageWriter *acfg) { - if (!acfg->use_bin_writer) - asm_writer_emit_unset_mode (acfg); + asm_writer_emit_unset_mode (acfg); } /* @@ -2338,55 +677,23 @@ mono_img_writer_emit_unset_mode (MonoImageWriter *acfg) guint8* mono_img_writer_get_output (MonoImageWriter *acfg, guint32 *size) { -#ifdef USE_BIN_WRITER - guint8 *buf; - - g_assert (acfg->use_bin_writer); - - buf = acfg->out_buf; - *size = acfg->out_buf_size; - acfg->out_buf = NULL; - return buf; -#else g_assert_not_reached (); return NULL; -#endif -} - -/* - * Return whenever the binary writer is supported on this platform. - */ -gboolean -mono_bin_writer_supported (void) -{ -#ifdef USE_BIN_WRITER - return TRUE; -#else - return FALSE; -#endif } /* * mono_img_writer_create: * - * Create an image writer writing to FP. If USE_BIN_WRITER is TRUE, FP can be NULL, - * in this case the image writer will write to a memory buffer obtainable by calling - * mono_img_writer_get_output (). + * Create an image writer writing to FP. */ MonoImageWriter* -mono_img_writer_create (FILE *fp, gboolean use_bin_writer) +mono_img_writer_create (FILE *fp) { MonoImageWriter *w = g_new0 (MonoImageWriter, 1); - -#ifndef USE_BIN_WRITER - g_assert (!use_bin_writer); -#endif - if (!use_bin_writer) - g_assert (fp); + g_assert (fp); w->fp = fp; - w->use_bin_writer = use_bin_writer; w->mempool = mono_mempool_new (); return w; @@ -2404,7 +711,7 @@ gboolean mono_img_writer_subsections_supported (MonoImageWriter *acfg) { #ifdef TARGET_ASM_APPLE - return acfg->use_bin_writer; + return FALSE; #else return TRUE; #endif diff --git a/src/mono/mono/mini/image-writer.h b/src/mono/mono/mini/image-writer.h index 309ec37c059a7..c6d855fa1b410 100644 --- a/src/mono/mono/mini/image-writer.h +++ b/src/mono/mono/mini/image-writer.h @@ -22,39 +22,7 @@ typedef struct _MonoImageWriter MonoImageWriter; -#if defined(TARGET_AMD64) && !defined(HOST_WIN32) && !defined(__APPLE__) -#define USE_ELF_WRITER 1 -#define USE_ELF_RELA 1 -#endif - -#if defined(TARGET_X86) && !defined(HOST_WIN32) && !defined(__APPLE__) -#define USE_ELF_WRITER 1 -#endif - -#if defined(TARGET_ARM) && !defined(TARGET_MACH) && !defined(HOST_WIN32) -//#define USE_ELF_WRITER 1 -#endif - -#if defined(__mips__) -#define USE_ELF_WRITER 1 -#endif - -#if defined(TARGET_X86) && defined(__APPLE__) -//#define USE_MACH_WRITER -#endif - -#if defined(USE_ELF_WRITER) || defined(USE_MACH_WRITER) -#define USE_BIN_WRITER 1 -#endif - -/* Relocation types */ -#define R_ARM_CALL 28 -#define R_ARM_JUMP24 29 -#define R_ARM_ALU_PC_G0_NC 59 - -gboolean mono_bin_writer_supported (void); - -MonoImageWriter* mono_img_writer_create (FILE *fp, gboolean use_bin_writer); +MonoImageWriter* mono_img_writer_create (FILE *fp); void mono_img_writer_destroy (MonoImageWriter *w); diff --git a/src/mono/mono/mini/mini-runtime.c b/src/mono/mono/mini/mini-runtime.c index 36400c7e9fdbb..bea43f236a65c 100644 --- a/src/mono/mono/mini/mini-runtime.c +++ b/src/mono/mono/mini/mini-runtime.c @@ -523,7 +523,6 @@ mono_tramp_info_register_internal (MonoTrampInfo *info, MonoMemoryManager *mem_m copy->uw_info_len = info->uw_info_len; } - mono_save_trampoline_xdebug_info (info); mono_lldb_save_trampoline_info (info); #ifdef MONO_ARCH_HAVE_UNWIND_TABLE @@ -3934,7 +3933,7 @@ mini_parse_debug_option (const char *option) else if (!strcmp (option, "dyn-runtime-invoke")) mini_debug_options.dyn_runtime_invoke = TRUE; else if (!strcmp (option, "gdb")) - mini_debug_options.gdb = TRUE; + fprintf (stderr, "MONO_DEBUG=gdb is deprecated."); else if (!strcmp (option, "lldb")) mini_debug_options.lldb = TRUE; else if (!strcmp (option, "llvm-disable-inlining")) @@ -4431,21 +4430,6 @@ mini_init (const char *filename, const char *runtime_version) mono_dont_free_domains = TRUE; } -#ifdef XDEBUG_ENABLED - char *mono_xdebug = g_getenv ("MONO_XDEBUG"); - if (mono_xdebug) { - mono_xdebug_init (mono_xdebug); - g_free (mono_xdebug); - /* So methods for multiple domains don't have the same address */ - mono_dont_free_domains = TRUE; - mono_using_xdebug = TRUE; - } else if (mini_debug_options.gdb) { - mono_xdebug_init ((char*)"gdb"); - mono_dont_free_domains = TRUE; - mono_using_xdebug = TRUE; - } -#endif - #ifdef ENABLE_LLVM if (mono_use_llvm) mono_llvm_init (!mono_compile_aot); diff --git a/src/mono/mono/mini/mini-runtime.h b/src/mono/mono/mini/mini-runtime.h index 2e349a35ed031..562d98eb5357d 100644 --- a/src/mono/mono/mini/mini-runtime.h +++ b/src/mono/mono/mini/mini-runtime.h @@ -245,7 +245,6 @@ typedef struct MonoDebugOptions { gboolean suspend_on_exception; gboolean suspend_on_unhandled; gboolean dyn_runtime_invoke; - gboolean gdb; gboolean lldb; /* @@ -571,10 +570,6 @@ MONO_API char *mono_pmip (void *ip); MONO_API int mono_ee_api_version (void); gboolean mono_debug_count (void); -#ifdef __linux__ -#define XDEBUG_ENABLED 1 -#endif - #ifdef __linux__ /* maybe enable also for other systems? */ #define ENABLE_JIT_MAP 1 diff --git a/src/mono/mono/mini/mini.c b/src/mono/mono/mini/mini.c index 7d24fe6374b6c..f3cfa3895e67a 100644 --- a/src/mono/mono/mini/mini.c +++ b/src/mono/mono/mini/mini.c @@ -83,7 +83,6 @@ int mono_inject_async_exc_pos; MonoMethodDesc *mono_break_at_bb_method; int mono_break_at_bb_bb_num; gboolean mono_do_x86_stack_align = TRUE; -gboolean mono_using_xdebug; /* Counters */ static guint32 discarded_code; @@ -2046,19 +2045,9 @@ mono_codegen (MonoCompile *cfg) MonoBasicBlock *bb; int max_epilog_size; guint8 *code; - MonoMemoryManager *code_mem_manager; + MonoMemoryManager *code_mem_manager = cfg->mem_manager; guint unwindlen = 0; - if (mono_using_xdebug) - /* - * Recent gdb versions have trouble processing symbol files containing - * overlapping address ranges, so allocate all code from the code manager - * of the root domain. (#666152). - */ - code_mem_manager = get_default_mem_manager (); - else - code_mem_manager = cfg->mem_manager; - for (bb = cfg->bb_entry; bb; bb = bb->next_bb) { cfg->spill_count = 0; /* we reuse dfn here */ @@ -2133,11 +2122,7 @@ mono_codegen (MonoCompile *cfg) g_hash_table_insert (jit_mm->dynamic_code_hash, cfg->method, cfg->dynamic_info); jit_mm_unlock (jit_mm); - if (mono_using_xdebug) - /* See the comment for cfg->code_domain */ - code = (guint8 *)mono_mem_manager_code_reserve (code_mem_manager, cfg->code_size + cfg->thunk_area + unwindlen); - else - code = (guint8 *)mono_code_manager_reserve (cfg->dynamic_info->code_mp, cfg->code_size + cfg->thunk_area + unwindlen); + code = (guint8 *)mono_code_manager_reserve (cfg->dynamic_info->code_mp, cfg->code_size + cfg->thunk_area + unwindlen); } else { code = (guint8 *)mono_mem_manager_code_reserve (code_mem_manager, cfg->code_size + cfg->thunk_area + unwindlen); } @@ -2220,10 +2205,7 @@ mono_codegen (MonoCompile *cfg) } if (cfg->method->dynamic) { - if (mono_using_xdebug) - mono_mem_manager_code_commit (code_mem_manager, cfg->native_code, cfg->code_size, cfg->code_len); - else - mono_code_manager_commit (cfg->dynamic_info->code_mp, cfg->native_code, cfg->code_size, cfg->code_len); + mono_code_manager_commit (cfg->dynamic_info->code_mp, cfg->native_code, cfg->code_size, cfg->code_len); } else { mono_mem_manager_code_commit (code_mem_manager, cfg->native_code, cfg->code_size, cfg->code_len); } @@ -3381,18 +3363,6 @@ mini_method_compile (MonoMethod *method, guint32 opts, JitFlags flags, int parts cfg->disable_out_of_line_bblocks = TRUE; } - if (mono_using_xdebug) { - /* - * Make each variable use its own register/stack slot and extend - * their liveness to cover the whole method, making them displayable - * in gdb even after they are dead. - */ - cfg->disable_reuse_registers = TRUE; - cfg->disable_reuse_stack_slots = TRUE; - cfg->extend_live_ranges = TRUE; - cfg->compute_precise_live_ranges = TRUE; - } - mini_gc_init_cfg (cfg); if (method->wrapper_type == MONO_WRAPPER_OTHER) { @@ -3932,10 +3902,8 @@ mini_method_compile (MonoMethod *method, guint32 opts, JitFlags flags, int parts MONO_TIME_TRACK (mono_jit_stats.jit_gc_create_gc_map, mini_gc_create_gc_map (cfg)); MONO_TIME_TRACK (mono_jit_stats.jit_save_seq_point_info, mono_save_seq_point_info (cfg, cfg->jit_info)); - if (!cfg->compile_aot) { - mono_save_xdebug_info (cfg); + if (!cfg->compile_aot) mono_lldb_save_method_info (cfg); - } if (cfg->verbose_level >= 2) { char *id = mono_method_full_name (cfg->method, TRUE); @@ -4450,7 +4418,12 @@ mini_get_cpu_features (MonoCompile* cfg) #if defined(TARGET_ARM64) // All Arm64 devices have this set - features |= MONO_CPU_ARM64_BASE; + features |= MONO_CPU_ARM64_BASE; + + // This is a standard part of ARMv8-A; see A1.5 in "ARM + // Architecture Reference Manual ARMv8, for ARMv8-A + // architecture profile" + features |= MONO_CPU_ARM64_NEON; #endif // apply parameters passed via -mattr diff --git a/src/mono/mono/mini/mini.h b/src/mono/mono/mini/mini.h index e454d89ef41b8..5001ee38ddd09 100644 --- a/src/mono/mono/mini/mini.h +++ b/src/mono/mono/mini/mini.h @@ -365,7 +365,6 @@ extern int mono_inject_async_exc_pos; extern MonoMethodDesc *mono_break_at_bb_method; extern int mono_break_at_bb_bb_num; extern gboolean mono_do_x86_stack_align; -extern gboolean mono_using_xdebug; extern int mini_verbose; extern int valgrind_register; @@ -2206,12 +2205,6 @@ void mono_liveness_handle_exception_clauses (MonoCompile *cfg); gpointer mono_realloc_native_code (MonoCompile *cfg); -void mono_xdebug_init (const char *xdebug_opts); -void mono_save_xdebug_info (MonoCompile *cfg); -void mono_save_trampoline_xdebug_info (MonoTrampInfo *info); -/* This is an exported function */ -void mono_xdebug_flush (void); - void mono_register_opcode_emulation (int opcode, const char* name, MonoMethodSignature *sig, gpointer func, gboolean no_throw); void mono_draw_graph (MonoCompile *cfg, MonoGraphOptions draw_options); void mono_add_ins_to_end (MonoBasicBlock *bb, MonoInst *inst); diff --git a/src/mono/mono/mini/xdebug.c b/src/mono/mono/mini/xdebug.c deleted file mode 100644 index 868acaafacb01..0000000000000 --- a/src/mono/mono/mini/xdebug.c +++ /dev/null @@ -1,398 +0,0 @@ -/** - * \file - * Support for emitting gdb debug info for JITted code. - * - * Author: - * Zoltan Varga (vargaz@gmail.com) - * - * (C) 2010 Novell, Inc. - */ - -/* - * This works as follows: - * - the runtime writes out an xdb.s file containing DWARF debug info. - * - the user calls a gdb macro - * - the macro compiles and loads this shared library using add-symbol-file. - * - * This is based on the xdebug functionality in the Kaffe Java VM. - * - * We emit assembly code instead of using the ELF writer, so we can emit debug info - * incrementally as each method is JITted, and the debugger doesn't have to call - * into the runtime to emit the shared library, which would cause all kinds of - * complications, like threading issues, and the fact that the ELF writer's - * emit_writeout () function cannot be called more than once. - * GDB 7.0 and later has a JIT interface. - */ - -#include "config.h" -#include -#include "mini.h" -#include "mini-runtime.h" - -#include -#ifdef HAVE_UNISTD_H -#include -#endif -#ifdef HAVE_STDINT_H -#include -#endif -#include -#include -#include -#ifndef HOST_WIN32 -#include -#else -#include -#include -#endif - -#include -#include - -#include "image-writer.h" - -#if !defined(DISABLE_AOT) && !defined(DISABLE_JIT) && USE_BIN_WRITER - -#include "dwarfwriter.h" - -#include "mono/utils/mono-compiler.h" - -#define USE_GDB_JIT_INTERFACE - -/* The recommended gdb macro is: */ -/* - define xdb - shell rm -f xdb.so && as --64 -o xdb.o xdb.s && ld -shared -o xdb.so xdb.o - add-symbol-file xdb.so 0 - end -*/ - -/* - * GDB JIT interface definitions. - * - * http://sources.redhat.com/gdb/onlinedocs/gdb_30.html - */ -typedef enum -{ - JIT_NOACTION = 0, - JIT_REGISTER_FN, - JIT_UNREGISTER_FN -} jit_actions_t; - -struct jit_code_entry; -typedef struct jit_code_entry jit_code_entry; - -struct jit_code_entry -{ - jit_code_entry *next_entry; - jit_code_entry *prev_entry; - const char *symfile_addr; - /* - * The gdb code in gdb/jit.c which reads this structure ignores alignment - * requirements, so use two 32 bit fields. - */ - guint32 symfile_size1, symfile_size2; -}; - -typedef struct jit_descriptor -{ - guint32 version; - /* This type should be jit_actions_t, but we use guint32 - to be explicit about the bitwidth. */ - guint32 action_flag; - jit_code_entry *relevant_entry; - jit_code_entry *first_entry; -} jit_descriptor; - -G_BEGIN_DECLS - -/* GDB puts a breakpoint in this function. */ -void MONO_NEVER_INLINE __jit_debug_register_code(void); - -#if defined(ENABLE_LLVM) && !defined(MONO_CROSS_COMPILE) - -/* LLVM already defines these */ - -extern jit_descriptor __jit_debug_descriptor; - -#else - -/* gcc seems to inline/eliminate calls to noinline functions, thus the asm () */ -void MONO_NEVER_INLINE __jit_debug_register_code(void) { -#if defined(__GNUC__) - asm (""); -#endif -} - -/* Make sure to specify the version statically, because the - debugger may check the version before we can set it. */ -jit_descriptor __jit_debug_descriptor = { 1, 0, 0, 0 }; - -#endif - -G_END_DECLS - -static MonoImageWriter *xdebug_w; -static MonoDwarfWriter *xdebug_writer; -static FILE *xdebug_fp, *il_file; -static gboolean use_gdb_interface, save_symfiles; -static int il_file_line_index; -static GHashTable *xdebug_syms; - -void -mono_xdebug_init (const char *options) -{ - MonoImageWriter *w; - char **args, **ptr; - - args = g_strsplit (options, ",", -1); - for (ptr = args; ptr && *ptr; ptr ++) { - char *arg = *ptr; - - if (!strcmp (arg, "gdb")) - use_gdb_interface = TRUE; - if (!strcmp (arg, "save-symfiles")) - save_symfiles = TRUE; - } - - /* This file will contain the IL code for methods which don't have debug info */ - il_file = fopen ("xdb.il", "w"); - if (il_file == NULL) { - use_gdb_interface = FALSE; - g_warning ("** Unable to create xdb.il. Managed symbol names won't be available."); - return; - } - - if (use_gdb_interface) - return; - - unlink ("xdb.s"); - xdebug_fp = fopen ("xdb.s", "w"); - - w = mono_img_writer_create (xdebug_fp, FALSE); - - mono_img_writer_emit_start (w); - - xdebug_writer = mono_dwarf_writer_create (w, il_file, 0, TRUE); - - /* Emit something so the file has a text segment */ - mono_img_writer_emit_section_change (w, ".text", 0); - mono_img_writer_emit_string (w, ""); - - mono_dwarf_writer_emit_base_info (xdebug_writer, "JITted code", mono_unwind_get_cie_program ()); -} - -static void -xdebug_begin_emit (MonoImageWriter **out_w, MonoDwarfWriter **out_dw) -{ - MonoImageWriter *w; - MonoDwarfWriter *dw; - - w = mono_img_writer_create (NULL, TRUE); - - mono_img_writer_emit_start (w); - - /* This file will contain the IL code for methods which don't have debug info */ - if (!il_file) - il_file = fopen ("xdb.il", "w"); - - dw = mono_dwarf_writer_create (w, il_file, il_file_line_index, TRUE); - - mono_dwarf_writer_emit_base_info (dw, "JITted code", mono_unwind_get_cie_program ()); - - *out_w = w; - *out_dw = dw; -} - -static void -xdebug_end_emit (MonoImageWriter *w, MonoDwarfWriter *dw, MonoMethod *method) -{ - guint8 *img; - guint32 img_size; - jit_code_entry *entry; - guint64 *psize; - - il_file_line_index = mono_dwarf_writer_get_il_file_line_index (dw); - mono_dwarf_writer_close (dw); - - mono_img_writer_emit_writeout (w); - - img = mono_img_writer_get_output (w, &img_size); - - mono_img_writer_destroy (w); - - if (FALSE) { - /* Save the symbol files to help debugging */ - FILE *fp; - char *file_name; - static int file_counter; - - file_counter ++; - file_name = g_strdup_printf ("xdb-%d.o", file_counter); - printf ("%s %p %d\n", file_name, img, img_size); - - fp = fopen (file_name, "w"); - fwrite (img, img_size, 1, fp); - fclose (fp); - g_free (file_name); - } - - /* Register the image with GDB */ - - entry = g_malloc0 (sizeof (jit_code_entry)); - - entry->symfile_addr = (const char*)img; - psize = (guint64*)&entry->symfile_size1; - *psize = img_size; - - entry->next_entry = __jit_debug_descriptor.first_entry; - if (__jit_debug_descriptor.first_entry) - __jit_debug_descriptor.first_entry->prev_entry = entry; - __jit_debug_descriptor.first_entry = entry; - - __jit_debug_descriptor.relevant_entry = entry; - __jit_debug_descriptor.action_flag = JIT_REGISTER_FN; - - __jit_debug_register_code (); -} - -/* - * mono_xdebug_flush: - * - * This could be called from inside gdb to flush the debugging information not yet - * registered with gdb. - */ -void -mono_xdebug_flush (void) -{ - if (xdebug_w) - xdebug_end_emit (xdebug_w, xdebug_writer, NULL); - - xdebug_begin_emit (&xdebug_w, &xdebug_writer); -} - -static int xdebug_method_count; - -/* - * mono_save_xdebug_info: - * - * Emit debugging info for METHOD into an assembly file which can be assembled - * and loaded into gdb to provide debugging info for JITted code. - * LOCKING: Acquires the loader lock. - */ -void -mono_save_xdebug_info (MonoCompile *cfg) -{ - MonoDebugMethodJitInfo *dmji; - - if (use_gdb_interface) { - mono_loader_lock (); - - if (!xdebug_syms) - xdebug_syms = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); - - /* - * gdb is not designed to handle 1000s of symbol files (one per method). So we - * group them into groups of 100. - */ - if ((xdebug_method_count % 100) == 0) - mono_xdebug_flush (); - - xdebug_method_count ++; - - dmji = mono_debug_find_method (jinfo_get_method (cfg->jit_info), mono_domain_get ()); - mono_dwarf_writer_emit_method (xdebug_writer, cfg, jinfo_get_method (cfg->jit_info), NULL, NULL, NULL, - (guint8*)cfg->jit_info->code_start, cfg->jit_info->code_size, cfg->args, cfg->locals, cfg->unwind_ops, dmji); - mono_debug_free_method_jit_info (dmji); - -#if 0 - /* - * Emit a symbol for the code by emitting it at the beginning of the text - * segment, and setting the text segment to have an absolute address. - * This symbol can be used to set breakpoints in gdb. - * FIXME: This doesn't work when multiple methods are emitted into the same file. - */ - sym = get_debug_sym (cfg->jit_info->method, "", xdebug_syms); - mono_img_writer_emit_section_change (w, ".text", 0); - if (!xdebug_text_addr) { - xdebug_text_addr = cfg->jit_info->code_start; - mono_img_writer_set_section_addr (w, (gssize)xdebug_text_addr); - } - mono_img_writer_emit_global_with_size (w, sym, cfg->jit_info->code_size, TRUE); - mono_img_writer_emit_label (w, sym); - mono_img_writer_emit_bytes (w, cfg->jit_info->code_start, cfg->jit_info->code_size); - g_free (sym); -#endif - - mono_loader_unlock (); - } else { - if (!xdebug_writer) - return; - - mono_loader_lock (); - dmji = mono_debug_find_method (jinfo_get_method (cfg->jit_info), mono_domain_get ()); - mono_dwarf_writer_emit_method (xdebug_writer, cfg, jinfo_get_method (cfg->jit_info), NULL, NULL, NULL, - (guint8*)cfg->jit_info->code_start, cfg->jit_info->code_size, cfg->args, cfg->locals, cfg->unwind_ops, dmji); - mono_debug_free_method_jit_info (dmji); - fflush (xdebug_fp); - mono_loader_unlock (); - } - -} - -/* - * mono_save_trampoline_xdebug_info: - * - * Same as mono_save_xdebug_info, but for trampolines. - * LOCKING: Acquires the loader lock. - */ -void -mono_save_trampoline_xdebug_info (MonoTrampInfo *info) -{ - const char *info_name = info->name; - if (info_name == NULL) - info_name = ""; - - if (use_gdb_interface) { - MonoImageWriter *w; - MonoDwarfWriter *dw; - - /* This can be called before the loader lock is initialized */ - mono_loader_lock_if_inited (); - - xdebug_begin_emit (&w, &dw); - - mono_dwarf_writer_emit_trampoline (dw, info_name, NULL, NULL, info->code, info->code_size, info->unwind_ops); - - xdebug_end_emit (w, dw, NULL); - - mono_loader_unlock_if_inited (); - } else { - if (!xdebug_writer) - return; - - mono_loader_lock_if_inited (); - mono_dwarf_writer_emit_trampoline (xdebug_writer, info_name, NULL, NULL, info->code, info->code_size, info->unwind_ops); - fflush (xdebug_fp); - mono_loader_unlock_if_inited (); - } -} - -#else /* !defined(DISABLE_AOT) && !defined(DISABLE_JIT) */ - -void -mono_xdebug_init (const char *options) -{ -} - -void -mono_save_xdebug_info (MonoCompile *cfg) -{ -} - -void -mono_save_trampoline_xdebug_info (MonoTrampInfo *info) -{ -} - -#endif diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs b/src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs index c1e8ce60bda6c..c398ca8a2c120 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs @@ -453,14 +453,16 @@ public VarInfo[] GetLiveVarsAt(int offset) internal class TypeInfo { - private AssemblyInfo assembly; + internal AssemblyInfo assembly; private TypeDefinition type; private List methods; + public int Token { get; } - public TypeInfo(AssemblyInfo assembly, TypeDefinition type) + public TypeInfo(AssemblyInfo assembly, TypeDefinitionHandle typeHandle, TypeDefinition type) { this.assembly = assembly; var metadataReader = assembly.asmMetadataReader; + Token = MetadataTokens.GetToken(metadataReader, typeHandle); this.type = type; methods = new List(); Name = metadataReader.GetString(type.Name); @@ -594,7 +596,7 @@ SourceFile FindSource(DocumentHandle doc, int rowid, string documentName) { var typeDefinition = asmMetadataReader.GetTypeDefinition(type); - var typeInfo = new TypeInfo(this, typeDefinition); + var typeInfo = new TypeInfo(this, type, typeDefinition); typesByName[typeInfo.FullName] = typeInfo; if (pdbMetadataReader != null) { @@ -876,7 +878,7 @@ public object ToScriptSource(int executionContextId, object executionContextAuxD internal class DebugStore { - private List assemblies = new List(); + internal List assemblies = new List(); private readonly HttpClient client; private readonly ILogger logger; diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/MemberReferenceResolver.cs b/src/mono/wasm/debugger/BrowserDebugProxy/MemberReferenceResolver.cs index 3e791f2f3e057..e08904a99b6eb 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/MemberReferenceResolver.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/MemberReferenceResolver.cs @@ -75,6 +75,57 @@ public async Task GetValueFromObject(JToken objRet, CancellationToken t } return null; } + + public async Task TryToRunOnLoadedClasses(string varName, CancellationToken token) + { + string classNameToFind = ""; + string[] parts = varName.Split("."); + var typeId = -1; + foreach (string part in parts) + { + if (classNameToFind.Length > 0) + classNameToFind += "."; + classNameToFind += part.Trim(); + if (typeId != -1) + { + var fields = await proxy.SdbHelper.GetTypeFields(sessionId, typeId, token); + foreach (var field in fields) + { + if (field.Name == part.Trim()) + { + var isInitialized = await proxy.SdbHelper.TypeIsInitialized(sessionId, typeId, token); + if (isInitialized == 0) + { + isInitialized = await proxy.SdbHelper.TypeInitialize(sessionId, typeId, token); + } + var valueRet = await proxy.SdbHelper.GetFieldValue(sessionId, typeId, field.Id, token); + return await GetValueFromObject(valueRet, token); + } + } + var methodId = await proxy.SdbHelper.GetPropertyMethodIdByName(sessionId, typeId, part.Trim(), token); + if (methodId != -1) + { + var commandParamsObj = new MemoryStream(); + var commandParamsObjWriter = new MonoBinaryWriter(commandParamsObj); + commandParamsObjWriter.Write(0); //param count + var retMethod = await proxy.SdbHelper.InvokeMethod(sessionId, commandParamsObj.ToArray(), methodId, "methodRet", token); + return await GetValueFromObject(retMethod, token); + } + } + var store = await proxy.LoadStore(sessionId, token); + foreach (var asm in store.assemblies) + { + var type = asm.GetTypeByName(classNameToFind); + if (type != null) + { + var assemblyId = await proxy.SdbHelper.GetAssemblyId(sessionId, type.assembly.Name, token); + typeId = await proxy.SdbHelper.GetTypeIdFromToken(sessionId, assemblyId, type.Token, token); + } + } + } + return null; + } + // Checks Locals, followed by `this` public async Task Resolve(string varName, CancellationToken token) { @@ -140,7 +191,8 @@ public async Task Resolve(string varName, CancellationToken token) } else { - return null; + rootObject = await TryToRunOnLoadedClasses(varName, token); + return rootObject; } } } @@ -177,8 +229,8 @@ public async Task Resolve(InvocationExpressionSyntax method, Dictionary var typeName = await proxy.SdbHelper.GetTypeName(sessionId, typeId[0], token); throw new Exception($"Method '{methodName}' not found in type '{typeName}'"); } - var command_params_obj = new MemoryStream(); - var commandParamsObjWriter = new MonoBinaryWriter(command_params_obj); + var commandParamsObj = new MemoryStream(); + var commandParamsObjWriter = new MonoBinaryWriter(commandParamsObj); commandParamsObjWriter.WriteObj(objectId, proxy.SdbHelper); if (method.ArgumentList != null) { @@ -197,7 +249,7 @@ public async Task Resolve(InvocationExpressionSyntax method, Dictionary return null; } } - var retMethod = await proxy.SdbHelper.InvokeMethod(sessionId, command_params_obj.ToArray(), methodId, "methodRet", token); + var retMethod = await proxy.SdbHelper.InvokeMethod(sessionId, commandParamsObj.ToArray(), methodId, "methodRet", token); return await GetValueFromObject(retMethod, token); } } diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/MonoSDBHelper.cs b/src/mono/wasm/debugger/BrowserDebugProxy/MonoSDBHelper.cs index bbb7eb88e7f47..9b4b51c28596d 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/MonoSDBHelper.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/MonoSDBHelper.cs @@ -240,7 +240,8 @@ internal enum CmdType { CreateInstance = 19, GetValueSize = 20, GetValuesICorDbg = 21, - GetParents = 22 + GetParents = 22, + Initialize = 23, } internal enum CmdArray { @@ -929,6 +930,41 @@ public async Task ClearSingleStep(SessionId sessionId, int req_id, Cancell return false; } + public async Task GetFieldValue(SessionId sessionId, int typeId, int fieldId, CancellationToken token) + { + var ret = new List(); + var commandParams = new MemoryStream(); + var commandParamsWriter = new MonoBinaryWriter(commandParams); + commandParamsWriter.Write(typeId); + commandParamsWriter.Write(1); + commandParamsWriter.Write(fieldId); + + var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdType.GetValues, commandParams, token); + return await CreateJObjectForVariableValue(sessionId, retDebuggerCmdReader, "", false, -1, token); + } + + public async Task TypeIsInitialized(SessionId sessionId, int typeId, CancellationToken token) + { + var ret = new List(); + var commandParams = new MemoryStream(); + var commandParamsWriter = new MonoBinaryWriter(commandParams); + commandParamsWriter.Write(typeId); + + var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdType.IsInitialized, commandParams, token); + return retDebuggerCmdReader.ReadInt32(); + } + + public async Task TypeInitialize(SessionId sessionId, int typeId, CancellationToken token) + { + var ret = new List(); + var commandParams = new MemoryStream(); + var commandParamsWriter = new MonoBinaryWriter(commandParams); + commandParamsWriter.Write(typeId); + + var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdType.Initialize, commandParams, token); + return retDebuggerCmdReader.ReadInt32(); + } + public async Task> GetTypeFields(SessionId sessionId, int type_id, CancellationToken token) { var ret = new List(); @@ -1131,6 +1167,17 @@ public async Task GetClassNameFromObject(SessionId sessionId, int object return await GetTypeName(sessionId, type_id[0], token); } + public async Task GetTypeIdFromToken(SessionId sessionId, int assemblyId, int typeToken, CancellationToken token) + { + var ret = new List(); + var commandParams = new MemoryStream(); + var commandParamsWriter = new MonoBinaryWriter(commandParams); + commandParamsWriter.Write((int)assemblyId); + commandParamsWriter.Write((int)typeToken); + var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdAssembly.GetTypeFromToken, commandParams, token); + return retDebuggerCmdReader.ReadInt32(); + } + public async Task GetMethodIdByName(SessionId sessionId, int type_id, string method_name, CancellationToken token) { var ret = new List(); @@ -1194,6 +1241,30 @@ public async Task InvokeMethod(SessionId sessionId, byte[] valueTypeBuf retDebuggerCmdReader.ReadByte(); //number of objects returned. return await CreateJObjectForVariableValue(sessionId, retDebuggerCmdReader, varName, false, -1, token); } + + public async Task GetPropertyMethodIdByName(SessionId sessionId, int typeId, string propertyName, CancellationToken token) + { + var commandParams = new MemoryStream(); + var commandParamsWriter = new MonoBinaryWriter(commandParams); + commandParamsWriter.Write(typeId); + + var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdType.GetProperties, commandParams, token); + var nProperties = retDebuggerCmdReader.ReadInt32(); + for (int i = 0 ; i < nProperties; i++) + { + retDebuggerCmdReader.ReadInt32(); //propertyId + string propertyNameStr = retDebuggerCmdReader.ReadString(); + var getMethodId = retDebuggerCmdReader.ReadInt32(); + retDebuggerCmdReader.ReadInt32(); //setmethod + var attrs = retDebuggerCmdReader.ReadInt32(); //attrs + if (propertyNameStr == propertyName) + { + return getMethodId; + } + } + return -1; + } + public async Task CreateJArrayForProperties(SessionId sessionId, int typeId, byte[] object_buffer, JArray attributes, bool isAutoExpandable, string objectId, bool isOwn, CancellationToken token) { JArray ret = new JArray(); diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/EvaluateOnCallFrameTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/EvaluateOnCallFrameTests.cs index a28080c4c70f7..91f369b71be82 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/EvaluateOnCallFrameTests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/EvaluateOnCallFrameTests.cs @@ -585,6 +585,41 @@ async Task EvaluateOnCallFrameFail(string call_frame_id, params (string expressi props = await GetObjectOnFrame(frame, "this"); CheckNumber(props, "a", 11); }); + + [Fact] + public async Task EvaluateStaticClass() => await CheckInspectLocalsAtBreakpointSite( + "DebuggerTests.EvaluateMethodTestsClass/TestEvaluate", "run", 9, "run", + "window.setTimeout(function() { invoke_static_method ('[debugger-test] DebuggerTests.EvaluateMethodTestsClass:EvaluateMethods'); })", + wait_for_event_fn: async (pause_location) => + { + var id = pause_location["callFrames"][0]["callFrameId"].Value(); + + var frame = pause_location["callFrames"][0]; + + await EvaluateOnCallFrameAndCheck(id, + ("DebuggerTests.EvaluateStaticClass.StaticField1", TNumber(10))); + await EvaluateOnCallFrameAndCheck(id, + ("DebuggerTests.EvaluateStaticClass.StaticProperty1", TString("StaticProperty1"))); + await EvaluateOnCallFrameAndCheck(id, + ("DebuggerTests.EvaluateStaticClass.StaticPropertyWithError", TString("System.Exception: not implemented"))); + }); + + [Fact] + public async Task EvaluateStaticClassInvalidField() => await CheckInspectLocalsAtBreakpointSite( + "DebuggerTests.EvaluateMethodTestsClass/TestEvaluate", "run", 9, "run", + "window.setTimeout(function() { invoke_static_method ('[debugger-test] DebuggerTests.EvaluateMethodTestsClass:EvaluateMethods'); })", + wait_for_event_fn: async (pause_location) => + { + var id = pause_location["callFrames"][0]["callFrameId"].Value(); + + var frame = pause_location["callFrames"][0]; + + var (_, res) = await EvaluateOnCallFrame(id, "DebuggerTests.EvaluateStaticClass.StaticProperty2", expect_ok: false); + AssertEqual("Failed to resolve member access for DebuggerTests.EvaluateStaticClass.StaticProperty2", res.Error["result"]?["description"]?.Value(), "wrong error message"); + + (_, res) = await EvaluateOnCallFrame(id, "DebuggerTests.InvalidEvaluateStaticClass.StaticProperty2", expect_ok: false); + AssertEqual("Failed to resolve member access for DebuggerTests.InvalidEvaluateStaticClass.StaticProperty2", res.Error["result"]?["description"]?.Value(), "wrong error message"); + }); } } diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/GetPropertiesTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/GetPropertiesTests.cs index 3215ef1184d89..6b4dcd65900be 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/GetPropertiesTests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/GetPropertiesTests.cs @@ -335,6 +335,32 @@ public async Task GetPropertiesTestJSAndManaged(bool test_js, bool? own_properti AssertEqual(expected_names.Length, filtered_props.Count(), $"expected number of properties"); } + [Fact] + public async Task GetObjectValueWithInheritance() + { + var pause_location = await EvaluateAndCheck( + "window.setTimeout(function() { invoke_static_method('[debugger-test] TestChild:TestWatchWithInheritance'); }, 1);", + "dotnet://debugger-test.dll/debugger-test2.cs", 83, 4, + "TestWatchWithInheritance"); + var frame_id = pause_location["callFrames"][0]["callFrameId"].Value(); + var frame_locals = await GetProperties(frame_id); + var test_props = await GetObjectOnLocals(frame_locals, "test"); + await CheckProps(test_props, new + { + j = TNumber(20), + i = TNumber(50), + k = TNumber(30), + GetJ = TGetter("GetJ"), + GetI = TGetter("GetI"), + GetK = TGetter("GetK") + }, "test_props"); + await EvaluateOnCallFrameAndCheck(frame_id, + ($"test.GetJ", TNumber(20)), + ($"test.GetI", TNumber(50)), + ($"test.GetK", TNumber(30)) + ); + } + private async Task CheckExpectedProperties(string[] expected_names, Func get_actual_prop, Dictionary all_props) { foreach (var exp_name in expected_names) diff --git a/src/mono/wasm/debugger/tests/debugger-test/debugger-evaluate-test.cs b/src/mono/wasm/debugger/tests/debugger-test/debugger-evaluate-test.cs index 1583ce1fd6f86..01bdda2868ddd 100644 --- a/src/mono/wasm/debugger/tests/debugger-test/debugger-evaluate-test.cs +++ b/src/mono/wasm/debugger/tests/debugger-test/debugger-evaluate-test.cs @@ -406,4 +406,11 @@ public static void EvaluateMethods() } + public static class EvaluateStaticClass + { + public static int StaticField1 = 10; + public static string StaticProperty1 => "StaticProperty1"; + public static string StaticPropertyWithError => throw new Exception("not implemented"); + } + } diff --git a/src/mono/wasm/debugger/tests/debugger-test/debugger-test2.cs b/src/mono/wasm/debugger/tests/debugger-test/debugger-test2.cs index 157109c74580c..2a5d525392fc9 100644 --- a/src/mono/wasm/debugger/tests/debugger-test/debugger-test2.cs +++ b/src/mono/wasm/debugger/tests/debugger-test/debugger-test2.cs @@ -95,3 +95,30 @@ public static async System.Threading.Tasks.Task RunInspectTask() } } } + +public class TestParent2 +{ + public int k = 30; + public int GetK => k; +} + +public class TestParent : TestParent2 +{ + public int j = 20; + public int GetJ => j; +} + +public class TestChild : TestParent +{ + public int i = 50; + public int GetI => i; + public TestChild() + { + Console.WriteLine("Hi"); + } + public static void TestWatchWithInheritance() + { + TestChild test = new TestChild(); + Debugger.Break(); + } +} diff --git a/src/mono/wasm/runtime-test.js b/src/mono/wasm/runtime-test.js index 89b9c5d70cc7e..e661a5423a0d2 100644 --- a/src/mono/wasm/runtime-test.js +++ b/src/mono/wasm/runtime-test.js @@ -18,15 +18,21 @@ globalThis.testConsole = console; function proxyMethod (prefix, func, asJson) { return function() { - var args = [...arguments]; + const args = [...arguments]; + var payload= args[0]; + if(payload === undefined) payload = 'undefined'; + else if(payload === null) payload = 'null'; + else if(typeof payload === 'function') payload = payload.toString(); + else if(typeof payload !== 'string') payload = JSON.stringify(payload); + if (asJson) { func (JSON.stringify({ method: prefix, - payload: args[0], + payload: payload, arguments: args })); } else { - func([prefix + args[0], ...args.slice(1)]); + func([prefix + payload, ...args.slice(1)]); } }; }; diff --git a/src/tests/FunctionalTests/iOS/Simulator/XmlSerializer_Deserialize/Program.cs b/src/tests/FunctionalTests/iOS/Simulator/XmlSerializer_Deserialize/Program.cs new file mode 100644 index 0000000000000..05da0aed4b2c5 --- /dev/null +++ b/src/tests/FunctionalTests/iOS/Simulator/XmlSerializer_Deserialize/Program.cs @@ -0,0 +1,43 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Runtime.InteropServices; +using System.Threading.Tasks; +using System.Xml; +using System.Xml.Schema; +using System.Xml.Serialization; + +public static class Program +{ + public static async Task Main(string[] args) + { + using StringReader stringReader = new StringReader(@" + + sample + "); + + var serializer = new XmlSerializer(typeof(TestClass)); + TestClass obj = (TestClass)serializer.Deserialize(stringReader); + + var result = obj.TestData == "sample" ? 42 : 1; + + Console.WriteLine("Done!"); + await Task.Delay(5000); + + return result; + } + + [XmlType("TestClass", AnonymousType = true, Namespace = "")] + public class TestClass + { + public TestClass() + { + } + + [XmlElement("TestData")] + public string TestData { get; set; } + } +} diff --git a/src/tests/FunctionalTests/iOS/Simulator/XmlSerializer_Deserialize/iOS.Simulator.XmlSerializer_Deserialize.Test.csproj b/src/tests/FunctionalTests/iOS/Simulator/XmlSerializer_Deserialize/iOS.Simulator.XmlSerializer_Deserialize.Test.csproj new file mode 100644 index 0000000000000..e56efb092cec7 --- /dev/null +++ b/src/tests/FunctionalTests/iOS/Simulator/XmlSerializer_Deserialize/iOS.Simulator.XmlSerializer_Deserialize.Test.csproj @@ -0,0 +1,19 @@ + + + + Exe + false + true + true + $(NetCoreAppCurrent) + iOSSimulator + iOS.Simulator.XmlSerializer_Deserialize.Test.dll + false + 42 + true + + + + + + diff --git a/src/tests/Interop/IJW/CopyConstructorMarshaler/CopyConstructorMarshaler.cs b/src/tests/Interop/IJW/CopyConstructorMarshaler/CopyConstructorMarshaler.cs index 7c04e2890f097..4b3008aa72dd0 100644 --- a/src/tests/Interop/IJW/CopyConstructorMarshaler/CopyConstructorMarshaler.cs +++ b/src/tests/Interop/IJW/CopyConstructorMarshaler/CopyConstructorMarshaler.cs @@ -20,7 +20,7 @@ static int Main(string[] args) try { - Assembly ijwNativeDll = IjwHelper.LoadIjwAssembly("IjwCopyConstructorMarshaler"); + Assembly ijwNativeDll = Assembly.Load("IjwCopyConstructorMarshaler"); Type testType = ijwNativeDll.GetType("TestClass"); object testInstance = Activator.CreateInstance(testType); MethodInfo testMethod = testType.GetMethod("PInvokeNumCopies"); @@ -33,7 +33,7 @@ static int Main(string[] args) // Reverse PInvoke will copy 3 times. Two are from the same paths as the PInvoke, // and the third is from the reverse P/Invoke call. Assert.AreEqual(3, (int)testMethod.Invoke(testInstance, null)); - + testMethod = testType.GetMethod("PInvokeNumCopiesDerivedType"); // PInvoke will copy twice. Once from argument to parameter, and once from the managed to native parameter. diff --git a/src/tests/Interop/IJW/CopyConstructorMarshaler/CopyConstructorMarshaler.csproj b/src/tests/Interop/IJW/CopyConstructorMarshaler/CopyConstructorMarshaler.csproj index 47e6c3d8060e2..1cebb6f073014 100644 --- a/src/tests/Interop/IJW/CopyConstructorMarshaler/CopyConstructorMarshaler.csproj +++ b/src/tests/Interop/IJW/CopyConstructorMarshaler/CopyConstructorMarshaler.csproj @@ -14,7 +14,6 @@ - diff --git a/src/tests/Interop/IJW/FixupCallsHostWhenLoaded/FixupCallsHostWhenLoaded.cs b/src/tests/Interop/IJW/FixupCallsHostWhenLoaded/FixupCallsHostWhenLoaded.cs index 9997f1d6857fc..5007ec3c80f0a 100644 --- a/src/tests/Interop/IJW/FixupCallsHostWhenLoaded/FixupCallsHostWhenLoaded.cs +++ b/src/tests/Interop/IJW/FixupCallsHostWhenLoaded/FixupCallsHostWhenLoaded.cs @@ -21,8 +21,7 @@ static int Main(string[] args) try { - // Load a fake mscoree.dll to avoid starting desktop - IntPtr ijwHost = NativeLibrary.Load(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "mscoree.dll")); + IntPtr ijwHost = NativeLibrary.Load(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "ijwhost.dll")); WasModuleVTableQueriedDelegate wasModuleVTableQueried = Marshal.GetDelegateForFunctionPointer(NativeLibrary.GetExport(ijwHost, "WasModuleVTableQueried")); @@ -30,7 +29,7 @@ static int Main(string[] args) Assembly.Load("IjwNativeDll"); IntPtr ijwModuleHandle = GetModuleHandle("IjwNativeDll.dll"); - + Assert.AreNotEqual(IntPtr.Zero, ijwModuleHandle); Assert.IsTrue(wasModuleVTableQueried(ijwModuleHandle)); } diff --git a/src/tests/Interop/IJW/FixupCallsHostWhenLoaded/FixupCallsHostWhenLoaded.csproj b/src/tests/Interop/IJW/FixupCallsHostWhenLoaded/FixupCallsHostWhenLoaded.csproj index 4343f56386fa4..d6cec7a1845e1 100644 --- a/src/tests/Interop/IJW/FixupCallsHostWhenLoaded/FixupCallsHostWhenLoaded.csproj +++ b/src/tests/Interop/IJW/FixupCallsHostWhenLoaded/FixupCallsHostWhenLoaded.csproj @@ -14,7 +14,6 @@ - diff --git a/src/tests/Interop/IJW/IJW.cmake b/src/tests/Interop/IJW/IJW.cmake index b41a83794d99b..1ba007427185c 100644 --- a/src/tests/Interop/IJW/IJW.cmake +++ b/src/tests/Interop/IJW/IJW.cmake @@ -3,7 +3,7 @@ if (CLR_CMAKE_HOST_WIN32) add_compile_options(/wd4365) # IJW - add_compile_options(/clr) + add_compile_options(/clr:netcore) # IJW requires the CRT as a dll, not linked in set(CMAKE_MSVC_RUNTIME_LIBRARY MultiThreaded$<$,$>:Debug>DLL) @@ -32,4 +32,32 @@ if (CLR_CMAKE_HOST_WIN32) string(REPLACE "/GR-" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") endif() + set(CLR_SDK_REF_PACK "") + set(CLR_SDK_REF_PACK_DISCOVERY_ERROR "") + set(CLR_SDK_REF_PACK_DISCOVERY_RESULT 0) + + if (CPP_CLI_LIVE_REF_ASSEMBLIES) + message("Using live-built ref assemblies for C++/CLI runtime tests.") + execute_process( + COMMAND powershell -ExecutionPolicy ByPass -NoProfile "${CMAKE_CURRENT_LIST_DIR}/getRefPackFolderFromArtifacts.ps1" + OUTPUT_VARIABLE CLR_SDK_REF_PACK + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_VARIABLE CLR_SDK_REF_PACK_DISCOVERY_ERROR + RESULT_VARIABLE CLR_SDK_REF_PACK_DISCOVERY_RESULT) + else() + execute_process( + COMMAND powershell -ExecutionPolicy ByPass -NoProfile "${CMAKE_CURRENT_LIST_DIR}/getRefPackFolderFromSdk.ps1" + OUTPUT_VARIABLE CLR_SDK_REF_PACK + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_VARIABLE CLR_SDK_REF_PACK_DISCOVERY_ERROR + RESULT_VARIABLE CLR_SDK_REF_PACK_DISCOVERY_RESULT) + endif() + + if (NOT CLR_SDK_REF_PACK_DISCOVERY_RESULT EQUAL 0) + message(FATAL_ERROR "Unable to find reference assemblies: ${CLR_SDK_REF_PACK_DISCOVERY_ERROR}") + endif() + + add_compile_options(/AI${CLR_SDK_REF_PACK}) + + list(APPEND LINK_LIBRARIES_ADDITIONAL ijwhost) endif() diff --git a/src/tests/Interop/IJW/IjwHelper.cs b/src/tests/Interop/IJW/IjwHelper.cs deleted file mode 100644 index 007229b8a1880..0000000000000 --- a/src/tests/Interop/IJW/IjwHelper.cs +++ /dev/null @@ -1,21 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.IO; -using System.Reflection; -using System.Runtime.InteropServices; -using TestLibrary; - -class IjwHelper -{ - private const string ijwHostName = "mscoree.dll"; - - public static Assembly LoadIjwAssembly(string name) - { - // Load our mock ijwhost before we load the IJW assembly. - NativeLibrary.Load(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), ijwHostName)); - - return Assembly.Load(name); - } -} diff --git a/src/tests/Interop/IJW/LoadIjwFromModuleHandle/LoadIjwFromModuleHandle.cs b/src/tests/Interop/IJW/LoadIjwFromModuleHandle/LoadIjwFromModuleHandle.cs index 6dca0e8853e8d..cdcacd6b3eb2a 100644 --- a/src/tests/Interop/IJW/LoadIjwFromModuleHandle/LoadIjwFromModuleHandle.cs +++ b/src/tests/Interop/IJW/LoadIjwFromModuleHandle/LoadIjwFromModuleHandle.cs @@ -26,9 +26,6 @@ unsafe static int Main(string[] args) { HostPolicyMock.Initialize(Environment.CurrentDirectory, null); - // Load our fake mscoree to prevent .NET Framework from loading. - NativeLibrary.Load(Path.Combine(Environment.CurrentDirectory, "mscoree.dll")); - Console.WriteLine("Verify that we can load an IJW assembly from native code."); string ijwModulePath = Path.Combine(Environment.CurrentDirectory, "IjwNativeCallingManagedDll.dll"); IntPtr ijwNativeHandle = NativeLibrary.Load(ijwModulePath); @@ -42,7 +39,7 @@ unsafe static int Main(string[] args) { InMemoryAssemblyLoader.LoadInMemoryAssembly(ijwNativeHandle, (IntPtr)path); } - + NativeEntryPointDelegate nativeEntryPoint = Marshal.GetDelegateForFunctionPointer(NativeLibrary.GetExport(ijwNativeHandle, "NativeEntryPoint")); Assert.AreEqual(100, nativeEntryPoint()); @@ -63,7 +60,7 @@ unsafe static int Main(string[] args) changeReturnedValueMethod.Invoke(null, new object[] { newValue }); Assert.AreEqual(newValue, (int)getReturnValueMethod.Invoke(null, null)); - + // Native images are only loaded into memory once. As a result, the stubs in the vtfixup table // will always point to JIT stubs that exist in the first ALC that the module was loaded into. // As a result, if an IJW module is loaded into two different ALCs, or if the module is diff --git a/src/tests/Interop/IJW/ManagedCallingNative/ManagedCallingNative.cs b/src/tests/Interop/IJW/ManagedCallingNative/ManagedCallingNative.cs index 6fbd95199e0ff..19910a66d973a 100644 --- a/src/tests/Interop/IJW/ManagedCallingNative/ManagedCallingNative.cs +++ b/src/tests/Interop/IJW/ManagedCallingNative/ManagedCallingNative.cs @@ -20,7 +20,7 @@ static int Main(string[] args) } bool success = true; - Assembly ijwNativeDll = IjwHelper.LoadIjwAssembly("IjwNativeDll"); + Assembly ijwNativeDll = Assembly.Load("IjwNativeDll"); TestFramework.BeginTestCase("Call native method returning int"); Type testType = ijwNativeDll.GetType("TestClass"); @@ -45,19 +45,7 @@ static int Main(string[] args) catch { } TestFramework.EndTestCase(); - TestFramework.BeginTestCase("Ensure .NET Framework was not loaded"); - IntPtr clrHandle = GetModuleHandle("mscoreei.dll"); - if (clrHandle != IntPtr.Zero) - { - TestFramework.LogError("IJW", ".NET Framework loaded by IJw module load"); - success = false; - } - TestFramework.EndTestCase(); - return success ? 100 : 99; } - - [DllImport("kernel32.dll")] - static extern IntPtr GetModuleHandle(string lpModuleName); } } diff --git a/src/tests/Interop/IJW/ManagedCallingNative/ManagedCallingNative.csproj b/src/tests/Interop/IJW/ManagedCallingNative/ManagedCallingNative.csproj index f9af5043b8faf..858100113ee54 100644 --- a/src/tests/Interop/IJW/ManagedCallingNative/ManagedCallingNative.csproj +++ b/src/tests/Interop/IJW/ManagedCallingNative/ManagedCallingNative.csproj @@ -14,7 +14,6 @@ - diff --git a/src/tests/Interop/IJW/NativeCallingManaged/NativeCallingManaged.cs b/src/tests/Interop/IJW/NativeCallingManaged/NativeCallingManaged.cs index adf1ac4b4d769..95516edb90ef0 100644 --- a/src/tests/Interop/IJW/NativeCallingManaged/NativeCallingManaged.cs +++ b/src/tests/Interop/IJW/NativeCallingManaged/NativeCallingManaged.cs @@ -20,7 +20,7 @@ static int Main(string[] args) } bool success = true; - Assembly ijwNativeDll = IjwHelper.LoadIjwAssembly("IjwNativeCallingManagedDll"); + Assembly ijwNativeDll = Assembly.Load("IjwNativeCallingManagedDll"); TestFramework.BeginTestCase("Call native method returning int"); Type testType = ijwNativeDll.GetType("TestClass"); @@ -34,19 +34,7 @@ static int Main(string[] args) } TestFramework.EndTestCase(); - TestFramework.BeginTestCase("Ensure .NET Framework was not loaded"); - IntPtr clrHandle = GetModuleHandle("mscoreei.dll"); - if (clrHandle != IntPtr.Zero) - { - TestFramework.LogError("IJW", ".NET Framework loaded by IJw module load"); - success = false; - } - TestFramework.EndTestCase(); - return success ? 100 : 99; } - - [DllImport("kernel32.dll")] - static extern IntPtr GetModuleHandle(string lpModuleName); } } diff --git a/src/tests/Interop/IJW/NativeCallingManaged/NativeCallingManaged.csproj b/src/tests/Interop/IJW/NativeCallingManaged/NativeCallingManaged.csproj index e2699c214d49a..9ea4b4cde8a49 100644 --- a/src/tests/Interop/IJW/NativeCallingManaged/NativeCallingManaged.csproj +++ b/src/tests/Interop/IJW/NativeCallingManaged/NativeCallingManaged.csproj @@ -14,7 +14,6 @@ - diff --git a/src/tests/Interop/IJW/NativeVarargs/IjwNativeVarargs.cpp b/src/tests/Interop/IJW/NativeVarargs/IjwNativeVarargs.cpp index 23b382365b180..a2b9cc92ce858 100644 --- a/src/tests/Interop/IJW/NativeVarargs/IjwNativeVarargs.cpp +++ b/src/tests/Interop/IJW/NativeVarargs/IjwNativeVarargs.cpp @@ -8,7 +8,8 @@ #include #include #include -#using +#using +#using using namespace System::Collections::Generic; public enum class TestCases diff --git a/src/tests/Interop/IJW/NativeVarargs/NativeVarargsTest.cs b/src/tests/Interop/IJW/NativeVarargs/NativeVarargsTest.cs index abc8374353b6b..ffbf04eda1d30 100644 --- a/src/tests/Interop/IJW/NativeVarargs/NativeVarargsTest.cs +++ b/src/tests/Interop/IJW/NativeVarargs/NativeVarargsTest.cs @@ -26,7 +26,7 @@ static int Main(string[] args) try { - Assembly ijwNativeDll = IjwHelper.LoadIjwAssembly("IjwNativeVarargs"); + Assembly ijwNativeDll = Assembly.Load("IjwNativeVarargs"); Type testType = ijwNativeDll.GetType("TestClass"); object testInstance = Activator.CreateInstance(testType); MethodInfo testMethod = testType.GetMethod("RunTests"); diff --git a/src/tests/Interop/IJW/NativeVarargs/NativeVarargsTest.csproj b/src/tests/Interop/IJW/NativeVarargs/NativeVarargsTest.csproj index 157d90264bc02..b8d593f7ba87c 100644 --- a/src/tests/Interop/IJW/NativeVarargs/NativeVarargsTest.csproj +++ b/src/tests/Interop/IJW/NativeVarargs/NativeVarargsTest.csproj @@ -16,7 +16,6 @@ - diff --git a/src/tests/Interop/IJW/getRefPackFolderFromArtifacts.ps1 b/src/tests/Interop/IJW/getRefPackFolderFromArtifacts.ps1 new file mode 100644 index 0000000000000..aaf5e93661ae3 --- /dev/null +++ b/src/tests/Interop/IJW/getRefPackFolderFromArtifacts.ps1 @@ -0,0 +1,21 @@ +# Licensed to the .NET Foundation under one or more agreements. +# The .NET Foundation licenses this file to you under the MIT license. +$interopFolder = Split-Path $PSScriptRoot -Parent +$testsFolder = Split-Path $interopFolder -Parent +$srcFolder = Split-Path $testsFolder -Parent +$repoRoot = Split-Path $srcFolder -Parent + +$versionPropsFile = "$repoRoot/eng/Versions.props" + +$majorVersion = Select-Xml -Path $versionPropsFile -XPath "/Project/PropertyGroup/MajorVersion" | %{$_.Node.InnerText} +$minorVersion = Select-Xml -Path $versionPropsFile -XPath "/Project/PropertyGroup/MinorVersion" | %{$_.Node.InnerText} + +$refPackPath = "$repoRoot/artifacts/bin/ref/net$majorVersion.$minorVersion" + +if (-not (Test-Path $refPackPath)) +{ + Write-Error "Reference assemblies not found in the artifacts folder at '$refPackPath'. Did you build the libs.ref subset? Did the repo layout change?" + return 1 +} + +Write-Output $refPackPath diff --git a/src/tests/Interop/IJW/getRefPackFolderFromSdk.ps1 b/src/tests/Interop/IJW/getRefPackFolderFromSdk.ps1 new file mode 100644 index 0000000000000..bb2404d27a626 --- /dev/null +++ b/src/tests/Interop/IJW/getRefPackFolderFromSdk.ps1 @@ -0,0 +1,28 @@ +# Licensed to the .NET Foundation under one or more agreements. +# The .NET Foundation licenses this file to you under the MIT license. +$interopFolder = Split-Path $PSScriptRoot -Parent +$testsFolder = Split-Path $interopFolder -Parent +$srcFolder = Split-Path $testsFolder -Parent +$repoRoot = Split-Path $srcFolder -Parent + + +. "$repoRoot/eng/common/tools.ps1" + +$dotnetRoot = InitializeDotNetCli $true $false + +$dotnetSdkVersion = $GlobalJson.tools.dotnet + +$sdkBundledVersionsFile = "$dotnetRoot/sdk/$dotnetSdkVersion/Microsoft.NETCoreSdk.BundledVersions.props" + +$refPackVersion = Select-Xml -Path $sdkBundledVersionsFile -XPath "/Project/PropertyGroup/BundledNETCoreAppPackageVersion" | %{$_.Node.InnerText} +$refPackTfmVersion = Select-Xml -Path $sdkBundledVersionsFile -XPath "/Project/PropertyGroup/BundledNETCoreAppTargetFrameworkVersion" | %{$_.Node.InnerText} + +$refPackPath = "$dotnetRoot/packs/Microsoft.NETCore.App.Ref/$refPackVersion/ref/net$refPackTfmVersion" + +if (-not (Test-Path $refPackPath)) +{ + Write-Error "Reference assemblies not found in the SDK folder. Did the SDK layout change? Did the SDK change how it describes the bundled runtime version?" + return 1 +} + +Write-Output $refPackPath diff --git a/src/tests/Interop/IJW/ijwhostmock/CMakeLists.txt b/src/tests/Interop/IJW/ijwhostmock/CMakeLists.txt index df4b193419572..b6bbd047ab37f 100644 --- a/src/tests/Interop/IJW/ijwhostmock/CMakeLists.txt +++ b/src/tests/Interop/IJW/ijwhostmock/CMakeLists.txt @@ -1,10 +1,10 @@ project (mscoree) include_directories( ${INC_PLATFORM_DIR} ) -set(SOURCES mscoree.cpp) +set(SOURCES ijwhost.cpp) # add the shared library -add_library (mscoree SHARED ${SOURCES}) -target_link_libraries(mscoree ${LINK_LIBRARIES_ADDITIONAL}) +add_library (ijwhost SHARED ${SOURCES}) +target_link_libraries(ijwhost ${LINK_LIBRARIES_ADDITIONAL}) # add the install targets -install (TARGETS mscoree DESTINATION bin) +install (TARGETS ijwhost DESTINATION bin) diff --git a/src/tests/Interop/IJW/ijwhostmock/mscoree.cpp b/src/tests/Interop/IJW/ijwhostmock/ijwhost.cpp similarity index 79% rename from src/tests/Interop/IJW/ijwhostmock/mscoree.cpp rename to src/tests/Interop/IJW/ijwhostmock/ijwhost.cpp index 8c466d3996f42..abc554b81b9f8 100644 --- a/src/tests/Interop/IJW/ijwhostmock/mscoree.cpp +++ b/src/tests/Interop/IJW/ijwhostmock/ijwhost.cpp @@ -8,9 +8,6 @@ std::set g_modulesQueried = {}; #if defined HOST_X86 -// We need to use a double-underscore here because the VC linker drops the first underscore -// to help people who are exporting cdecl functions to easily export the right thing. -#pragma comment(linker, "/export:__CorDllMain=__CorDllMain@12") #pragma comment(linker, "/export:GetTokenForVTableEntry=_GetTokenForVTableEntry@8") #endif diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_4781/Runtime_4781.cs b/src/tests/JIT/Regression/JitBlue/Runtime_4781/Runtime_4781.cs new file mode 100644 index 0000000000000..8d2221fb2280c --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_4781/Runtime_4781.cs @@ -0,0 +1,52 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; + +// Test for proper ordering of exception-causing ctor args and +// the newobj allocation + +class Foo : IDisposable +{ + public bool IsConstructed { get; } = true; + public Foo(int ignored) { } + + ~Foo() + { + if (!IsConstructed) + { + Console.WriteLine("Finalizing a non-constructed object?!"); + Runtime_4781.Fail(); + } + } + + public void Dispose() => GC.SuppressFinalize(this); +} + +class Runtime_4781 +{ + private static int Throw() => throw new NotSupportedException(); + private static bool failed = false; + public static void Fail() { failed = true; } + + private static IDisposable Test() + { + try + { + int x = Throw(); + return new Foo(x); + } + catch + { + } + return new Foo(2); + } + + static int Main(string[] args) + { + Test().Dispose(); + GC.Collect(); + GC.WaitForPendingFinalizers(); + return failed ? -1 : 100; + } +} diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_4781/Runtime_4781.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_4781/Runtime_4781.csproj new file mode 100644 index 0000000000000..f3e1cbd44b404 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_4781/Runtime_4781.csproj @@ -0,0 +1,12 @@ + + + Exe + + + None + True + + + + + diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_4781/Runtime_4781_1.cs b/src/tests/JIT/Regression/JitBlue/Runtime_4781/Runtime_4781_1.cs new file mode 100644 index 0000000000000..a7cf8fe4a455e --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_4781/Runtime_4781_1.cs @@ -0,0 +1,49 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; + +// Test for proper ordering of a gc safepoint inducing arg and +// the newobj allocation + +class Bar +{ + public Bar() + { + GC.Collect(); + GC.WaitForPendingFinalizers(); + } +} + +static class Observer +{ + public static bool failed; +} + +class Foo : IDisposable +{ + + public Foo(Bar b) + { + Console.WriteLine($"new Foo"); + } + + ~Foo() + { + Console.WriteLine($"~Foo"); + Observer.failed = true; + } + + public void Dispose() => GC.SuppressFinalize(this); +} + +class Runtime_4781_1 +{ + static Bar s_bar = new Bar(); + + static int Main(string[] args) + { + var f = new Foo(s_bar); + return Observer.failed ? -1 : 100; + } +} diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_4781/Runtime_4781_1.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_4781/Runtime_4781_1.csproj new file mode 100644 index 0000000000000..7052da0bcb87e --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_4781/Runtime_4781_1.csproj @@ -0,0 +1,13 @@ + + + Exe + + + None + True + true + + + + + diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_55107/Runtime_55107.cs b/src/tests/JIT/Regression/JitBlue/Runtime_55107/Runtime_55107.cs new file mode 100644 index 0000000000000..366bd506c1bac --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_55107/Runtime_55107.cs @@ -0,0 +1,40 @@ + +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Runtime.CompilerServices; + +namespace Runtime_55107 +{ + class Program + { + class G + { + } + + static int Main(string[] args) + { + G g = new G(); + + ref G iprnull = ref Unsafe.NullRef(); + ref G ipr1 = ref g; + + if(Unsafe.AreSame(ref ipr1, ref iprnull)) + { + // Failure case 1 + return -101; + } + else if(Unsafe.AreSame(ref ipr1, ref Unsafe.NullRef())) + { + // Failure case 2 + return -102; + } + else + { + // Successful exit + return 100; + } + } + } +} diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_55107/Runtime_55107.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_55107/Runtime_55107.csproj new file mode 100644 index 0000000000000..dad19c468a03a --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_55107/Runtime_55107.csproj @@ -0,0 +1,22 @@ + + + Exe + + + + True + + + + + + + + + diff --git a/src/tests/build.cmd b/src/tests/build.cmd index 453bc09efcbb2..aac5ffd6fb164 100644 --- a/src/tests/build.cmd +++ b/src/tests/build.cmd @@ -56,6 +56,7 @@ set __CopyNativeProjectsAfterCombinedTestBuild=true set __SkipGenerateLayout=0 set __GenerateLayoutOnly=0 set __Ninja=1 +set __CMakeArgs= @REM CMD has a nasty habit of eating "=" on the argument list, so passing: @REM -priority=1 @@ -97,7 +98,7 @@ if /i "%1" == "skipgeneratelayout" (set __SkipGenerateLayout=1&set processedA if /i "%1" == "copynativeonly" (set __CopyNativeTestBinaries=1&set __SkipNative=1&set __CopyNativeProjectsAfterCombinedTestBuild=false&set __SkipGenerateLayout=1&set __SkipTestWrappers=1&set __SkipCrossgenFramework=1&set processedArgs=!processedArgs! %1&shift&goto Arg_Loop) if /i "%1" == "generatelayoutonly" (set __SkipManaged=1&set __SkipNative=1&set __CopyNativeProjectsAfterCombinedTestBuild=false&set processedArgs=!processedArgs! %1&shift&goto Arg_Loop) if /i "%1" == "buildtestwrappersonly" (set __SkipNative=1&set __SkipManaged=1&set __BuildTestWrappersOnly=1&set __SkipGenerateLayout=1&set processedArgs=!processedArgs! %1&shift&goto Arg_Loop) - +if /i "%1" == "-cmakeargs" (set __CMakeArgs="%2=%3" %__CMakeArgs%&set "processedArgs=!processedArgs! %1 %2=%3"&shift&shift&goto Arg_Loop) if /i "%1" == "-msbuild" (set __Ninja=0&set processedArgs=!processedArgs! %1&shift&goto Arg_Loop) if /i "%1" == "buildagainstpackages" (echo error: Remove /BuildAgainstPackages switch&&exit /b1) if /i "%1" == "crossgen2" (set __DoCrossgen2=1&set __TestBuildMode=crossgen2&set processedArgs=!processedArgs! %1&shift&goto Arg_Loop) @@ -226,7 +227,7 @@ if %__Ninja% EQU 1 ( ) else ( set __ExtraCmakeArgs="-DCMAKE_SYSTEM_VERSION=10.0" ) -call "%__RepoRootDir%\eng\native\gen-buildsys.cmd" "%__ProjectFilesDir%" "%__NativeTestIntermediatesDir%" %__VSVersion% %__BuildArch% !__ExtraCmakeArgs! +call "%__RepoRootDir%\eng\native\gen-buildsys.cmd" "%__ProjectFilesDir%" "%__NativeTestIntermediatesDir%" %__VSVersion% %__BuildArch% !__ExtraCmakeArgs! !__CMakeArgs! if not !errorlevel! == 0 ( echo %__ErrMsgPrefix%%__MsgPrefix%Error: failed to generate native component build project! diff --git a/src/tests/issues.targets b/src/tests/issues.targets index 854204fd744fc..747903cb427ad 100644 --- a/src/tests/issues.targets +++ b/src/tests/issues.targets @@ -719,16 +719,6 @@ - - - - https://github.com/dotnet/runtime/issues/47096 - - - https://github.com/dotnet/runtime/issues/47096 - - - diff --git a/src/tests/run.proj b/src/tests/run.proj index 3289e9c9ee645..4f17417636d84 100644 --- a/src/tests/run.proj +++ b/src/tests/run.proj @@ -601,7 +601,6 @@ namespace $([System.String]::Copy($(Category)).Replace(".","_").Replace("\",""). -