diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json
index b0ca8df7b5fef8..37cc0681fbf9db 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 88779ccdac0290..556b399aa3dc05 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 00c05415425cfd..997aa1fd3772a8 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 2629df320d2887..ee874e85abde58 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 3819907618b4b9..dccf41f9b86bc7 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 e7aa6be63cf979..5a693bd7bc00e4 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 05e276bfa18d91..b1f8ce8b27f247 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 b13cc449379c09..2a4f7a6a74987b 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 e20637ed6a177d..705b7a1c847b99 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 d6344a0b666d79..6af2a73afc12dd 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 699983fa0c38c6..e94d630ba2e957 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 1c3e46304dfa67..0c62c3a2ba62ec 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 f0a10200a5103b..ad51e8c2d4275c 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 6f34f7dcef5f42..0914c0ca7600c2 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 c1c243b8d02306..230bb06bd810ed 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 cb7bd41495f6dc..5a5fd3e8b129f0 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 @@ private static extern bool GetCodeBase(QCallAssembly assembly,
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 @@ private static extern void InternalLoad(ObjectHandleOnStack assemblyName,
// 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 @@ private static extern void InternalLoad(ObjectHandleOnStack assemblyName,
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 a85a2226265b88..a5aad806bf07fa 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 8538e63c068801..a6351198a2c595 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 60e38832295192..511db52edc1020 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 e421e15aadd00b..06f02a3d0da95e 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 a6e9461a475ae6..f39b4db15a4377 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 968664489d8909..4e729c8733964b 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 d5f60df957c8bc..1b86b463802048 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 558ac0c33471b3..691171f3af91cb 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 b768bc2a588a25..9c8acf346ff424 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 00000000000000..f690a6cddc8ead
--- /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 348279b5b69110..3a4697a96da2bd 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 b572e6cb3764bf..2f27df72e1cbc0 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 36a1e8326aff72..bbc7e055f2661a 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 410c57264c02bf..917aa9420349e7 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 31d7c208ebaf01..d5667a2b1c90c2 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 3517306b959a7f..da396f145bfe05 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 26e2e15f375718..3a5cfaa7f5b5bf 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 ff268b787e440d..d5dc33be71cf71 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 4b5d4a7ca31684..c1207a4b5b2f00 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 ReadyToRunCodegenCompilationBuilder(
((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 d5418516e1cd16..afae84f57f6fac 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 4b1fc1af499083..7959568995ac49 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 b3b381b2f9bef4..4b6bd668033202 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 6b4f71f2455308..6e32957944d136 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 c5a9d98ac6e4e2..8540e907ffb455 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 81116102682c62..963ee161605540 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 d6dbe8e7b40ba7..f71511cbb9ac3d 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 c6d1b6d2f1eddd..3dd1c44aa26498 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 1c250c7d40a091..9f1f9624941a57 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 51c87fa8d678e3..692c35eb6dae7e 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 feb9ed94f7e1f3..c231cc865ccaea 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 6bea537f1c8e1e..ec2aef0cc03987 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 20f5cbfaf72799..75f78f55d62e36 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 cf2803dec9375b..0253d59e09c22f 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 80fbbace5b58a9..85fb5c7691a9e4 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 c1bb1854ff1ba1..d44f9bcfdd6614 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 2e90117f462b4c..1964e8ef8b8f92 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 23046099e10ada..00000000000000
--- 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 8d90792dd6ffe1..8f8f7feae0fbb3 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 294956a5e737ee..5ea29116ca2d9b 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 EnvironmentVariablesConfigurationProvider(string prefix) =>
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 b275c71c780c76..dc32454f1759ac 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 00000000000000..eb381de19d6153
--- /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 3a09880ba32d15..00000000000000
--- 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 b93c0a8e61e66b..7ee51306d042d5 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 e76446a526b4fc..efbb7cc4a7451f 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 a2e02ce4f50010..06bcdf632879ca 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 afe118acf79093..a05e82f8a44986 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 073451c2cd9f08..698e3ec3dd659c 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 8d6a78029fefff..da24dca4e92cf9 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
-
-
-
+
+
+
+
@@ -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 ffee155326a5f1..fbb8ab78b3a630 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 @@ public static explicit operator double(BigInteger value)
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 bb75e77a228d01..de1001d7f4f38f 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 @@ private static unsafe void Divide(uint* left, int leftLength,
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 @@ private static bool DivideGuessTooBig(ulong q, ulong valHi, uint valLo,
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 d984912ec62467..9368891c0428e2 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 ExtractDigits(ref BitsBuffer xBuffer,
}
// 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 9325be0d806c27..8ec356e6dc2153 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 e89bc4acd13e8f..0926f69e2ba685 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 a94b40b28eec0a..380e0a2e7f1009 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 virtual event System.Reflection.ModuleResolveEventHandler? ModuleResolve
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 99a987c5792917..757d8d63d51338 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 @@ internal 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 6de74aef8ec3b6..71ccc3f4b24b32 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 1d0eb05631c47b..87b6953f46765b 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 64e891b5b0f1f1..b4e666bc96b8a5 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 1a90f20a2744ca..bb00474f510fa7 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 d762f2b639fc9d..d90c0685451f3a 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 f67803e79972bc..0bc55ebbffd53b 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 c1a3f16e19ec1c..00000000000000
--- 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 17a7f16890297a..00000000000000
--- 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 6c24d93bbb4860..09f1be0796e397 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 a1ec1ea4bd1c98..4cccee8eede3c0 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 8bffafc8e918d2..022944a2e0e024 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 b54cf42617011d..00000000000000
--- 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 46711d09936571..00000000000000
--- 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 b2c4858b1e1f47..e0baba921e330e 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 e4080b6116eb20..544ebe1b25f332 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 9885f574fc6d80..4ade3e1c90441e 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 54945167821c83..69f17447741d89 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 5862082f7e3ef9..0faa26075e2d7d 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 86ba437fa10287..427767a5fbc5d0 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 d5fa9e4e31d83b..95aed378b17070 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 extern override MethodInfo? EntryPoint
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 692d7ff29926c9..9b92b126780d82 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 91de21bee9b78d..2b6842c11fea65 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 292b723cc351b1..6bce7c5ff2ec1e 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 d87ab17fdab75c..9702920b3c26eb 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 b07e58569160c2..3e9ca497336abf 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 ba1c7ea043c7e2..369016e11892d6 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 f2792e4e6a4e41..3e7a07c17c674a 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 97d1a042c0fd82..cc81ac7b070dcd 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 309ec37c059a77..c6d855fa1b4103 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 36400c7e9fdbbe..bea43f236a65c8 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 2e349a35ed0317..562d98eb5357d6 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 7d24fe6374b6c5..f3cfa3895e67a5 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 e454d89ef41b81..5001ee38ddd091 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 868acaafacb011..00000000000000
--- 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 c1e8ce60bda6c2..c398ca8a2c1208 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 3e791f2f3e057d..e08904a99b6eb8 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 bbb7eb88e7f476..9b4b51c28596d7 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 a28080c4c70f7c..91f369b71be821 100644
--- a/src/mono/wasm/debugger/DebuggerTestSuite/EvaluateOnCallFrameTests.cs
+++ b/src/mono/wasm/debugger/DebuggerTestSuite/EvaluateOnCallFrameTests.cs
@@ -585,6 +585,41 @@ await EvaluateOnCallFrameAndCheck(id,
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 3215ef1184d89c..6b4dcd65900be9 100644
--- a/src/mono/wasm/debugger/DebuggerTestSuite/GetPropertiesTests.cs
+++ b/src/mono/wasm/debugger/DebuggerTestSuite/GetPropertiesTests.cs
@@ -335,6 +335,32 @@ await CheckExpectedProperties(
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 1583ce1fd6f86d..01bdda2868ddde 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 157109c74580c0..2a5d525392fc99 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 @@ await getJsonTask.ContinueWith(t =>
}
}
}
+
+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 89b9c5d70cc7e8..e661a5423a0d2d 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 00000000000000..05da0aed4b2c5b
--- /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 00000000000000..e56efb092cec72
--- /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 7c04e2890f0972..4b3008aa72dd02 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 47e6c3d8060e2c..1cebb6f0730140 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 9997f1d6857fc2..5007ec3c80f0a4 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 4343f56386fa4a..d6cec7a1845e1e 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 b41a83794d99b1..1ba007427185c2 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 007229b8a18805..00000000000000
--- 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 6dca0e8853e8d0..cdcacd6b3eb2a0 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 6fbd95199e0ff8..19910a66d973a0 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 f9af5043b8faf7..858100113ee548 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 adf1ac4b4d7690..95516edb90ef02 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 e2699c214d49ae..9ea4b4cde8a492 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 23b382365b1807..a2b9cc92ce8585 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 abc8374353b6b2..ffbf04eda1d309 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 157d90264bc024..b8d593f7ba87cb 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 00000000000000..aaf5e93661ae3a
--- /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 00000000000000..bb2404d27a6265
--- /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 df4b1934195729..b6bbd047ab37f0 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 8c466d3996f427..abc554b81b9f89 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 00000000000000..8d2221fb2280ca
--- /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 00000000000000..f3e1cbd44b4041
--- /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 00000000000000..a7cf8fe4a455e8
--- /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 00000000000000..7052da0bcb87ed
--- /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 00000000000000..366bd506c1bac4
--- /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 00000000000000..dad19c468a03ae
--- /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 453bc09efcbb24..aac5ffd6fb1646 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 854204fd744fc9..747903cb427adf 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 3289e9c9ee6453..4f17417636d840 100644
--- a/src/tests/run.proj
+++ b/src/tests/run.proj
@@ -601,7 +601,6 @@ namespace $([System.String]::Copy($(Category)).Replace(".","_").Replace("\","").
-