diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json
index 89a0e5a4637dba..2c22fb6b2f0bcb 100644
--- a/.config/dotnet-tools.json
+++ b/.config/dotnet-tools.json
@@ -15,7 +15,7 @@
]
},
"microsoft.dotnet.xharness.cli": {
- "version": "10.0.0-prerelease.25405.1",
+ "version": "10.0.0-prerelease.25506.2",
"commands": [
"xharness"
]
diff --git a/Directory.Build.props b/Directory.Build.props
index 99eee260233d71..21c3a57182edbc 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -269,6 +269,10 @@
$(WarningsNotAsErrors);NU1901;NU1902;NU1903;NU1904
$(NoWarn);CS8500;CS8969
+
+ $(NoWarn);IDE0100
+
+ $(NoWarn);IDE0060
$(NoWarn);CS1591
diff --git a/docs/design/coreclr/jit/viewing-jit-dumps.md b/docs/design/coreclr/jit/viewing-jit-dumps.md
index f5da320507b2c3..3632c3c48a9df6 100644
--- a/docs/design/coreclr/jit/viewing-jit-dumps.md
+++ b/docs/design/coreclr/jit/viewing-jit-dumps.md
@@ -283,7 +283,7 @@ by a third-party disassembler for a particular set of code bytes.
The late disassembler currently is only available in Debug/Checked builds.
-(Note: coredistools is curently version 1.4.0, based on LLVM 17.0.6. The source code is [here](https://github.com/dotnet/jitutils)).
+(Note: coredistools is currently version 1.6.0, based on LLVM 20.1.0. The source code is [here](https://github.com/dotnet/jitutils)).
To invoke the late disassembler, use:
* `DOTNET_JitLateDisasm`={method-list} - output late disassembly for the specified functions. E.g., `DOTNET_JitLateDisasm=Main`,
diff --git a/eng/CodeAnalysis.src.globalconfig b/eng/CodeAnalysis.src.globalconfig
index a4f79c6da3cfc5..e8bd600fafc250 100644
--- a/eng/CodeAnalysis.src.globalconfig
+++ b/eng/CodeAnalysis.src.globalconfig
@@ -1667,7 +1667,7 @@ dotnet_diagnostic.IDE0029.severity = warning
dotnet_diagnostic.IDE0030.severity = warning
# IDE0031: Use null propagation
-dotnet_diagnostic.IDE0031.severity = warning
+dotnet_diagnostic.IDE0031.severity = suggestion
# IDE0032: Use auto property
dotnet_diagnostic.IDE0032.severity = silent
diff --git a/eng/Version.Details.props b/eng/Version.Details.props
index f835914c56a741..a7267e3d8c37d2 100644
--- a/eng/Version.Details.props
+++ b/eng/Version.Details.props
@@ -1,4 +1,3 @@
-
- 10.0.0-preview.6.25302.1
+ 10.0.0-rtm.25502.1
4.9.0-rc2.21473.1
- 19.1.0-alpha.1.25167.1
- 19.1.0-alpha.1.25167.1
- 19.1.0-alpha.1.25167.1
- 19.1.0-alpha.1.25167.1
- 19.1.0-alpha.1.25167.1
- 19.1.0-alpha.1.25167.1
- 19.1.0-alpha.1.25167.1
- 19.1.0-alpha.1.25167.1
- 19.1.0-alpha.1.25167.1
- 19.1.0-alpha.1.25167.1
- 19.1.0-alpha.1.25167.1
- 19.1.0-alpha.1.25167.1
- 19.1.0-alpha.1.25167.1
- 19.1.0-alpha.1.25167.1
- 19.1.0-alpha.1.25167.1
- 19.1.0-alpha.1.25167.1
- 19.1.0-alpha.1.25167.1
- 19.1.0-alpha.1.25167.1
- 19.1.0-alpha.1.25167.1
- 19.1.0-alpha.1.25167.1
- 19.1.0-alpha.1.25167.1
- 19.1.0-alpha.1.25167.1
- 19.1.0-alpha.1.25167.1
- 19.1.0-alpha.1.25167.1
- 19.1.0-alpha.1.25167.1
- 19.1.0-alpha.1.25167.1
- 19.1.0-alpha.1.25167.1
- 19.1.0-alpha.1.25167.1
- 19.1.0-alpha.1.25167.1
+ 19.1.0-alpha.1.25461.1
+ 19.1.0-alpha.1.25461.1
+ 19.1.0-alpha.1.25461.1
+ 19.1.0-alpha.1.25461.1
+ 19.1.0-alpha.1.25461.1
+ 19.1.0-alpha.1.25461.1
+ 19.1.0-alpha.1.25461.1
+ 19.1.0-alpha.1.25461.1
+ 19.1.0-alpha.1.25461.1
+ 19.1.0-alpha.1.25461.1
+ 19.1.0-alpha.1.25461.1
+ 19.1.0-alpha.1.25461.1
+ 19.1.0-alpha.1.25461.1
+ 19.1.0-alpha.1.25461.1
+ 19.1.0-alpha.1.25461.1
+ 19.1.0-alpha.1.25461.1
+ 19.1.0-alpha.1.25461.1
+ 19.1.0-alpha.1.25461.1
+ 19.1.0-alpha.1.25461.1
+ 19.1.0-alpha.1.25461.1
+ 19.1.0-alpha.1.25461.1
+ 19.1.0-alpha.1.25461.1
+ 19.1.0-alpha.1.25461.1
+ 19.1.0-alpha.1.25461.1
+ 19.1.0-alpha.1.25461.1
+ 19.1.0-alpha.1.25461.1
+ 19.1.0-alpha.1.25461.1
+ 19.1.0-alpha.1.25461.1
+ 19.1.0-alpha.1.25461.1
- 5.0.0-2.25414.103
- 5.0.0-2.25414.103
- 5.0.0-2.25414.103
- 10.0.0-preview.25414.103
- 10.0.100-rc.1.25414.103
- 10.0.0-beta.25414.103
- 10.0.0-beta.25414.103
- 10.0.0-beta.25414.103
- 10.0.0-beta.25414.103
- 10.0.0-beta.25414.103
- 10.0.0-beta.25414.103
- 10.0.0-beta.25414.103
- 10.0.0-beta.25414.103
- 0.11.5-alpha.25414.103
- 10.0.0-beta.25414.103
- 10.0.0-beta.25414.103
- 10.0.0-beta.25414.103
- 10.0.0-beta.25414.103
- 10.0.0-beta.25414.103
- 10.0.0-beta.25414.103
- 10.0.0-beta.25414.103
- 10.0.0-beta.25414.103
- 2.9.3-beta.25414.103
- 2.9.3-beta.25414.103
- 10.0.0-beta.25414.103
- 5.0.0-2.25414.103
- 10.0.0-rc.1.25414.103
- 10.0.100-rc.1.25414.103
- 10.0.0-rc.1.25414.103
- 10.0.0-rc.1.25414.103
- 7.0.0-preview.1.42003
- 7.0.0-preview.1.42003
- 7.0.0-preview.1.42003
- 7.0.0-preview.1.42003
- 10.0.0-rc.1.25414.103
- 2.0.0-rc.1.25414.103
- 10.0.0-rc.1.25414.103
- 10.0.0-rc.1.25414.103
- 10.0.0-rc.1.25414.103
+ 5.0.0-2.25509.106
+ 5.0.0-2.25509.106
+ 5.0.0-2.25509.106
+ 10.0.100-rtm.25509.106
+ 10.0.100-rtm.25509.106
+ 10.0.0-beta.25509.106
+ 10.0.0-beta.25509.106
+ 10.0.0-beta.25509.106
+ 10.0.0-beta.25509.106
+ 10.0.0-beta.25509.106
+ 10.0.0-beta.25509.106
+ 10.0.0-beta.25509.106
+ 10.0.0-beta.25509.106
+ 0.11.5-alpha.25509.106
+ 10.0.0-beta.25509.106
+ 10.0.0-beta.25509.106
+ 10.0.0-beta.25509.106
+ 10.0.0-beta.25509.106
+ 10.0.0-beta.25509.106
+ 10.0.0-beta.25509.106
+ 10.0.0-beta.25509.106
+ 10.0.0-beta.25509.106
+ 2.9.3-beta.25509.106
+ 2.9.3-beta.25509.106
+ 10.0.0-beta.25509.106
+ 5.0.0-2.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.100-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 7.0.0-rc.1006
+ 7.0.0-rc.1006
+ 7.0.0-rc.1006
+ 7.0.0-rc.1006
+ 10.0.0-rtm.25509.106
+ 2.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
- 10.0.0-beta.25310.1
- 10.0.0-beta.25310.1
- 10.0.0-beta.25310.1
- 10.0.0-beta.25310.1
- 10.0.0-beta.25310.1
- 10.0.0-beta.25310.1
- 10.0.0-beta.25310.1
- 10.0.0-beta.25310.1
- 10.0.0-beta.25310.1
- 10.0.0-beta.25310.1
- 10.0.0-beta.25310.1
- 10.0.0-beta.25310.1
- 10.0.0-beta.25310.1
- 10.0.0-beta.25310.1
- 10.0.0-beta.25310.1
+ 10.0.0-beta.25418.1
+ 10.0.0-beta.25418.1
+ 10.0.0-beta.25418.1
+ 10.0.0-beta.25418.1
+ 10.0.0-beta.25418.1
+ 10.0.0-beta.25418.1
+ 10.0.0-beta.25418.1
+ 10.0.0-beta.25418.1
+ 10.0.0-beta.25418.1
+ 10.0.0-beta.25418.1
+ 10.0.0-beta.25418.1
+ 10.0.0-beta.25418.1
+ 10.0.0-beta.25418.1
+ 10.0.0-beta.25418.1
+ 10.0.0-beta.25418.1
- 10.0.0-prerelease.25405.1
- 10.0.0-prerelease.25405.1
- 10.0.0-prerelease.25405.1
+ 10.0.0-prerelease.25506.2
+ 10.0.0-prerelease.25506.2
+ 10.0.0-prerelease.25506.2
- 1.0.0-prerelease.25413.5
- 1.0.0-prerelease.25413.5
- 1.0.0-prerelease.25413.5
- 1.0.0-prerelease.25413.5
- 1.0.0-prerelease.25413.5
- 1.0.0-prerelease.25413.5
+ 1.0.0-prerelease.25502.1
+ 1.0.0-prerelease.25502.1
+ 1.0.0-prerelease.25502.1
+ 1.0.0-prerelease.25502.1
+ 1.0.0-prerelease.25502.1
+ 1.0.0-prerelease.25502.1
- 10.0.0-alpha.0.25302.2
+ 10.0.0-alpha.0.25479.2
- 10.0.0-alpha.1.25169.1
- 10.0.0-alpha.1.25169.1
- 10.0.0-alpha.1.25169.1
- 10.0.0-alpha.1.25169.1
- 10.0.0-alpha.1.25169.1
- 10.0.0-alpha.1.25169.1
- 10.0.0-alpha.1.25169.1
- 10.0.0-alpha.1.25169.1
+ 10.0.0-alpha.1.25378.2
+ 10.0.0-alpha.1.25378.2
+ 10.0.0-alpha.1.25378.2
+ 10.0.0-alpha.1.25378.2
+ 10.0.0-alpha.1.25378.2
+ 10.0.0-alpha.1.25378.2
+ 10.0.0-alpha.1.25378.2
+ 10.0.0-alpha.1.25378.2
diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml
index 3ac18f0b9cd027..27c28944cf8fb1 100644
--- a/eng/Version.Details.xml
+++ b/eng/Version.Details.xml
@@ -1,421 +1,421 @@
-
+
-
+
https://github.com/dotnet/icu
- f1c69ff2e9f10ec8d6a2f79acd7632828ce4d137
+ a91b254e70decd379d76338b7bb171ee98301aef
https://github.com/dotnet/wcf
7f504aabb1988e9a093c1e74d8040bd52feb2f01
-
+
https://github.com/dotnet/llvm-project
- da5dd054a531e6fea65643b7e754285b73eab433
+ 2cfe42ea4a7fe364dcb197beca469af8edec0ad6
-
+
https://github.com/dotnet/llvm-project
- da5dd054a531e6fea65643b7e754285b73eab433
+ 2cfe42ea4a7fe364dcb197beca469af8edec0ad6
-
+
https://github.com/dotnet/llvm-project
- da5dd054a531e6fea65643b7e754285b73eab433
+ 2cfe42ea4a7fe364dcb197beca469af8edec0ad6
-
+
https://github.com/dotnet/llvm-project
- da5dd054a531e6fea65643b7e754285b73eab433
+ 2cfe42ea4a7fe364dcb197beca469af8edec0ad6
-
+
https://github.com/dotnet/llvm-project
- da5dd054a531e6fea65643b7e754285b73eab433
+ 2cfe42ea4a7fe364dcb197beca469af8edec0ad6
-
+
https://github.com/dotnet/llvm-project
- da5dd054a531e6fea65643b7e754285b73eab433
+ 2cfe42ea4a7fe364dcb197beca469af8edec0ad6
-
+
https://github.com/dotnet/llvm-project
- da5dd054a531e6fea65643b7e754285b73eab433
+ 2cfe42ea4a7fe364dcb197beca469af8edec0ad6
-
+
https://github.com/dotnet/llvm-project
- da5dd054a531e6fea65643b7e754285b73eab433
+ 2cfe42ea4a7fe364dcb197beca469af8edec0ad6
-
+
https://github.com/dotnet/dotnet
- 5088919af0e4a144ce5b294542f472bf668c9cc8
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+
https://github.com/dotnet/dotnet
- 5088919af0e4a144ce5b294542f472bf668c9cc8
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+
https://github.com/dotnet/dotnet
- 5088919af0e4a144ce5b294542f472bf668c9cc8
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+
https://github.com/dotnet/dotnet
- 5088919af0e4a144ce5b294542f472bf668c9cc8
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+
https://github.com/dotnet/dotnet
- 5088919af0e4a144ce5b294542f472bf668c9cc8
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+
https://github.com/dotnet/dotnet
- 5088919af0e4a144ce5b294542f472bf668c9cc8
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+
https://github.com/dotnet/dotnet
- 5088919af0e4a144ce5b294542f472bf668c9cc8
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+
https://github.com/dotnet/dotnet
- 5088919af0e4a144ce5b294542f472bf668c9cc8
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+
https://github.com/dotnet/dotnet
- 5088919af0e4a144ce5b294542f472bf668c9cc8
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+
https://github.com/dotnet/dotnet
- 5088919af0e4a144ce5b294542f472bf668c9cc8
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+
https://github.com/dotnet/dotnet
- 5088919af0e4a144ce5b294542f472bf668c9cc8
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+
https://github.com/dotnet/dotnet
- 5088919af0e4a144ce5b294542f472bf668c9cc8
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+
https://github.com/dotnet/dotnet
- 5088919af0e4a144ce5b294542f472bf668c9cc8
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+
https://github.com/dotnet/dotnet
- 5088919af0e4a144ce5b294542f472bf668c9cc8
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+
https://github.com/dotnet/dotnet
- 5088919af0e4a144ce5b294542f472bf668c9cc8
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+
https://github.com/dotnet/dotnet
- 5088919af0e4a144ce5b294542f472bf668c9cc8
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+
https://github.com/dotnet/dotnet
- 5088919af0e4a144ce5b294542f472bf668c9cc8
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+
https://github.com/dotnet/dotnet
- 5088919af0e4a144ce5b294542f472bf668c9cc8
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+
https://github.com/dotnet/dotnet
- 5088919af0e4a144ce5b294542f472bf668c9cc8
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+
https://github.com/dotnet/dotnet
- 5088919af0e4a144ce5b294542f472bf668c9cc8
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+
https://github.com/dotnet/dotnet
- 5088919af0e4a144ce5b294542f472bf668c9cc8
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+
https://github.com/dotnet/runtime-assets
- 385d085eb055cabeaed3dde958a900e7b31cf6ce
+ 3910cd6230be3d4d283edd6a52bff27f549dd675
-
+
https://github.com/dotnet/runtime-assets
- 385d085eb055cabeaed3dde958a900e7b31cf6ce
+ 3910cd6230be3d4d283edd6a52bff27f549dd675
-
+
https://github.com/dotnet/runtime-assets
- 385d085eb055cabeaed3dde958a900e7b31cf6ce
+ 3910cd6230be3d4d283edd6a52bff27f549dd675
-
+
https://github.com/dotnet/runtime-assets
- 385d085eb055cabeaed3dde958a900e7b31cf6ce
+ 3910cd6230be3d4d283edd6a52bff27f549dd675
-
+
https://github.com/dotnet/runtime-assets
- 385d085eb055cabeaed3dde958a900e7b31cf6ce
+ 3910cd6230be3d4d283edd6a52bff27f549dd675
-
+
https://github.com/dotnet/runtime-assets
- 385d085eb055cabeaed3dde958a900e7b31cf6ce
+ 3910cd6230be3d4d283edd6a52bff27f549dd675
-
+
https://github.com/dotnet/runtime-assets
- 385d085eb055cabeaed3dde958a900e7b31cf6ce
+ 3910cd6230be3d4d283edd6a52bff27f549dd675
-
+
https://github.com/dotnet/runtime-assets
- 385d085eb055cabeaed3dde958a900e7b31cf6ce
+ 3910cd6230be3d4d283edd6a52bff27f549dd675
-
+
https://github.com/dotnet/runtime-assets
- 385d085eb055cabeaed3dde958a900e7b31cf6ce
+ 3910cd6230be3d4d283edd6a52bff27f549dd675
-
+
https://github.com/dotnet/runtime-assets
- 385d085eb055cabeaed3dde958a900e7b31cf6ce
+ 3910cd6230be3d4d283edd6a52bff27f549dd675
-
+
https://github.com/dotnet/runtime-assets
- 385d085eb055cabeaed3dde958a900e7b31cf6ce
+ 3910cd6230be3d4d283edd6a52bff27f549dd675
-
+
https://github.com/dotnet/runtime-assets
- 385d085eb055cabeaed3dde958a900e7b31cf6ce
+ 3910cd6230be3d4d283edd6a52bff27f549dd675
-
+
https://github.com/dotnet/runtime-assets
- 385d085eb055cabeaed3dde958a900e7b31cf6ce
+ 3910cd6230be3d4d283edd6a52bff27f549dd675
-
+
https://github.com/dotnet/llvm-project
- da5dd054a531e6fea65643b7e754285b73eab433
+ 2cfe42ea4a7fe364dcb197beca469af8edec0ad6
-
+
https://github.com/dotnet/llvm-project
- da5dd054a531e6fea65643b7e754285b73eab433
+ 2cfe42ea4a7fe364dcb197beca469af8edec0ad6
-
+
https://github.com/dotnet/llvm-project
- da5dd054a531e6fea65643b7e754285b73eab433
+ 2cfe42ea4a7fe364dcb197beca469af8edec0ad6
-
+
https://github.com/dotnet/llvm-project
- da5dd054a531e6fea65643b7e754285b73eab433
+ 2cfe42ea4a7fe364dcb197beca469af8edec0ad6
-
+
https://github.com/dotnet/llvm-project
- da5dd054a531e6fea65643b7e754285b73eab433
+ 2cfe42ea4a7fe364dcb197beca469af8edec0ad6
-
+
https://github.com/dotnet/llvm-project
- da5dd054a531e6fea65643b7e754285b73eab433
+ 2cfe42ea4a7fe364dcb197beca469af8edec0ad6
-
+
https://github.com/dotnet/llvm-project
- da5dd054a531e6fea65643b7e754285b73eab433
+ 2cfe42ea4a7fe364dcb197beca469af8edec0ad6
-
+
https://github.com/dotnet/llvm-project
- da5dd054a531e6fea65643b7e754285b73eab433
+ 2cfe42ea4a7fe364dcb197beca469af8edec0ad6
-
+
https://github.com/dotnet/llvm-project
- da5dd054a531e6fea65643b7e754285b73eab433
+ 2cfe42ea4a7fe364dcb197beca469af8edec0ad6
-
+
https://github.com/dotnet/llvm-project
- da5dd054a531e6fea65643b7e754285b73eab433
+ 2cfe42ea4a7fe364dcb197beca469af8edec0ad6
-
+
https://github.com/dotnet/llvm-project
- da5dd054a531e6fea65643b7e754285b73eab433
+ 2cfe42ea4a7fe364dcb197beca469af8edec0ad6
-
+
https://github.com/dotnet/llvm-project
- da5dd054a531e6fea65643b7e754285b73eab433
+ 2cfe42ea4a7fe364dcb197beca469af8edec0ad6
-
+
https://github.com/dotnet/llvm-project
- da5dd054a531e6fea65643b7e754285b73eab433
+ 2cfe42ea4a7fe364dcb197beca469af8edec0ad6
-
+
https://github.com/dotnet/llvm-project
- da5dd054a531e6fea65643b7e754285b73eab433
+ 2cfe42ea4a7fe364dcb197beca469af8edec0ad6
-
+
https://github.com/dotnet/llvm-project
- da5dd054a531e6fea65643b7e754285b73eab433
+ 2cfe42ea4a7fe364dcb197beca469af8edec0ad6
-
+
https://github.com/dotnet/llvm-project
- da5dd054a531e6fea65643b7e754285b73eab433
+ 2cfe42ea4a7fe364dcb197beca469af8edec0ad6
-
+
https://github.com/dotnet/llvm-project
- da5dd054a531e6fea65643b7e754285b73eab433
+ 2cfe42ea4a7fe364dcb197beca469af8edec0ad6
-
+
https://github.com/dotnet/llvm-project
- da5dd054a531e6fea65643b7e754285b73eab433
+ 2cfe42ea4a7fe364dcb197beca469af8edec0ad6
-
+
https://github.com/dotnet/llvm-project
- da5dd054a531e6fea65643b7e754285b73eab433
+ 2cfe42ea4a7fe364dcb197beca469af8edec0ad6
-
+
https://github.com/dotnet/llvm-project
- da5dd054a531e6fea65643b7e754285b73eab433
+ 2cfe42ea4a7fe364dcb197beca469af8edec0ad6
-
+
https://github.com/dotnet/llvm-project
- da5dd054a531e6fea65643b7e754285b73eab433
+ 2cfe42ea4a7fe364dcb197beca469af8edec0ad6
-
+
https://github.com/dotnet/dotnet
- 5088919af0e4a144ce5b294542f472bf668c9cc8
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+
https://github.com/dotnet/dotnet
- 5088919af0e4a144ce5b294542f472bf668c9cc8
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+
https://github.com/dotnet/dotnet
- 5088919af0e4a144ce5b294542f472bf668c9cc8
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+
https://github.com/dotnet/dotnet
- 5088919af0e4a144ce5b294542f472bf668c9cc8
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+
https://github.com/dotnet/dotnet
- 5088919af0e4a144ce5b294542f472bf668c9cc8
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+
https://github.com/dotnet/dotnet
- 5088919af0e4a144ce5b294542f472bf668c9cc8
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+
https://github.com/dotnet/dotnet
- 5088919af0e4a144ce5b294542f472bf668c9cc8
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+
https://github.com/dotnet/xharness
- 4c17e23fcb7575baa9de575e5a96258096cbaea1
+ 5b5722171c6c28f6c9f6b6148f148199b9dd0f5b
-
+
https://github.com/dotnet/xharness
- 4c17e23fcb7575baa9de575e5a96258096cbaea1
+ 5b5722171c6c28f6c9f6b6148f148199b9dd0f5b
-
+
https://github.com/dotnet/xharness
- 4c17e23fcb7575baa9de575e5a96258096cbaea1
+ 5b5722171c6c28f6c9f6b6148f148199b9dd0f5b
-
+
https://github.com/dotnet/dotnet
- 5088919af0e4a144ce5b294542f472bf668c9cc8
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-optimization
- e7f12ca10fc5b13e4ebc33244b585081da7f8bfb
+ 71ce9774e9875270b80faaac1d6b60568a80e1fa
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-optimization
- e7f12ca10fc5b13e4ebc33244b585081da7f8bfb
+ 71ce9774e9875270b80faaac1d6b60568a80e1fa
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-optimization
- e7f12ca10fc5b13e4ebc33244b585081da7f8bfb
+ 71ce9774e9875270b80faaac1d6b60568a80e1fa
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-optimization
- e7f12ca10fc5b13e4ebc33244b585081da7f8bfb
+ 71ce9774e9875270b80faaac1d6b60568a80e1fa
-
+
https://github.com/dotnet/hotreload-utils
- 04c41ac37048c157dafd7793f07340bc701989ce
+ 63256197c9b16908e14ef6ccc6adcf88f0eb843a
-
+
https://github.com/dotnet/runtime-assets
- 385d085eb055cabeaed3dde958a900e7b31cf6ce
+ 3910cd6230be3d4d283edd6a52bff27f549dd675
-
+
https://github.com/dotnet/dotnet
- 5088919af0e4a144ce5b294542f472bf668c9cc8
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+
https://github.com/dotnet/dotnet
- 5088919af0e4a144ce5b294542f472bf668c9cc8
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+
https://github.com/dotnet/dotnet
- 5088919af0e4a144ce5b294542f472bf668c9cc8
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+
https://github.com/dotnet/dotnet
- 5088919af0e4a144ce5b294542f472bf668c9cc8
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+
https://github.com/dotnet/dotnet
- 5088919af0e4a144ce5b294542f472bf668c9cc8
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+
https://github.com/dotnet/dotnet
- 5088919af0e4a144ce5b294542f472bf668c9cc8
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-optimization
- e7f12ca10fc5b13e4ebc33244b585081da7f8bfb
+ 71ce9774e9875270b80faaac1d6b60568a80e1fa
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-optimization
- e7f12ca10fc5b13e4ebc33244b585081da7f8bfb
+ 71ce9774e9875270b80faaac1d6b60568a80e1fa
-
+
https://github.com/dotnet/dotnet
- 5088919af0e4a144ce5b294542f472bf668c9cc8
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+
https://github.com/dotnet/dotnet
- 5088919af0e4a144ce5b294542f472bf668c9cc8
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+
https://github.com/dotnet/dotnet
- 5088919af0e4a144ce5b294542f472bf668c9cc8
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+
https://github.com/dotnet/dotnet
- 5088919af0e4a144ce5b294542f472bf668c9cc8
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+
https://github.com/dotnet/node
- 7f33d14aae0d91f2d5befda939160177e13b3f47
+ b33c02ba2bb3cdd585f5da9198305915fa4451ee
-
+
https://github.com/dotnet/node
- 7f33d14aae0d91f2d5befda939160177e13b3f47
+ b33c02ba2bb3cdd585f5da9198305915fa4451ee
-
+
https://github.com/dotnet/node
- 7f33d14aae0d91f2d5befda939160177e13b3f47
+ b33c02ba2bb3cdd585f5da9198305915fa4451ee
-
+
https://github.com/dotnet/node
- 7f33d14aae0d91f2d5befda939160177e13b3f47
+ b33c02ba2bb3cdd585f5da9198305915fa4451ee
-
+
https://github.com/dotnet/node
- 7f33d14aae0d91f2d5befda939160177e13b3f47
+ b33c02ba2bb3cdd585f5da9198305915fa4451ee
-
+
https://github.com/dotnet/node
- 7f33d14aae0d91f2d5befda939160177e13b3f47
+ b33c02ba2bb3cdd585f5da9198305915fa4451ee
-
+
https://github.com/dotnet/node
- 7f33d14aae0d91f2d5befda939160177e13b3f47
+ b33c02ba2bb3cdd585f5da9198305915fa4451ee
-
+
https://github.com/dotnet/node
- 7f33d14aae0d91f2d5befda939160177e13b3f47
+ b33c02ba2bb3cdd585f5da9198305915fa4451ee
-
+
https://github.com/dotnet/runtime-assets
- 385d085eb055cabeaed3dde958a900e7b31cf6ce
+ 3910cd6230be3d4d283edd6a52bff27f549dd675
diff --git a/eng/Versions.props b/eng/Versions.props
index d61001668130e5..817c41269fc73a 100644
--- a/eng/Versions.props
+++ b/eng/Versions.props
@@ -12,8 +12,8 @@
8.0.$([MSBuild]::Add($([System.Version]::Parse('$(PackageVersionNet9)').Build),11))
7.0.20
6.0.36
- rc
- 1
+ rtm
+
false
release
@@ -56,7 +56,7 @@
Source-build builds the product with the most recent previously source-built release. Thankfully, these two requirements line up nicely
such that any version that satisfies the VS version requirement will also satisfy the .NET SDK version requirement because of how we ship.
-->
- 4.8.0
+ 4.14.0
3.3.5-beta1.23270.2
@@ -97,6 +97,7 @@
7.0.0
8.0.0
+ 6.0.1
4.5.1
8.0.0
4.5.5
@@ -120,7 +121,7 @@
7.0.412701
6.0
- 1.5.0
+ 1.6.0
17.4.0-preview-20220707-01
3.12.0
4.5.0
@@ -146,9 +147,9 @@
10.2.0
17.0.46
- 9.0.0-preview-20241010.1
+ 10.0.0-preview-20250912.1
- 2.4.8
+ 2.4.16
9.0.0-alpha.1.24167.3
- $(MicrosoftDotNetApiCompatTaskVersion)
+ 10.0.100-rc.2.25501.103
10.0.0-preview.7.25359.101
$(runtimewinx64MicrosoftNETCoreRuntimeWasmNodeTransportPackageVersion)
3.1.56
+
+ 5.0.2-dotnet.2737382
+ 5.0.2-dotnet.2737382
+ 5.0.2-dotnet.2737382
+ 5.0.2-dotnet.2737382
+ 5.0.2-dotnet.2737382
+ 5.0.2-dotnet.2737382
diff --git a/eng/build.ps1 b/eng/build.ps1
index f642b35f228900..52977efcecfbbb 100644
--- a/eng/build.ps1
+++ b/eng/build.ps1
@@ -24,6 +24,8 @@ Param(
[string]$cmakeargs,
[switch]$pgoinstrument,
[string[]]$fsanitize,
+ [switch]$bootstrap,
+ [switch]$useBoostrap,
[Parameter(ValueFromRemainingArguments=$true)][String[]]$properties
)
@@ -57,6 +59,8 @@ function Get-Help() {
Write-Host " -usemonoruntime Product a .NET runtime with Mono as the underlying runtime."
Write-Host " -verbosity (-v) MSBuild verbosity: q[uiet], m[inimal], n[ormal], d[etailed], and diag[nostic]."
Write-Host " [Default: Minimal]"
+ Write-Host " --useBootstrap Use the results of building the bootstrap subset to build published tools on the target machine."
+ Write-Host " --bootstrap Build the bootstrap subset and then build the repo with --use-bootstrap."
Write-Host " -vs Open the solution with Visual Studio using the locally acquired SDK."
Write-Host " Path or any project or solution name is accepted."
Write-Host " (Example: -vs Microsoft.CSharp or -vs CoreCLR.sln)"
@@ -330,6 +334,7 @@ foreach ($argument in $PSBoundParameters.Keys)
"configuration" {}
"arch" {}
"fsanitize" { $arguments += " /p:EnableNativeSanitizers=$($PSBoundParameters[$argument])"}
+ "useBootstrap" { $arguments += " /p:UseBootstrap=$($PSBoundParameters[$argument])" }
default { $arguments += " /p:$argument=$($PSBoundParameters[$argument])" }
}
}
@@ -345,6 +350,49 @@ $arguments += " /tl:false"
# The later changes are ignored when using the cache.
$env:DOTNETSDK_ALLOW_TARGETING_PACK_CACHING=0
+if ($bootstrap -eq $True) {
+
+ if ($actionPassedIn) {
+ # Filter out all actions
+ $bootstrapArguments = $(($arguments -split ' ') | Where-Object {
+ $_ -notmatch '^/p:(' + ($actionPassedIn -join '|') + ')=.*'
+ }) -join ' '
+
+ # Preserve Restore and Build if they're passed in
+ if ($arguments -match "/p:Restore=true") {
+ $bootstrapArguments += "/p:Restore=true"
+ }
+ if ($arguments -match "/p:Build=true") {
+ $bootstrapArguments += "/p:Build=true"
+ }
+ } else {
+ $bootstrapArguments = $arguments
+ }
+
+ if ($configuration.Count -gt 1) {
+ Write-Error "Building the bootstrap build does not support multiple configurations. Please specify a single configuration using -configuration."
+ exit 1
+ }
+
+ if ($arch.Count -gt 1) {
+ Write-Error "Building the bootstrap build does not support multiple architectures. Please specify a single architecture using -arch."
+ exit 1
+ }
+
+ $bootstrapArguments += " /p:TargetArchitecture=$($arch[0])"
+ $config = $((Get-Culture).TextInfo.ToTitleCase($configuration[0]))
+ $bootstrapArguments += " -configuration $config"
+
+ $bootstrapArguments += " /p:Subset=bootstrap /bl:$PSScriptRoot/../artifacts/log/$config/bootstrap.binlog"
+ Invoke-Expression "& `"$PSScriptRoot/common/build.ps1`" $bootstrapArguments"
+
+ # Remove artifacts from the bootstrap build so the product build is a "clean" build.
+ Write-Host "Cleaning up artifacts from bootstrap build..."
+ Remove-Item -Recurse "$PSScriptRoot/../artifacts/bin"
+ Remove-Item -Recurse "$PSScriptRoot/../artifacts/obj"
+ $arguments += " /p:UseBootstrap=true"
+}
+
$failedBuilds = @()
foreach ($config in $configuration) {
diff --git a/eng/build.sh b/eng/build.sh
index 2a79304978faae..2fb64c61ff2a7f 100755
--- a/eng/build.sh
+++ b/eng/build.sh
@@ -159,6 +159,7 @@ extraargs=()
crossBuild=0
portableBuild=1
bootstrap=0
+bootstrapConfig='Debug'
source $scriptroot/common/native/init-os-and-arch.sh
@@ -241,6 +242,7 @@ while [[ $# > 0 ]]; do
exit 1
;;
esac
+ bootstrapConfig=$val
arguments+=("-configuration" "$val")
shift 2
;;
@@ -598,7 +600,7 @@ if [[ "$bootstrap" == "1" ]]; then
bootstrapArguments+=("$argument")
fi
done
- "$scriptroot/common/build.sh" ${bootstrapArguments[@]+"${bootstrapArguments[@]}"} /p:Subset=bootstrap -bl:$scriptroot/../artifacts/log/bootstrap.binlog
+ "$scriptroot/common/build.sh" ${bootstrapArguments[@]+"${bootstrapArguments[@]}"} /p:Subset=bootstrap -bl:$scriptroot/../artifacts/log/$bootstrapConfig/bootstrap.binlog
# Remove artifacts from the bootstrap build so the product build is a "clean" build.
echo "Cleaning up artifacts from bootstrap build..."
diff --git a/eng/common/SetupNugetSources.ps1 b/eng/common/SetupNugetSources.ps1
index 5db4ad71ee2f3e..9445c3143258d7 100644
--- a/eng/common/SetupNugetSources.ps1
+++ b/eng/common/SetupNugetSources.ps1
@@ -10,8 +10,8 @@
# displayName: Setup Private Feeds Credentials
# condition: eq(variables['Agent.OS'], 'Windows_NT')
# inputs:
-# filePath: $(Build.SourcesDirectory)/eng/common/SetupNugetSources.ps1
-# arguments: -ConfigFile $(Build.SourcesDirectory)/NuGet.config -Password $Env:Token
+# filePath: $(System.DefaultWorkingDirectory)/eng/common/SetupNugetSources.ps1
+# arguments: -ConfigFile $(System.DefaultWorkingDirectory)/NuGet.config -Password $Env:Token
# env:
# Token: $(dn-bot-dnceng-artifact-feeds-rw)
#
@@ -157,7 +157,7 @@ if ($dotnet31Source -ne $null) {
AddPackageSource -Sources $sources -SourceName "dotnet3.1-internal-transport" -SourceEndPoint "https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3.1-internal-transport/nuget/v2" -Creds $creds -Username $userName -pwd $Password
}
-$dotnetVersions = @('5','6','7','8','9')
+$dotnetVersions = @('5','6','7','8','9','10')
foreach ($dotnetVersion in $dotnetVersions) {
$feedPrefix = "dotnet" + $dotnetVersion;
diff --git a/eng/common/SetupNugetSources.sh b/eng/common/SetupNugetSources.sh
index 4604b61b0323ae..ddf4efc81a4a34 100755
--- a/eng/common/SetupNugetSources.sh
+++ b/eng/common/SetupNugetSources.sh
@@ -11,8 +11,8 @@
# - task: Bash@3
# displayName: Setup Internal Feeds
# inputs:
-# filePath: $(Build.SourcesDirectory)/eng/common/SetupNugetSources.sh
-# arguments: $(Build.SourcesDirectory)/NuGet.config
+# filePath: $(System.DefaultWorkingDirectory)/eng/common/SetupNugetSources.sh
+# arguments: $(System.DefaultWorkingDirectory)/NuGet.config
# condition: ne(variables['Agent.OS'], 'Windows_NT')
# - task: NuGetAuthenticate@1
#
@@ -99,7 +99,7 @@ if [ "$?" == "0" ]; then
PackageSources+=('dotnet3.1-internal-transport')
fi
-DotNetVersions=('5' '6' '7' '8' '9')
+DotNetVersions=('5' '6' '7' '8' '9' '10')
for DotNetVersion in ${DotNetVersions[@]} ; do
FeedPrefix="dotnet${DotNetVersion}";
diff --git a/eng/common/core-templates/job/job.yml b/eng/common/core-templates/job/job.yml
index d9013251542c73..5ce51840619888 100644
--- a/eng/common/core-templates/job/job.yml
+++ b/eng/common/core-templates/job/job.yml
@@ -163,7 +163,7 @@ jobs:
inputs:
testResultsFormat: 'xUnit'
testResultsFiles: '*.xml'
- searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)'
+ searchFolder: '$(System.DefaultWorkingDirectory)/artifacts/TestResults/$(_BuildConfig)'
testRunTitle: ${{ coalesce(parameters.testRunTitle, parameters.name, '$(System.JobName)') }}-xunit
mergeTestResults: ${{ parameters.mergeTestResults }}
continueOnError: true
@@ -174,7 +174,7 @@ jobs:
inputs:
testResultsFormat: 'VSTest'
testResultsFiles: '*.trx'
- searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)'
+ searchFolder: '$(System.DefaultWorkingDirectory)/artifacts/TestResults/$(_BuildConfig)'
testRunTitle: ${{ coalesce(parameters.testRunTitle, parameters.name, '$(System.JobName)') }}-trx
mergeTestResults: ${{ parameters.mergeTestResults }}
continueOnError: true
@@ -218,7 +218,7 @@ jobs:
- task: CopyFiles@2
displayName: Gather buildconfiguration for build retry
inputs:
- SourceFolder: '$(Build.SourcesDirectory)/eng/common/BuildConfiguration'
+ SourceFolder: '$(System.DefaultWorkingDirectory)/eng/common/BuildConfiguration'
Contents: '**'
TargetFolder: '$(Build.ArtifactStagingDirectory)/eng/common/BuildConfiguration'
continueOnError: true
diff --git a/eng/common/core-templates/job/onelocbuild.yml b/eng/common/core-templates/job/onelocbuild.yml
index 8bf7d23355bc5e..c5788829a872e5 100644
--- a/eng/common/core-templates/job/onelocbuild.yml
+++ b/eng/common/core-templates/job/onelocbuild.yml
@@ -8,7 +8,7 @@ parameters:
CeapexPat: $(dn-bot-ceapex-package-r) # PAT for the loc AzDO instance https://dev.azure.com/ceapex
GithubPat: $(BotAccount-dotnet-bot-repo-PAT)
- SourcesDirectory: $(Build.SourcesDirectory)
+ SourcesDirectory: $(System.DefaultWorkingDirectory)
CreatePr: true
AutoCompletePr: false
ReusePr: true
@@ -68,7 +68,7 @@ jobs:
- ${{ if ne(parameters.SkipLocProjectJsonGeneration, 'true') }}:
- task: Powershell@2
inputs:
- filePath: $(Build.SourcesDirectory)/eng/common/generate-locproject.ps1
+ filePath: $(System.DefaultWorkingDirectory)/eng/common/generate-locproject.ps1
arguments: $(_GenerateLocProjectArguments)
displayName: Generate LocProject.json
condition: ${{ parameters.condition }}
@@ -103,7 +103,7 @@ jobs:
- task: CopyFiles@2
displayName: Copy LocProject.json
inputs:
- SourceFolder: '$(Build.SourcesDirectory)/eng/Localize/'
+ SourceFolder: '$(System.DefaultWorkingDirectory)/eng/Localize/'
Contents: 'LocProject.json'
TargetFolder: '$(Build.ArtifactStagingDirectory)/loc'
condition: ${{ parameters.condition }}
diff --git a/eng/common/core-templates/job/publish-build-assets.yml b/eng/common/core-templates/job/publish-build-assets.yml
index d5303229c97e27..37dff559fc1b9a 100644
--- a/eng/common/core-templates/job/publish-build-assets.yml
+++ b/eng/common/core-templates/job/publish-build-assets.yml
@@ -38,6 +38,10 @@ parameters:
# Optional: A minimatch pattern for the asset manifests to publish to BAR
assetManifestsPattern: '*/manifests/**/*.xml'
+ repositoryAlias: self
+
+ officialBuildId: ''
+
jobs:
- job: Asset_Registry_Publish
@@ -60,6 +64,11 @@ jobs:
value: false
# unconditional - needed for logs publishing (redactor tool version)
- template: /eng/common/core-templates/post-build/common-variables.yml
+ - name: OfficialBuildId
+ ${{ if ne(parameters.officialBuildId, '') }}:
+ value: ${{ parameters.officialBuildId }}
+ ${{ else }}:
+ value: $(Build.BuildNumber)
pool:
# We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com)
@@ -78,7 +87,7 @@ jobs:
- 'Illegal entry point, is1ESPipeline is not defined. Repository yaml should not directly reference templates in core-templates folder.': error
- ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}:
- - checkout: self
+ - checkout: ${{ parameters.repositoryAlias }}
fetchDepth: 3
clean: true
@@ -117,12 +126,12 @@ jobs:
azureSubscription: "Darc: Maestro Production"
scriptType: ps
scriptLocation: scriptPath
- scriptPath: $(Build.SourcesDirectory)/eng/common/sdk-task.ps1
+ scriptPath: $(System.DefaultWorkingDirectory)/eng/common/sdk-task.ps1
arguments: -task PublishBuildAssets -restore -msbuildEngine dotnet
/p:ManifestsPath='$(Build.StagingDirectory)/AssetManifests'
/p:IsAssetlessBuild=${{ parameters.isAssetlessBuild }}
/p:MaestroApiEndpoint=https://maestro.dot.net
- /p:OfficialBuildId=$(Build.BuildNumber)
+ /p:OfficialBuildId=$(OfficialBuildId)
condition: ${{ parameters.condition }}
continueOnError: ${{ parameters.continueOnError }}
@@ -137,7 +146,7 @@ jobs:
Add-Content -Path $filePath -Value "$(DefaultChannels)"
Add-Content -Path $filePath -Value $(IsStableBuild)
- $symbolExclusionfile = "$(Build.SourcesDirectory)/eng/SymbolPublishingExclusionsFile.txt"
+ $symbolExclusionfile = "$(System.DefaultWorkingDirectory)/eng/SymbolPublishingExclusionsFile.txt"
if (Test-Path -Path $symbolExclusionfile)
{
Write-Host "SymbolExclusionFile exists"
@@ -177,7 +186,7 @@ jobs:
azureSubscription: "Darc: Maestro Production"
scriptType: ps
scriptLocation: scriptPath
- scriptPath: $(Build.SourcesDirectory)/eng/common/post-build/publish-using-darc.ps1
+ scriptPath: $(System.DefaultWorkingDirectory)/eng/common/post-build/publish-using-darc.ps1
arguments: >
-BuildId $(BARBuildId)
-PublishingInfraVersion 3
diff --git a/eng/common/core-templates/jobs/codeql-build.yml b/eng/common/core-templates/jobs/codeql-build.yml
index 693b00b370447b..dbc14ac580a271 100644
--- a/eng/common/core-templates/jobs/codeql-build.yml
+++ b/eng/common/core-templates/jobs/codeql-build.yml
@@ -24,7 +24,7 @@ jobs:
- name: DefaultGuardianVersion
value: 0.109.0
- name: GuardianPackagesConfigFile
- value: $(Build.SourcesDirectory)\eng\common\sdl\packages.config
+ value: $(System.DefaultWorkingDirectory)\eng\common\sdl\packages.config
- name: GuardianVersion
value: ${{ coalesce(parameters.overrideGuardianVersion, '$(DefaultGuardianVersion)') }}
diff --git a/eng/common/core-templates/jobs/jobs.yml b/eng/common/core-templates/jobs/jobs.yml
index 2f992b2c6eccbd..01ada747665145 100644
--- a/eng/common/core-templates/jobs/jobs.yml
+++ b/eng/common/core-templates/jobs/jobs.yml
@@ -43,6 +43,8 @@ parameters:
artifacts: {}
is1ESPipeline: ''
+ repositoryAlias: self
+ officialBuildId: ''
# Internal resources (telemetry, microbuild) can only be accessed from non-public projects,
# and some (Microbuild) should only be applied to non-PR cases for internal builds.
@@ -114,3 +116,5 @@ jobs:
enablePublishBuildArtifacts: ${{ parameters.enablePublishBuildArtifacts }}
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
signingValidationAdditionalParameters: ${{ parameters.signingValidationAdditionalParameters }}
+ repositoryAlias: ${{ parameters.repositoryAlias }}
+ officialBuildId: ${{ parameters.officialBuildId }}
diff --git a/eng/common/core-templates/post-build/post-build.yml b/eng/common/core-templates/post-build/post-build.yml
index a151fd811e3e48..f6f87fe5c675d9 100644
--- a/eng/common/core-templates/post-build/post-build.yml
+++ b/eng/common/core-templates/post-build/post-build.yml
@@ -154,7 +154,7 @@ stages:
- task: PowerShell@2
displayName: Validate
inputs:
- filePath: $(Build.SourcesDirectory)/eng/common/post-build/nuget-validation.ps1
+ filePath: $(System.DefaultWorkingDirectory)/eng/common/post-build/nuget-validation.ps1
arguments: -PackagesPath $(Build.ArtifactStagingDirectory)/PackageArtifacts/
- job:
@@ -208,7 +208,7 @@ stages:
filePath: eng\common\sdk-task.ps1
arguments: -task SigningValidation -restore -msbuildEngine vs
/p:PackageBasePath='$(Build.ArtifactStagingDirectory)/PackageArtifacts'
- /p:SignCheckExclusionsFile='$(Build.SourcesDirectory)/eng/SignCheckExclusionsFile.txt'
+ /p:SignCheckExclusionsFile='$(System.DefaultWorkingDirectory)/eng/SignCheckExclusionsFile.txt'
${{ parameters.signingValidationAdditionalParameters }}
- template: /eng/common/core-templates/steps/publish-logs.yml
@@ -258,7 +258,7 @@ stages:
- task: PowerShell@2
displayName: Validate
inputs:
- filePath: $(Build.SourcesDirectory)/eng/common/post-build/sourcelink-validation.ps1
+ filePath: $(System.DefaultWorkingDirectory)/eng/common/post-build/sourcelink-validation.ps1
arguments: -InputPath $(Build.ArtifactStagingDirectory)/BlobArtifacts/
-ExtractPath $(Agent.BuildDirectory)/Extract/
-GHRepoName $(Build.Repository.Name)
@@ -313,7 +313,7 @@ stages:
azureSubscription: "Darc: Maestro Production"
scriptType: ps
scriptLocation: scriptPath
- scriptPath: $(Build.SourcesDirectory)/eng/common/post-build/publish-using-darc.ps1
+ scriptPath: $(System.DefaultWorkingDirectory)/eng/common/post-build/publish-using-darc.ps1
arguments: >
-BuildId $(BARBuildId)
-PublishingInfraVersion ${{ parameters.publishingInfraVersion }}
diff --git a/eng/common/core-templates/post-build/setup-maestro-vars.yml b/eng/common/core-templates/post-build/setup-maestro-vars.yml
index f7602980dbe721..a7abd58c4bb609 100644
--- a/eng/common/core-templates/post-build/setup-maestro-vars.yml
+++ b/eng/common/core-templates/post-build/setup-maestro-vars.yml
@@ -36,7 +36,7 @@ steps:
$AzureDevOpsBuildId = $Env:Build_BuildId
}
else {
- . $(Build.SourcesDirectory)\eng\common\tools.ps1
+ . $(System.DefaultWorkingDirectory)\eng\common\tools.ps1
$darc = Get-Darc
$buildInfo = & $darc get-build `
--id ${{ parameters.BARBuildId }} `
diff --git a/eng/common/core-templates/steps/enable-internal-sources.yml b/eng/common/core-templates/steps/enable-internal-sources.yml
index 64f881bffc3cf1..4085512b690910 100644
--- a/eng/common/core-templates/steps/enable-internal-sources.yml
+++ b/eng/common/core-templates/steps/enable-internal-sources.yml
@@ -17,8 +17,8 @@ steps:
- task: PowerShell@2
displayName: Setup Internal Feeds
inputs:
- filePath: $(Build.SourcesDirectory)/eng/common/SetupNugetSources.ps1
- arguments: -ConfigFile $(Build.SourcesDirectory)/NuGet.config -Password $Env:Token
+ filePath: $(System.DefaultWorkingDirectory)/eng/common/SetupNugetSources.ps1
+ arguments: -ConfigFile $(System.DefaultWorkingDirectory)/NuGet.config -Password $Env:Token
env:
Token: ${{ parameters.legacyCredential }}
# If running on dnceng (internal project), just use the default behavior for NuGetAuthenticate.
@@ -29,8 +29,8 @@ steps:
- task: PowerShell@2
displayName: Setup Internal Feeds
inputs:
- filePath: $(Build.SourcesDirectory)/eng/common/SetupNugetSources.ps1
- arguments: -ConfigFile $(Build.SourcesDirectory)/NuGet.config
+ filePath: $(System.DefaultWorkingDirectory)/eng/common/SetupNugetSources.ps1
+ arguments: -ConfigFile $(System.DefaultWorkingDirectory)/NuGet.config
- ${{ else }}:
- template: /eng/common/templates/steps/get-federated-access-token.yml
parameters:
@@ -39,8 +39,8 @@ steps:
- task: PowerShell@2
displayName: Setup Internal Feeds
inputs:
- filePath: $(Build.SourcesDirectory)/eng/common/SetupNugetSources.ps1
- arguments: -ConfigFile $(Build.SourcesDirectory)/NuGet.config -Password $(dnceng-artifacts-feeds-read-access-token)
+ filePath: $(System.DefaultWorkingDirectory)/eng/common/SetupNugetSources.ps1
+ arguments: -ConfigFile $(System.DefaultWorkingDirectory)/NuGet.config -Password $(dnceng-artifacts-feeds-read-access-token)
# This is required in certain scenarios to install the ADO credential provider.
# It installed by default in some msbuild invocations (e.g. VS msbuild), but needs to be installed for others
# (e.g. dotnet msbuild).
diff --git a/eng/common/core-templates/steps/generate-sbom.yml b/eng/common/core-templates/steps/generate-sbom.yml
index 44a9636cdff90a..c05f650279795f 100644
--- a/eng/common/core-templates/steps/generate-sbom.yml
+++ b/eng/common/core-templates/steps/generate-sbom.yml
@@ -6,7 +6,7 @@
parameters:
PackageVersion: 10.0.0
- BuildDropPath: '$(Build.SourcesDirectory)/artifacts'
+ BuildDropPath: '$(System.DefaultWorkingDirectory)/artifacts'
PackageName: '.NET'
ManifestDirPath: $(Build.ArtifactStagingDirectory)/sbom
IgnoreDirectories: ''
diff --git a/eng/common/core-templates/steps/install-microbuild.yml b/eng/common/core-templates/steps/install-microbuild.yml
index da30e67bc34c95..d6b9878f54db7f 100644
--- a/eng/common/core-templates/steps/install-microbuild.yml
+++ b/eng/common/core-templates/steps/install-microbuild.yml
@@ -12,6 +12,7 @@ parameters:
# variable is not available in template expression. _SignType has a very large proliferation across .NET, so replacing it is tough.
microbuildUseESRP: true
# Location of the MicroBuild output folder
+ # NOTE: There's something that relies on this being in the "default" source directory for tasks such as Signing to work properly.
microBuildOutputFolder: '$(Build.SourcesDirectory)'
continueOnError: false
@@ -46,17 +47,19 @@ steps:
displayName: 'Validate ESRP usage (Non-Windows)'
condition: and(succeeded(), ne(variables['Agent.Os'], 'Windows_NT'))
+ # Two different MB install steps. This is due to not being able to use the agent OS during
+ # YAML expansion, and Windows vs. Linux/Mac uses different service connections. However,
+ # we can avoid including the MB install step if not enabled at all. This avoids a bunch of
+ # extra pipeline authorizations, since most pipelines do not sign on non-Windows.
- task: MicroBuildSigningPlugin@4
- displayName: Install MicroBuild plugin
+ displayName: Install MicroBuild plugin (Windows)
inputs:
signType: $(_SignType)
zipSources: false
feedSource: https://dnceng.pkgs.visualstudio.com/_packaging/MicroBuildToolset/nuget/v3/index.json
${{ if eq(parameters.microbuildUseESRP, true) }}:
- ${{ if eq(parameters.enableMicrobuildForMacAndLinux, 'true') }}:
- azureSubscription: 'MicroBuild Signing Task (DevDiv)'
- useEsrpCli: true
- ${{ elseif eq(variables['System.TeamProject'], 'DevDiv') }}:
+ ConnectedServiceName: 'MicroBuild Signing Task (DevDiv)'
+ ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}:
ConnectedPMEServiceName: 6cc74545-d7b9-4050-9dfa-ebefcc8961ea
${{ else }}:
ConnectedPMEServiceName: 248d384a-b39b-46e3-8ad5-c2c210d5e7ca
@@ -65,16 +68,24 @@ steps:
MicroBuildOutputFolderOverride: ${{ parameters.microBuildOutputFolder }}
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
continueOnError: ${{ parameters.continueOnError }}
- condition: and(
- succeeded(),
- or(
- and(
- eq(variables['Agent.Os'], 'Windows_NT'),
- in(variables['_SignType'], 'real', 'test')
- ),
- and(
- ${{ eq(parameters.enableMicrobuildForMacAndLinux, true) }},
- ne(variables['Agent.Os'], 'Windows_NT'),
- eq(variables['_SignType'], 'real')
- )
- ))
+ condition: and(succeeded(), eq(variables['Agent.Os'], 'Windows_NT'), in(variables['_SignType'], 'real', 'test'))
+
+ - ${{ if eq(parameters.enableMicrobuildForMacAndLinux, true) }}:
+ - task: MicroBuildSigningPlugin@4
+ displayName: Install MicroBuild plugin (non-Windows)
+ inputs:
+ signType: $(_SignType)
+ zipSources: false
+ feedSource: https://dnceng.pkgs.visualstudio.com/_packaging/MicroBuildToolset/nuget/v3/index.json
+ ${{ if eq(parameters.microbuildUseESRP, true) }}:
+ ConnectedServiceName: 'MicroBuild Signing Task (DevDiv)'
+ ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}:
+ ConnectedPMEServiceName: beb8cb23-b303-4c95-ab26-9e44bc958d39
+ ${{ else }}:
+ ConnectedPMEServiceName: c24de2a5-cc7a-493d-95e4-8e5ff5cad2bc
+ env:
+ TeamName: $(_TeamName)
+ MicroBuildOutputFolderOverride: ${{ parameters.microBuildOutputFolder }}
+ SYSTEM_ACCESSTOKEN: $(System.AccessToken)
+ continueOnError: ${{ parameters.continueOnError }}
+ condition: and(succeeded(), ne(variables['Agent.Os'], 'Windows_NT'), eq(variables['_SignType'], 'real'))
diff --git a/eng/common/core-templates/steps/publish-logs.yml b/eng/common/core-templates/steps/publish-logs.yml
index de24d0087c58bb..10f825e270a03b 100644
--- a/eng/common/core-templates/steps/publish-logs.yml
+++ b/eng/common/core-templates/steps/publish-logs.yml
@@ -12,22 +12,22 @@ steps:
inputs:
targetType: inline
script: |
- New-Item -ItemType Directory $(Build.SourcesDirectory)/PostBuildLogs/${{parameters.StageLabel}}/${{parameters.JobLabel}}/
- Move-Item -Path $(Build.SourcesDirectory)/artifacts/log/Debug/* $(Build.SourcesDirectory)/PostBuildLogs/${{parameters.StageLabel}}/${{parameters.JobLabel}}/
+ New-Item -ItemType Directory $(System.DefaultWorkingDirectory)/PostBuildLogs/${{parameters.StageLabel}}/${{parameters.JobLabel}}/
+ Move-Item -Path $(System.DefaultWorkingDirectory)/artifacts/log/Debug/* $(System.DefaultWorkingDirectory)/PostBuildLogs/${{parameters.StageLabel}}/${{parameters.JobLabel}}/
continueOnError: true
condition: always()
- task: PowerShell@2
displayName: Redact Logs
inputs:
- filePath: $(Build.SourcesDirectory)/eng/common/post-build/redact-logs.ps1
+ filePath: $(System.DefaultWorkingDirectory)/eng/common/post-build/redact-logs.ps1
# For now this needs to have explicit list of all sensitive data. Taken from eng/publishing/v3/publish.yml
- # Sensitive data can as well be added to $(Build.SourcesDirectory)/eng/BinlogSecretsRedactionFile.txt'
+ # Sensitive data can as well be added to $(System.DefaultWorkingDirectory)/eng/BinlogSecretsRedactionFile.txt'
# If the file exists - sensitive data for redaction will be sourced from it
# (single entry per line, lines starting with '# ' are considered comments and skipped)
- arguments: -InputPath '$(Build.SourcesDirectory)/PostBuildLogs'
+ arguments: -InputPath '$(System.DefaultWorkingDirectory)/PostBuildLogs'
-BinlogToolVersion ${{parameters.BinlogToolVersion}}
- -TokensFilePath '$(Build.SourcesDirectory)/eng/BinlogSecretsRedactionFile.txt'
+ -TokensFilePath '$(System.DefaultWorkingDirectory)/eng/BinlogSecretsRedactionFile.txt'
'$(publishing-dnceng-devdiv-code-r-build-re)'
'$(MaestroAccessToken)'
'$(dn-bot-all-orgs-artifact-feeds-rw)'
@@ -44,7 +44,7 @@ steps:
- task: CopyFiles@2
displayName: Gather post build logs
inputs:
- SourceFolder: '$(Build.SourcesDirectory)/PostBuildLogs'
+ SourceFolder: '$(System.DefaultWorkingDirectory)/PostBuildLogs'
Contents: '**'
TargetFolder: '$(Build.ArtifactStagingDirectory)/PostBuildLogs'
condition: always()
diff --git a/eng/common/core-templates/steps/source-index-stage1-publish.yml b/eng/common/core-templates/steps/source-index-stage1-publish.yml
index c2917c1efc1cb7..e9a694afa58e66 100644
--- a/eng/common/core-templates/steps/source-index-stage1-publish.yml
+++ b/eng/common/core-templates/steps/source-index-stage1-publish.yml
@@ -1,6 +1,6 @@
parameters:
- sourceIndexUploadPackageVersion: 2.0.0-20250425.2
- sourceIndexProcessBinlogPackageVersion: 1.0.1-20250515.1
+ sourceIndexUploadPackageVersion: 2.0.0-20250818.1
+ sourceIndexProcessBinlogPackageVersion: 1.0.1-20250818.1
sourceIndexPackageSource: https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json
binlogPath: artifacts/log/Debug/Build.binlog
@@ -20,7 +20,7 @@ steps:
# Set working directory to temp directory so 'dotnet' doesn't try to use global.json and use the repo's sdk.
workingDirectory: $(Agent.TempDirectory)
-- script: $(Agent.TempDirectory)/.source-index/tools/BinLogToSln -i ${{parameters.BinlogPath}} -r $(Build.SourcesDirectory) -n $(Build.Repository.Name) -o .source-index/stage1output
+- script: $(Agent.TempDirectory)/.source-index/tools/BinLogToSln -i ${{parameters.BinlogPath}} -r $(System.DefaultWorkingDirectory) -n $(Build.Repository.Name) -o .source-index/stage1output
displayName: "Source Index: Process Binlog into indexable sln"
- ${{ if and(ne(parameters.runAsPublic, 'true'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}:
diff --git a/eng/common/generate-locproject.ps1 b/eng/common/generate-locproject.ps1
index 524aaa57f2b742..fa1cdc2b30076a 100644
--- a/eng/common/generate-locproject.ps1
+++ b/eng/common/generate-locproject.ps1
@@ -33,15 +33,27 @@ $jsonTemplateFiles | ForEach-Object {
$jsonWinformsTemplateFiles = Get-ChildItem -Recurse -Path "$SourcesDirectory" | Where-Object { $_.FullName -Match "en\\strings\.json" } # current winforms pattern
+$wxlFilesV3 = @()
+$wxlFilesV5 = @()
$wxlFiles = Get-ChildItem -Recurse -Path "$SourcesDirectory" | Where-Object { $_.FullName -Match "\\.+\.wxl" -And -Not( $_.Directory.Name -Match "\d{4}" ) } # localized files live in four digit lang ID directories; this excludes them
if (-not $wxlFiles) {
$wxlEnFiles = Get-ChildItem -Recurse -Path "$SourcesDirectory" | Where-Object { $_.FullName -Match "\\1033\\.+\.wxl" } # pick up en files (1033 = en) specifically so we can copy them to use as the neutral xlf files
if ($wxlEnFiles) {
- $wxlFiles = @()
- $wxlEnFiles | ForEach-Object {
- $destinationFile = "$($_.Directory.Parent.FullName)\$($_.Name)"
- $wxlFiles += Copy-Item "$($_.FullName)" -Destination $destinationFile -PassThru
- }
+ $wxlFiles = @()
+ $wxlEnFiles | ForEach-Object {
+ $destinationFile = "$($_.Directory.Parent.FullName)\$($_.Name)"
+ $content = Get-Content $_.FullName -Raw
+
+ # Split files on schema to select different parser settings in the generated project.
+ if ($content -like "*http://wixtoolset.org/schemas/v4/wxl*")
+ {
+ $wxlFilesV5 += Copy-Item $_.FullName -Destination $destinationFile -PassThru
+ }
+ elseif ($content -like "*http://schemas.microsoft.com/wix/2006/localization*")
+ {
+ $wxlFilesV3 += Copy-Item $_.FullName -Destination $destinationFile -PassThru
+ }
+ }
}
}
@@ -114,7 +126,32 @@ $locJson = @{
CloneLanguageSet = "WiX_CloneLanguages"
LssFiles = @( "wxl_loc.lss" )
LocItems = @(
- $wxlFiles | ForEach-Object {
+ $wxlFilesV3 | ForEach-Object {
+ $outputPath = "$($_.Directory.FullName | Resolve-Path -Relative)\"
+ $continue = $true
+ foreach ($exclusion in $exclusions.Exclusions) {
+ if ($_.FullName.Contains($exclusion)) {
+ $continue = $false
+ }
+ }
+ $sourceFile = ($_.FullName | Resolve-Path -Relative)
+ if ($continue)
+ {
+ return @{
+ SourceFile = $sourceFile
+ CopyOption = "LangIDOnPath"
+ OutputPath = $outputPath
+ }
+ }
+ }
+ )
+ },
+ @{
+ LanguageSet = $LanguageSet
+ CloneLanguageSet = "WiX_CloneLanguages"
+ LssFiles = @( "P210WxlSchemaV4.lss" )
+ LocItems = @(
+ $wxlFilesV5 | ForEach-Object {
$outputPath = "$($_.Directory.FullName | Resolve-Path -Relative)\"
$continue = $true
foreach ($exclusion in $exclusions.Exclusions) {
diff --git a/eng/common/post-build/nuget-verification.ps1 b/eng/common/post-build/nuget-verification.ps1
index a365194a938904..ac5c69ffcac59a 100644
--- a/eng/common/post-build/nuget-verification.ps1
+++ b/eng/common/post-build/nuget-verification.ps1
@@ -30,7 +30,7 @@
[CmdletBinding(PositionalBinding = $false)]
param(
[string]$NuGetExePath,
- [string]$PackageSource = "https://api.nuget.org/v3/index.json",
+ [string]$PackageSource = "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public/nuget/v3/index.json",
[string]$DownloadPath,
[Parameter(ValueFromRemainingArguments = $true)]
[string[]]$args
diff --git a/eng/common/sdk-task.ps1 b/eng/common/sdk-task.ps1
index a9d2a2d2699666..b62e132d32a40d 100644
--- a/eng/common/sdk-task.ps1
+++ b/eng/common/sdk-task.ps1
@@ -7,13 +7,14 @@ Param(
[switch] $restore,
[switch] $prepareMachine,
[switch][Alias('nobl')]$excludeCIBinaryLog,
+ [switch]$noWarnAsError,
[switch] $help,
[Parameter(ValueFromRemainingArguments=$true)][String[]]$properties
)
$ci = $true
$binaryLog = if ($excludeCIBinaryLog) { $false } else { $true }
-$warnAsError = $true
+$warnAsError = if ($noWarnAsError) { $false } else { $true }
. $PSScriptRoot\tools.ps1
diff --git a/eng/common/sdk-task.sh b/eng/common/sdk-task.sh
index 2f83adc0269faf..3270f83fa9a76a 100755
--- a/eng/common/sdk-task.sh
+++ b/eng/common/sdk-task.sh
@@ -10,6 +10,7 @@ show_usage() {
echo "Advanced settings:"
echo " --excludeCIBinarylog Don't output binary log (short: -nobl)"
+ echo " --noWarnAsError Do not warn as error"
echo ""
echo "Command line arguments not listed above are passed thru to msbuild."
}
@@ -52,6 +53,7 @@ exclude_ci_binary_log=false
restore=false
help=false
properties=''
+warnAsError=true
while (($# > 0)); do
lowerI="$(echo $1 | tr "[:upper:]" "[:lower:]")"
@@ -73,6 +75,10 @@ while (($# > 0)); do
exclude_ci_binary_log=true
shift 1
;;
+ --noWarnAsError)
+ warnAsError=false
+ shift 1
+ ;;
--help)
help=true
shift 1
@@ -85,7 +91,6 @@ while (($# > 0)); do
done
ci=true
-warnAsError=true
if $help; then
show_usage
diff --git a/eng/common/template-guidance.md b/eng/common/template-guidance.md
index 98bbc1ded0ba88..4bf4cf41bd7c76 100644
--- a/eng/common/template-guidance.md
+++ b/eng/common/template-guidance.md
@@ -50,7 +50,7 @@ extends:
- task: CopyFiles@2
displayName: Gather build output
inputs:
- SourceFolder: '$(Build.SourcesDirectory)/artifacts/marvel'
+ SourceFolder: '$(System.DefaultWorkingDirectory)/artifacts/marvel'
Contents: '**'
TargetFolder: '$(Build.ArtifactStagingDirectory)/artifacts/marvel'
```
diff --git a/eng/common/templates-official/job/job.yml b/eng/common/templates-official/job/job.yml
index a8a94328745823..92a0664f5647d5 100644
--- a/eng/common/templates-official/job/job.yml
+++ b/eng/common/templates-official/job/job.yml
@@ -3,7 +3,7 @@ parameters:
enableSbom: true
runAsPublic: false
PackageVersion: 9.0.0
- BuildDropPath: '$(Build.SourcesDirectory)/artifacts'
+ BuildDropPath: '$(System.DefaultWorkingDirectory)/artifacts'
jobs:
- template: /eng/common/core-templates/job/job.yml
diff --git a/eng/common/templates-official/variables/sdl-variables.yml b/eng/common/templates-official/variables/sdl-variables.yml
index dbdd66d4a4b3a0..f1311bbb1b33d9 100644
--- a/eng/common/templates-official/variables/sdl-variables.yml
+++ b/eng/common/templates-official/variables/sdl-variables.yml
@@ -4,4 +4,4 @@ variables:
- name: DefaultGuardianVersion
value: 0.109.0
- name: GuardianPackagesConfigFile
- value: $(Build.SourcesDirectory)\eng\common\sdl\packages.config
\ No newline at end of file
+ value: $(System.DefaultWorkingDirectory)\eng\common\sdl\packages.config
\ No newline at end of file
diff --git a/eng/common/templates/job/job.yml b/eng/common/templates/job/job.yml
index 7cbf668c22bc04..238fa0818f7b27 100644
--- a/eng/common/templates/job/job.yml
+++ b/eng/common/templates/job/job.yml
@@ -6,7 +6,7 @@ parameters:
enableSbom: true
runAsPublic: false
PackageVersion: 9.0.0
- BuildDropPath: '$(Build.SourcesDirectory)/artifacts'
+ BuildDropPath: '$(System.DefaultWorkingDirectory)/artifacts'
jobs:
- template: /eng/common/core-templates/job/job.yml
@@ -77,7 +77,7 @@ jobs:
parameters:
is1ESPipeline: false
args:
- targetPath: '$(Build.SourcesDirectory)\eng\common\BuildConfiguration'
+ targetPath: '$(System.DefaultWorkingDirectory)\eng\common\BuildConfiguration'
artifactName: 'BuildConfiguration'
displayName: 'Publish build retry configuration'
continueOnError: true
diff --git a/eng/common/tools.ps1 b/eng/common/tools.ps1
index d4cfd9ccd806c9..06b44de78709cf 100644
--- a/eng/common/tools.ps1
+++ b/eng/common/tools.ps1
@@ -544,7 +544,8 @@ function LocateVisualStudio([object]$vsRequirements = $null){
if (Get-Member -InputObject $GlobalJson.tools -Name 'vswhere') {
$vswhereVersion = $GlobalJson.tools.vswhere
} else {
- $vswhereVersion = '2.5.2'
+ # keep this in sync with the VSWhereVersion in DefaultVersions.props
+ $vswhereVersion = '3.1.7'
}
$vsWhereDir = Join-Path $ToolsDir "vswhere\$vswhereVersion"
@@ -552,7 +553,8 @@ function LocateVisualStudio([object]$vsRequirements = $null){
if (!(Test-Path $vsWhereExe)) {
Create-Directory $vsWhereDir
- Write-Host 'Downloading vswhere'
+ Write-Host "Downloading vswhere $vswhereVersion"
+ $ProgressPreference = 'SilentlyContinue' # Don't display the console progress UI - it's a huge perf hit
Retry({
Invoke-WebRequest "https://netcorenativeassets.blob.core.windows.net/resource-packages/external/windows/vswhere/$vswhereVersion/vswhere.exe" -OutFile $vswhereExe
})
diff --git a/eng/intellisense.targets b/eng/intellisense.targets
index 53614511d96725..e53bf035e91367 100644
--- a/eng/intellisense.targets
+++ b/eng/intellisense.targets
@@ -6,10 +6,10 @@
$([MSBuild]::NormalizeDirectory('$(NuGetPackageRoot)', 'microsoft.private.intellisense', '$(MicrosoftPrivateIntellisenseVersion)', 'IntellisenseFiles'))
+ $([MSBuild]::NormalizePath('$(IntellisensePackageXmlRootFolder)', 'net-$(NetCoreAppCurrentVersion)', '1033', '$(AssemblyName).xml'))
$([MSBuild]::NormalizePath('$(IntellisensePackageXmlRootFolder)', 'net', '1033', '$(AssemblyName).xml'))
- $([MSBuild]::NormalizePath('$(IntellisensePackageXmlRootFolder)', 'dotnet-plat-ext', '1033', '$(AssemblyName).xml'))
+ $(IntellisensePackageXmlFilePathFromNetVersionFolder)
$(IntellisensePackageXmlFilePathFromNetFolder)
- $(IntellisensePackageXmlFilePathFromDotNetPlatExtFolder)
$([MSBuild]::NormalizePath('$(IntermediateOutputPath)', 'intellisense-package', '$(TargetName).xml'))
diff --git a/eng/native/configurecompiler.cmake b/eng/native/configurecompiler.cmake
index 2957221d466617..901f601c333341 100644
--- a/eng/native/configurecompiler.cmake
+++ b/eng/native/configurecompiler.cmake
@@ -34,6 +34,13 @@ if (CLR_CMAKE_HOST_UNIX)
endif()
endif()
+# Force usage of classic linker on Xcode 15
+if (CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang" AND
+ CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 15 AND
+ CMAKE_CXX_COMPILER_VERSION VERSION_LESS 16)
+ add_link_options("-Wl,-ld_classic")
+endif()
+
if (CMAKE_CONFIGURATION_TYPES) # multi-configuration generator?
set(CMAKE_CONFIGURATION_TYPES "Debug;Checked;Release;RelWithDebInfo" CACHE STRING "" FORCE)
endif (CMAKE_CONFIGURATION_TYPES)
@@ -676,9 +683,21 @@ if (CLR_CMAKE_HOST_UNIX)
# a value for mmacosx-version-min (blank CMAKE_OSX_DEPLOYMENT_TARGET gets
# replaced with a default value, and always gets expanded to an OS version.
# https://gitlab.kitware.com/cmake/cmake/-/issues/20132
- # We need to disable the warning that -tagret replaces -mmacosx-version-min
- set(DISABLE_OVERRIDING_MIN_VERSION_ERROR -Wno-overriding-t-option)
- add_link_options(-Wno-overriding-t-option)
+ # We need to disable the warning that -target replaces -mmacosx-version-min
+ #
+ # With https://github.com/llvm/llvm-project/commit/1c66d08b0137cef7761b8220d3b7cb7833f57cdb clang renamed the option so we need to check for both
+ check_c_compiler_flag("-Wno-overriding-option" COMPILER_SUPPORTS_W_NO_OVERRIDING_OPTION)
+ if (COMPILER_SUPPORTS_W_NO_OVERRIDING_OPTION)
+ set(DISABLE_OVERRIDING_MIN_VERSION_ERROR -Wno-overriding-option)
+ else()
+ check_c_compiler_flag("-Wno-overriding-t-option" COMPILER_SUPPORTS_W_NO_OVERRIDING_T_OPTION)
+ if (COMPILER_SUPPORTS_W_NO_OVERRIDING_T_OPTION)
+ set(DISABLE_OVERRIDING_MIN_VERSION_ERROR -Wno-overriding-t-option)
+ else()
+ message(FATAL_ERROR "Compiler does not support -Wno-overriding-option or -Wno-overriding-t-option, needed for Mac Catalyst builds.")
+ endif()
+ endif()
+ add_link_options(${DISABLE_OVERRIDING_MIN_VERSION_ERROR})
if(CLR_CMAKE_HOST_ARCH_ARM64)
set(CLR_CMAKE_MACCATALYST_COMPILER_TARGET "arm64-apple-ios15.0-macabi")
add_link_options(-target ${CLR_CMAKE_MACCATALYST_COMPILER_TARGET})
diff --git a/eng/native/configureplatform.cmake b/eng/native/configureplatform.cmake
index 0855b88bffed1a..0154f877e7f72b 100644
--- a/eng/native/configureplatform.cmake
+++ b/eng/native/configureplatform.cmake
@@ -2,7 +2,7 @@ include(${CMAKE_CURRENT_LIST_DIR}/functions.cmake)
# If set, indicates that this is not an officially supported release.
# Release branches should set this to false.
-set(PRERELEASE 1)
+set(PRERELEASE 0)
#----------------------------------------
# Detect and set platform variable names
diff --git a/eng/packaging.targets b/eng/packaging.targets
index 23498173934306..60010a81a62f74 100644
--- a/eng/packaging.targets
+++ b/eng/packaging.targets
@@ -37,7 +37,7 @@
false
-
+
@@ -254,7 +254,7 @@
+ Condition="'$(IncludeSymbols)' == 'true' and '$(IncludeSymbolsInPackage)' != 'true'" />
diff --git a/eng/pipelines/coreclr/templates/helix-queues-setup.yml b/eng/pipelines/coreclr/templates/helix-queues-setup.yml
index 3b1ae77b6d6abe..fa680394c451ba 100644
--- a/eng/pipelines/coreclr/templates/helix-queues-setup.yml
+++ b/eng/pipelines/coreclr/templates/helix-queues-setup.yml
@@ -110,7 +110,7 @@ jobs:
# superpmi is not about testing platform differences, so go with highest capacity queue
- OSX.14.Arm64.Open
- ${{ if eq(variables['System.TeamProject'], 'internal') }}:
- - OSX.1200.Arm64
+ - OSX.14.Arm64
# OSX x64
- ${{ if eq(parameters.platform, 'osx_x64') }}:
diff --git a/eng/pipelines/libraries/stress/http.yml b/eng/pipelines/libraries/stress/http.yml
index e083bbac2a6e43..bdc5c956051ee8 100644
--- a/eng/pipelines/libraries/stress/http.yml
+++ b/eng/pipelines/libraries/stress/http.yml
@@ -72,6 +72,7 @@ extends:
export STRESS_CLIENT_ARGS="$HTTPSTRESS_CLIENT_ARGS -http 2.0"
export STRESS_SERVER_ARGS="$HTTPSTRESS_SERVER_ARGS -http 2.0"
mkdir -p $DUMPS_SHARE
+ docker-compose down
docker-compose up --abort-on-container-exit --no-color
displayName: Run HttpStress - HTTP 2.0
condition: and(eq(variables['buildRuntime.succeeded'], 'true'), eq(variables['buildStress.succeeded'], 'true'))
@@ -81,6 +82,7 @@ extends:
export STRESS_CLIENT_ARGS="$HTTPSTRESS_CLIENT_ARGS -http 1.1"
export STRESS_SERVER_ARGS="$HTTPSTRESS_SERVER_ARGS -http 1.1"
mkdir -p $DUMPS_SHARE
+ docker-compose down
docker-compose up --abort-on-container-exit --no-color
displayName: Run HttpStress - HTTP 1.1
condition: and(eq(variables['buildRuntime.succeeded'], 'true'), eq(variables['buildStress.succeeded'], 'true'))
diff --git a/eng/pipelines/performance/templates/build-perf-sample-apps.yml b/eng/pipelines/performance/templates/build-perf-sample-apps.yml
index be23c6465cbd44..f3a8eb3a3acf2d 100644
--- a/eng/pipelines/performance/templates/build-perf-sample-apps.yml
+++ b/eng/pipelines/performance/templates/build-perf-sample-apps.yml
@@ -2,7 +2,6 @@ parameters:
osGroup: ''
runtimeType: 'mono' # Currently only used for Android Hello World app
nameSuffix: ''
- hybridGlobalization: False
steps:
# Build Android sample app
@@ -125,11 +124,11 @@ steps:
displayName: clean bindir
- ${{ if and(eq(parameters.osGroup, 'ios'), eq(parameters.nameSuffix, 'iOSMono')) }}:
- - script: make build-appbundle TARGET_OS=ios TARGET_ARCH=arm64 BUILD_CONFIG=Release AOT=True USE_LLVM=False DEPLOY_AND_RUN=false STRIP_DEBUG_SYMBOLS=false HYBRID_GLOBALIZATION=${{ parameters.hybridGlobalization }}
+ - script: make build-appbundle TARGET_OS=ios TARGET_ARCH=arm64 BUILD_CONFIG=Release AOT=True USE_LLVM=False DEPLOY_AND_RUN=false STRIP_DEBUG_SYMBOLS=false
env:
DevTeamProvisioning: '-'
workingDirectory: $(Build.SourcesDirectory)/src/mono/sample/iOS
- displayName: Build HelloiOS AOT sample app LLVM=False STRIP_SYMBOLS=False HYBRID_GLOBALIZATION=${{ parameters.hybridGlobalization }}
+ displayName: Build HelloiOS AOT sample app LLVM=False STRIP_SYMBOLS=False
- task: PublishBuildArtifacts@1
condition: succeededOrFailed()
displayName: 'Publish binlog'
@@ -141,17 +140,17 @@ steps:
rootFolder: $(Build.SourcesDirectory)/src/mono/sample/iOS/bin/ios-arm64/Bundle/HelloiOS/Release-iphoneos/HelloiOS.app
includeRootFolder: true
displayName: iOS Sample App NoLLVM
- artifactName: iOSSampleAppNoLLVMSymbolsHybridGlobalization${{parameters.hybridGlobalization}}
+ artifactName: iOSSampleAppNoLLVMSymbols
archiveExtension: '.zip'
archiveType: zip
- script: rm -r -f $(Build.SourcesDirectory)/src/mono/sample/iOS/bin
workingDirectory: $(Build.SourcesDirectory)/src/mono/sample/iOS
displayName: Clean bindir
- - script: make build-appbundle TARGET_OS=ios TARGET_ARCH=arm64 BUILD_CONFIG=Release AOT=True USE_LLVM=False DEPLOY_AND_RUN=false STRIP_DEBUG_SYMBOLS=true HYBRID_GLOBALIZATION=${{ parameters.hybridGlobalization }}
+ - script: make build-appbundle TARGET_OS=ios TARGET_ARCH=arm64 BUILD_CONFIG=Release AOT=True USE_LLVM=False DEPLOY_AND_RUN=false STRIP_DEBUG_SYMBOLS=true
env:
DevTeamProvisioning: '-'
workingDirectory: $(Build.SourcesDirectory)/src/mono/sample/iOS
- displayName: Build HelloiOS AOT sample app LLVM=False STRIP_SYMBOLS=True HYBRID_GLOBALIZATION=${{ parameters.hybridGlobalization }}
+ displayName: Build HelloiOS AOT sample app LLVM=False STRIP_SYMBOLS=True
- task: PublishBuildArtifacts@1
condition: succeededOrFailed()
displayName: 'Publish binlog'
@@ -163,17 +162,17 @@ steps:
rootFolder: $(Build.SourcesDirectory)/src/mono/sample/iOS/bin/ios-arm64/Bundle/HelloiOS/Release-iphoneos/HelloiOS.app
includeRootFolder: true
displayName: iOS Sample App NoLLVM NoSymbols
- artifactName: iOSSampleAppNoLLVMNoSymbolsHybridGlobalization${{parameters.hybridGlobalization}}
+ artifactName: iOSSampleAppNoLLVMNoSymbols
archiveExtension: '.zip'
archiveType: zip
- script: rm -r -f $(Build.SourcesDirectory)/src/mono/sample/iOS/bin
workingDirectory: $(Build.SourcesDirectory)/src/mono/sample/iOS
displayName: Clean bindir
- - script: make build-appbundle TARGET_OS=ios TARGET_ARCH=arm64 BUILD_CONFIG=Release AOT=True USE_LLVM=True DEPLOY_AND_RUN=false STRIP_DEBUG_SYMBOLS=false HYBRID_GLOBALIZATION=${{ parameters.hybridGlobalization }}
+ - script: make build-appbundle TARGET_OS=ios TARGET_ARCH=arm64 BUILD_CONFIG=Release AOT=True USE_LLVM=True DEPLOY_AND_RUN=false STRIP_DEBUG_SYMBOLS=false
env:
DevTeamProvisioning: '-'
workingDirectory: $(Build.SourcesDirectory)/src/mono/sample/iOS
- displayName: Build HelloiOS AOT sample app LLVM=True STRIP_SYMBOLS=False HYBRID_GLOBALIZATION=${{ parameters.hybridGlobalization }}
+ displayName: Build HelloiOS AOT sample app LLVM=True STRIP_SYMBOLS=False
- task: PublishBuildArtifacts@1
condition: succeededOrFailed()
displayName: 'Publish binlog'
@@ -185,17 +184,17 @@ steps:
rootFolder: $(Build.SourcesDirectory)/src/mono/sample/iOS/bin/ios-arm64/Bundle/HelloiOS/Release-iphoneos/HelloiOS.app
includeRootFolder: true
displayName: iOS Sample App LLVM
- artifactName: iOSSampleAppLLVMSymbolsHybridGlobalization${{parameters.hybridGlobalization}}
+ artifactName: iOSSampleAppLLVMSymbols
archiveExtension: '.zip'
archiveType: zip
- script: rm -r -f $(Build.SourcesDirectory)/src/mono/sample/iOS/bin
workingDirectory: $(Build.SourcesDirectory)/src/mono/sample/iOS
displayName: Clean bindir
- - script: make build-appbundle TARGET_OS=ios TARGET_ARCH=arm64 BUILD_CONFIG=Release AOT=True USE_LLVM=True DEPLOY_AND_RUN=false STRIP_DEBUG_SYMBOLS=true HYBRID_GLOBALIZATION=${{ parameters.hybridGlobalization }}
+ - script: make build-appbundle TARGET_OS=ios TARGET_ARCH=arm64 BUILD_CONFIG=Release AOT=True USE_LLVM=True DEPLOY_AND_RUN=false STRIP_DEBUG_SYMBOLS=true
env:
DevTeamProvisioning: '-'
workingDirectory: $(Build.SourcesDirectory)/src/mono/sample/iOS
- displayName: Build HelloiOS AOT sample app LLVM=True STRIP_SYMBOLS=True HYBRID_GLOBALIZATION=${{ parameters.hybridGlobalization }}
+ displayName: Build HelloiOS AOT sample app LLVM=True STRIP_SYMBOLS=True
- task: PublishBuildArtifacts@1
condition: succeededOrFailed()
displayName: 'Publish binlog'
@@ -207,16 +206,16 @@ steps:
rootFolder: $(Build.SourcesDirectory)/src/mono/sample/iOS/bin/ios-arm64/Bundle/HelloiOS/Release-iphoneos/HelloiOS.app
includeRootFolder: true
displayName: iOS Sample App LLVM NoSymbols
- artifactName: iOSSampleAppLLVMNoSymbolsHybridGlobalization${{parameters.hybridGlobalization}}
+ artifactName: iOSSampleAppLLVMNoSymbols
archiveExtension: '.zip'
archiveType: zip
- ${{ if and(eq(parameters.osGroup, 'ios'), eq(parameters.nameSuffix, 'iOSNativeAOT')) }}:
- - script: make hello-app TARGET_OS=ios TARGET_ARCH=arm64 BUILD_CONFIG=Release DEPLOY_AND_RUN=false STRIP_DEBUG_SYMBOLS=false HYBRID_GLOBALIZATION=${{ parameters.hybridGlobalization }}
+ - script: make hello-app TARGET_OS=ios TARGET_ARCH=arm64 BUILD_CONFIG=Release DEPLOY_AND_RUN=false STRIP_DEBUG_SYMBOLS=false
env:
DevTeamProvisioning: '-'
workingDirectory: $(Build.SourcesDirectory)/src/mono/sample/iOS-NativeAOT
- displayName: Build HelloiOS Native AOT sample app STRIP_SYMBOLS=False HYBRID_GLOBALIZATION=${{ parameters.hybridGlobalization }}
+ displayName: Build HelloiOS Native AOT sample app STRIP_SYMBOLS=False
- task: PublishBuildArtifacts@1
condition: succeededOrFailed()
displayName: 'Publish binlog'
@@ -228,17 +227,17 @@ steps:
rootFolder: $(Build.SourcesDirectory)/src/mono/sample/iOS-NativeAOT/bin/ios-arm64/Bundle/HelloiOS/Release-iphoneos/HelloiOS.app
includeRootFolder: true
displayName: iOS Sample App Symbols
- artifactName: iOSSampleAppSymbolsHybridGlobalization${{parameters.hybridGlobalization}}
+ artifactName: iOSSampleAppSymbols
archiveExtension: '.zip'
archiveType: zip
- script: rm -r -f $(Build.SourcesDirectory)/src/mono/sample/iOS-NativeAOT/bin
workingDirectory: $(Build.SourcesDirectory)/src/mono/sample/iOS-NativeAOT
displayName: Clean bindir
- - script: make hello-app TARGET_OS=ios TARGET_ARCH=arm64 BUILD_CONFIG=Release DEPLOY_AND_RUN=false STRIP_DEBUG_SYMBOLS=true HYBRID_GLOBALIZATION=${{ parameters.hybridGlobalization }}
+ - script: make hello-app TARGET_OS=ios TARGET_ARCH=arm64 BUILD_CONFIG=Release DEPLOY_AND_RUN=false STRIP_DEBUG_SYMBOLS=true
env:
DevTeamProvisioning: '-'
workingDirectory: $(Build.SourcesDirectory)/src/mono/sample/iOS-NativeAOT
- displayName: Build HelloiOS Native AOT sample app STRIP_SYMBOLS=True HYBRID_GLOBALIZATION=${{ parameters.hybridGlobalization }}
+ displayName: Build HelloiOS Native AOT sample app STRIP_SYMBOLS=True
- task: PublishBuildArtifacts@1
condition: succeededOrFailed()
displayName: 'Publish binlog'
@@ -250,6 +249,6 @@ steps:
rootFolder: $(Build.SourcesDirectory)/src/mono/sample/iOS-NativeAOT/bin/ios-arm64/Bundle/HelloiOS/Release-iphoneos/HelloiOS.app
includeRootFolder: true
displayName: iOS Sample App NoSymbols
- artifactName: iOSSampleAppNoSymbolsHybridGlobalization${{parameters.hybridGlobalization}}
+ artifactName: iOSSampleAppNoSymbols
archiveExtension: '.zip'
archiveType: zip
diff --git a/es-metadata.yml b/es-metadata.yml
new file mode 100644
index 00000000000000..3bdb1ce3e0b3a3
--- /dev/null
+++ b/es-metadata.yml
@@ -0,0 +1,8 @@
+schemaVersion: 0.0.1
+isProduction: true
+accountableOwners:
+ service: 1dc8dedc-8f5f-4b94-b182-ec3bdfb207b0
+routing:
+ defaultAreaPath:
+ org: devdiv
+ path: DevDiv\NET Runtime
diff --git a/global.json b/global.json
index 5da2c8d6d5d1cd..038a7e3c00a758 100644
--- a/global.json
+++ b/global.json
@@ -1,18 +1,18 @@
{
"sdk": {
- "version": "10.0.100-rc.1.25411.109",
+ "version": "10.0.100-rc.1.25451.107",
"allowPrerelease": true,
"rollForward": "major"
},
"tools": {
- "dotnet": "10.0.100-rc.1.25411.109"
+ "dotnet": "10.0.100-rc.1.25451.107"
},
"msbuild-sdks": {
- "Microsoft.DotNet.Arcade.Sdk": "10.0.0-beta.25414.103",
- "Microsoft.DotNet.Helix.Sdk": "10.0.0-beta.25414.103",
- "Microsoft.DotNet.SharedFramework.Sdk": "10.0.0-beta.25414.103",
+ "Microsoft.DotNet.Arcade.Sdk": "10.0.0-beta.25509.106",
+ "Microsoft.DotNet.Helix.Sdk": "10.0.0-beta.25509.106",
+ "Microsoft.DotNet.SharedFramework.Sdk": "10.0.0-beta.25509.106",
"Microsoft.Build.NoTargets": "3.7.0",
"Microsoft.Build.Traversal": "3.4.0",
- "Microsoft.NET.Sdk.IL": "10.0.0-rc.1.25414.103"
+ "Microsoft.NET.Sdk.IL": "10.0.0-rtm.25509.106"
}
}
diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Metadata/RuntimeTypeMetadataUpdateHandler.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Metadata/RuntimeTypeMetadataUpdateHandler.cs
index e45e84efb60f01..9c54c27f28b41a 100644
--- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Metadata/RuntimeTypeMetadataUpdateHandler.cs
+++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Metadata/RuntimeTypeMetadataUpdateHandler.cs
@@ -3,6 +3,7 @@
using System.Diagnostics.CodeAnalysis;
using System.Reflection.Metadata;
+using System.Runtime.CompilerServices;
[assembly: MetadataUpdateHandler(typeof(RuntimeTypeMetadataUpdateHandler))]
@@ -11,11 +12,21 @@ namespace System.Reflection.Metadata
/// Metadata update handler used to clear a Type's reflection cache in response to a metadata update notification.
internal static class RuntimeTypeMetadataUpdateHandler
{
+ ///
+ /// True to enable filtering deleted members from Reflection results. Set after the first metadata update.
+ ///
+ internal static bool FilterDeletedMembers { get; private set; }
+
+ internal static bool IsMetadataUpdateDeleted(RuntimeModule module, int memberToken)
+ => CustomAttribute.IsCustomAttributeDefined(module, memberToken, (RuntimeType)typeof(MetadataUpdateDeletedAttribute));
+
/// Clear type caches in response to an update notification.
/// The specific types to be cleared, or null to clear everything.
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "Clearing the caches on a Type isn't affected if a Type is trimmed, or has any of its members trimmed.")]
public static void ClearCache(Type[]? types)
{
+ FilterDeletedMembers = true;
+
if (RequiresClearingAllTypes(types))
{
// TODO: This should ideally be in a QCall in the runtime. As written here:
diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.CoreCLR.cs
index dd855b65fdee93..67180ec563730d 100644
--- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.CoreCLR.cs
+++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.CoreCLR.cs
@@ -173,7 +173,7 @@ public override IList GetCustomAttributesData()
internal RuntimeType GetRuntimeType() { return m_declaringType; }
internal RuntimeModule GetRuntimeModule() { return RuntimeTypeHandle.GetModule(m_declaringType); }
internal RuntimeAssembly GetRuntimeAssembly() { return GetRuntimeModule().GetRuntimeAssembly(); }
- public override bool IsCollectible => m_declaringType.IsCollectible;
+ public override bool IsCollectible => ReflectedTypeInternal.IsCollectible;
#endregion
#region MethodBase Overrides
diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeCustomAttributeData.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeCustomAttributeData.cs
index ae42fa55d03630..2ba39f98cf07b8 100644
--- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeCustomAttributeData.cs
+++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeCustomAttributeData.cs
@@ -1407,7 +1407,7 @@ internal static bool IsAttributeDefined(RuntimeModule decoratedModule, int decor
return IsCustomAttributeDefined(decoratedModule, decoratedMetadataToken, null, attributeCtorToken, false);
}
- private static bool IsCustomAttributeDefined(
+ internal static bool IsCustomAttributeDefined(
RuntimeModule decoratedModule, int decoratedMetadataToken, RuntimeType? attributeFilterType)
{
return IsCustomAttributeDefined(decoratedModule, decoratedMetadataToken, attributeFilterType, 0, false);
diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeEventInfo.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeEventInfo.cs
index e09a405a4144c3..cdef2ad754f7a8 100644
--- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeEventInfo.cs
+++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeEventInfo.cs
@@ -129,7 +129,7 @@ public override IList GetCustomAttributesData()
public override int MetadataToken => m_token;
public override Module Module => GetRuntimeModule();
internal RuntimeModule GetRuntimeModule() { return m_declaringType.GetRuntimeModule(); }
- public override bool IsCollectible => m_declaringType.IsCollectible;
+ public override bool IsCollectible => ReflectedTypeInternal.IsCollectible;
#endregion
#region EventInfo Overrides
diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeFieldInfo.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeFieldInfo.cs
index a314edaab2a15f..665fbd2076fe54 100644
--- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeFieldInfo.cs
+++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeFieldInfo.cs
@@ -45,7 +45,7 @@ internal RuntimeType GetDeclaringTypeInternal()
public sealed override bool HasSameMetadataDefinitionAs(MemberInfo other) => HasSameMetadataDefinitionAsCore(other);
public override Module Module => GetRuntimeModule();
- public override bool IsCollectible => m_declaringType.IsCollectible;
+ public override bool IsCollectible => ReflectedTypeInternal.IsCollectible;
#endregion
diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.CoreCLR.cs
index 3a72a2e1174e4b..8b604ebd0f8797 100644
--- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.CoreCLR.cs
+++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.CoreCLR.cs
@@ -319,7 +319,18 @@ internal void InvokePropertySetter(object? obj, BindingFlags invokeAttr, Binder?
public override ParameterInfo ReturnParameter => FetchReturnParameter();
- public override bool IsCollectible => RuntimeMethodHandle.GetIsCollectible(new RuntimeMethodHandleInternal(m_handle)) != Interop.BOOL.FALSE;
+ public override bool IsCollectible
+ {
+ get
+ {
+ if (ReflectedTypeInternal.IsCollectible)
+ return true;
+
+ bool isCollectible = RuntimeMethodHandle.GetIsCollectible(new RuntimeMethodHandleInternal(m_handle)) != Interop.BOOL.FALSE;
+ GC.KeepAlive(this); // We directly pass the native handle above - make sure this object stays alive for the call
+ return isCollectible;
+ }
+ }
public override MethodInfo GetBaseDefinition()
{
diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimePropertyInfo.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimePropertyInfo.cs
index 51b1f84864b1a9..7ebc2b7331b466 100644
--- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimePropertyInfo.cs
+++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimePropertyInfo.cs
@@ -180,7 +180,7 @@ public override IList GetCustomAttributesData()
public override Module Module => GetRuntimeModule();
internal RuntimeModule GetRuntimeModule() { return m_declaringType.GetRuntimeModule(); }
- public override bool IsCollectible => m_declaringType.IsCollectible;
+ public override bool IsCollectible => ReflectedTypeInternal.IsCollectible;
public override bool Equals(object? obj) =>
ReferenceEquals(this, obj) ||
diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/ExceptionServices/AsmOffsets.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/ExceptionServices/AsmOffsets.cs
index 86cb928e36e89d..4b9dae8a00dbf7 100644
--- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/ExceptionServices/AsmOffsets.cs
+++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/ExceptionServices/AsmOffsets.cs
@@ -68,17 +68,17 @@ class AsmOffsets
public const int OFFSETOF__StackFrameIterator__m_isRuntimeWrappedExceptions = 0x132;
#elif TARGET_X86
public const int OFFSETOF__REGDISPLAY__m_pCurrentContext = 0x4;
- public const int SIZEOF__StackFrameIterator = 0x3d4;
+ public const int SIZEOF__StackFrameIterator = 0x3d0;
public const int OFFSETOF__StackFrameIterator__m_isRuntimeWrappedExceptions = 0x3c2;
- public const int OFFSETOF__StackFrameIterator__m_AdjustedControlPC = 0x3d0;
+ public const int OFFSETOF__StackFrameIterator__m_AdjustedControlPC = 0x3cc;
#else // TARGET_64BIT
public const int OFFSETOF__REGDISPLAY__m_pCurrentContext = 0x4;
#if FEATURE_INTERPRETER
- public const int SIZEOF__StackFrameIterator = 0xdc;
- public const int OFFSETOF__StackFrameIterator__m_AdjustedControlPC = 0xd8;
+ public const int SIZEOF__StackFrameIterator = 0xd8;
+ public const int OFFSETOF__StackFrameIterator__m_AdjustedControlPC = 0xd4;
#else
- public const int SIZEOF__StackFrameIterator = 0xcc;
- public const int OFFSETOF__StackFrameIterator__m_AdjustedControlPC = 0xc8;
+ public const int SIZEOF__StackFrameIterator = 0xc8;
+ public const int OFFSETOF__StackFrameIterator__m_AdjustedControlPC = 0xc4;
#endif
public const int OFFSETOF__StackFrameIterator__m_isRuntimeWrappedExceptions = 0xba;
#endif // TARGET_64BIT
@@ -139,17 +139,17 @@ class AsmOffsets
public const int OFFSETOF__StackFrameIterator__m_isRuntimeWrappedExceptions = 0x12a;
#elif TARGET_X86
public const int OFFSETOF__REGDISPLAY__m_pCurrentContext = 0x4;
- public const int SIZEOF__StackFrameIterator = 0x3cc;
+ public const int SIZEOF__StackFrameIterator = 0x3c8;
public const int OFFSETOF__StackFrameIterator__m_isRuntimeWrappedExceptions = 0x3ba;
- public const int OFFSETOF__StackFrameIterator__m_AdjustedControlPC = 0x3c8;
+ public const int OFFSETOF__StackFrameIterator__m_AdjustedControlPC = 0x3c4;
#else // TARGET_64BIT
public const int OFFSETOF__REGDISPLAY__m_pCurrentContext = 0x4;
#if FEATURE_INTERPRETER
- public const int SIZEOF__StackFrameIterator = 0xd4;
- public const int OFFSETOF__StackFrameIterator__m_AdjustedControlPC = 0xd0;
+ public const int SIZEOF__StackFrameIterator = 0xd0;
+ public const int OFFSETOF__StackFrameIterator__m_AdjustedControlPC = 0xcc;
#else
- public const int SIZEOF__StackFrameIterator = 0xc4;
- public const int OFFSETOF__StackFrameIterator__m_AdjustedControlPC = 0xc0;
+ public const int SIZEOF__StackFrameIterator = 0xc0;
+ public const int OFFSETOF__StackFrameIterator__m_AdjustedControlPC = 0xbc;
#endif
public const int OFFSETOF__StackFrameIterator__m_isRuntimeWrappedExceptions = 0xb2;
#endif // TARGET_64BIT
@@ -217,6 +217,23 @@ class AsmOffsets
public const int OFFSETOF__ExInfo__m_idxCurClause = 0xbc;
public const int OFFSETOF__ExInfo__m_frameIter = 0xc0;
public const int OFFSETOF__ExInfo__m_notifyDebuggerSP = OFFSETOF__ExInfo__m_frameIter + SIZEOF__StackFrameIterator;
+ public const int OFFSETOF__ExInfo__m_pCatchHandler = OFFSETOF__ExInfo__m_frameIter + SIZEOF__StackFrameIterator + 0x48;
+ public const int OFFSETOF__ExInfo__m_handlingFrameSP = OFFSETOF__ExInfo__m_frameIter + SIZEOF__StackFrameIterator + 0x50;
+
+#if TARGET_ARM64
+ public const int OFFSETOF__ExInfo__m_handlingFramePC = OFFSETOF__ExInfo__m_frameIter + SIZEOF__StackFrameIterator + 0x58;
+#endif
+
+#if TARGET_UNIX
+#if TARGET_ARM64
+ public const int OFFSETOF__ExInfo__m_pReversePInvokePropagationCallback = OFFSETOF__ExInfo__m_frameIter + SIZEOF__StackFrameIterator + 0x68;
+ public const int OFFSETOF__ExInfo__m_pReversePInvokePropagationContext = OFFSETOF__ExInfo__m_frameIter + SIZEOF__StackFrameIterator + 0x70;
+#else // TARGET_ARM64
+ public const int OFFSETOF__ExInfo__m_pReversePInvokePropagationCallback = OFFSETOF__ExInfo__m_frameIter + SIZEOF__StackFrameIterator + 0x60;
+ public const int OFFSETOF__ExInfo__m_pReversePInvokePropagationContext = OFFSETOF__ExInfo__m_frameIter + SIZEOF__StackFrameIterator + 0x68;
+#endif // TARGET_ARM64
+#endif // TARGET_UNIX
+
#else // TARGET_64BIT
public const int SIZEOF__EHEnum = 0x10;
public const int OFFSETOF__StackFrameIterator__m_pRegDisplay = 0x14;
@@ -228,6 +245,14 @@ class AsmOffsets
public const int OFFSETOF__ExInfo__m_idxCurClause = 0x68;
public const int OFFSETOF__ExInfo__m_frameIter = 0x6c;
public const int OFFSETOF__ExInfo__m_notifyDebuggerSP = OFFSETOF__ExInfo__m_frameIter + SIZEOF__StackFrameIterator;
+ public const int OFFSETOF__ExInfo__m_pCatchHandler = OFFSETOF__ExInfo__m_frameIter + SIZEOF__StackFrameIterator + 0x2c;
+ public const int OFFSETOF__ExInfo__m_handlingFrameSP = OFFSETOF__ExInfo__m_frameIter + SIZEOF__StackFrameIterator + 0x30;
+
+#if TARGET_UNIX
+ public const int OFFSETOF__ExInfo__m_pReversePInvokePropagationCallback = OFFSETOF__ExInfo__m_frameIter + SIZEOF__StackFrameIterator + 0x38;
+ public const int OFFSETOF__ExInfo__m_pReversePInvokePropagationContext = OFFSETOF__ExInfo__m_frameIter + SIZEOF__StackFrameIterator + 0x3c;
+#endif
+
#endif // TARGET_64BIT
#if __cplusplus
@@ -268,8 +293,18 @@ class AsmOffsets
static_assert_no_msg(offsetof(ExInfo, m_idxCurClause) == OFFSETOF__ExInfo__m_idxCurClause);
static_assert_no_msg(offsetof(ExInfo, m_frameIter) == OFFSETOF__ExInfo__m_frameIter);
static_assert_no_msg(offsetof(ExInfo, m_notifyDebuggerSP) == OFFSETOF__ExInfo__m_notifyDebuggerSP);
+ static_assert_no_msg(offsetof(ExInfo, m_pCatchHandler) == OFFSETOF__ExInfo__m_pCatchHandler);
+ static_assert_no_msg(offsetof(ExInfo, m_handlingFrameSP) == OFFSETOF__ExInfo__m_handlingFrameSP);
+#if TARGET_ARM64
+ static_assert_no_msg(offsetof(ExInfo, m_handlingFramePC) == OFFSETOF__ExInfo__m_handlingFramePC);
#endif
+#if TARGET_UNIX
+ static_assert_no_msg(offsetof(ExInfo, m_propagateExceptionCallback) == OFFSETOF__ExInfo__m_pReversePInvokePropagationCallback);
+ static_assert_no_msg(offsetof(ExInfo, m_propagateExceptionContext) == OFFSETOF__ExInfo__m_pReversePInvokePropagationContext);
+#endif
+
+#endif
}
#if __cplusplus
;
diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/ExceptionServices/InternalCalls.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/ExceptionServices/InternalCalls.cs
index 608d52d768911e..c1314ff9fe9db0 100644
--- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/ExceptionServices/InternalCalls.cs
+++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/ExceptionServices/InternalCalls.cs
@@ -20,16 +20,6 @@ internal static partial class InternalCalls
[return: MarshalAs(UnmanagedType.U1)]
internal static unsafe partial bool RhpSfiNext(ref StackFrameIterator pThis, uint* uExCollideClauseIdx, bool* fUnwoundReversePInvoke, bool* fIsExceptionIntercepted);
- [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "ResumeAtInterceptionLocation")]
- internal static unsafe partial void ResumeAtInterceptionLocation(void* pvRegDisplay);
-
- [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "CallCatchFunclet")]
- internal static unsafe partial IntPtr RhpCallCatchFunclet(
- ObjectHandleOnStack exceptionObj, byte* pHandlerIP, void* pvRegDisplay, EH.ExInfo* exInfo);
-
- [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "CallFinallyFunclet")]
- internal static unsafe partial void RhpCallFinallyFunclet(byte* pHandlerIP, void* pvRegDisplay, EH.ExInfo* exInfo);
-
[LibraryImport(RuntimeHelpers.QCall, EntryPoint = "CallFilterFunclet")]
[return: MarshalAs(UnmanagedType.U1)]
internal static unsafe partial bool RhpCallFilterFunclet(
diff --git a/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs b/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs
index b8ae179ff25ce5..63f4c6dbd58b4f 100644
--- a/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs
+++ b/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs
@@ -1118,7 +1118,7 @@ internal static int GetSlot(IRuntimeMethodInfo method)
}
[MethodImpl(MethodImplOptions.InternalCall)]
- private static extern int GetMethodDef(RuntimeMethodHandleInternal method);
+ internal static extern int GetMethodDef(RuntimeMethodHandleInternal method);
internal static int GetMethodDef(IRuntimeMethodInfo method)
{
@@ -1569,7 +1569,7 @@ internal static ref byte GetFieldDataReference(ref byte target, RuntimeFieldInfo
private static unsafe partial void GetFieldDataReference(IntPtr fieldDesc, ObjectHandleOnStack target, ByteRefOnStack fieldDataRef);
[MethodImpl(MethodImplOptions.InternalCall)]
- private static extern int GetToken(IntPtr fieldDesc);
+ internal static extern int GetToken(IntPtr fieldDesc);
internal static int GetToken(RtFieldInfo field)
{
diff --git a/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs
index 1e53282c7fc52c..209e5c17df0e35 100644
--- a/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs
+++ b/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs
@@ -6,7 +6,9 @@
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
+using System.IO;
using System.Reflection;
+using System.Reflection.Metadata;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
@@ -605,6 +607,13 @@ private unsafe RuntimeMethodInfo[] PopulateMethods(Filter filter)
continue;
#endregion
+ if (MetadataUpdater.IsSupported &&
+ RuntimeTypeMetadataUpdateHandler.FilterDeletedMembers &&
+ RuntimeTypeMetadataUpdateHandler.IsMetadataUpdateDeleted(declaringType.GetRuntimeModule(), RuntimeMethodHandle.GetMethodDef(methodHandle)))
+ {
+ continue;
+ }
+
#region Calculate Binding Flags
bool isPublic = (methodAttributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Public;
bool isStatic = (methodAttributes & MethodAttributes.Static) != 0;
@@ -615,7 +624,7 @@ private unsafe RuntimeMethodInfo[] PopulateMethods(Filter filter)
RuntimeMethodHandleInternal instantiatedHandle = RuntimeMethodHandle.GetStubIfNeeded(methodHandle, declaringType, null);
RuntimeMethodInfo runtimeMethodInfo = new RuntimeMethodInfo(
- instantiatedHandle, declaringType, m_runtimeTypeCache, methodAttributes, bindingFlags, null);
+ instantiatedHandle, declaringType, m_runtimeTypeCache, methodAttributes, bindingFlags, null);
list.Add(runtimeMethodInfo);
#endregion
@@ -685,6 +694,14 @@ private unsafe RuntimeMethodInfo[] PopulateMethods(Filter filter)
#endregion
+ // Filter out deleted method before setting override state, so that a deleted override in a subclass does not hide override in an ancestor.
+ if (MetadataUpdater.IsSupported &&
+ RuntimeTypeMetadataUpdateHandler.FilterDeletedMembers &&
+ RuntimeTypeMetadataUpdateHandler.IsMetadataUpdateDeleted(declaringType.GetRuntimeModule(), RuntimeMethodHandle.GetMethodDef(methodHandle)))
+ {
+ continue;
+ }
+
#region Continue if this is a virtual and is already overridden
if (isVirtual)
{
@@ -719,7 +736,7 @@ private unsafe RuntimeMethodInfo[] PopulateMethods(Filter filter)
RuntimeMethodHandleInternal instantiatedHandle = RuntimeMethodHandle.GetStubIfNeeded(methodHandle, declaringType, null);
RuntimeMethodInfo runtimeMethodInfo = new RuntimeMethodInfo(
- instantiatedHandle, declaringType, m_runtimeTypeCache, methodAttributes, bindingFlags, null);
+ instantiatedHandle, declaringType, m_runtimeTypeCache, methodAttributes, bindingFlags, null);
list.Add(runtimeMethodInfo);
#endregion
@@ -764,6 +781,13 @@ private RuntimeConstructorInfo[] PopulateConstructors(Filter filter)
(methodAttributes & MethodAttributes.Abstract) == 0 &&
(methodAttributes & MethodAttributes.Virtual) == 0);
+ if (MetadataUpdater.IsSupported &&
+ RuntimeTypeMetadataUpdateHandler.FilterDeletedMembers &&
+ RuntimeTypeMetadataUpdateHandler.IsMetadataUpdateDeleted(declaringType.GetRuntimeModule(), RuntimeMethodHandle.GetMethodDef(methodHandle)))
+ {
+ continue;
+ }
+
#region Calculate Binding Flags
bool isPublic = (methodAttributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Public;
bool isStatic = (methodAttributes & MethodAttributes.Static) != 0;
@@ -875,6 +899,13 @@ private void PopulateRtFields(Filter filter,
continue;
}
+ if (MetadataUpdater.IsSupported &&
+ RuntimeTypeMetadataUpdateHandler.FilterDeletedMembers &&
+ RuntimeTypeMetadataUpdateHandler.IsMetadataUpdateDeleted(declaringType.GetRuntimeModule(), RuntimeFieldHandle.GetToken(handle)))
+ {
+ continue;
+ }
+
#region Calculate Binding Flags
bool isPublic = fieldAccess == FieldAttributes.Public;
bool isStatic = (fieldAttributes & FieldAttributes.Static) != 0;
@@ -885,8 +916,7 @@ private void PopulateRtFields(Filter filter,
if (needsStaticFieldForGeneric && isStatic)
runtimeFieldHandle = RuntimeFieldHandle.GetStaticFieldForGenericType(runtimeFieldHandle, declaringType);
- RuntimeFieldInfo runtimeFieldInfo =
- new RtFieldInfo(runtimeFieldHandle, declaringType, m_runtimeTypeCache, bindingFlags);
+ var runtimeFieldInfo = new RtFieldInfo(runtimeFieldHandle, declaringType, m_runtimeTypeCache, bindingFlags);
list.Add(runtimeFieldInfo);
}
@@ -903,8 +933,8 @@ private void PopulateLiteralFields(Filter filter, RuntimeType declaringType, ref
if (MdToken.IsNullToken(tkDeclaringType))
return;
- RuntimeModule module = declaringType.GetRuntimeModule();
- MetadataImport scope = module.MetadataImport;
+ RuntimeModule declaringModule = declaringType.GetRuntimeModule();
+ MetadataImport scope = declaringModule.MetadataImport;
scope.EnumFields(tkDeclaringType, out MetadataEnumResult tkFields);
@@ -936,6 +966,13 @@ private void PopulateLiteralFields(Filter filter, RuntimeType declaringType, ref
continue;
}
+ if (MetadataUpdater.IsSupported &&
+ RuntimeTypeMetadataUpdateHandler.FilterDeletedMembers &&
+ RuntimeTypeMetadataUpdateHandler.IsMetadataUpdateDeleted(declaringModule, tkField))
+ {
+ continue;
+ }
+
#region Calculate Binding Flags
bool isPublic = fieldAccess == FieldAttributes.Public;
bool isStatic = (fieldAttributes & FieldAttributes.Static) != 0;
@@ -948,7 +985,7 @@ private void PopulateLiteralFields(Filter filter, RuntimeType declaringType, ref
list.Add(runtimeFieldInfo);
}
}
- GC.KeepAlive(module);
+ GC.KeepAlive(declaringModule);
}
private void AddSpecialInterface(
@@ -1144,8 +1181,8 @@ private void PopulateEvents(
if (MdToken.IsNullToken(tkDeclaringType))
return;
- RuntimeModule module = declaringType.GetRuntimeModule();
- MetadataImport scope = module.MetadataImport;
+ RuntimeModule declaringModule = declaringType.GetRuntimeModule();
+ MetadataImport scope = declaringModule.MetadataImport;
scope.EnumEvents(tkDeclaringType, out MetadataEnumResult tkEvents);
@@ -1164,6 +1201,13 @@ private void PopulateEvents(
continue;
}
+ if (MetadataUpdater.IsSupported &&
+ RuntimeTypeMetadataUpdateHandler.FilterDeletedMembers &&
+ RuntimeTypeMetadataUpdateHandler.IsMetadataUpdateDeleted(declaringModule, tkEvent))
+ {
+ continue;
+ }
+
RuntimeEventInfo eventInfo = new RuntimeEventInfo(
tkEvent, declaringType, m_runtimeTypeCache, out bool isPrivate);
@@ -1191,7 +1235,7 @@ private void PopulateEvents(
list.Add(eventInfo);
}
- GC.KeepAlive(module);
+ GC.KeepAlive(declaringModule);
}
private RuntimePropertyInfo[] PopulateProperties(Filter filter)
@@ -1251,8 +1295,8 @@ private void PopulateProperties(
if (MdToken.IsNullToken(tkDeclaringType))
return;
- RuntimeModule module = declaringType.GetRuntimeModule();
- MetadataImport scope = module.MetadataImport;
+ RuntimeModule declaringModule = declaringType.GetRuntimeModule();
+ MetadataImport scope = declaringModule.MetadataImport;
scope.EnumProperties(tkDeclaringType, out MetadataEnumResult tkProperties);
@@ -1276,6 +1320,14 @@ private void PopulateProperties(
continue;
}
+ // Filter out deleted property before updating usedSlots, so that a deleted override in a subclass does not hide override in an ancestor.
+ if (MetadataUpdater.IsSupported &&
+ RuntimeTypeMetadataUpdateHandler.FilterDeletedMembers &&
+ RuntimeTypeMetadataUpdateHandler.IsMetadataUpdateDeleted(declaringModule, tkProperty))
+ {
+ continue;
+ }
+
RuntimePropertyInfo propertyInfo =
new RuntimePropertyInfo(
tkProperty, declaringType, m_runtimeTypeCache, out bool isPrivate);
@@ -1365,7 +1417,7 @@ private void PopulateProperties(
list.Add(propertyInfo);
}
- GC.KeepAlive(module);
+ GC.KeepAlive(declaringModule);
}
#endregion
@@ -1458,6 +1510,7 @@ private MemberInfoCache GetMemberCache(ref MemberInfoCache? m_cache)
return existingCache;
}
+
#endregion
#region Internal Members
diff --git a/src/coreclr/debug/daccess/request.cpp b/src/coreclr/debug/daccess/request.cpp
index 9f567d48809b39..462846d6027fe5 100644
--- a/src/coreclr/debug/daccess/request.cpp
+++ b/src/coreclr/debug/daccess/request.cpp
@@ -3249,7 +3249,7 @@ ClrDataAccess::GetHeapAnalyzeStaticData(struct DacpGcHeapAnalyzeData *analyzeDat
SOSDacEnter();
- analyzeData->internal_root_array = dac_cast(g_gcDacGlobals->internal_root_array);
+ analyzeData->internal_root_array = TO_CDADDR((TADDR)(*g_gcDacGlobals->internal_root_array));
analyzeData->internal_root_array_index = *g_gcDacGlobals->internal_root_array_index;
analyzeData->heap_analyze_success = *g_gcDacGlobals->heap_analyze_success;
diff --git a/src/coreclr/debug/daccess/request_svr.cpp b/src/coreclr/debug/daccess/request_svr.cpp
index d1dd6f046e8370..388c74ee12026c 100644
--- a/src/coreclr/debug/daccess/request_svr.cpp
+++ b/src/coreclr/debug/daccess/request_svr.cpp
@@ -225,7 +225,9 @@ HRESULT
ClrDataAccess::ServerGCInterestingInfoData(CLRDATA_ADDRESS addr, DacpGCInterestingInfoData *interestingInfoData)
{
#ifdef GC_CONFIG_DRIVEN
- dac_gc_heap *pHeap = __DPtr(TO_TADDR(addr));
+ TADDR heapAddress = TO_TADDR(addr);
+ dac_gc_heap heap = LoadGcHeapData(heapAddress);
+ dac_gc_heap* pHeap = &heap;
size_t* dataPoints = (size_t*)&(pHeap->interesting_data_per_heap);
for (int i = 0; i < NUM_GC_DATA_POINTS; i++)
diff --git a/src/coreclr/debug/dbgutil/elfreader.cpp b/src/coreclr/debug/dbgutil/elfreader.cpp
index c0b1c3cf4dbaaa..cb47e117644343 100644
--- a/src/coreclr/debug/dbgutil/elfreader.cpp
+++ b/src/coreclr/debug/dbgutil/elfreader.cpp
@@ -127,9 +127,8 @@ ElfReader::PopulateForSymbolLookup(uint64_t baseAddress)
// Enumerate program headers searching for the PT_DYNAMIC header, etc.
if (!EnumerateProgramHeaders(
baseAddress,
-#if defined(TARGET_LINUX_MUSL) || defined(TARGET_RISCV64)
- // On musl based platforms (Alpine) and RISCV64 (VisionFive2 board),
- // the below dynamic entries for hash,
+#if defined(TARGET_LINUX_MUSL) || defined(TARGET_RISCV64) || defined(TARGET_ANDROID)
+ // On some platforms, the below dynamic entries for hash,
// string table, etc. are RVAs instead of absolute address like on all
// other Linux distros. Get the "loadbias" (basically the base address
// of the module) and add to these RVAs.
diff --git a/src/coreclr/debug/di/process.cpp b/src/coreclr/debug/di/process.cpp
index 57e436c006300d..225c61843da634 100644
--- a/src/coreclr/debug/di/process.cpp
+++ b/src/coreclr/debug/di/process.cpp
@@ -963,7 +963,9 @@ CordbProcess::CordbProcess(ULONG64 clrInstanceId,
m_writableMetadataUpdateMode(LegacyCompatPolicy)
#ifdef OUT_OF_PROCESS_SETTHREADCONTEXT
,
- m_dwOutOfProcessStepping(0)
+ m_dwOutOfProcessStepping(0),
+ m_fOutOfProcessSetThreadContextEventReceived(false),
+ m_detachSetThreadContextNeededEvent(NULL)
#endif
{
_ASSERTE((m_id == 0) == (pShim == NULL));
@@ -1458,6 +1460,14 @@ void CordbProcess::CloseIPCHandles()
CloseHandle(m_stopWaitEvent);
m_stopWaitEvent = NULL;
}
+
+#ifdef OUT_OF_PROCESS_SETTHREADCONTEXT
+ if (m_detachSetThreadContextNeededEvent != NULL)
+ {
+ CloseHandle(m_detachSetThreadContextNeededEvent);
+ m_detachSetThreadContextNeededEvent = NULL;
+ }
+#endif
}
@@ -1775,6 +1785,14 @@ HRESULT CordbProcess::Init()
ThrowLastError();
}
+#ifdef OUT_OF_PROCESS_SETTHREADCONTEXT
+ m_detachSetThreadContextNeededEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+ if (m_detachSetThreadContextNeededEvent == NULL)
+ {
+ ThrowLastError();
+ }
+#endif
+
if (m_pShim != NULL)
{
// Get a handle to the debuggee.
@@ -3109,8 +3127,58 @@ void CordbProcess::DetachShim()
InitIPCEvent(pIPCEvent, DB_IPCE_DETACH_FROM_PROCESS, true, VMPTR_AppDomain::NullPtr());
hr = m_cordb->SendIPCEvent(this, pIPCEvent, CorDBIPC_BUFFER_SIZE);
+#ifdef OUT_OF_PROCESS_SETTHREADCONTEXT
+ if (hr == CORDBG_E_PROCESS_TERMINATED)
+ {
+ // If the process exited just after continuing the process, simply detach as if it had succeeded.
+ m_detached = true;
+ m_stopCount = 0;
+ return;
+ }
+#endif
hr = WORST_HR(hr, pIPCEvent->hr);
IfFailThrow(hr);
+
+#ifdef OUT_OF_PROCESS_SETTHREADCONTEXT
+ const HANDLE rghWaitSet[] = {
+ m_detachSetThreadContextNeededEvent, // Signaled on every debug event after the first SendCanDetach request
+ UnsafeGetProcessHandle() // Signaled when the process exits
+ };
+
+ bool fDetachComplete = !m_fOutOfProcessSetThreadContextEventReceived;
+ const DWORD DETACH_WAIT_TIMEOUT_MS = 5000; // 5 seconds
+ if (!fDetachComplete)
+ {
+ TryDetach(); // signal ourselves to see if we can detach right away
+ }
+ while (!fDetachComplete)
+ {
+ DWORD dwResult = WaitForMultipleObjectsEx(_countof(rghWaitSet), rghWaitSet, FALSE, DETACH_WAIT_TIMEOUT_MS, FALSE);
+ if (dwResult == WAIT_OBJECT_0)
+ {
+ // We have been signaled via TryDetach() to determine if it is safe to detach
+ // so call CanDetach and then detach if it returns S_OK
+ fDetachComplete = (this->m_pShim->GetWin32EventThread()->SendCanDetach() == S_OK);
+ }
+ else if (dwResult == WAIT_OBJECT_0 + 1 /*UnsafeGetProcessHandle()*/)
+ {
+ // The process has exited while waiting for the detach to complete
+ m_detached = true;
+ m_stopCount = 0;
+ return;
+ }
+ else
+ {
+ // We timed out waiting for debug events, indicating the process is idle.
+ // Simply detach as if it had succeeded.
+
+ _ASSERTE(dwResult == WAIT_TIMEOUT);
+ CONSISTENCY_CHECK_MSGF(false, ("Timeout while waiting for detach to complete"));
+
+ fDetachComplete = true;
+ }
+ }
+#endif
}
else
{
@@ -10833,7 +10901,10 @@ enum
W32ETA_CREATE_PROCESS = 1,
W32ETA_ATTACH_PROCESS = 2,
W32ETA_CONTINUE = 3,
- W32ETA_DETACH = 4
+ W32ETA_DETACH = 4,
+#ifdef OUT_OF_PROCESS_SETTHREADCONTEXT
+ W32ETA_CAN_DETACH = 5
+#endif // OUT_OF_PROCESS_SETTHREADCONTEXT
};
@@ -11111,7 +11182,7 @@ void CordbProcess::FilterClrNotification(
}
#ifdef OUT_OF_PROCESS_SETTHREADCONTEXT
-void CordbProcess::HandleSetThreadContextNeeded(DWORD dwThreadId)
+bool CordbProcess::HandleSetThreadContextNeeded(DWORD dwThreadId)
{
LOG((LF_CORDB, LL_INFO10000, "RS HandleSetThreadContextNeeded\n"));
@@ -11129,216 +11200,303 @@ void CordbProcess::HandleSetThreadContextNeeded(DWORD dwThreadId)
// Windows causes the process to have higher privileges.
// We are now caching the thread handle in the unmanaged thread hash table when the thread is created.
- UnmanagedThreadTracker * curThread = m_unmanagedThreadHashTable.Lookup(dwThreadId);
-
- if (curThread == NULL || curThread->GetThreadId() != dwThreadId)
+ class SetThreadContextNeededInfo
{
- LOG((LF_CORDB, LL_INFO10000, "RS HandleSetThreadContextNeeded - Thread not found\n"));
- ThrowHR(CORDBG_E_BAD_THREAD_STATE);
- }
+ TADDR m_lsContextAddr = 0;
+ DWORD m_contextSize = 0;
+ bool m_fIsInPlaceSingleStep = false;
+ bool m_fHasDebuggerPatchSkip = false;
+ bool m_fClearSetIP = false;
+ PRD_TYPE m_opcode = 0;
- HANDLE hThread = curThread->GetThreadHandle();
- if (hThread == INVALID_HANDLE_VALUE)
- {
- LOG((LF_CORDB, LL_INFO10000, "RS HandleSetThreadContextNeeded - Thread handle not found\n"));
- ThrowHR(CORDBG_E_BAD_THREAD_STATE);
- }
+ public:
+ void Update(DT_CONTEXT * pContext)
+ {
+ this->m_lsContextAddr = (TADDR)pContext->Rcx;
+ this->m_contextSize = (DWORD)pContext->Rdx;
+ this->m_fIsInPlaceSingleStep = (pContext->R8 & 0x1) != 0;
+ this->m_fHasDebuggerPatchSkip = (pContext->R8 & 0x2) != 0;
+ this->m_fClearSetIP = (pContext->R8 & 0x4) != 0;
+ this->m_opcode = (PRD_TYPE)pContext->R9;
+ }
- // Suspend the thread and so that we can read the thread context.
- DWORD previousSuspendCount = ::SuspendThread(hThread);
- if (previousSuspendCount == (DWORD)-1)
- {
- LOG((LF_CORDB, LL_INFO10000, "RS HandleSetThreadContextNeeded - Unexpected result from SuspendThread\n"));
- ThrowHR(HRESULT_FROM_GetLastError());
- }
+ TADDR ContextAddr() { return m_lsContextAddr; }
+ DWORD ContextSize() { return m_contextSize; }
+ bool IsInPlaceSingleStep() { return m_fIsInPlaceSingleStep; }
+ bool HasDebuggerPatchSkip() { return m_fHasDebuggerPatchSkip; }
+ bool IsClearSetIP() { return m_fClearSetIP; }
+ PRD_TYPE Opcode() { return m_opcode; }
- DT_CONTEXT context = { 0 };
- context.ContextFlags = CONTEXT_FULL;
+ HRESULT IsValid()
+ {
+ bool isValid = m_contextSize != 0 && m_contextSize <= sizeof(CONTEXT) + 25000;
+ return isValid ? S_OK : E_UNEXPECTED;
+ }
+ };
- // we originally used GetDataTarget()->GetThreadContext, but
- // the implementation uses ShimLocalDataTarget::GetThreadContext which
- // depends on OpenThread which might fail with an Access Denied error (see note above)
- BOOL success = ::GetThreadContext(hThread, (CONTEXT*)(&context));
- if (!success)
+ class ThreadSuspendResumeHolder
{
- LOG((LF_CORDB, LL_INFO10000, "RS HandleSetThreadContextNeeded - Unexpected result from GetThreadContext\n"));
- ThrowHR(HRESULT_FROM_GetLastError());
- }
+ UnmanagedThreadTracker *m_pThreadTracker;
+ HANDLE m_hThread;
+ BOOL m_suspended;
+ DWORD m_previousSuspendCount;
+ SetThreadContextNeededInfo m_Info;
- // Read the pointer to the left-side context and the size of the context from the thread context.
- TADDR lsContextAddr = (TADDR)context.Rcx;
- DWORD contextSize = (DWORD)context.Rdx;
+ public:
+ ThreadSuspendResumeHolder(UnmanagedThreadTracker *pThreadTracker) : m_pThreadTracker(pThreadTracker), m_hThread(NULL), m_suspended(FALSE), m_previousSuspendCount(0)
+ {
+ }
- bool fIsInPlaceSingleStep = (bool)(context.R8&0x1);
- PRD_TYPE opcode = (PRD_TYPE)context.R9;
+ ~ThreadSuspendResumeHolder()
+ {
+ Resume();
+ }
- if (contextSize == 0 || contextSize > sizeof(CONTEXT) + 25000)
- {
- _ASSERTE(!"Corrupted HandleSetThreadContextNeeded message received");
+ HRESULT Suspend()
+ {
+ if (!m_suspended)
+ {
+ m_hThread = m_pThreadTracker->GetThreadHandle();
+ if (m_hThread != INVALID_HANDLE_VALUE)
+ {
+ m_previousSuspendCount = ::SuspendThread(m_hThread);
+ if (m_previousSuspendCount != (DWORD)-1)
+ {
+ m_suspended = TRUE;
+ return S_OK;
+ }
+ }
+ }
+ return CORDBG_E_BAD_THREAD_STATE;
+ }
- LOG((LF_CORDB, LL_INFO10000, "RS HandleSetThreadContextNeeded - Corrupted HandleSetThreadContextNeeded message received\n"));
+ HRESULT Resume()
+ {
+ if (m_suspended)
+ {
+ DWORD suspendCount = ::ResumeThread(m_hThread);
+ _ASSERTE(suspendCount == m_previousSuspendCount + 1);
+ m_suspended = FALSE;
+ return S_OK;
+ }
+ return CORDBG_E_BAD_THREAD_STATE;
+ }
- ThrowHR(E_UNEXPECTED);
- }
+ HRESULT DecodeContextAndTrack()
+ {
+ if (!m_suspended || m_hThread == NULL || m_hThread == INVALID_HANDLE_VALUE)
+ {
+ return CORDBG_E_BAD_THREAD_STATE;
+ }
- PCONTEXT pContext = (PCONTEXT)_alloca(contextSize);
- ULONG32 cbRead;
- HRESULT hr = GetDataTarget()->ReadVirtual(lsContextAddr, reinterpret_cast(pContext), contextSize, &cbRead);
- if (FAILED(hr))
- {
- _ASSERTE(!"ReadVirtual failed");
+ DT_CONTEXT context = { 0 };
+ context.ContextFlags = CONTEXT_FULL;
- LOG((LF_CORDB, LL_INFO10000, "RS HandleSetThreadContextNeeded - ReadVirtual (error: 0x%X).\n", hr));
+ // we originally used GetDataTarget()->GetThreadContext, but
+ // the implementation uses ShimLocalDataTarget::GetThreadContext which
+ // depends on OpenThread which might fail with an Access Denied error (see note above)
+ BOOL success = ::GetThreadContext(m_hThread, (CONTEXT*)(&context));
+ if (!success)
+ {
+ return HRESULT_FROM_WIN32(GetLastError());
+ }
- ThrowHR(CORDBG_E_READVIRTUAL_FAILURE);
- }
+ m_Info.Update(&context);
- if (cbRead != contextSize)
- {
- _ASSERTE(!"ReadVirtual context size mismatch");
+#ifdef _DEBUG
+ m_pThreadTracker->SetIsDebuggerPatchSkip(m_Info.HasDebuggerPatchSkip());
+#endif
+ m_pThreadTracker->SetPendingSetIP(m_Info.IsInPlaceSingleStep() || m_Info.HasDebuggerPatchSkip());
- LOG((LF_CORDB, LL_INFO10000, "RS HandleSetThreadContextNeeded - ReadVirtual context size mismatch\n"));
+ return S_OK;
+ }
- ThrowHR(ERROR_PARTIAL_COPY);
- }
+ HRESULT GetLocalContextSize(PCONTEXT pContext, DWORD * pContextSize)
+ {
+ // The initialize call should fail but return contextSize
+ if (pContext == NULL || pContextSize == NULL)
+ {
+ return E_INVALIDARG;
+ }
+ *pContextSize = 0;
+ DWORD contextFlags = pContext->ContextFlags;
+ BOOL success = InitializeContext(NULL, contextFlags, NULL, pContextSize);
+ if(success || GetLastError() != ERROR_INSUFFICIENT_BUFFER)
+ {
+ return CORDBG_E_BAD_THREAD_STATE;
+ }
- // TODO: Ideally we would use ICorDebugMutableDataTarget::SetThreadContext however this API currently only handles the legacy context.
- // We should combine the following code with the shared implementation
+ return S_OK;
+ }
- // The initialize call should fail but return contextSize
- contextSize = 0;
- DWORD contextFlags = pContext->ContextFlags;
- success = InitializeContext(NULL, contextFlags, NULL, &contextSize);
+ HRESULT CopyContextLocal(PVOID pBuffer, PCONTEXT pContext, PCONTEXT * ppFrameContext, DWORD * pContextSize)
+ {
+ if (pBuffer == NULL || pContext == NULL || ppFrameContext == NULL || pContextSize == NULL)
+ {
+ return E_INVALIDARG;
+ }
+ BOOL success = ::InitializeContext(pBuffer, pContext->ContextFlags, ppFrameContext, pContextSize);
+ if (!success)
+ {
+ return HRESULT_FROM_WIN32(GetLastError());
+ }
+ if (*ppFrameContext == NULL || *pContextSize == 0)
+ {
+ return E_UNEXPECTED;
+ }
- if(success || GetLastError() != ERROR_INSUFFICIENT_BUFFER)
- {
- _ASSERTE(!"InitializeContext unexpectedly succeeded or didn't return ERROR_INSUFFICIENT_BUFFER");
+ _ASSERTE((BYTE*)*ppFrameContext == pBuffer);
- LOG((LF_CORDB, LL_INFO10000, "RS HandleSetThreadContextNeeded - InitializeContext unexpectedly succeeded or didn't return ERROR_INSUFFICIENT_BUFFER\n"));
+ success = ::CopyContext(*ppFrameContext, pContext->ContextFlags, pContext);
+ if (!success)
+ {
+ return HRESULT_FROM_WIN32(GetLastError());
+ }
- ThrowHR(E_UNEXPECTED);
- }
+ return S_OK;
+ }
- LOG((LF_CORDB, LL_INFO10000, "RS HandleSetThreadContextNeeded - InitializeContext ContextSize %d\n", contextSize));
+ HRESULT SetThreadContext(PCONTEXT pFrameContext)
+ {
+ if (!m_suspended || pFrameContext == NULL || m_hThread == NULL || m_hThread == INVALID_HANDLE_VALUE)
+ {
+ return CORDBG_E_BAD_THREAD_STATE;
+ }
- PVOID pBuffer = _alloca(contextSize);
- PCONTEXT pFrameContext = NULL;
- success = InitializeContext(pBuffer, contextFlags, &pFrameContext, &contextSize);
- if (!success)
- {
- HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
- _ASSERTE(!"InitializeContext failed");
+ // TODO: Ideally we would use ICorDebugMutableDataTarget::SetThreadContext however this API currently only handles the legacy context.
+ // We should combine the following code with the shared implementation
+ BOOL success = ::SetThreadContext(m_hThread, pFrameContext);
+ if (!success)
+ {
+ return HRESULT_FROM_WIN32(GetLastError());
+ }
+ return S_OK;
+ }
- LOG((LF_CORDB, LL_INFO10000, "RS HandleSetThreadContextNeeded - Unexpected result from InitializeContext (error: 0x%X [%d]).\n", hr, GetLastError()));
+ SetThreadContextNeededInfo * Info() { return &m_Info; }
+ };
- ThrowHR(hr);
- }
+ m_fOutOfProcessSetThreadContextEventReceived = true;
- _ASSERTE((BYTE*)pFrameContext == pBuffer);
+ UnmanagedThreadTracker * curThread = m_unmanagedThreadHashTable.Lookup(dwThreadId);
- success = CopyContext(pFrameContext, contextFlags, pContext);
- LOG((LF_CORDB, LL_INFO10000, "RS HandleSetThreadContextNeeded - CopyContext=%s %d\n", success?"SUCCESS":"FAIL", GetLastError()));
- if (!success)
+ if (curThread == NULL || curThread->GetThreadId() != dwThreadId)
{
- HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
- _ASSERTE(!"CopyContext failed");
-
- LOG((LF_CORDB, LL_INFO10000, "RS HandleSetThreadContextNeeded - Unexpected result from CopyContext (error: 0x%X [%d]).\n", hr, GetLastError()));
-
- ThrowHR(hr);
+ LOG((LF_CORDB, LL_INFO10000, "RS HandleSetThreadContextNeeded - Thread not found\n"));
+ ThrowHR(CORDBG_E_BAD_THREAD_STATE);
}
- LOG((LF_CORDB, LL_INFO10000, "RS HandleSetThreadContextNeeded - Set Thread Context - ID = 0x%X, SS enabled = %d\n", dwThreadId, /*(uint64_t)hThread,*/ (pContext->EFlags & 0x100) != 0));
+ ThreadSuspendResumeHolder threadHolder(curThread);
- DWORD lastError = 0;
+ IfFailThrow(threadHolder.Suspend());
+
+ // Read the pointer to the left-side context and the size of the context from the thread context.
+ IfFailThrow(threadHolder.DecodeContextAndTrack());
- // Perform the actual SetThreadContext operation.
- success = ::SetThreadContext(hThread, pFrameContext);
- if (!success)
+ if (threadHolder.Info()->IsClearSetIP())
{
- lastError = ::GetLastError();
+ _ASSERTE(!threadHolder.Info()->IsInPlaceSingleStep() && !threadHolder.Info()->HasDebuggerPatchSkip());
+ LOG((LF_CORDB, LL_INFO10000, "RS HandleSetThreadContextNeeded - Clear the pending SetIP flag for this thread\n"));
+ return false; // we should let this event propagate back to the left side
}
- LOG((LF_CORDB, LL_INFO10000, "RS HandleSetThreadContextNeeded - Set Thread Context Completed: Success=%d GetLastError=%d hr=0x%X\n", success, lastError, HRESULT_FROM_WIN32(lastError)));
- _ASSERTE(success);
+ IfFailThrow(threadHolder.Info()->IsValid());
- // Now that we have completed the SetThreadContext, resume the thread
- DWORD suspendCount = ::ResumeThread(hThread);
- if (suspendCount == (DWORD)-1)
+ LOG((LF_CORDB, LL_INFO10000, "RS HandleSetThreadContextNeeded - Thread 0x%X fHasDebuggerPatchSkip=%d\n", dwThreadId, threadHolder.Info()->HasDebuggerPatchSkip()));
+
+ PCONTEXT pLocalContext = (PCONTEXT)_alloca(threadHolder.Info()->ContextSize());
+ ULONG32 cbRead;
+ HRESULT hr = GetDataTarget()->ReadVirtual(threadHolder.Info()->ContextAddr(), reinterpret_cast(pLocalContext), threadHolder.Info()->ContextSize(), &cbRead);
+ if (FAILED(hr) || cbRead != threadHolder.Info()->ContextSize())
{
- LOG((LF_CORDB, LL_INFO10000, "RS HandleSetThreadContextNeeded - Unexpected result from ResumeThread\n"));
- ThrowHR(HRESULT_FROM_GetLastError());
+ _ASSERTE(!"ReadVirtual failed");
+
+ LOG((LF_CORDB, LL_INFO10000, "RS HandleSetThreadContextNeeded - ReadVirtual (error: 0x%X).\n", hr));
+
+ ThrowHR(CORDBG_E_READVIRTUAL_FAILURE);
}
- if (suspendCount != previousSuspendCount + 1)
+
+ DWORD localContextSize = 0;
+ IfFailThrow(threadHolder.GetLocalContextSize(pLocalContext, &localContextSize));
+
+ PVOID pBuffer = _alloca(localContextSize);
+ PCONTEXT pFrameContext = NULL;
+ IfFailThrow(threadHolder.CopyContextLocal(pBuffer, pLocalContext, &pFrameContext, &localContextSize));
+
+ LOG((LF_CORDB, LL_INFO10000, "RS HandleSetThreadContextNeeded - Set Thread Context - ID = 0x%X, SS enabled = %d\n", dwThreadId, (pLocalContext->EFlags & 0x100) != 0));
+ IfFailThrow(threadHolder.SetThreadContext(pFrameContext));
+
+ IfFailThrow(threadHolder.Resume());
+
+ if (threadHolder.Info()->IsInPlaceSingleStep())
{
- LOG((LF_CORDB, LL_INFO10000, "RS HandleSetThreadContextNeeded - Unexpected result from ResumeThread\n"));
- ThrowHR(E_UNEXPECTED);
+ IfFailThrow(EnableInPlaceSingleStepping(curThread, (CORDB_ADDRESS_TYPE*)pFrameContext->Rip, threadHolder.Info()->Opcode()));
}
- if (!success)
+ return true; // this event was handled, so we should not let this event propagate back to the left side
+#else
+ #error Platform not supported
+#endif
+}
+
+HRESULT CordbProcess::EnableInPlaceSingleStepping(UnmanagedThreadTracker * pCurThread, CORDB_ADDRESS_TYPE *patchSkipAddr, PRD_TYPE opcode)
+{
+ if (pCurThread == NULL || patchSkipAddr == NULL)
{
- LOG((LF_CORDB, LL_INFO10000, "RS HandleSetThreadContextNeeded - Unexpected result from SetThreadContext\n"));
- ThrowHR(HRESULT_FROM_WIN32(lastError));
+ return E_INVALIDARG;
}
+ HANDLE hProcess = UnsafeGetProcessHandle();
+ LPVOID baseAddress = (LPVOID)(patchSkipAddr);
+ DWORD oldProt;
- if (fIsInPlaceSingleStep)
+ if (!VirtualProtectEx(hProcess,
+ baseAddress,
+ CORDbg_BREAK_INSTRUCTION_SIZE,
+ PAGE_EXECUTE_READWRITE, &oldProt))
{
- CORDB_ADDRESS_TYPE *patchSkipAddr = (CORDB_ADDRESS_TYPE*)pFrameContext->Rip;
-
- HANDLE hProcess = UnsafeGetProcessHandle();
- LPVOID baseAddress = (LPVOID)(patchSkipAddr);
- DWORD oldProt;
-
+ // we may be seeing unwriteable directly mapped executable memory.
+ // let's try copy-on-write instead,
if (!VirtualProtectEx(hProcess,
- baseAddress,
- CORDbg_BREAK_INSTRUCTION_SIZE,
- PAGE_EXECUTE_READWRITE, &oldProt))
+ baseAddress,
+ CORDbg_BREAK_INSTRUCTION_SIZE,
+ PAGE_EXECUTE_WRITECOPY, &oldProt))
{
- // we may be seeing unwriteable directly mapped executable memory.
- // let's try copy-on-write instead,
- if (!VirtualProtectEx(hProcess,
- baseAddress,
- CORDbg_BREAK_INSTRUCTION_SIZE,
- PAGE_EXECUTE_WRITECOPY, &oldProt))
- {
- _ASSERTE(!"VirtualProtect of code page failed");
- ThrowHR(HRESULT_FROM_GetLastError());
- }
+ _ASSERTE(!"VirtualProtect of code page failed");
+ return HRESULT_FROM_GetLastError();
}
+ }
- LOG((LF_CORDB, LL_INFO10000, "RS HandleSetThreadContextNeeded - address=0x%p opcode=0x%x\n", patchSkipAddr, opcode));
- HRESULT hr = RemoveRemotePatch(this, (void*)patchSkipAddr, opcode);
- IfFailThrow(hr);
+ LOG((LF_CORDB, LL_INFO10000, "RS EnableInPlaceSingleStepping - address=0x%p opcode=0x%x\n", patchSkipAddr, opcode));
+ HRESULT hr = RemoveRemotePatch(this, (void*)patchSkipAddr, opcode);
+ IfFailRet(hr);
- if (!VirtualProtectEx(hProcess,
- baseAddress,
- CORDbg_BREAK_INSTRUCTION_SIZE,
- oldProt, &oldProt))
- {
- _ASSERTE(!"VirtualProtect of code page failed");
- ThrowHR(HRESULT_FROM_GetLastError());
- }
+ if (!VirtualProtectEx(hProcess,
+ baseAddress,
+ CORDbg_BREAK_INSTRUCTION_SIZE,
+ oldProt, &oldProt))
+ {
+ _ASSERTE(!"VirtualProtect of code page failed");
+ return HRESULT_FROM_GetLastError();
+ }
- curThread->SetPatchSkipAddress(patchSkipAddr);
+ pCurThread->SetPatchSkipAddress(patchSkipAddr);
- // suspend all other threads
- m_dwOutOfProcessStepping++;
- CUnmanagedThreadHashTableIterator beginIter = m_unmanagedThreadHashTable.Begin();
- CUnmanagedThreadHashTableIterator endIter = m_unmanagedThreadHashTable.End();
- for (CUnmanagedThreadHashTableIterator curIter = beginIter; curIter != endIter; ++curIter)
+ // suspend all other threads
+ m_dwOutOfProcessStepping++;
+ CUnmanagedThreadHashTableIterator beginIter = m_unmanagedThreadHashTable.Begin();
+ CUnmanagedThreadHashTableIterator endIter = m_unmanagedThreadHashTable.End();
+ for (CUnmanagedThreadHashTableIterator curIter = beginIter; curIter != endIter; ++curIter)
+ {
+ UnmanagedThreadTracker * pUnmanagedThread = *curIter;
+ _ASSERTE(pUnmanagedThread != NULL);
+ if (pUnmanagedThread == NULL || pUnmanagedThread->GetThreadId() == pCurThread->GetThreadId())
{
- UnmanagedThreadTracker * pUnmanagedThread = *curIter;
- _ASSERTE(pUnmanagedThread != NULL);
- if (pUnmanagedThread == NULL || pUnmanagedThread->GetThreadId() == dwThreadId)
- {
- continue;
- }
- pUnmanagedThread->Suspend();
+ continue;
}
+ pUnmanagedThread->Suspend();
}
-#else
- #error Platform not supported
-#endif
+
+ return S_OK;
}
bool CordbProcess::HandleInPlaceSingleStep(DWORD dwThreadId, PVOID pExceptionAddress)
@@ -11402,11 +11560,34 @@ bool CordbProcess::HandleInPlaceSingleStep(DWORD dwThreadId, PVOID pExceptionAdd
pUnmanagedThread->Resume();
}
+ LOG((LF_CORDB, LL_INFO10000, "RS HandleInPlaceSingleStep - Thread 0x%X\n", dwThreadId));
+#ifdef _DEBUG
+ _ASSERTE(curThread->IsDebuggerPatchSkip());
+ curThread->SetIsDebuggerPatchSkip(false);
+#endif
+ _ASSERTE(curThread->HasPendingSetIP());
+ curThread->SetPendingSetIP(false);
+
return true;
}
return false;
}
+
+bool CordbProcess::SetPendingSetIP(DWORD dwThreadId)
+{
+ HRESULT hr = S_OK;
+ UnmanagedThreadTracker * curThread = m_unmanagedThreadHashTable.Lookup(dwThreadId);
+
+ if (curThread == NULL || curThread->GetThreadId() != dwThreadId)
+ {
+ CONSISTENCY_CHECK_MSG(false, ("SetPendingSetIP - Thread not found"));
+ return false;
+ }
+
+ curThread->SetPendingSetIP(true);
+ return true;
+}
#endif // OUT_OF_PROCESS_SETTHREADCONTEXT
//
@@ -11656,21 +11837,40 @@ HRESULT CordbProcess::Filter(
// holder will invoke DeleteIPCEventHelper(pManagedEvent).
}
#ifdef OUT_OF_PROCESS_SETTHREADCONTEXT
- else if (dwFirstChance && pRecord->ExceptionCode == STATUS_BREAKPOINT && pRecord->ExceptionAddress == m_runtimeOffsets.m_setThreadContextNeededAddr)
+ else if (dwFirstChance && pRecord->ExceptionCode == STATUS_BREAKPOINT)
{
- // this is a request to set the thread context out of process
+ if (pRecord->ExceptionAddress == m_runtimeOffsets.m_setThreadContextNeededAddr)
+ {
+ // this is a request to set the thread context out of process
- HandleSetThreadContextNeeded(dwThreadId);
- *pContinueStatus = DBG_CONTINUE;
+ if (HandleSetThreadContextNeeded(dwThreadId))
+ {
+ *pContinueStatus = DBG_CONTINUE;
+ }
+ else
+ {
+ *pContinueStatus = DBG_EXCEPTION_NOT_HANDLED;
+ }
+ }
+ else
+ {
+ if (!SetPendingSetIP(dwThreadId))
+ {
+ _ASSERTE(!"SetPendingSetIP failed");
+ }
+ }
}
- else if (dwFirstChance && pRecord->ExceptionCode == STATUS_SINGLE_STEP && m_dwOutOfProcessStepping > 0)
+ else if (dwFirstChance && pRecord->ExceptionCode == STATUS_SINGLE_STEP)
{
- // this may be an in-place step, and if so place the breakpoint instruction back to the patch location and resume the threads
-
- if (HandleInPlaceSingleStep(dwThreadId, pRecord->ExceptionAddress))
+ if (m_dwOutOfProcessStepping > 0)
{
- // let the normal left side debugger stepper logic execute for this single step
- *pContinueStatus = DBG_EXCEPTION_NOT_HANDLED;
+ // this may be an in-place step, and if so place the breakpoint instruction back to the patch location and resume the threads
+
+ if (HandleInPlaceSingleStep(dwThreadId, pRecord->ExceptionAddress))
+ {
+ // let the normal left side debugger stepper logic execute for this single step
+ *pContinueStatus = DBG_EXCEPTION_NOT_HANDLED;
+ }
}
}
#endif
@@ -11745,6 +11945,8 @@ void CordbWin32EventThread::Win32EventLoop()
// Allow the timeout for WFDE to be adjustable. Default to 25 ms based off perf numbers (see issue VSWhidbey 132368).
DWORD dwWFDETimeout = CLRConfig::GetConfigValue(CLRConfig::UNSUPPORTED_DbgWFDETimeout);
+ BOOL fIsDetaching = FALSE;
+
while (m_run)
{
BOOL fEventAvailable = FALSE;
@@ -11885,6 +12087,13 @@ void CordbWin32EventThread::Win32EventLoop()
HandleUnmanagedContinue();
}
#endif // FEATURE_INTEROP_DEBUGGING
+#ifdef OUT_OF_PROCESS_SETTHREADCONTEXT
+ else if (m_action == W32ETA_CAN_DETACH)
+ {
+ HandleCanDetach();
+ fIsDetaching = TRUE;
+ }
+#endif
// We don't need to sweep the FCH threads since we never hijack a thread in cooperative mode.
@@ -11907,6 +12116,18 @@ void CordbWin32EventThread::Win32EventLoop()
// Must flush the dac cache since we were just running.
m_pProcess->ForceDacFlush();
+#ifdef OUT_OF_PROCESS_SETTHREADCONTEXT
+ bool fOutOfProcessSteppingDuringDetach = false;
+ if (fIsDetaching &&
+ event.dwDebugEventCode == EXCEPTION_DEBUG_EVENT &&
+ event.u.Exception.dwFirstChance &&
+ event.u.Exception.ExceptionRecord.ExceptionCode == STATUS_SINGLE_STEP &&
+ m_pProcess->IsOutOfProcessStepping())
+ {
+ fOutOfProcessSteppingDuringDetach = true;
+ }
+#endif
+
// So we've filtered out CLR events.
// Let the shim handle the remaining events. This will call back into Filter() if appropriate.
// This will also ensure the debug event gets continued.
@@ -11915,6 +12136,22 @@ void CordbWin32EventThread::Win32EventLoop()
PUBLIC_CALLBACK_IN_THIS_SCOPE0_NO_LOCK(NULL);
hrShim = m_pShim->HandleWin32DebugEvent(&event);
}
+#ifdef OUT_OF_PROCESS_SETTHREADCONTEXT
+ // If we are detaching and have 1) handled a SetThreadContextNeeded flare or 2) out-of-process stepping event,
+ // then signal that we should re-evaluate if detach is possible.
+ if (fIsDetaching &&
+ event.dwDebugEventCode == EXCEPTION_DEBUG_EVENT &&
+ event.u.Exception.dwFirstChance &&
+ ( event.u.Exception.ExceptionRecord.ExceptionCode == STATUS_BREAKPOINT &&
+ event.u.Exception.ExceptionRecord.ExceptionAddress == m_pProcess->m_runtimeOffsets.m_setThreadContextNeededAddr
+ ||
+ event.u.Exception.ExceptionRecord.ExceptionCode == STATUS_SINGLE_STEP &&
+ fOutOfProcessSteppingDuringDetach
+ ))
+ {
+ m_pProcess->TryDetach();
+ }
+#endif
// Any errors from the shim (eg. failure to load DAC) are unrecoverable
SetUnrecoverableIfFailed(m_pProcess, hrShim);
@@ -14911,6 +15148,49 @@ void CordbWin32EventThread::ExitProcess(bool fDetach)
m_pProcess.Clear();
}
+#ifdef OUT_OF_PROCESS_SETTHREADCONTEXT
+HRESULT CordbWin32EventThread::SendCanDetach()
+{
+ HRESULT hr = S_OK;
+
+ LockSendToWin32EventThreadMutex();
+
+ m_action = W32ETA_CAN_DETACH;
+
+ BOOL succ = SetEvent(m_threadControlEvent);
+
+ if (succ)
+ {
+ DWORD ret = WaitForSingleObject(m_actionTakenEvent, INFINITE);
+
+ if (ret == WAIT_OBJECT_0)
+ hr = m_actionResult;
+ else
+ hr = HRESULT_FROM_GetLastError();
+ }
+ else
+ hr = HRESULT_FROM_GetLastError();
+
+ UnlockSendToWin32EventThreadMutex();
+
+ return hr;
+}
+
+void CordbWin32EventThread::HandleCanDetach()
+{
+ _ASSERTE(IsWin32EventThread());
+ _ASSERTE(m_pProcess != NULL);
+
+ m_action = W32ETA_NONE;
+ HRESULT hr = S_OK;
+
+ bool canDetach = m_pProcess->CanDetach();
+
+ // Signal the hr to the caller.
+ m_actionResult = canDetach ? S_OK : S_FALSE;
+ SetEvent(m_actionTakenEvent);
+}
+#endif
//
// Start actually creates and starts the thread.
@@ -15521,4 +15801,39 @@ void CordbProcess::HandleDebugEventForInPlaceStepping(const DEBUG_EVENT * pEvent
break;
}
}
+
+bool CordbProcess::CanDetach()
+{
+ HRESULT hr = S_OK;
+
+ CUnmanagedThreadHashTableIterator beginIter = m_unmanagedThreadHashTable.Begin();
+ CUnmanagedThreadHashTableIterator endIter = m_unmanagedThreadHashTable.End();
+ for (CUnmanagedThreadHashTableIterator curIter = beginIter; curIter != endIter; ++curIter)
+ {
+ UnmanagedThreadTracker * pUnmanagedThread = *curIter;
+ _ASSERTE(pUnmanagedThread != NULL);
+ if (pUnmanagedThread == NULL)
+ {
+ continue;
+ }
+ if (pUnmanagedThread->IsInPlaceStepping())
+ {
+ return false;
+ }
+ if (pUnmanagedThread->HasPendingSetIP())
+ {
+ return false;
+ }
+#ifdef _DEBUG
+ _ASSERTE(!pUnmanagedThread->IsDebuggerPatchSkip());
+#endif
+ }
+
+ return true;
+}
+
+void CordbProcess::TryDetach()
+{
+ SetEvent(m_detachSetThreadContextNeededEvent);
+}
#endif // OUT_OF_PROCESS_SETTHREADCONTEXT
diff --git a/src/coreclr/debug/di/rspriv.h b/src/coreclr/debug/di/rspriv.h
index 21a7703838f134..eea9a94b58182d 100644
--- a/src/coreclr/debug/di/rspriv.h
+++ b/src/coreclr/debug/di/rspriv.h
@@ -2920,10 +2920,14 @@ struct DbgAssertAppDomainDeletedData
#ifdef OUT_OF_PROCESS_SETTHREADCONTEXT
class UnmanagedThreadTracker
{
- DWORD m_dwThreadId = (DWORD)-1;
- HANDLE m_hThread = INVALID_HANDLE_VALUE;
- CORDB_ADDRESS_TYPE *m_pPatchSkipAddress = NULL;
- DWORD m_dwSuspendCount = 0;
+ DWORD m_dwThreadId = (DWORD)-1; // The OS thread ID of the unmanaged thread we are tracking
+ HANDLE m_hThread = INVALID_HANDLE_VALUE; // Handle to the unmanaged thread, used for suspending and resuming the thread
+ CORDB_ADDRESS_TYPE *m_pPatchSkipAddress = NULL; // If non-NULL, this is the address to which we should set the IP when resuming the thread.
+ DWORD m_dwSuspendCount = 0; // The suspend count of the thread when we last checked it.
+ bool m_pendingSetIP = false; // Set to true if there is a breakpoint or outstanding single-step operation on target thread
+#ifdef _DEBUG
+ bool m_fIsDebuggerPatchSkip = false; // Set to true if the thread is currently in a debugger patch skip
+#endif
public:
UnmanagedThreadTracker(DWORD wThreadId, HANDLE hThread) : m_dwThreadId(wThreadId), m_hThread(hThread) {}
@@ -2937,6 +2941,14 @@ class UnmanagedThreadTracker
void Suspend();
void Resume();
void Close();
+#ifdef OUT_OF_PROCESS_SETTHREADCONTEXT
+ void SetPendingSetIP(bool fPendingSetIP) { m_pendingSetIP = fPendingSetIP; }
+ bool HasPendingSetIP() const { return m_pendingSetIP; }
+#ifdef _DEBUG
+ void SetIsDebuggerPatchSkip(bool fIsDebuggerPatchSkip) { m_fIsDebuggerPatchSkip = fIsDebuggerPatchSkip; }
+ bool IsDebuggerPatchSkip() const { return m_fIsDebuggerPatchSkip; }
+#endif
+#endif // OUT_OF_PROCESS_SETTHREADCONTEXT
};
class EMPTY_BASES_DECL CUnmanagedThreadSHashTraits : public DefaultSHashTraits
@@ -3316,8 +3328,9 @@ class CordbProcess :
}
#ifdef OUT_OF_PROCESS_SETTHREADCONTEXT
- void HandleSetThreadContextNeeded(DWORD dwThreadId);
+ bool HandleSetThreadContextNeeded(DWORD dwThreadId);
bool HandleInPlaceSingleStep(DWORD dwThreadId, PVOID pExceptionAddress);
+ bool SetPendingSetIP(DWORD dwThreadId);
#endif
//
@@ -4151,8 +4164,15 @@ class CordbProcess :
#ifdef OUT_OF_PROCESS_SETTHREADCONTEXT
CUnmanagedThreadHashTableImpl m_unmanagedThreadHashTable;
DWORD m_dwOutOfProcessStepping;
+ bool m_fOutOfProcessSetThreadContextEventReceived;
+ HRESULT EnableInPlaceSingleStepping(UnmanagedThreadTracker * pCurThread, CORDB_ADDRESS_TYPE *patchSkipAddr, PRD_TYPE opcode);
public:
void HandleDebugEventForInPlaceStepping(const DEBUG_EVENT * pEvent);
+ bool CanDetach(); // Must only be called on the Win32ET, determines if it is safe to detach. Only used by W32ETA_CAN_DETACH
+ void TryDetach(); // Sets detach state to TryDetach, starting the detach evacuation counter.
+ bool IsOutOfProcessStepping() { return m_dwOutOfProcessStepping != 0; }
+private:
+ HANDLE m_detachSetThreadContextNeededEvent;
#endif // OUT_OF_PROCESS_SETTHREADCONTEXT
};
@@ -10160,6 +10180,10 @@ class CordbWin32EventThread
HRESULT SendDetachProcessEvent(CordbProcess *pProcess);
+#ifdef OUT_OF_PROCESS_SETTHREADCONTEXT
+ HRESULT SendCanDetach();
+#endif
+
#ifdef FEATURE_INTEROP_DEBUGGING
HRESULT SendUnmanagedContinue(CordbProcess *pProcess,
EUMContinueType eContType);
@@ -10211,6 +10235,10 @@ class CordbWin32EventThread
void ExitProcess(bool fDetach);
+#ifdef OUT_OF_PROCESS_SETTHREADCONTEXT
+ void HandleCanDetach();
+#endif
+
private:
RSSmartPtr m_cordb;
diff --git a/src/coreclr/debug/ee/controller.cpp b/src/coreclr/debug/ee/controller.cpp
index 794f0a693bfeb8..0a6644c273e40a 100644
--- a/src/coreclr/debug/ee/controller.cpp
+++ b/src/coreclr/debug/ee/controller.cpp
@@ -1153,8 +1153,10 @@ void DebuggerController::DeleteAllControllers()
while (pDebuggerController != NULL)
{
pNextDebuggerController = pDebuggerController->m_next;
- pDebuggerController->DebuggerDetachClean();
- pDebuggerController->Delete();
+ if (pDebuggerController->DebuggerDetachClean())
+ {
+ pDebuggerController->Delete();
+ }
pDebuggerController = pNextDebuggerController;
}
}
@@ -1216,9 +1218,10 @@ void DebuggerController::Delete()
}
}
-void DebuggerController::DebuggerDetachClean()
+bool DebuggerController::DebuggerDetachClean()
{
//do nothing here
+ return true;
}
//static
@@ -4466,9 +4469,9 @@ bool DebuggerController::DispatchNativeException(EXCEPTION_RECORD *pException,
// so remember the attach state now.
#ifdef _DEBUG
bool fWasAttached = false;
-#ifdef DEBUGGING_SUPPORTED
+#if defined(DEBUGGING_SUPPORTED) && !defined(OUT_OF_PROCESS_SETTHREADCONTEXT)
fWasAttached = (CORDebuggerAttached() != 0);
-#endif //DEBUGGING_SUPPORTED
+#endif //DEBUGGING_SUPPORTED && !OUT_OF_PROCESS_SETTHREADCONTEXT
#endif //_DEBUG
{
@@ -4574,12 +4577,14 @@ bool DebuggerController::DispatchNativeException(EXCEPTION_RECORD *pException,
);
LOG((LF_CORDB, LL_EVERYTHING, "DC::DNE DispatchPatch call returned\n"));
+#ifndef OUT_OF_PROCESS_SETTHREADCONTEXT
// If we detached, we should remove all our breakpoints. So if we try
// to handle this breakpoint, make sure that we're attached.
if (IsInUsedAction(result) == true)
{
_ASSERTE(fWasAttached);
}
+#endif
break;
case EXCEPTION_SINGLE_STEP:
@@ -4773,7 +4778,7 @@ DebuggerPatchSkip::~DebuggerPatchSkip()
#endif // !FEATURE_EMULATE_SINGLESTEP
}
-void DebuggerPatchSkip::DebuggerDetachClean()
+bool DebuggerPatchSkip::DebuggerDetachClean()
{
// Since for ARM/ARM64 SharedPatchBypassBuffer isn't existed, we don't have to anything here.
#ifndef FEATURE_EMULATE_SINGLESTEP
@@ -4792,6 +4797,15 @@ void DebuggerPatchSkip::DebuggerDetachClean()
// 2. Create a "stack walking" implementation for native code and use it to get the current IP and
// set the IP to the right place.
+#ifdef OUT_OF_PROCESS_SETTHREADCONTEXT
+ // during detach we need to ensure the context is only being updated out of process
+ bool bUsingOutOfProcEvents = g_pDebugInterface->IsOutOfProcessSetContextEnabled();
+ if (bUsingOutOfProcEvents)
+ {
+ return false;
+ }
+#endif
+
Thread *thread = GetThreadNULLOk();
if (thread != NULL)
{
@@ -4806,6 +4820,8 @@ void DebuggerPatchSkip::DebuggerDetachClean()
}
}
#endif // !FEATURE_EMULATE_SINGLESTEP
+
+ return true;
}
TP_RESULT DebuggerPatchSkip::TriggerPatch(DebuggerControllerPatch *patch,
diff --git a/src/coreclr/debug/ee/controller.h b/src/coreclr/debug/ee/controller.h
index 32138edc36aba7..10bc8c8a26da50 100644
--- a/src/coreclr/debug/ee/controller.h
+++ b/src/coreclr/debug/ee/controller.h
@@ -1223,7 +1223,7 @@ class DebuggerController
static void ApplyTraceFlag(Thread *thread);
static void UnapplyTraceFlag(Thread *thread);
- virtual void DebuggerDetachClean();
+ virtual bool DebuggerDetachClean();
public:
static const BYTE *GetILPrestubDestination(const BYTE *prestub);
@@ -1525,7 +1525,7 @@ class DebuggerPatchSkip : public DebuggerController
void DecodeInstruction(CORDB_ADDRESS_TYPE *code);
- void DebuggerDetachClean();
+ bool DebuggerDetachClean();
CORDB_ADDRESS_TYPE *m_address;
int m_iOrigDisp; // the original displacement of a relative call or jump
diff --git a/src/coreclr/debug/ee/debugger.cpp b/src/coreclr/debug/ee/debugger.cpp
index 9bc5cda485d176..c051ab386fa701 100644
--- a/src/coreclr/debug/ee/debugger.cpp
+++ b/src/coreclr/debug/ee/debugger.cpp
@@ -5451,6 +5451,14 @@ bool Debugger::FirstChanceNativeException(EXCEPTION_RECORD *exception,
bool retVal;
#ifdef OUT_OF_PROCESS_SETTHREADCONTEXT
DebuggerSteppingInfo debuggerSteppingInfo;
+ if ((void*)GetIP(context) == (void*)SetThreadContextNeededFlare)
+ {
+ // The out-of-proc debugger is ignoring the SetThreadContextNeeded flare
+ // SSP will be pointing to the instruction after the breakpoint, so advance the IP to that instruction and continue
+ PCODE ip = ::GetIP(context);
+ ::SetIP(context, ip + CORDbg_BREAK_INSTRUCTION_SIZE);
+ return true;
+ }
#endif
{
@@ -5473,11 +5481,15 @@ bool Debugger::FirstChanceNativeException(EXCEPTION_RECORD *exception,
}
#if defined(OUT_OF_PROCESS_SETTHREADCONTEXT) && !defined(DACCESS_COMPILE)
- if (retVal && fIsVEH)
+ // NOTE: During detach, the right-side will wait until all SendSetThreadContextNeeded flares have been sent
+ // We assume that any breakpoint debug event caught on the right-side will result in a SendSetThreadContextNeeded flare
+ // If there is an active patch skip on the thread, then we assume there will be an additional
+ // SendSetThreadContextNeeded flare to move the instruction pointer out of the patch buffer
+ if ((retVal || code == EXCEPTION_BREAKPOINT) && fIsVEH)
{
- // This does not return. Out-of-proc debugger will update the thread context
- // within this call.
- SendSetThreadContextNeeded(context, &debuggerSteppingInfo);
+ // If retVal is true, the out-of-proc debugger will update the thread context within this call.
+ // Otherwise we are sending a ClearSetIP request, and in which case the out-of-proc debugger will ignore the SetThreadContextNeeded request and simply clear the PendingSetIP flag
+ SendSetThreadContextNeeded(context, &debuggerSteppingInfo, thread->HasActivePatchSkip(), !retVal);
}
#endif
return retVal;
@@ -11708,6 +11720,7 @@ void Debugger::TypeHandleToExpandedTypeInfo(AreValueTypesBoxed boxed,
res->ClassTypeData.metadataToken = th.GetCl();
DebuggerModule * pModule = LookupOrCreateModule(th.GetModule());
res->ClassTypeData.vmDomainAssembly.SetRawPtr((pModule ? pModule->GetDomainAssembly() : NULL));
+ res->ClassTypeData.vmModule.SetRawPtr(NULL);
_ASSERTE(!res->ClassTypeData.vmDomainAssembly.IsNull());
break;
}
@@ -16167,7 +16180,7 @@ void Debugger::StartCanaryThread()
#ifndef DACCESS_COMPILE
#ifdef OUT_OF_PROCESS_SETTHREADCONTEXT
-void Debugger::SendSetThreadContextNeeded(CONTEXT *context, DebuggerSteppingInfo *pDebuggerSteppingInfo)
+void Debugger::SendSetThreadContextNeeded(CONTEXT *context, DebuggerSteppingInfo *pDebuggerSteppingInfo, bool fHasDebuggerPatchSkip, bool fClearSetIP)
{
STATIC_CONTRACT_NOTHROW;
STATIC_CONTRACT_GC_NOTRIGGER;
@@ -16222,10 +16235,20 @@ void Debugger::SendSetThreadContextNeeded(CONTEXT *context, DebuggerSteppingInfo
PRD_TYPE opcode = pDebuggerSteppingInfo != NULL ? pDebuggerSteppingInfo->GetOpcode() : CORDbg_BREAK_INSTRUCTION;
// send the context to the right side
- LOG((LF_CORDB, LL_INFO10000, "D::SSTCN ContextFlags=0x%X contextSize=%d fIsInPlaceSingleStep=%d opcode=%x\n", contextFlags, contextSize, fIsInPlaceSingleStep, opcode));
+ LOG((LF_CORDB, LL_INFO10000, "D::SSTCN ContextFlags=0x%X contextSize=%d fIsInPlaceSingleStep=%d opcode=%x fHasDebuggerPatchSkip=%d\n", contextFlags, contextSize, fIsInPlaceSingleStep, opcode, fHasDebuggerPatchSkip));
EX_TRY
{
- SetThreadContextNeededFlare((TADDR)pContext, contextSize, fIsInPlaceSingleStep, opcode);
+ DWORD flag = fIsInPlaceSingleStep ? 0x1 : 0;
+ if (fHasDebuggerPatchSkip)
+ {
+ flag |= 0x2;
+ }
+ if (fClearSetIP)
+ {
+ _ASSERTE(!fIsInPlaceSingleStep && !fHasDebuggerPatchSkip);
+ flag |= 0x4;
+ }
+ SetThreadContextNeededFlare((TADDR)pContext, contextSize, flag, opcode);
}
EX_CATCH
{
@@ -16236,7 +16259,7 @@ void Debugger::SendSetThreadContextNeeded(CONTEXT *context, DebuggerSteppingInfo
#endif
LOG((LF_CORDB, LL_INFO10000, "D::SSTCN SetThreadContextNeededFlare returned\n"));
- _ASSERTE(!"We failed to SetThreadContext from out of process!");
+ _ASSERTE(fClearSetIP);
}
BOOL Debugger::IsOutOfProcessSetContextEnabled()
@@ -16244,7 +16267,7 @@ BOOL Debugger::IsOutOfProcessSetContextEnabled()
return m_fOutOfProcessSetContextEnabled;
}
#else
-void Debugger::SendSetThreadContextNeeded(CONTEXT* context, DebuggerSteppingInfo *pDebuggerSteppingInfo)
+void Debugger::SendSetThreadContextNeeded(CONTEXT* context, DebuggerSteppingInfo *pDebuggerSteppingInfo, bool fHasDebuggerPatchSkip, bool fClearSetIP)
{
_ASSERTE(!"SendSetThreadContextNeeded is not enabled on this platform");
}
diff --git a/src/coreclr/debug/ee/debugger.h b/src/coreclr/debug/ee/debugger.h
index 403add11227084..c3a14ee8133775 100644
--- a/src/coreclr/debug/ee/debugger.h
+++ b/src/coreclr/debug/ee/debugger.h
@@ -1864,7 +1864,7 @@ extern "C" void __stdcall NotifyRightSideOfSyncCompleteFlare(void);
extern "C" void __stdcall NotifySecondChanceReadyForDataFlare(void);
#ifdef OUT_OF_PROCESS_SETTHREADCONTEXT
#if defined(TARGET_WINDOWS) && defined(TARGET_AMD64)
-extern "C" void __stdcall SetThreadContextNeededFlare(TADDR pContext, DWORD size, bool fIsInPlaceSingleStep, PRD_TYPE opcode);
+extern "C" void __stdcall SetThreadContextNeededFlare(TADDR pContext, DWORD size, DWORD64 flag, PRD_TYPE opcode);
#else
#error Platform not supported
#endif
@@ -3025,7 +3025,7 @@ class Debugger : public DebugInterface
BOOL m_fOutOfProcessSetContextEnabled;
public:
// Used by Debugger::FirstChanceNativeException to update the context from out of process
- void SendSetThreadContextNeeded(CONTEXT *context, DebuggerSteppingInfo *pDebuggerSteppingInfo = NULL);
+ void SendSetThreadContextNeeded(CONTEXT *context, DebuggerSteppingInfo *pDebuggerSteppingInfo = NULL, bool fHasActivePatchSkip = false, bool fClearSetIP = false);
BOOL IsOutOfProcessSetContextEnabled();
};
diff --git a/src/coreclr/gc/gc.cpp b/src/coreclr/gc/gc.cpp
index d2c6420aa265dd..91248211f80081 100644
--- a/src/coreclr/gc/gc.cpp
+++ b/src/coreclr/gc/gc.cpp
@@ -49417,8 +49417,15 @@ HRESULT GCHeap::Initialize()
}
else
{
- // If no hard_limit is configured the reservation size is min of 1/2 GetVirtualMemoryLimit() or max of 256Gb or 2x physical limit.
- gc_heap::regions_range = max((size_t)256 * 1024 * 1024 * 1024, (size_t)(2 * gc_heap::total_physical_mem));
+ gc_heap::regions_range =
+#ifdef MULTIPLE_HEAPS
+ // For SVR use max of 2x total_physical_memory or 256gb
+ max(
+#else // MULTIPLE_HEAPS
+ // for WKS use min
+ min(
+#endif // MULTIPLE_HEAPS
+ (size_t)256 * 1024 * 1024 * 1024, (size_t)(2 * gc_heap::total_physical_mem));
}
size_t virtual_mem_limit = GCToOSInterface::GetVirtualMemoryLimit();
gc_heap::regions_range = min(gc_heap::regions_range, virtual_mem_limit/2);
diff --git a/src/coreclr/jit/assertionprop.cpp b/src/coreclr/jit/assertionprop.cpp
index c30f63f7be3281..070beb796c7a62 100644
--- a/src/coreclr/jit/assertionprop.cpp
+++ b/src/coreclr/jit/assertionprop.cpp
@@ -4703,6 +4703,13 @@ GenTree* Compiler::optAssertionPropLocal_RelOp(ASSERT_VALARG_TP assertions, GenT
// Find an equal or not equal assertion about op1 var.
unsigned lclNum = op1->AsLclVarCommon()->GetLclNum();
+
+ // Make sure the local is not truncated.
+ if (!op1->TypeIs(lvaGetRealType(lclNum)))
+ {
+ return nullptr;
+ }
+
noway_assert(lclNum < lvaCount);
AssertionIndex index = optLocalAssertionIsEqualOrNotEqual(op1Kind, lclNum, op2Kind, cnsVal, assertions);
diff --git a/src/coreclr/jit/async.cpp b/src/coreclr/jit/async.cpp
index e685e632aef289..ec92f9b23ca6a7 100644
--- a/src/coreclr/jit/async.cpp
+++ b/src/coreclr/jit/async.cpp
@@ -169,6 +169,8 @@ PhaseStatus Compiler::SaveAsyncContexts()
// Await is inside a try, need to insert try-finally around it.
restoreBB = InsertTryFinallyForContextRestore(curBB, stmt, restoreAfterStmt);
restoreAfterStmt = nullptr;
+ // we have split the block that could have another await.
+ nextBB = restoreBB->Next();
#endif
}
@@ -1506,8 +1508,9 @@ void AsyncTransformation::FillInGCPointersOnSuspension(GenTreeCall*
if (layout.ContinuationContextGCDataIndex != UINT_MAX)
{
const AsyncCallInfo& callInfo = call->GetAsyncInfo();
- assert(callInfo.SaveAndRestoreSynchronizationContextField &&
- (callInfo.SynchronizationContextLclNum != BAD_VAR_NUM));
+ assert(callInfo.SaveAndRestoreSynchronizationContextField);
+ assert(callInfo.ExecutionContextHandling == ExecutionContextHandling::SaveAndRestore);
+ assert(callInfo.SynchronizationContextLclNum != BAD_VAR_NUM);
// Insert call
// AsyncHelpers.CaptureContinuationContext(
diff --git a/src/coreclr/jit/codegencommon.cpp b/src/coreclr/jit/codegencommon.cpp
index d5d04802c56125..81bf1907a6eeaa 100644
--- a/src/coreclr/jit/codegencommon.cpp
+++ b/src/coreclr/jit/codegencommon.cpp
@@ -1483,7 +1483,7 @@ bool CodeGen::genCreateAddrMode(GenTree* addr,
mul = 0;
rv2 = nullptr;
}
- else if (index->IsIntCnsFitsInI32())
+ else if (index->IsIntCnsFitsInI32() && !index->AsIntConCommon()->ImmedValNeedsReloc(compiler))
{
ssize_t constantIndex = index->AsIntConCommon()->IconValue() * indexScale;
if (constantIndex == 0)
diff --git a/src/coreclr/jit/codegenxarch.cpp b/src/coreclr/jit/codegenxarch.cpp
index af4031d3520511..0857ee820fb2ae 100644
--- a/src/coreclr/jit/codegenxarch.cpp
+++ b/src/coreclr/jit/codegenxarch.cpp
@@ -106,14 +106,21 @@ void CodeGen::genEmitGSCookieCheck(bool pushReg)
// we are generating GS cookie check after a GT_RETURN block.
// Note: On Amd64 System V RDX is an arg register - REG_ARG_2 - as well
// as return register for two-register-returned structs.
+#ifdef TARGET_X86
+ // Note: ARG_0 can be REG_ASYNC_CONTINUATION_RET
+ // we will check for that later if we end up saving/restoring this.
+ regGSCheck = REG_ARG_0;
+ regNumber regGSCheckAlternative = REG_ARG_1;
+#else
+ // these cannot be a part of any kind of return
+ regGSCheck = REG_R8;
+ regNumber regGSCheckAlternative = REG_R9;
+#endif
+
if (compiler->lvaKeepAliveAndReportThis() && compiler->lvaGetDesc(compiler->info.compThisArg)->lvIsInReg() &&
- (compiler->lvaGetDesc(compiler->info.compThisArg)->GetRegNum() == REG_ARG_0))
+ (compiler->lvaGetDesc(compiler->info.compThisArg)->GetRegNum() == regGSCheck))
{
- regGSCheck = REG_ARG_1;
- }
- else
- {
- regGSCheck = REG_ARG_0;
+ regGSCheck = regGSCheckAlternative;
}
}
else
@@ -158,6 +165,14 @@ void CodeGen::genEmitGSCookieCheck(bool pushReg)
{
// AOT case - GS cookie value needs to be accessed through an indirection.
+ // if we use the continuation reg, the pop/push requires no-GC
+ // this can happen only when AOT supports async on x86
+ if (compiler->compIsAsync() && (regGSCheck == REG_ASYNC_CONTINUATION_RET))
+ {
+ regMaskGSCheck = RBM_ASYNC_CONTINUATION_RET;
+ GetEmitter()->emitDisableGC();
+ }
+
pushedRegs = genPushRegs(regMaskGSCheck, &byrefPushedRegs, &norefPushedRegs);
instGen_Set_Reg_To_Imm(EA_HANDLE_CNS_RELOC, regGSCheck, (ssize_t)compiler->gsGlobalSecurityCookieAddr);
diff --git a/src/coreclr/jit/compiler.hpp b/src/coreclr/jit/compiler.hpp
index 49472de89254f4..0b9e8a3af4c878 100644
--- a/src/coreclr/jit/compiler.hpp
+++ b/src/coreclr/jit/compiler.hpp
@@ -4233,19 +4233,8 @@ inline Compiler::lvaPromotionType Compiler::lvaGetPromotionType(const LclVarDsc*
// The struct is not enregistered
return PROMOTION_TYPE_DEPENDENT;
}
- if (!varDsc->lvIsParam)
- {
- // The struct is a register candidate
- return PROMOTION_TYPE_INDEPENDENT;
- }
-// We have a parameter that could be enregistered
-#if defined(TARGET_ARM)
- // TODO-Cleanup: return INDEPENDENT for arm32.
- return PROMOTION_TYPE_DEPENDENT;
-#else // !TARGET_ARM
return PROMOTION_TYPE_INDEPENDENT;
-#endif // !TARGET_ARM
}
/*****************************************************************************
diff --git a/src/coreclr/jit/decomposelongs.cpp b/src/coreclr/jit/decomposelongs.cpp
index c67c62e6d38f03..b10dac4d3361e0 100644
--- a/src/coreclr/jit/decomposelongs.cpp
+++ b/src/coreclr/jit/decomposelongs.cpp
@@ -2452,5 +2452,13 @@ void DecomposeLongs::TryPromoteLongVar(unsigned lclNum)
fieldVarDsc->lvIsRegArg = varDsc->lvIsRegArg;
}
}
+
+#ifdef TARGET_ARM
+ if (varDsc->lvIsParam)
+ {
+ // TODO-Cleanup: Allow independent promotion for ARM parameters
+ m_compiler->lvaSetVarDoNotEnregister(lclNum DEBUGARG(DoNotEnregisterReason::IsStructArg));
+ }
+#endif
}
#endif // !defined(TARGET_64BIT)
diff --git a/src/coreclr/jit/emitarm64sve.cpp b/src/coreclr/jit/emitarm64sve.cpp
index 83e367392ac9c7..cc21be120234a6 100644
--- a/src/coreclr/jit/emitarm64sve.cpp
+++ b/src/coreclr/jit/emitarm64sve.cpp
@@ -18690,6 +18690,701 @@ void emitter::emitInsPairSanityCheck(instrDesc* firstId, instrDesc* secondId)
// "predicated using the same governing predicate register and source element size as this instruction."
assert(firstId->idInsOpt() == secondId->idInsOpt());
}
+
+ // The following instructions cannot use predicated movprfx, else the behaviour will be unpredictable.
+ switch (secondId->idIns())
+ {
+ case INS_sve_sqdecd:
+ case INS_sve_sqdech:
+ case INS_sve_sqdecw:
+ case INS_sve_sqincd:
+ case INS_sve_sqinch:
+ case INS_sve_sqincw:
+ case INS_sve_uqdecd:
+ case INS_sve_uqdech:
+ case INS_sve_uqdecw:
+ case INS_sve_uqincd:
+ case INS_sve_uqinch:
+ case INS_sve_uqincw:
+ {
+ switch (secondId->idInsFmt())
+ {
+ case IF_SVE_BP_1A:
+ assert(!movprefxIsPredicated);
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ case INS_sve_smlalb:
+ case INS_sve_smlalt:
+ case INS_sve_smlslb:
+ case INS_sve_smlslt:
+ case INS_sve_umlalb:
+ case INS_sve_umlalt:
+ case INS_sve_umlslb:
+ case INS_sve_umlslt:
+ {
+ switch (secondId->idInsFmt())
+ {
+ case IF_SVE_EL_3A:
+ case IF_SVE_FG_3A:
+ case IF_SVE_FG_3B:
+ assert(!movprefxIsPredicated);
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ case INS_sve_add:
+ case INS_sve_sqadd:
+ case INS_sve_sqsub:
+ case INS_sve_sub:
+ case INS_sve_subr:
+ case INS_sve_uqadd:
+ case INS_sve_uqsub:
+ {
+ switch (secondId->idInsFmt())
+ {
+ case IF_SVE_EC_1A:
+ assert(!movprefxIsPredicated);
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ case INS_sve_and:
+ case INS_sve_bic:
+ case INS_sve_eon:
+ case INS_sve_eor:
+ case INS_sve_orn:
+ case INS_sve_orr:
+ {
+ switch (secondId->idInsFmt())
+ {
+ case IF_SVE_BS_1A:
+ assert(!movprefxIsPredicated);
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ case INS_sve_bcax:
+ case INS_sve_bsl:
+ case INS_sve_bsl1n:
+ case INS_sve_bsl2n:
+ case INS_sve_eor3:
+ case INS_sve_nbsl:
+ {
+ switch (secondId->idInsFmt())
+ {
+ case IF_SVE_AV_3A:
+ assert(!movprefxIsPredicated);
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ case INS_sve_bfmlalb:
+ case INS_sve_bfmlalt:
+ case INS_sve_bfmlslb:
+ case INS_sve_bfmlslt:
+ case INS_sve_fmlslb:
+ case INS_sve_fmlslt:
+ {
+ switch (secondId->idInsFmt())
+ {
+ case IF_SVE_GZ_3A:
+ case IF_SVE_HB_3A:
+ assert(!movprefxIsPredicated);
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ case INS_sve_decd:
+ case INS_sve_dech:
+ case INS_sve_decw:
+ case INS_sve_incd:
+ case INS_sve_inch:
+ case INS_sve_incw:
+ {
+ switch (secondId->idInsFmt())
+ {
+ case IF_SVE_BN_1A:
+ assert(!movprefxIsPredicated);
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ case INS_sve_sabalb:
+ case INS_sve_sabalt:
+ case INS_sve_sqdmlalbt:
+ case INS_sve_sqdmlslbt:
+ case INS_sve_uabalb:
+ case INS_sve_uabalt:
+ {
+ switch (secondId->idInsFmt())
+ {
+ case IF_SVE_EL_3A:
+ assert(!movprefxIsPredicated);
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ case INS_sve_addp:
+ case INS_sve_smaxp:
+ case INS_sve_sminp:
+ case INS_sve_umaxp:
+ case INS_sve_uminp:
+ {
+ switch (secondId->idInsFmt())
+ {
+ case IF_SVE_AA_3A:
+ assert(!movprefxIsPredicated);
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ case INS_sve_eorbt:
+ case INS_sve_eortb:
+ case INS_sve_fclamp:
+ case INS_sve_sclamp:
+ case INS_sve_uclamp:
+ {
+ switch (secondId->idInsFmt())
+ {
+ case IF_SVE_AT_3A:
+ assert(!movprefxIsPredicated);
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ case INS_sve_faddp:
+ case INS_sve_fmaxnmp:
+ case INS_sve_fmaxp:
+ case INS_sve_fminnmp:
+ case INS_sve_fminp:
+ {
+ switch (secondId->idInsFmt())
+ {
+ case IF_SVE_GR_3A:
+ assert(!movprefxIsPredicated);
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ case INS_sve_adclb:
+ case INS_sve_adclt:
+ case INS_sve_sbclb:
+ case INS_sve_sbclt:
+ {
+ switch (secondId->idInsFmt())
+ {
+ case IF_SVE_FY_3A:
+ assert(!movprefxIsPredicated);
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ case INS_sve_fmlallbb:
+ case INS_sve_fmlallbt:
+ case INS_sve_fmlalltb:
+ case INS_sve_fmlalltt:
+ {
+ switch (secondId->idInsFmt())
+ {
+ case IF_SVE_GO_3A:
+ case IF_SVE_HC_3A:
+ assert(!movprefxIsPredicated);
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ case INS_sve_smax:
+ case INS_sve_smin:
+ case INS_sve_umax:
+ case INS_sve_umin:
+ {
+ switch (secondId->idInsFmt())
+ {
+ case IF_SVE_ED_1A:
+ assert(!movprefxIsPredicated);
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ case INS_sve_sqdecp:
+ case INS_sve_sqincp:
+ case INS_sve_uqdecp:
+ case INS_sve_uqincp:
+ {
+ switch (secondId->idInsFmt())
+ {
+ case IF_SVE_DP_2A:
+ assert(!movprefxIsPredicated);
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ case INS_sve_sqdmlalb:
+ case INS_sve_sqdmlalt:
+ case INS_sve_sqdmlslb:
+ case INS_sve_sqdmlslt:
+ {
+ switch (secondId->idInsFmt())
+ {
+ case IF_SVE_EL_3A:
+ case IF_SVE_FJ_3A:
+ case IF_SVE_FJ_3B:
+ assert(!movprefxIsPredicated);
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ case INS_sve_srsra:
+ case INS_sve_ssra:
+ case INS_sve_ursra:
+ case INS_sve_usra:
+ {
+ switch (secondId->idInsFmt())
+ {
+ case IF_SVE_FU_2A:
+ assert(!movprefxIsPredicated);
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ case INS_sve_smmla:
+ case INS_sve_ummla:
+ case INS_sve_usmmla:
+ {
+ switch (secondId->idInsFmt())
+ {
+ case IF_SVE_FO_3A:
+ assert(!movprefxIsPredicated);
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ case INS_sve_bfmla:
+ case INS_sve_bfmls:
+ {
+ switch (secondId->idInsFmt())
+ {
+ case IF_SVE_GU_3C:
+ assert(!movprefxIsPredicated);
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ case INS_sve_cadd:
+ case INS_sve_sqcadd:
+ {
+ switch (secondId->idInsFmt())
+ {
+ case IF_SVE_FV_2A:
+ assert(!movprefxIsPredicated);
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ case INS_sve_clasta:
+ case INS_sve_clastb:
+ {
+ switch (secondId->idInsFmt())
+ {
+ case IF_SVE_CM_3A:
+ assert(!movprefxIsPredicated);
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ case INS_sve_decp:
+ case INS_sve_incp:
+ {
+ switch (secondId->idInsFmt())
+ {
+ case IF_SVE_DN_2A:
+ assert(!movprefxIsPredicated);
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ case INS_sve_fmla:
+ case INS_sve_fmls:
+ {
+ switch (secondId->idInsFmt())
+ {
+ case IF_SVE_GU_3A:
+ case IF_SVE_GU_3B:
+ assert(!movprefxIsPredicated);
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ case INS_sve_fmlalb:
+ case INS_sve_fmlalt:
+ {
+ switch (secondId->idInsFmt())
+ {
+ case IF_SVE_GM_3A:
+ case IF_SVE_GN_3A:
+ case IF_SVE_GZ_3A:
+ case IF_SVE_HB_3A:
+ assert(!movprefxIsPredicated);
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ case INS_sve_mla:
+ case INS_sve_mls:
+ {
+ switch (secondId->idInsFmt())
+ {
+ case IF_SVE_FF_3A:
+ case IF_SVE_FF_3B:
+ case IF_SVE_FF_3C:
+ assert(!movprefxIsPredicated);
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ case INS_sve_saba:
+ case INS_sve_uaba:
+ {
+ switch (secondId->idInsFmt())
+ {
+ case IF_SVE_FW_3A:
+ assert(!movprefxIsPredicated);
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ case INS_sve_sdot:
+ case INS_sve_udot:
+ {
+ switch (secondId->idInsFmt())
+ {
+ case IF_SVE_EF_3A:
+ case IF_SVE_EG_3A:
+ case IF_SVE_EH_3A:
+ case IF_SVE_EY_3A:
+ case IF_SVE_EY_3B:
+ assert(!movprefxIsPredicated);
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ case INS_sve_sqrdmlah:
+ case INS_sve_sqrdmlsh:
+ {
+ switch (secondId->idInsFmt())
+ {
+ case IF_SVE_EM_3A:
+ case IF_SVE_FK_3A:
+ case IF_SVE_FK_3B:
+ case IF_SVE_FK_3C:
+ assert(!movprefxIsPredicated);
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ case INS_sve_bfclamp:
+ {
+ switch (secondId->idInsFmt())
+ {
+ case IF_SVE_GW_3B:
+ assert(!movprefxIsPredicated);
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ case INS_sve_bfdot:
+ {
+ switch (secondId->idInsFmt())
+ {
+ case IF_SVE_GY_3B:
+ case IF_SVE_HA_3A:
+ assert(!movprefxIsPredicated);
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ case INS_sve_bfmmla:
+ {
+ switch (secondId->idInsFmt())
+ {
+ case IF_SVE_HD_3A:
+ assert(!movprefxIsPredicated);
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ case INS_sve_cdot:
+ {
+ switch (secondId->idInsFmt())
+ {
+ case IF_SVE_EJ_3A:
+ case IF_SVE_FA_3A:
+ case IF_SVE_FA_3B:
+ assert(!movprefxIsPredicated);
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ case INS_sve_cmla:
+ {
+ switch (secondId->idInsFmt())
+ {
+ case IF_SVE_EK_3A:
+ case IF_SVE_FB_3A:
+ case IF_SVE_FB_3B:
+ assert(!movprefxIsPredicated);
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ case INS_sve_extq:
+ {
+ switch (secondId->idInsFmt())
+ {
+ case IF_SVE_BY_2A:
+ assert(!movprefxIsPredicated);
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ case INS_sve_fcmla:
+ {
+ switch (secondId->idInsFmt())
+ {
+ case IF_SVE_GV_3A:
+ assert(!movprefxIsPredicated);
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ case INS_sve_fdot:
+ {
+ switch (secondId->idInsFmt())
+ {
+ case IF_SVE_GY_3A:
+ case IF_SVE_GY_3B:
+ case IF_SVE_GY_3B_D:
+ case IF_SVE_HA_3A:
+ case IF_SVE_HA_3A_E:
+ case IF_SVE_HA_3A_F:
+ assert(!movprefxIsPredicated);
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ case INS_sve_fmmla:
+ {
+ switch (secondId->idInsFmt())
+ {
+ case IF_SVE_HD_3A_A:
+ assert(!movprefxIsPredicated);
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ case INS_sve_ftmad:
+ {
+ switch (secondId->idInsFmt())
+ {
+ case IF_SVE_HN_2A:
+ assert(!movprefxIsPredicated);
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ case INS_sve_insr:
+ {
+ switch (secondId->idInsFmt())
+ {
+ case IF_SVE_CC_2A:
+ case IF_SVE_CD_2A:
+ assert(!movprefxIsPredicated);
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ case INS_sve_madpt:
+ {
+ switch (secondId->idInsFmt())
+ {
+ case IF_SVE_EW_3B:
+ assert(!movprefxIsPredicated);
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ case INS_sve_mlapt:
+ {
+ switch (secondId->idInsFmt())
+ {
+ case IF_SVE_EW_3A:
+ assert(!movprefxIsPredicated);
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ case INS_sve_mul:
+ {
+ switch (secondId->idInsFmt())
+ {
+ case IF_SVE_EE_1A:
+ assert(!movprefxIsPredicated);
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ case INS_sve_revd:
+ {
+ switch (secondId->idInsFmt())
+ {
+ case IF_SVE_CT_3A:
+ assert(!movprefxIsPredicated);
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ case INS_sve_sqrdcmlah:
+ {
+ switch (secondId->idInsFmt())
+ {
+ case IF_SVE_EK_3A:
+ case IF_SVE_FC_3A:
+ case IF_SVE_FC_3B:
+ assert(!movprefxIsPredicated);
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ case INS_sve_sudot:
+ {
+ switch (secondId->idInsFmt())
+ {
+ case IF_SVE_EZ_3A:
+ assert(!movprefxIsPredicated);
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ case INS_sve_usdot:
+ {
+ switch (secondId->idInsFmt())
+ {
+ case IF_SVE_EI_3A:
+ case IF_SVE_EZ_3A:
+ assert(!movprefxIsPredicated);
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ case INS_sve_xar:
+ {
+ switch (secondId->idInsFmt())
+ {
+ case IF_SVE_AW_2A:
+ assert(!movprefxIsPredicated);
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
}
#endif // DEBUG
diff --git a/src/coreclr/jit/fgbasic.cpp b/src/coreclr/jit/fgbasic.cpp
index 02bb832c24a4f2..1b58b09a5d1b76 100644
--- a/src/coreclr/jit/fgbasic.cpp
+++ b/src/coreclr/jit/fgbasic.cpp
@@ -3741,24 +3741,22 @@ void Compiler::fgFindBasicBlocks()
}
else
{
- HBtab->ebdTyp = clause.ClassToken;
-
- /* Set bbCatchTyp as appropriate */
-
+ // Set ebdTyp and bbCatchTyp as appropriate
+ //
if (clause.Flags & CORINFO_EH_CLAUSE_FINALLY)
{
hndBegBB->bbCatchTyp = BBCT_FINALLY;
+ HBtab->ebdTyp = 0;
}
else
{
if (clause.Flags & CORINFO_EH_CLAUSE_FAULT)
{
hndBegBB->bbCatchTyp = BBCT_FAULT;
+ HBtab->ebdTyp = 0;
}
else
{
- hndBegBB->bbCatchTyp = clause.ClassToken;
-
// These values should be non-zero value that will
// not collide with real tokens for bbCatchTyp
if (clause.ClassToken == 0)
@@ -3766,6 +3764,9 @@ void Compiler::fgFindBasicBlocks()
BADCODE("Exception catch type is Null");
}
+ hndBegBB->bbCatchTyp = clause.ClassToken;
+ HBtab->ebdTyp = clause.ClassToken;
+
noway_assert(clause.ClassToken != BBCT_FAULT);
noway_assert(clause.ClassToken != BBCT_FINALLY);
noway_assert(clause.ClassToken != BBCT_FILTER);
diff --git a/src/coreclr/jit/fginline.cpp b/src/coreclr/jit/fginline.cpp
index 8a58dcbe813169..67773bbe865762 100644
--- a/src/coreclr/jit/fginline.cpp
+++ b/src/coreclr/jit/fginline.cpp
@@ -731,10 +731,39 @@ class SubstitutePlaceholdersAndDevirtualizeWalker : public GenTreeVisitorOperIs(GT_JTRUE))
{
// See if this jtrue is now foldable.
- BasicBlock* block = m_compiler->compCurBB;
- GenTree* condTree = tree->AsOp()->gtOp1;
+ BasicBlock* block = m_compiler->compCurBB;
+ GenTree* condTree = tree->AsOp()->gtOp1;
+ bool modifiedTree = false;
assert(tree == block->lastStmt()->GetRootNode());
+ while (condTree->OperIs(GT_COMMA))
+ {
+ // Tree is a root node, and condTree its only child.
+ // Move comma effects to a prior statement.
+ //
+ GenTree* sideEffects = nullptr;
+ m_compiler->gtExtractSideEffList(condTree->gtGetOp1(), &sideEffects);
+
+ if (sideEffects != nullptr)
+ {
+ m_compiler->fgNewStmtNearEnd(block, sideEffects);
+ }
+
+ // Splice out the comma with its value
+ //
+ GenTree* const valueTree = condTree->gtGetOp2();
+ condTree = valueTree;
+ tree->AsOp()->gtOp1 = valueTree;
+ modifiedTree = true;
+ }
+
+ if (modifiedTree)
+ {
+ m_compiler->gtUpdateNodeSideEffects(tree);
+ }
+
+ assert(condTree->OperIs(GT_CNS_INT) || condTree->OperIsCompare());
+
if (condTree->OperIs(GT_CNS_INT))
{
JITDUMP(" ... found foldable jtrue at [%06u] in " FMT_BB "\n", m_compiler->dspTreeID(tree),
diff --git a/src/coreclr/jit/hwintrinsiccodegenarm64.cpp b/src/coreclr/jit/hwintrinsiccodegenarm64.cpp
index 13c7163c4fcbb1..624c59347b475b 100644
--- a/src/coreclr/jit/hwintrinsiccodegenarm64.cpp
+++ b/src/coreclr/jit/hwintrinsiccodegenarm64.cpp
@@ -783,6 +783,21 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node)
emitInsHelper(targetReg, maskReg, embMaskOp2Reg);
break;
+ case NI_Sve2_AddPairwise:
+ case NI_Sve2_MaxNumberPairwise:
+ case NI_Sve2_MaxPairwise:
+ case NI_Sve2_MinNumberPairwise:
+ case NI_Sve2_MinPairwise:
+ // These instructions have unpredictable behaviour when using predicated movprfx,
+ // so the unpredicated variant must be used here.
+ assert(!intrin.op3->isContained() && falseReg != REG_NA);
+ GetEmitter()->emitIns_R_R(INS_sve_movprfx, EA_SCALABLE, targetReg, embMaskOp1Reg);
+ GetEmitter()->emitIns_R_R_R(insEmbMask, emitSize, targetReg, maskReg, embMaskOp2Reg,
+ embOpt, sopt);
+ GetEmitter()->emitIns_R_R_R_R(INS_sve_sel, emitSize, targetReg, maskReg, targetReg,
+ falseReg, opt);
+ break;
+
default:
assert(targetReg != embMaskOp2Reg);
@@ -2223,11 +2238,20 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node)
// GatherVector...(Vector mask, T* address, Vector indices)
emitAttr baseSize = emitActualTypeSize(intrin.baseType);
- bool isLoadingBytes =
- ((ins == INS_sve_ld1b) || (ins == INS_sve_ld1sb) || (ins == INS_sve_ldff1b) ||
- (ins == INS_sve_ldff1sb) || (intrin.id == NI_Sve_GatherVectorWithByteOffsetFirstFaulting) ||
+ bool isLoadingFromOffsets =
+ ((intrin.id == NI_Sve_GatherVectorByteZeroExtend) ||
+ (intrin.id == NI_Sve_GatherVectorByteZeroExtendFirstFaulting) ||
+ (intrin.id == NI_Sve_GatherVectorInt16WithByteOffsetsSignExtend) ||
+ (intrin.id == NI_Sve_GatherVectorInt16WithByteOffsetsSignExtendFirstFaulting) ||
+ (intrin.id == NI_Sve_GatherVectorInt32WithByteOffsetsSignExtend) ||
+ (intrin.id == NI_Sve_GatherVectorInt32WithByteOffsetsSignExtendFirstFaulting) ||
+ (intrin.id == NI_Sve_GatherVectorSByteSignExtend) ||
+ (intrin.id == NI_Sve_GatherVectorSByteSignExtendFirstFaulting) ||
+ (intrin.id == NI_Sve_GatherVectorUInt16WithByteOffsetsZeroExtend) ||
+ (intrin.id == NI_Sve_GatherVectorUInt16WithByteOffsetsZeroExtendFirstFaulting) ||
+ (intrin.id == NI_Sve_GatherVectorUInt32WithByteOffsetsZeroExtend) ||
(intrin.id == NI_Sve_GatherVectorUInt32WithByteOffsetsZeroExtendFirstFaulting) ||
- (intrin.id == NI_Sve_GatherVectorUInt16WithByteOffsetsZeroExtendFirstFaulting));
+ (intrin.id == NI_Sve_GatherVectorWithByteOffsetFirstFaulting));
insScalableOpts sopt = INS_SCALABLE_OPTS_NONE;
if (baseSize == EA_4BYTE)
@@ -2236,13 +2260,13 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node)
opt = varTypeIsUnsigned(node->GetAuxiliaryType()) ? INS_OPTS_SCALABLE_S_UXTW
: INS_OPTS_SCALABLE_S_SXTW;
- sopt = isLoadingBytes ? INS_SCALABLE_OPTS_NONE : INS_SCALABLE_OPTS_MOD_N;
+ sopt = isLoadingFromOffsets ? INS_SCALABLE_OPTS_NONE : INS_SCALABLE_OPTS_MOD_N;
}
else
{
// Index is multiplied.
assert(baseSize == EA_8BYTE);
- sopt = isLoadingBytes ? INS_SCALABLE_OPTS_NONE : INS_SCALABLE_OPTS_LSL_N;
+ sopt = isLoadingFromOffsets ? INS_SCALABLE_OPTS_NONE : INS_SCALABLE_OPTS_LSL_N;
}
GetEmitter()->emitIns_R_R_R_R(ins, emitSize, targetReg, op1Reg, op2Reg, op3Reg, opt, sopt);
@@ -2285,12 +2309,8 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node)
case NI_Sve_Scatter:
case NI_Sve_Scatter16BitNarrowing:
- case NI_Sve_Scatter16BitWithByteOffsetsNarrowing:
case NI_Sve_Scatter32BitNarrowing:
- case NI_Sve_Scatter32BitWithByteOffsetsNarrowing:
case NI_Sve_Scatter8BitNarrowing:
- case NI_Sve_Scatter8BitWithByteOffsetsNarrowing:
- case NI_Sve_ScatterWithByteOffsets:
{
if (!varTypeIsSIMD(intrin.op2->gtType))
{
@@ -2325,6 +2345,23 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node)
break;
}
+ case NI_Sve_Scatter16BitWithByteOffsetsNarrowing:
+ case NI_Sve_Scatter32BitWithByteOffsetsNarrowing:
+ case NI_Sve_Scatter8BitWithByteOffsetsNarrowing:
+ case NI_Sve_ScatterWithByteOffsets:
+ {
+ emitAttr baseSize = emitActualTypeSize(intrin.baseType);
+
+ if (baseSize == EA_4BYTE)
+ {
+ opt = varTypeIsUnsigned(node->GetAuxiliaryType()) ? INS_OPTS_SCALABLE_S_UXTW
+ : INS_OPTS_SCALABLE_S_SXTW;
+ }
+
+ GetEmitter()->emitIns_R_R_R_R(ins, emitSize, op4Reg, op1Reg, op2Reg, op3Reg, opt);
+ break;
+ }
+
case NI_Sve_StoreNarrowing:
opt = emitter::optGetSveInsOpt(emitTypeSize(intrin.baseType));
GetEmitter()->emitIns_R_R_R_I(ins, emitSize, op3Reg, op1Reg, op2Reg, 0, opt);
diff --git a/src/coreclr/jit/hwintrinsiccodegenxarch.cpp b/src/coreclr/jit/hwintrinsiccodegenxarch.cpp
index 9dc8a978174c9d..537de0e97194a7 100644
--- a/src/coreclr/jit/hwintrinsiccodegenxarch.cpp
+++ b/src/coreclr/jit/hwintrinsiccodegenxarch.cpp
@@ -2027,6 +2027,8 @@ void CodeGen::genBaseIntrinsic(GenTreeHWIntrinsic* node, insOpts instOptions)
assert(genStackLevel == 0);
#endif // !FEATURE_FIXED_OUT_ARGS
+ assert(op2->TypeIs(TYP_I_IMPL));
+
regNumber indexReg = op2->GetRegNum();
regNumber valueReg = op3->GetRegNum(); // New element value to be stored
@@ -2061,6 +2063,8 @@ void CodeGen::genBaseIntrinsic(GenTreeHWIntrinsic* node, insOpts instOptions)
simdType = TYP_SIMD16;
}
+ assert(op2->TypeIs(TYP_I_IMPL));
+
// Optimize the case of op1 is in memory and trying to access i'th element.
if (!op1->isUsedFromReg())
{
diff --git a/src/coreclr/jit/hwintrinsiclistarm64.h b/src/coreclr/jit/hwintrinsiclistarm64.h
index ec721f567c50f3..fc9da5da2fe59d 100644
--- a/src/coreclr/jit/hwintrinsiclistarm64.h
+++ b/src/coreclr/jit/hwintrinsiclistarm64.h
@@ -49,16 +49,16 @@ HARDWARE_INTRINSIC(Vector64, CreateScalar,
HARDWARE_INTRINSIC(Vector64, CreateScalarUnsafe, 8, 1, {INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_invalid, INS_invalid, INS_fmov, INS_invalid}, HW_Category_SIMD, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_SupportsContainment)
HARDWARE_INTRINSIC(Vector64, CreateSequence, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId)
HARDWARE_INTRINSIC(Vector64, Dot, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg)
-HARDWARE_INTRINSIC(Vector64, Equals, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId)
+HARDWARE_INTRINSIC(Vector64, Equals, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg)
HARDWARE_INTRINSIC(Vector64, EqualsAny, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg)
HARDWARE_INTRINSIC(Vector64, ExtractMostSignificantBits, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
HARDWARE_INTRINSIC(Vector64, Floor, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId)
HARDWARE_INTRINSIC(Vector64, FusedMultiplyAdd, 8, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId)
HARDWARE_INTRINSIC(Vector64, GetElement, 8, 2, {INS_smov, INS_umov, INS_smov, INS_umov, INS_smov, INS_umov, INS_umov, INS_umov, INS_dup, INS_dup}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg|HW_Flag_SupportsContainment)
-HARDWARE_INTRINSIC(Vector64, GreaterThan, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId)
+HARDWARE_INTRINSIC(Vector64, GreaterThan, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg)
HARDWARE_INTRINSIC(Vector64, GreaterThanAll, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg)
HARDWARE_INTRINSIC(Vector64, GreaterThanAny, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg)
-HARDWARE_INTRINSIC(Vector64, GreaterThanOrEqual, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId)
+HARDWARE_INTRINSIC(Vector64, GreaterThanOrEqual, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg)
HARDWARE_INTRINSIC(Vector64, GreaterThanOrEqualAll, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg)
HARDWARE_INTRINSIC(Vector64, GreaterThanOrEqualAny, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg)
HARDWARE_INTRINSIC(Vector64, IsEvenInteger, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId)
@@ -74,10 +74,10 @@ HARDWARE_INTRINSIC(Vector64, IsPositive,
HARDWARE_INTRINSIC(Vector64, IsPositiveInfinity, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId)
HARDWARE_INTRINSIC(Vector64, IsSubnormal, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId)
HARDWARE_INTRINSIC(Vector64, IsZero, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId)
-HARDWARE_INTRINSIC(Vector64, LessThan, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId)
+HARDWARE_INTRINSIC(Vector64, LessThan, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg)
HARDWARE_INTRINSIC(Vector64, LessThanAll, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg)
HARDWARE_INTRINSIC(Vector64, LessThanAny, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg)
-HARDWARE_INTRINSIC(Vector64, LessThanOrEqual, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId)
+HARDWARE_INTRINSIC(Vector64, LessThanOrEqual, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg)
HARDWARE_INTRINSIC(Vector64, LessThanOrEqualAll, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg)
HARDWARE_INTRINSIC(Vector64, LessThanOrEqualAny, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg)
HARDWARE_INTRINSIC(Vector64, LoadAligned, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId)
@@ -180,7 +180,7 @@ HARDWARE_INTRINSIC(Vector128, CreateScalar,
HARDWARE_INTRINSIC(Vector128, CreateScalarUnsafe, 16, 1, {INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_fmov, INS_fmov}, HW_Category_SIMD, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_SupportsContainment)
HARDWARE_INTRINSIC(Vector128, CreateSequence, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId)
HARDWARE_INTRINSIC(Vector128, Dot, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg)
-HARDWARE_INTRINSIC(Vector128, Equals, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId)
+HARDWARE_INTRINSIC(Vector128, Equals, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg)
HARDWARE_INTRINSIC(Vector128, EqualsAny, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg)
HARDWARE_INTRINSIC(Vector128, ExtractMostSignificantBits, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
HARDWARE_INTRINSIC(Vector128, Floor, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId)
@@ -188,10 +188,10 @@ HARDWARE_INTRINSIC(Vector128, FusedMultiplyAdd,
HARDWARE_INTRINSIC(Vector128, GetElement, 16, 2, {INS_smov, INS_umov, INS_smov, INS_umov, INS_smov, INS_umov, INS_umov, INS_umov, INS_dup, INS_dup}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg|HW_Flag_SupportsContainment)
HARDWARE_INTRINSIC(Vector128, GetLower, 16, 1, {INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov}, HW_Category_SIMD, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen)
HARDWARE_INTRINSIC(Vector128, GetUpper, 16, 1, {INS_ext, INS_ext, INS_ext, INS_ext, INS_ext, INS_ext, INS_ext, INS_ext, INS_ext, INS_ext}, HW_Category_SIMD, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen)
-HARDWARE_INTRINSIC(Vector128, GreaterThan, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId)
+HARDWARE_INTRINSIC(Vector128, GreaterThan, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg)
HARDWARE_INTRINSIC(Vector128, GreaterThanAll, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg)
HARDWARE_INTRINSIC(Vector128, GreaterThanAny, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg)
-HARDWARE_INTRINSIC(Vector128, GreaterThanOrEqual, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId)
+HARDWARE_INTRINSIC(Vector128, GreaterThanOrEqual, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg)
HARDWARE_INTRINSIC(Vector128, GreaterThanOrEqualAll, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg)
HARDWARE_INTRINSIC(Vector128, GreaterThanOrEqualAny, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg)
HARDWARE_INTRINSIC(Vector128, IsEvenInteger, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId)
@@ -207,10 +207,10 @@ HARDWARE_INTRINSIC(Vector128, IsPositive,
HARDWARE_INTRINSIC(Vector128, IsPositiveInfinity, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId)
HARDWARE_INTRINSIC(Vector128, IsSubnormal, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId)
HARDWARE_INTRINSIC(Vector128, IsZero, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId)
-HARDWARE_INTRINSIC(Vector128, LessThan, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId)
+HARDWARE_INTRINSIC(Vector128, LessThan, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg)
HARDWARE_INTRINSIC(Vector128, LessThanAll, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg)
HARDWARE_INTRINSIC(Vector128, LessThanAny, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg)
-HARDWARE_INTRINSIC(Vector128, LessThanOrEqual, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId)
+HARDWARE_INTRINSIC(Vector128, LessThanOrEqual, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg)
HARDWARE_INTRINSIC(Vector128, LessThanOrEqualAll, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg)
HARDWARE_INTRINSIC(Vector128, LessThanOrEqualAny, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg)
HARDWARE_INTRINSIC(Vector128, LoadAligned, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId)
diff --git a/src/coreclr/jit/hwintrinsiclistxarch.h b/src/coreclr/jit/hwintrinsiclistxarch.h
index be680becff0b52..b1084d010c7808 100644
--- a/src/coreclr/jit/hwintrinsiclistxarch.h
+++ b/src/coreclr/jit/hwintrinsiclistxarch.h
@@ -67,16 +67,16 @@ HARDWARE_INTRINSIC(Vector128, CreateScalar,
HARDWARE_INTRINSIC(Vector128, CreateScalarUnsafe, 16, 1, {INS_movd32, INS_movd32, INS_movd32, INS_movd32, INS_movd32, INS_movd32, INS_movd64, INS_movd64, INS_movss, INS_movsd_simd}, HW_Category_SIMDScalar, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_NoRMWSemantics)
HARDWARE_INTRINSIC(Vector128, CreateSequence, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId)
HARDWARE_INTRINSIC(Vector128, Dot, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg)
-HARDWARE_INTRINSIC(Vector128, Equals, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId)
+HARDWARE_INTRINSIC(Vector128, Equals, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg)
HARDWARE_INTRINSIC(Vector128, EqualsAny, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg)
HARDWARE_INTRINSIC(Vector128, ExtractMostSignificantBits, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
HARDWARE_INTRINSIC(Vector128, Floor, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId)
HARDWARE_INTRINSIC(Vector128, FusedMultiplyAdd, 16, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId)
HARDWARE_INTRINSIC(Vector128, GetElement, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_extractps, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg)
-HARDWARE_INTRINSIC(Vector128, GreaterThan, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId)
+HARDWARE_INTRINSIC(Vector128, GreaterThan, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg)
HARDWARE_INTRINSIC(Vector128, GreaterThanAll, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg)
HARDWARE_INTRINSIC(Vector128, GreaterThanAny, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg)
-HARDWARE_INTRINSIC(Vector128, GreaterThanOrEqual, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId)
+HARDWARE_INTRINSIC(Vector128, GreaterThanOrEqual, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg)
HARDWARE_INTRINSIC(Vector128, GreaterThanOrEqualAll, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg)
HARDWARE_INTRINSIC(Vector128, GreaterThanOrEqualAny, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg)
HARDWARE_INTRINSIC(Vector128, IsEvenInteger, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId)
@@ -92,10 +92,10 @@ HARDWARE_INTRINSIC(Vector128, IsPositive,
HARDWARE_INTRINSIC(Vector128, IsPositiveInfinity, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId)
HARDWARE_INTRINSIC(Vector128, IsSubnormal, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId)
HARDWARE_INTRINSIC(Vector128, IsZero, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId)
-HARDWARE_INTRINSIC(Vector128, LessThan, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId)
+HARDWARE_INTRINSIC(Vector128, LessThan, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg)
HARDWARE_INTRINSIC(Vector128, LessThanAll, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg)
HARDWARE_INTRINSIC(Vector128, LessThanAny, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg)
-HARDWARE_INTRINSIC(Vector128, LessThanOrEqual, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId)
+HARDWARE_INTRINSIC(Vector128, LessThanOrEqual, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg)
HARDWARE_INTRINSIC(Vector128, LessThanOrEqualAll, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg)
HARDWARE_INTRINSIC(Vector128, LessThanOrEqualAny, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg)
HARDWARE_INTRINSIC(Vector128, LoadAligned, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId)
@@ -195,7 +195,7 @@ HARDWARE_INTRINSIC(Vector256, CreateScalar,
HARDWARE_INTRINSIC(Vector256, CreateScalarUnsafe, 32, 1, {INS_movd32, INS_movd32, INS_movd32, INS_movd32, INS_movd32, INS_movd32, INS_movd64, INS_movd64, INS_movss, INS_movsd_simd}, HW_Category_SIMDScalar, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_AvxOnlyCompatible)
HARDWARE_INTRINSIC(Vector256, CreateSequence, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_AvxOnlyCompatible)
HARDWARE_INTRINSIC(Vector256, Dot, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg)
-HARDWARE_INTRINSIC(Vector256, Equals, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId)
+HARDWARE_INTRINSIC(Vector256, Equals, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg)
HARDWARE_INTRINSIC(Vector256, EqualsAny, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg)
HARDWARE_INTRINSIC(Vector256, ExtractMostSignificantBits, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
HARDWARE_INTRINSIC(Vector256, Floor, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_AvxOnlyCompatible)
@@ -203,10 +203,10 @@ HARDWARE_INTRINSIC(Vector256, FusedMultiplyAdd,
HARDWARE_INTRINSIC(Vector256, GetElement, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_AvxOnlyCompatible)
HARDWARE_INTRINSIC(Vector256, GetLower, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movdqu32, INS_movdqu32, INS_movdqu32, INS_movdqu32, INS_movups, INS_movupd}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_AvxOnlyCompatible|HW_Flag_NormalizeSmallTypeToInt)
HARDWARE_INTRINSIC(Vector256, GetUpper, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_AvxOnlyCompatible)
-HARDWARE_INTRINSIC(Vector256, GreaterThan, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId)
+HARDWARE_INTRINSIC(Vector256, GreaterThan, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg)
HARDWARE_INTRINSIC(Vector256, GreaterThanAll, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg)
HARDWARE_INTRINSIC(Vector256, GreaterThanAny, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg)
-HARDWARE_INTRINSIC(Vector256, GreaterThanOrEqual, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId)
+HARDWARE_INTRINSIC(Vector256, GreaterThanOrEqual, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg)
HARDWARE_INTRINSIC(Vector256, GreaterThanOrEqualAll, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg)
HARDWARE_INTRINSIC(Vector256, GreaterThanOrEqualAny, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg)
HARDWARE_INTRINSIC(Vector256, IsEvenInteger, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId)
@@ -222,10 +222,10 @@ HARDWARE_INTRINSIC(Vector256, IsPositive,
HARDWARE_INTRINSIC(Vector256, IsPositiveInfinity, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId)
HARDWARE_INTRINSIC(Vector256, IsSubnormal, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId)
HARDWARE_INTRINSIC(Vector256, IsZero, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId)
-HARDWARE_INTRINSIC(Vector256, LessThan, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId)
+HARDWARE_INTRINSIC(Vector256, LessThan, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg)
HARDWARE_INTRINSIC(Vector256, LessThanAll, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg)
HARDWARE_INTRINSIC(Vector256, LessThanAny, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg)
-HARDWARE_INTRINSIC(Vector256, LessThanOrEqual, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId)
+HARDWARE_INTRINSIC(Vector256, LessThanOrEqual, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg)
HARDWARE_INTRINSIC(Vector256, LessThanOrEqualAll, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg)
HARDWARE_INTRINSIC(Vector256, LessThanOrEqualAny, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg)
HARDWARE_INTRINSIC(Vector256, LoadAligned, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_AvxOnlyCompatible)
@@ -335,10 +335,10 @@ HARDWARE_INTRINSIC(Vector512, GetElement,
HARDWARE_INTRINSIC(Vector512, GetLower, 64, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movdqu32, INS_movdqu32, INS_vmovdqu64, INS_vmovdqu64, INS_movups, INS_movupd}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_NormalizeSmallTypeToInt)
HARDWARE_INTRINSIC(Vector512, GetLower128, 64, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movdqu32, INS_movdqu32, INS_vmovdqu64, INS_vmovdqu64, INS_movups, INS_movupd}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_NormalizeSmallTypeToInt|HW_Flag_BaseTypeFromFirstArg)
HARDWARE_INTRINSIC(Vector512, GetUpper, 64, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
-HARDWARE_INTRINSIC(Vector512, GreaterThan, 64, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId)
+HARDWARE_INTRINSIC(Vector512, GreaterThan, 64, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg)
HARDWARE_INTRINSIC(Vector512, GreaterThanAll, 64, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg)
HARDWARE_INTRINSIC(Vector512, GreaterThanAny, 64, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg)
-HARDWARE_INTRINSIC(Vector512, GreaterThanOrEqual, 64, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId)
+HARDWARE_INTRINSIC(Vector512, GreaterThanOrEqual, 64, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg)
HARDWARE_INTRINSIC(Vector512, GreaterThanOrEqualAll, 64, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg)
HARDWARE_INTRINSIC(Vector512, GreaterThanOrEqualAny, 64, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg)
HARDWARE_INTRINSIC(Vector512, IsEvenInteger, 64, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId)
@@ -354,10 +354,10 @@ HARDWARE_INTRINSIC(Vector512, IsPositive,
HARDWARE_INTRINSIC(Vector512, IsPositiveInfinity, 64, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId)
HARDWARE_INTRINSIC(Vector512, IsSubnormal, 64, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId)
HARDWARE_INTRINSIC(Vector512, IsZero, 64, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId)
-HARDWARE_INTRINSIC(Vector512, LessThan, 64, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId)
+HARDWARE_INTRINSIC(Vector512, LessThan, 64, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg)
HARDWARE_INTRINSIC(Vector512, LessThanAll, 64, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg)
HARDWARE_INTRINSIC(Vector512, LessThanAny, 64, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg)
-HARDWARE_INTRINSIC(Vector512, LessThanOrEqual, 64, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId)
+HARDWARE_INTRINSIC(Vector512, LessThanOrEqual, 64, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg)
HARDWARE_INTRINSIC(Vector512, LessThanOrEqualAll, 64, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg)
HARDWARE_INTRINSIC(Vector512, LessThanOrEqualAny, 64, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg)
HARDWARE_INTRINSIC(Vector512, LoadAligned, 64, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId)
diff --git a/src/coreclr/jit/importercalls.cpp b/src/coreclr/jit/importercalls.cpp
index f69407f58bb049..7db020168b0abb 100644
--- a/src/coreclr/jit/importercalls.cpp
+++ b/src/coreclr/jit/importercalls.cpp
@@ -1098,9 +1098,10 @@ var_types Compiler::impImportCall(OPCODE opcode,
}
// For opportunistic tailcalls we allow implicit widening, i.e. tailcalls from int32 -> int16, since the
- // managed calling convention dictates that the callee widens the value. For explicit tailcalls we don't
- // want to require this detail of the calling convention to bubble up to the tailcall helpers
- bool allowWidening = isImplicitTailCall;
+ // managed calling convention dictates that the callee widens the value. For explicit tailcalls or async
+ // functions we don't want to require this detail of the calling convention to bubble up to helper
+ // infrastructure.
+ bool allowWidening = isImplicitTailCall && !call->AsCall()->IsAsync();
if (canTailCall &&
!impTailCallRetTypeCompatible(allowWidening, info.compRetType, info.compMethodInfo->args.retTypeClass,
info.compCallConv, callRetTyp, sig->retTypeClass,
@@ -10762,6 +10763,10 @@ NamedIntrinsic Compiler::lookupNamedIntrinsic(CORINFO_METHOD_HANDLE method)
lookupMethodName = nullptr;
}
}
+ else if (strcmp(methodName, "SquareRoot") == 0)
+ {
+ lookupMethodName = "Sqrt";
+ }
if (lookupMethodName != nullptr)
{
diff --git a/src/coreclr/jit/jiteh.cpp b/src/coreclr/jit/jiteh.cpp
index bf7ba8cb03bc9a..287cd28393d388 100644
--- a/src/coreclr/jit/jiteh.cpp
+++ b/src/coreclr/jit/jiteh.cpp
@@ -1522,6 +1522,8 @@ void Compiler::fgAllocEHTable()
compHndBBtab = new (this, CMK_BasicBlock) EHblkDsc[compHndBBtabAllocCount];
+ memset(compHndBBtab, 0, compHndBBtabAllocCount * sizeof(*compHndBBtab));
+
compHndBBtabCount = info.compXcptnsCount;
}
@@ -1883,6 +1885,10 @@ EHblkDsc* Compiler::fgTryAddEHTableEntries(unsigned XTnum, unsigned count, bool
EHblkDsc* newTable = new (this, CMK_BasicBlock) EHblkDsc[compHndBBtabAllocCount];
+ // Zero the storage
+
+ memset(newTable, 0, compHndBBtabAllocCount * sizeof(*compHndBBtab));
+
// Move over the stuff before the new entries
memcpy_s(newTable, compHndBBtabAllocCount * sizeof(*compHndBBtab), compHndBBtab, XTnum * sizeof(*compHndBBtab));
diff --git a/src/coreclr/jit/lclmorph.cpp b/src/coreclr/jit/lclmorph.cpp
index cd464797e79890..ecb01980013518 100644
--- a/src/coreclr/jit/lclmorph.cpp
+++ b/src/coreclr/jit/lclmorph.cpp
@@ -2020,7 +2020,7 @@ class LocalAddressVisitor final : public GenTreeVisitor
}
if ((genTypeSize(indir) == genTypeSize(varDsc)) && (genTypeSize(indir) <= TARGET_POINTER_SIZE) &&
- (varTypeIsFloating(indir) || varTypeIsFloating(varDsc)))
+ (varTypeIsFloating(indir) || varTypeIsFloating(varDsc)) && !varDsc->lvPromoted)
{
return IndirTransform::BitCast;
}
diff --git a/src/coreclr/jit/lclvars.cpp b/src/coreclr/jit/lclvars.cpp
index f96943f2069bbe..4e6b559c989baf 100644
--- a/src/coreclr/jit/lclvars.cpp
+++ b/src/coreclr/jit/lclvars.cpp
@@ -2010,6 +2010,14 @@ void Compiler::StructPromotionHelper::PromoteStructVar(unsigned lclNum)
fieldVarDsc->lvKeepType = 1;
#endif
}
+
+#ifdef TARGET_ARM
+ if (varDsc->lvIsParam)
+ {
+ // TODO-Cleanup: Allow independent promotion for ARM struct parameters
+ compiler->lvaSetVarDoNotEnregister(lclNum DEBUGARG(DoNotEnregisterReason::IsStructArg));
+ }
+#endif
}
//--------------------------------------------------------------------------------------------
diff --git a/src/coreclr/jit/lower.cpp b/src/coreclr/jit/lower.cpp
index 9b1889e1673b8e..d629059d81b3f0 100644
--- a/src/coreclr/jit/lower.cpp
+++ b/src/coreclr/jit/lower.cpp
@@ -1562,8 +1562,6 @@ void Lowering::LowerArg(GenTreeCall* call, CallArg* callArg)
if (varTypeIsLong(arg))
{
- assert(callArg->AbiInfo.CountRegsAndStackSlots() == 2);
-
noway_assert(arg->OperIs(GT_LONG));
GenTreeFieldList* fieldList = new (comp, GT_FIELD_LIST) GenTreeFieldList();
fieldList->AddFieldLIR(comp, arg->gtGetOp1(), 0, TYP_INT);
@@ -2032,6 +2030,7 @@ void Lowering::LowerSpecialCopyArgs(GenTreeCall* call)
// The this parameter is always passed in registers, so we can ignore it.
unsigned argIndex = call->gtArgs.CountUserArgs() - 1;
assert(call->gtArgs.CountUserArgs() == comp->info.compILargsCount);
+ bool checkForUnmanagedThisArg = call->GetUnmanagedCallConv() == CorInfoCallConvExtension::Thiscall;
for (CallArg& arg : call->gtArgs.Args())
{
if (!arg.IsUserArg())
@@ -2039,10 +2038,10 @@ void Lowering::LowerSpecialCopyArgs(GenTreeCall* call)
continue;
}
- if (call->GetUnmanagedCallConv() == CorInfoCallConvExtension::Thiscall &&
- argIndex == call->gtArgs.CountUserArgs() - 1)
+ if (checkForUnmanagedThisArg && argIndex == call->gtArgs.CountUserArgs() - 1)
{
assert(arg.GetNode()->OperIs(GT_PUTARG_REG));
+ checkForUnmanagedThisArg = false;
continue;
}
@@ -5177,6 +5176,16 @@ bool Lowering::IsFieldListCompatibleWithRegisters(GenTreeFieldList* fieldList,
return false;
}
+ // int -> float is currently only supported if we can do it as a single bitcast (i.e. without insertions
+ // required)
+ if (varTypeUsesIntReg(use->GetNode()) && varTypeUsesFloatReg(regType) &&
+ (genTypeSize(regType) > TARGET_POINTER_SIZE))
+ {
+ JITDUMP("it is not; field [%06u] requires an insertion into float register %u of size %d\n",
+ Compiler::dspTreeID(use->GetNode()), i, genTypeSize(regType));
+ return false;
+ }
+
use = use->GetNext();
} while (use != nullptr);
}
@@ -11681,6 +11690,40 @@ GenTree* Lowering::InsertNewSimdCreateScalarUnsafeNode(var_types simdType,
}
return result;
}
+
+//----------------------------------------------------------------------------------------------
+// Lowering::NormalizeIndexToNativeSized:
+// Prepare to use an index for address calculations by ensuring it is native sized.
+//
+// Arguments:
+// index - The index that may be an int32
+//
+// Returns:
+// The node itself, or a cast added on top of the node to perform normalization.
+//
+// Remarks:
+// May insert a cast or may bash the node type in place for constants. Does
+// not replace the use.
+//
+GenTree* Lowering::NormalizeIndexToNativeSized(GenTree* index)
+{
+ if (genActualType(index) == TYP_I_IMPL)
+ {
+ return index;
+ }
+
+ if (index->OperIsConst())
+ {
+ index->gtType = TYP_I_IMPL;
+ return index;
+ }
+ else
+ {
+ GenTree* cast = comp->gtNewCastNode(TYP_I_IMPL, index, true, TYP_I_IMPL);
+ BlockRange().InsertAfter(index, cast);
+ return cast;
+ }
+}
#endif // FEATURE_HW_INTRINSICS
//----------------------------------------------------------------------------------------------
diff --git a/src/coreclr/jit/lower.h b/src/coreclr/jit/lower.h
index b3afd8cceaeb28..d923a40f04af7f 100644
--- a/src/coreclr/jit/lower.h
+++ b/src/coreclr/jit/lower.h
@@ -463,6 +463,7 @@ class Lowering final : public Phase
GenTree* op1,
CorInfoType simdBaseJitType,
unsigned simdSize);
+ GenTree* NormalizeIndexToNativeSized(GenTree* index);
#endif // FEATURE_HW_INTRINSICS
// Utility functions
diff --git a/src/coreclr/jit/lowerarmarch.cpp b/src/coreclr/jit/lowerarmarch.cpp
index 5fd53c25fbb137..a75814b38d3cc4 100644
--- a/src/coreclr/jit/lowerarmarch.cpp
+++ b/src/coreclr/jit/lowerarmarch.cpp
@@ -1684,6 +1684,9 @@ GenTree* Lowering::LowerHWIntrinsic(GenTreeHWIntrinsic* node)
GenTree* op1 = node->Op(1);
GenTree* op2 = node->Op(2);
+ op2 = NormalizeIndexToNativeSized(op2);
+ node->Op(2) = op2;
+
bool isContainableMemory = IsContainableMemoryOp(op1) && IsSafeToContainMem(node, op1);
if (isContainableMemory || !op2->OperIsConst())
@@ -4058,8 +4061,23 @@ void Lowering::ContainCheckHWIntrinsic(GenTreeHWIntrinsic* node)
// When we are merging with zero, we can specialize
// and avoid instantiating the vector constant.
// Do this only if op1 was AllTrueMask
- MakeSrcContained(node, op3);
- LABELEDDISPTREERANGE("Contained false mask op3 in ConditionalSelect", BlockRange(), op3);
+ switch (op2->AsHWIntrinsic()->GetHWIntrinsicId())
+ {
+ case NI_Sve2_AddPairwise:
+ case NI_Sve2_MaxNumberPairwise:
+ case NI_Sve2_MaxPairwise:
+ case NI_Sve2_MinNumberPairwise:
+ case NI_Sve2_MinPairwise:
+ // This is an edge case where these instructions have unpredictable behaviour when
+ // using predicated movprfx, so the unpredicated variant must be used here. This
+ // prevents us from performing this optimization as we will need the constant vector
+ // for masking the result.
+ break;
+
+ default:
+ MakeSrcContained(node, op3);
+ LABELEDDISPTREERANGE("Contained false mask op3 in ConditionalSelect", BlockRange(), op3);
+ }
}
break;
diff --git a/src/coreclr/jit/lowerxarch.cpp b/src/coreclr/jit/lowerxarch.cpp
index db9c8db0ba9f33..498e0fe936aa4d 100644
--- a/src/coreclr/jit/lowerxarch.cpp
+++ b/src/coreclr/jit/lowerxarch.cpp
@@ -5173,6 +5173,9 @@ GenTree* Lowering::LowerHWIntrinsicGetElement(GenTreeHWIntrinsic* node)
return LowerNode(node);
}
+ op2 = NormalizeIndexToNativeSized(op2);
+ node->Op(2) = op2;
+
uint32_t elemSize = genTypeSize(simdBaseType);
uint32_t count = simdSize / elemSize;
@@ -5535,6 +5538,12 @@ GenTree* Lowering::LowerHWIntrinsicGetElement(GenTreeHWIntrinsic* node)
{
// We specially handle float and double for more efficient codegen
resIntrinsic = NI_Vector128_GetElement;
+ // GetElement takes a native sized index after lowering, so change
+ // the type of the constant we inserted above.
+ // (This is generally only for the non constant index case,
+ // which is not the case here, but keep the index operand's
+ // type consistent)
+ op2->gtType = TYP_I_IMPL;
break;
}
@@ -5625,6 +5634,8 @@ GenTree* Lowering::LowerHWIntrinsicWithElement(GenTreeHWIntrinsic* node)
if (!op2->OperIsConst())
{
+ op2 = NormalizeIndexToNativeSized(op2);
+ node->Op(2) = op2;
// We will specially handle WithElement in codegen when op2 isn't a constant
ContainCheckHWIntrinsic(node);
return node->gtNext;
@@ -7685,7 +7696,7 @@ void Lowering::ContainCheckCallOperands(GenTreeCall* call)
}
else
#endif // TARGET_X86
- if (ctrlExpr->isIndir())
+ if (ctrlExpr->isIndir() && IsSafeToContainMem(call, ctrlExpr))
{
// We may have cases where we have set a register target on the ctrlExpr, but if it
// contained we must clear it.
diff --git a/src/coreclr/jit/lsra.cpp b/src/coreclr/jit/lsra.cpp
index 9370e2f6501679..4473b6a490178c 100644
--- a/src/coreclr/jit/lsra.cpp
+++ b/src/coreclr/jit/lsra.cpp
@@ -874,15 +874,15 @@ LinearScan::LinearScan(Compiler* theCompiler)
}
else
{
- regIndices =
- new regNumber[]{REG_RAX, REG_RCX, REG_RDX, REG_RBX, REG_RSP, REG_RBP, REG_RSI, REG_RDI,
- REG_R8, REG_R9, REG_R10, REG_R11, REG_R12, REG_R13, REG_R14, REG_R15,
- REG_XMM0, REG_XMM1, REG_XMM2, REG_XMM3, REG_XMM4, REG_XMM5, REG_XMM6, REG_XMM7,
- REG_XMM8, REG_XMM9, REG_XMM10, REG_XMM11, REG_XMM12, REG_XMM13, REG_XMM14, REG_XMM15,
- REG_XMM16, REG_XMM17, REG_XMM18, REG_XMM19, REG_XMM20, REG_XMM21, REG_XMM22, REG_XMM23,
- REG_XMM24, REG_XMM25, REG_XMM26, REG_XMM27, REG_XMM28, REG_XMM29, REG_XMM30, REG_XMM31,
- REG_K0, REG_K1, REG_K2, REG_K3, REG_K4, REG_K5, REG_K6, REG_K7,
- REG_COUNT};
+ regIndices = new (theCompiler, CMK_LSRA)
+ regNumber[]{REG_RAX, REG_RCX, REG_RDX, REG_RBX, REG_RSP, REG_RBP, REG_RSI, REG_RDI,
+ REG_R8, REG_R9, REG_R10, REG_R11, REG_R12, REG_R13, REG_R14, REG_R15,
+ REG_XMM0, REG_XMM1, REG_XMM2, REG_XMM3, REG_XMM4, REG_XMM5, REG_XMM6, REG_XMM7,
+ REG_XMM8, REG_XMM9, REG_XMM10, REG_XMM11, REG_XMM12, REG_XMM13, REG_XMM14, REG_XMM15,
+ REG_XMM16, REG_XMM17, REG_XMM18, REG_XMM19, REG_XMM20, REG_XMM21, REG_XMM22, REG_XMM23,
+ REG_XMM24, REG_XMM25, REG_XMM26, REG_XMM27, REG_XMM28, REG_XMM29, REG_XMM30, REG_XMM31,
+ REG_K0, REG_K1, REG_K2, REG_K3, REG_K4, REG_K5, REG_K6, REG_K7,
+ REG_COUNT};
}
#endif // TARGET_AMD64
@@ -12575,7 +12575,7 @@ LinearScan::RegisterSelection::RegisterSelection(LinearScan* linearScan)
this->linearScan = linearScan;
#ifdef DEBUG
- mappingTable = new ScoreMappingTable(linearScan->compiler->getAllocator(CMK_LSRA));
+ mappingTable = new (linearScan->compiler, CMK_LSRA) ScoreMappingTable(linearScan->compiler->getAllocator(CMK_LSRA));
#define REG_SEL_DEF(stat, value, shortname, orderSeqId) \
mappingTable->Set(stat, &LinearScan::RegisterSelection::try_##stat);
diff --git a/src/coreclr/jit/optimizer.cpp b/src/coreclr/jit/optimizer.cpp
index 383a1b425c2b37..31f5b7b0d2a4a6 100644
--- a/src/coreclr/jit/optimizer.cpp
+++ b/src/coreclr/jit/optimizer.cpp
@@ -3655,12 +3655,21 @@ bool Compiler::optHoistThisLoop(FlowGraphNaturalLoop* loop, LoopHoistContext* ho
}
#endif // FEATURE_MASKED_HW_INTRINSICS
- // Find the set of definitely-executed blocks. These will be given priority for hoisting.
+ // Find the set of definitely-executed blocks.
// Ideally, the definitely-executed blocks are the ones that post-dominate the entry block.
// Until we have post-dominators, we'll special-case for single-exit blocks.
//
- // TODO: We ought to consider hoisting more aggressively from conditionally executed blocks,
- // if they are frequently executed and it is safe to evaluate the tree early.
+ // Todo: it is not clear if this is a correctness requirement or a profitability heuristic.
+ // It seems like the latter. Ideally there are enough safeguards to prevent hoisting exception
+ // or side-effect dependent things. Note that HoistVisitor uses `m_canHoistSideEffects` to determine if it's
+ // ok to hoist a side-effect. It allows this only for the first block (the entry block), before any
+ // side-effect has been seen. After the first block, it assumes that there has been a side effect and
+ // no further side-effect can be hoisted. It is true that we don't analyze any program behavior in the
+ // flow graph between the entry block and the subsequent blocks, whether they be the next block dominating
+ // the exit block, or the pre-headers of nested loops.
+ //
+ // We really should consider hoisting from conditionally executed blocks, if they are frequently executed
+ // and it is safe to evaluate the tree early.
//
assert(m_dfsTree != nullptr);
BitVecTraits traits(m_dfsTree->PostOrderTraits());
@@ -4116,7 +4125,7 @@ void Compiler::optHoistLoopBlocks(FlowGraphNaturalLoop* loop,
};
ArrayStack m_valueStack;
- bool m_beforeSideEffect;
+ bool m_canHoistSideEffects;
FlowGraphNaturalLoop* m_loop;
LoopHoistContext* m_hoistContext;
BasicBlock* m_currentBlock;
@@ -4251,7 +4260,7 @@ void Compiler::optHoistLoopBlocks(FlowGraphNaturalLoop* loop,
BitVec defExec)
: GenTreeVisitor(compiler)
, m_valueStack(compiler->getAllocator(CMK_LoopHoist))
- , m_beforeSideEffect(true)
+ , m_canHoistSideEffects(true)
, m_loop(loop)
, m_hoistContext(hoistContext)
, m_currentBlock(nullptr)
@@ -4263,26 +4272,46 @@ void Compiler::optHoistLoopBlocks(FlowGraphNaturalLoop* loop,
void HoistBlock(BasicBlock* block)
{
m_currentBlock = block;
- for (Statement* const stmt : block->NonPhiStatements())
- {
- WalkTree(stmt->GetRootNodePointer(), nullptr);
- Value& top = m_valueStack.TopRef();
- assert(top.Node() == stmt->GetRootNode());
- // hoist the top node?
- if (top.m_hoistable)
- {
- const bool defExecuted = BitVecOps::IsMember(m_traits, m_defExec, block->bbPostorderNum);
- m_compiler->optHoistCandidate(stmt->GetRootNode(), block, m_loop, m_hoistContext, defExecuted);
- }
- else
+ const weight_t blockWeight = block->getBBWeight(m_compiler);
+
+ JITDUMP("\n HoistBlock " FMT_BB " (weight=%6s) of loop " FMT_LP " (head: " FMT_BB ")\n", block->bbNum,
+ refCntWtd2str(blockWeight, /* padForDecimalPlaces */ true), m_loop->GetIndex(),
+ m_loop->GetHeader()->bbNum);
+
+ if (blockWeight < (BB_UNITY_WEIGHT / 10))
+ {
+ JITDUMP(" block weight is too small to perform hoisting.\n");
+ }
+ else
+ {
+ for (Statement* const stmt : block->NonPhiStatements())
{
- JITDUMP(" [%06u] %s: %s\n", dspTreeID(top.Node()),
- top.m_invariant ? "not hoistable" : "not invariant", top.m_failReason);
- }
+ WalkTree(stmt->GetRootNodePointer(), nullptr);
+ Value& top = m_valueStack.TopRef();
+ assert(top.Node() == stmt->GetRootNode());
- m_valueStack.Reset();
+ // hoist the top node?
+ if (top.m_hoistable)
+ {
+ const bool defExecuted = BitVecOps::IsMember(m_traits, m_defExec, block->bbPostorderNum);
+ m_compiler->optHoistCandidate(stmt->GetRootNode(), block, m_loop, m_hoistContext, defExecuted);
+ }
+ else
+ {
+ JITDUMP(" [%06u] %s: %s\n", dspTreeID(top.Node()),
+ top.m_invariant ? "not hoistable" : "not invariant", top.m_failReason);
+ }
+
+ m_valueStack.Reset();
+ }
}
+
+ assert(!m_canHoistSideEffects || (block == m_loop->GetHeader()));
+ // After visiting the first block (which is expected to always be
+ // the loop header) we can no longer hoist out side effecting trees
+ // as the next blocks could be conditionally executed.
+ m_canHoistSideEffects = false;
}
fgWalkResult PreOrderVisit(GenTree** use, GenTree* user)
@@ -4458,10 +4487,11 @@ void Compiler::optHoistLoopBlocks(FlowGraphNaturalLoop* loop,
if (treeIsHoistable)
{
- if (!m_beforeSideEffect)
+ if (!m_canHoistSideEffects)
{
// For now, we give up on an expression that might raise an exception if it is after the
- // first possible global side effect.
+ // first possible global side effect (and we assume we're after that if we're not in the first
+ // block).
// TODO-CQ: this is when we might do loop cloning.
//
if ((tree->gtFlags & GTF_EXCEPT) != 0)
@@ -4484,11 +4514,11 @@ void Compiler::optHoistLoopBlocks(FlowGraphNaturalLoop* loop,
}
}
- // Next check if we need to set 'm_beforeSideEffect' to false.
+ // Next check if we need to set 'm_canHoistSideEffects' to false.
//
// If we have already set it to false then we can skip these checks
//
- if (m_beforeSideEffect)
+ if (m_canHoistSideEffects)
{
// Is the value of the whole tree loop invariant?
if (!treeIsInvariant)
@@ -4496,12 +4526,12 @@ void Compiler::optHoistLoopBlocks(FlowGraphNaturalLoop* loop,
// We have a tree that is not loop invariant and we thus cannot hoist
assert(treeIsHoistable == false);
- // Check if we should clear m_beforeSideEffect.
- // If 'tree' can throw an exception then we need to set m_beforeSideEffect to false.
+ // Check if we should clear m_canHoistSideEffects.
+ // If 'tree' can throw an exception then we need to set m_canHoistSideEffects to false.
// Note that calls are handled below
if (tree->OperMayThrow(m_compiler) && !tree->IsCall())
{
- m_beforeSideEffect = false;
+ m_canHoistSideEffects = false;
}
}
@@ -4517,19 +4547,19 @@ void Compiler::optHoistLoopBlocks(FlowGraphNaturalLoop* loop,
GenTreeCall* call = tree->AsCall();
if (!call->IsHelperCall())
{
- m_beforeSideEffect = false;
+ m_canHoistSideEffects = false;
}
else
{
CorInfoHelpFunc helpFunc = eeGetHelperNum(call->gtCallMethHnd);
if (s_helperCallProperties.MutatesHeap(helpFunc))
{
- m_beforeSideEffect = false;
+ m_canHoistSideEffects = false;
}
else if (s_helperCallProperties.MayRunCctor(helpFunc) &&
(call->gtFlags & GTF_CALL_HOISTABLE) == 0)
{
- m_beforeSideEffect = false;
+ m_canHoistSideEffects = false;
}
// Additional check for helper calls that throw exceptions
@@ -4541,7 +4571,7 @@ void Compiler::optHoistLoopBlocks(FlowGraphNaturalLoop* loop,
// Does this helper call throw?
if (!s_helperCallProperties.NoThrow(helpFunc))
{
- m_beforeSideEffect = false;
+ m_canHoistSideEffects = false;
}
}
}
@@ -4562,8 +4592,8 @@ void Compiler::optHoistLoopBlocks(FlowGraphNaturalLoop* loop,
if (isGloballyVisibleStore)
{
INDEBUG(failReason = "store to globally visible memory");
- treeIsHoistable = false;
- m_beforeSideEffect = false;
+ treeIsHoistable = false;
+ m_canHoistSideEffects = false;
}
}
}
@@ -4667,22 +4697,8 @@ void Compiler::optHoistLoopBlocks(FlowGraphNaturalLoop* loop,
};
HoistVisitor visitor(this, loop, hoistContext, traits, defExecuted);
- loop->VisitLoopBlocks([&](BasicBlock* block) -> BasicBlockVisit {
- const weight_t blockWeight = block->getBBWeight(this);
-
- JITDUMP("\n optHoistLoopBlocks " FMT_BB " (weight=%6s) of loop " FMT_LP " (head: " FMT_BB ")\n",
- block->bbNum, refCntWtd2str(blockWeight, /* padForDecimalPlaces */ true), loop->GetIndex(),
- loop->GetHeader()->bbNum);
-
- if (blockWeight < (BB_UNITY_WEIGHT / 10))
- {
- JITDUMP(" block weight is too small to perform hoisting.\n");
- }
- else
- {
- visitor.HoistBlock(block);
- }
-
+ loop->VisitLoopBlocksReversePostOrder([&](BasicBlock* block) -> BasicBlockVisit {
+ visitor.HoistBlock(block);
return BasicBlockVisit::Continue;
});
diff --git a/src/coreclr/jit/target.h b/src/coreclr/jit/target.h
index a123ce468bb659..3d0ea5df77d30b 100644
--- a/src/coreclr/jit/target.h
+++ b/src/coreclr/jit/target.h
@@ -954,17 +954,7 @@ inline SingleTypeRegSet genSingleTypeFloatMask(regNumber reg ARM_ARG(var_types t
inline SingleTypeRegSet genSingleTypeRegMask(regNumber reg)
{
assert((unsigned)reg < ArrLen(regMasks));
-#ifdef TARGET_AMD64
- // shift is faster than a L1 hit on modern x86
- // (L1 latency on sandy bridge is 4 cycles for [base] and 5 for [base + index*c] )
- // the reason this is AMD-only is because the x86 BE will try to get reg masks for REG_STK
- // and the result needs to be zero.
- SingleTypeRegSet result = 1ULL << reg;
- assert(result == regMasks[reg]);
- return result;
-#else
return regMasks[reg];
-#endif
}
//------------------------------------------------------------------------
diff --git a/src/coreclr/md/enc/mdinternalrw.cpp b/src/coreclr/md/enc/mdinternalrw.cpp
index 01fdc0e4b78da1..be1c2b3941e05e 100644
--- a/src/coreclr/md/enc/mdinternalrw.cpp
+++ b/src/coreclr/md/enc/mdinternalrw.cpp
@@ -51,15 +51,20 @@ HRESULT TranslateSigHelper( // S_OK or error.
ULONG* pcbSig) // [OUT] count of bytes in the translated signature
{
#ifdef FEATURE_METADATA_EMIT
+ HRESULT hr = S_OK;
IMetaModelCommon *pCommon = pImport->GetMetaModelCommon();
RegMeta *pAssemEmitRM = static_cast(pAssemEmit);
RegMeta *pEmitRM = static_cast(emit);
CMiniMdRW *pMiniMdAssemEmit = pAssemEmitRM ? &pAssemEmitRM->m_pStgdb->m_MiniMd : NULL;
CMiniMdRW *pMiniMdEmit = &(pEmitRM->m_pStgdb->m_MiniMd);
+
IMetaModelCommon *pCommonAssemImport = pAssemImport ? pAssemImport->GetMetaModelCommon() : NULL;
- return ImportHelper::MergeUpdateTokenInSig(
+ CMDSemReadWrite cSem(pEmitRM->m_pSemReadWrite);
+ IfFailGo(cSem.LockWrite());
+
+ hr = ImportHelper::MergeUpdateTokenInSig(
pMiniMdAssemEmit, // The assembly emit scope.
pMiniMdEmit, // The emit scope.
pCommonAssemImport, // Assembly scope where the signature is from.
@@ -73,6 +78,8 @@ HRESULT TranslateSigHelper( // S_OK or error.
NULL, // don't care how many bytes consumed
pcbSig); // [OUT] total number of bytes write to pqkSigEmit
+ErrExit:
+ return hr;
#else //!FEATURE_METADATA_EMIT
// This API doesn't make sense without supporting public Emit APIs
return E_NOTIMPL;
diff --git a/src/coreclr/minipal/Unix/doublemapping.cpp b/src/coreclr/minipal/Unix/doublemapping.cpp
index 47a91c6243d9c0..205a2cac789fae 100644
--- a/src/coreclr/minipal/Unix/doublemapping.cpp
+++ b/src/coreclr/minipal/Unix/doublemapping.cpp
@@ -15,6 +15,7 @@
#include
#include
#include
+#include
#if defined(TARGET_LINUX) && !defined(MFD_CLOEXEC)
#include
#include // __NR_memfd_create
@@ -81,14 +82,53 @@ bool VMToOSInterface::CreateDoubleMemoryMapper(void** pHandle, size_t *pMaxExecu
return false;
}
#endif
+ uint64_t maxDoubleMappedMemorySize = MaxDoubleMappedSize;
+
+ // Set the maximum double mapped memory size to the size of the physical memory
+ long pages = sysconf(_SC_PHYS_PAGES);
+ if (pages != -1)
+ {
+ long pageSize = sysconf(_SC_PAGE_SIZE);
+ if (pageSize != -1)
+ {
+ uint64_t physicalMemorySize = (uint64_t)pages * pageSize;
+ if (maxDoubleMappedMemorySize > physicalMemorySize)
+ {
+ maxDoubleMappedMemorySize = physicalMemorySize;
+ }
+ }
+ }
+
+ // Clip the maximum double mapped memory size to 1/4 of the virtual address space limit.
+ // When such a limit is set, GC reserves 1/2 of it, so we need to leave something
+ // for the rest of the process.
+ struct rlimit virtualAddressSpaceLimit;
+ if ((getrlimit(RLIMIT_AS, &virtualAddressSpaceLimit) == 0) && (virtualAddressSpaceLimit.rlim_cur != RLIM_INFINITY))
+ {
+ virtualAddressSpaceLimit.rlim_cur /= 4;
+ if (maxDoubleMappedMemorySize > virtualAddressSpaceLimit.rlim_cur)
+ {
+ maxDoubleMappedMemorySize = virtualAddressSpaceLimit.rlim_cur;
+ }
+ }
+
+ // Clip the maximum double mapped memory size to the file size limit
+ struct rlimit fileSizeLimit;
+ if ((getrlimit(RLIMIT_FSIZE, &fileSizeLimit) == 0) && (fileSizeLimit.rlim_cur != RLIM_INFINITY))
+ {
+ if (maxDoubleMappedMemorySize > fileSizeLimit.rlim_cur)
+ {
+ maxDoubleMappedMemorySize = fileSizeLimit.rlim_cur;
+ }
+ }
- if (ftruncate(fd, MaxDoubleMappedSize) == -1)
+ if (ftruncate(fd, maxDoubleMappedMemorySize) == -1)
{
close(fd);
return false;
}
- *pMaxExecutableCodeSize = MaxDoubleMappedSize;
+ *pMaxExecutableCodeSize = maxDoubleMappedMemorySize;
*pHandle = (void*)(size_t)fd;
#else // !TARGET_APPLE
diff --git a/src/coreclr/nativeaot/Bootstrap/main.cpp b/src/coreclr/nativeaot/Bootstrap/main.cpp
index 57eb0012666e1b..0fc322e2ee666c 100644
--- a/src/coreclr/nativeaot/Bootstrap/main.cpp
+++ b/src/coreclr/nativeaot/Bootstrap/main.cpp
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
#include
+#include
#if defined(DEBUG) && defined(_WIN32)
#include
@@ -138,10 +139,16 @@ MANAGED_RUNTIME_EXPORT(ObjectiveCMarshalGetUnhandledExceptionPropagationHandler)
typedef void (MANAGED_RUNTIME_EXPORT_CALLCONV *pfn)();
+#if defined(_WIN32)
+extern "C" int ThreadEntryPoint(void* pContext);
+#else
+extern "C" size_t ThreadEntryPoint(void* pContext);
+#endif
+
static const pfn c_classlibFunctions[] = {
&MANAGED_RUNTIME_EXPORT_NAME(GetRuntimeException),
&MANAGED_RUNTIME_EXPORT_NAME(RuntimeFailFast),
- nullptr, // &UnhandledExceptionHandler,
+ (pfn)&ThreadEntryPoint,
&MANAGED_RUNTIME_EXPORT_NAME(AppendExceptionStackFrame),
nullptr, // &CheckStaticClassConstruction,
&MANAGED_RUNTIME_EXPORT_NAME(GetSystemArrayEEType),
diff --git a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/ExceptionHandling.cs b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/ExceptionHandling.cs
index 75e8b469d6f686..93e1ba2af221cd 100644
--- a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/ExceptionHandling.cs
+++ b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/ExceptionHandling.cs
@@ -550,6 +550,30 @@ internal object ThrownException
[FieldOffset(AsmOffsets.OFFSETOF__ExInfo__m_notifyDebuggerSP)]
internal volatile UIntPtr _notifyDebuggerSP;
+#if !NATIVEAOT
+ [FieldOffset(AsmOffsets.OFFSETOF__ExInfo__m_pCatchHandler)]
+ internal volatile byte* _pCatchHandler;
+
+ [FieldOffset(AsmOffsets.OFFSETOF__ExInfo__m_handlingFrameSP)]
+ internal volatile UIntPtr _handlingFrameSP;
+
+#if TARGET_ARM64
+ // On ARM64, two frames can have the same SP, when a leaf function
+ // doesn't use any stack. So to distinguish between the caller frame
+ // and the leaf one, we also need to know the PC of the handling frame.
+ [FieldOffset(AsmOffsets.OFFSETOF__ExInfo__m_handlingFramePC)]
+ internal volatile byte* _handlingFramePC;
+#endif
+
+#if TARGET_UNIX
+ [FieldOffset(AsmOffsets.OFFSETOF__ExInfo__m_pReversePInvokePropagationCallback)]
+ internal volatile IntPtr _pReversePInvokePropagationCallback;
+
+ [FieldOffset(AsmOffsets.OFFSETOF__ExInfo__m_pReversePInvokePropagationContext)]
+ internal volatile IntPtr _pReversePInvokePropagationContext;
+#endif // TARGET_UNIX
+
+#endif // !NATIVEAOT
}
//
@@ -637,7 +661,9 @@ public static void RhThrowHwEx(uint exceptionCode, ref ExInfo exInfo)
exInfo.Init(exceptionToThrow!, instructionFault);
DispatchEx(ref exInfo._frameIter, ref exInfo);
+#if NATIVEAOT
FallbackFailFast(RhFailFastReason.InternalError, null);
+#endif
}
private const uint MaxTryRegionIdx = 0xFFFFFFFFu;
@@ -670,68 +696,11 @@ public static void RhThrowEx(object exceptionObj, ref ExInfo exInfo)
exInfo.Init(exceptionObj);
DispatchEx(ref exInfo._frameIter, ref exInfo);
+#if NATIVEAOT
FallbackFailFast(RhFailFastReason.InternalError, null);
+#endif
}
-#if !NATIVEAOT
- public static void RhUnwindAndIntercept(ref ExInfo exInfo, UIntPtr interceptStackFrameSP)
- {
- exInfo._passNumber = 2;
- exInfo._idxCurClause = MaxTryRegionIdx;
- uint startIdx = MaxTryRegionIdx;
- bool unwoundReversePInvoke = false;
- bool isExceptionIntercepted = false;
- bool isValid = exInfo._frameIter.Init(exInfo._pExContext, (exInfo._kind & ExKind.InstructionFaultFlag) != 0, &isExceptionIntercepted);
- for (; isValid && !isExceptionIntercepted && ((byte*)exInfo._frameIter.SP <= (byte*)interceptStackFrameSP); isValid = exInfo._frameIter.Next(&startIdx, &unwoundReversePInvoke, &isExceptionIntercepted))
- {
- Debug.Assert(isValid, "Unwind and intercept failed unexpectedly");
- DebugScanCallFrame(exInfo._passNumber, exInfo._frameIter.ControlPC, exInfo._frameIter.SP);
-
- if (unwoundReversePInvoke)
- {
- // Found the native frame that called the reverse P/invoke.
- // It is not possible to run managed second pass handlers on a native frame.
- break;
- }
-
- if (exInfo._frameIter.SP == interceptStackFrameSP)
- {
- break;
- }
-
- InvokeSecondPass(ref exInfo, startIdx);
- if (isExceptionIntercepted)
- {
- Debug.Assert(false);
- break;
- }
- }
-
- // ------------------------------------------------
- //
- // Call the interception code
- //
- // ------------------------------------------------
- if (unwoundReversePInvoke)
- {
- object exceptionObj = exInfo.ThrownException;
- fixed (EH.ExInfo* pExInfo = &exInfo)
- {
- InternalCalls.RhpCallCatchFunclet(
- ObjectHandleOnStack.Create(ref exceptionObj), null, exInfo._frameIter.RegisterSet, pExInfo);
- }
- }
- else
- {
- InternalCalls.ResumeAtInterceptionLocation(exInfo._frameIter.RegisterSet);
- }
-
- Debug.Fail("unreachable");
- FallbackFailFast(RhFailFastReason.InternalError, null);
- }
-#endif // !NATIVEAOT
-
-
#if NATIVEAOT
[RuntimeExport("RhRethrow")]
#endif
@@ -757,7 +726,9 @@ public static void RhRethrow(ref ExInfo activeExInfo, ref ExInfo exInfo)
exInfo.Init(rethrownException, ref activeExInfo);
DispatchEx(ref exInfo._frameIter, ref exInfo);
+#if NATIVEAOT
FallbackFailFast(RhFailFastReason.InternalError, null);
+#endif
}
[StackTraceHidden]
@@ -877,6 +848,21 @@ private static void DispatchEx(scoped ref StackFrameIterator frameIter, ref ExIn
Debug.Assert(pCatchHandler != null || pReversePInvokePropagationCallback != IntPtr.Zero || unwoundReversePInvoke || isExceptionIntercepted, "We should have a handler if we're starting the second pass");
Debug.Assert(!isExceptionIntercepted || (pCatchHandler == null), "No catch handler should be returned for intercepted exceptions in the first pass");
+#if !NATIVEAOT
+ exInfo._pCatchHandler = pCatchHandler;
+ exInfo._handlingFrameSP = handlingFrameSP;
+#if TARGET_ARM64
+ exInfo._handlingFramePC = prevOriginalPC;
+#endif
+#if TARGET_UNIX
+ exInfo._pReversePInvokePropagationCallback = pReversePInvokePropagationCallback;
+ exInfo._pReversePInvokePropagationContext = pReversePInvokePropagationContext;
+#endif // TARGET_UNIX
+ exInfo._idxCurClause = catchingTryRegionIdx;
+
+ return;
+
+#else // !NATIVEAOT
// ------------------------------------------------
//
// Second pass
@@ -888,9 +874,10 @@ private static void DispatchEx(scoped ref StackFrameIterator frameIter, ref ExIn
// 'collapse' funclets which gets confused when we walk out of the dispatch code and encounter the
// 'main body' without first encountering the funclet. The thunks used to invoke 2nd-pass
// funclets will always toggle this mode off before invoking them.
-#if NATIVEAOT
+
InternalCalls.RhpSetThreadDoNotTriggerGC();
-#endif
+
+
exInfo._passNumber = 2;
exInfo._idxCurClause = catchingTryRegionIdx;
startIdx = MaxTryRegionIdx;
@@ -910,10 +897,8 @@ private static void DispatchEx(scoped ref StackFrameIterator frameIter, ref ExIn
if (unwoundReversePInvoke)
{
-#if NATIVEAOT
Debug.Assert(pReversePInvokePropagationCallback != IntPtr.Zero, "Unwound to a reverse P/Invoke in the second pass. We should have a propagation handler.");
Debug.Assert(frameIter.PreviousTransitionFrame != IntPtr.Zero, "Should have a transition frame for reverse P/Invoke.");
-#endif
Debug.Assert(frameIter.SP == handlingFrameSP, "Encountered a different reverse P/Invoke frame in the second pass.");
// Found the native frame that called the reverse P/invoke.
// It is not possible to run managed second pass handlers on a native frame.
@@ -937,36 +922,26 @@ private static void DispatchEx(scoped ref StackFrameIterator frameIter, ref ExIn
#if FEATURE_OBJCMARSHAL
if (pReversePInvokePropagationCallback != IntPtr.Zero)
{
-#if NATIVEAOT
InternalCalls.RhpCallPropagateExceptionCallback(
pReversePInvokePropagationContext, pReversePInvokePropagationCallback, frameIter.RegisterSet, ref exInfo, frameIter.PreviousTransitionFrame);
// the helper should jump to propagation handler and not return
-#endif
Debug.Fail("unreachable");
FallbackFailFast(RhFailFastReason.InternalError, null);
}
#endif // FEATURE_OBJCMARSHAL
-
// ------------------------------------------------
//
// Call the handler and resume execution
//
// ------------------------------------------------
exInfo._idxCurClause = catchingTryRegionIdx;
-#if NATIVEAOT
InternalCalls.RhpCallCatchFunclet(
exceptionObj, pCatchHandler, frameIter.RegisterSet, ref exInfo);
-#else // NATIVEAOT
- fixed (EH.ExInfo* pExInfo = &exInfo)
- {
- InternalCalls.RhpCallCatchFunclet(
- ObjectHandleOnStack.Create(ref exceptionObj), pCatchHandler, frameIter.RegisterSet, pExInfo);
- }
-#endif // NATIVEAOT
// currently, RhpCallCatchFunclet will resume after the catch
Debug.Fail("unreachable");
FallbackFailFast(RhFailFastReason.InternalError, null);
+#endif // !NATIVEAOT
}
[System.Diagnostics.Conditional("DEBUG")]
@@ -1170,6 +1145,7 @@ private static bool ShouldTypedClauseCatchThisException(object exception, Method
#endif
}
+#if NATIVEAOT
private static void InvokeSecondPass(ref ExInfo exInfo, uint idxStart)
{
InvokeSecondPass(ref exInfo, idxStart, MaxTryRegionIdx);
@@ -1207,11 +1183,7 @@ private static void InvokeSecondPass(ref ExInfo exInfo, uint idxStart, uint idxL
// Now, we continue skipping while the try region is identical to the one that invoked the
// previous dispatch.
- if ((ehClause._tryStartOffset == lastTryStart) && (ehClause._tryEndOffset == lastTryEnd)
-#if !NATIVEAOT
- && (ehClause._isSameTry)
-#endif
- )
+ if ((ehClause._tryStartOffset == lastTryStart) && (ehClause._tryEndOffset == lastTryEnd))
continue;
// We are done skipping. This is required to handle empty finally block markers that are used
@@ -1242,19 +1214,11 @@ private static void InvokeSecondPass(ref ExInfo exInfo, uint idxStart, uint idxL
byte* pFinallyHandler = ehClause._handlerAddress;
exInfo._idxCurClause = curIdx;
-#if NATIVEAOT
InternalCalls.RhpCallFinallyFunclet(pFinallyHandler, exInfo._frameIter.RegisterSet);
-#else // NATIVEAOT
- fixed (EH.ExInfo* pExInfo = &exInfo)
- {
- InternalCalls.RhpCallFinallyFunclet(pFinallyHandler, exInfo._frameIter.RegisterSet, pExInfo);
- }
-#endif // NATIVEAOT
exInfo._idxCurClause = MaxTryRegionIdx;
}
}
-#if NATIVEAOT
#pragma warning disable IDE0060
[UnmanagedCallersOnly(EntryPoint = "RhpFailFastForPInvokeExceptionPreemp")]
public static void RhpFailFastForPInvokeExceptionPreemp(IntPtr PInvokeCallsiteReturnAddr, void* pExceptionRecord, void* pContextRecord)
diff --git a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/InternalCalls.cs b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/InternalCalls.cs
index d7557d654a7217..77acff31afa5e9 100644
--- a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/InternalCalls.cs
+++ b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/InternalCalls.cs
@@ -38,7 +38,7 @@ internal enum ClassLibFunctionId
{
GetRuntimeException = 0,
FailFast = 1,
- // UnhandledExceptionHandler = 2, // unused
+ ThreadEntryPoint = 2,
AppendExceptionStackFrame = 3,
// unused = 4,
GetSystemArrayEEType = 5,
diff --git a/src/coreclr/nativeaot/Runtime/ICodeManager.h b/src/coreclr/nativeaot/Runtime/ICodeManager.h
index b9e157c5cae41a..081ef729bdc4f8 100644
--- a/src/coreclr/nativeaot/Runtime/ICodeManager.h
+++ b/src/coreclr/nativeaot/Runtime/ICodeManager.h
@@ -99,7 +99,7 @@ enum class ClasslibFunctionId
{
GetRuntimeException = 0,
FailFast = 1,
- UnhandledExceptionHandler = 2,
+ ThreadEntryPoint = 2,
AppendExceptionStackFrame = 3,
// unused = 4,
GetSystemArrayEEType = 5,
diff --git a/src/coreclr/nativeaot/Runtime/amd64/ExceptionHandling.asm b/src/coreclr/nativeaot/Runtime/amd64/ExceptionHandling.asm
index 928a3a9bce785a..9efa43b41114fe 100644
--- a/src/coreclr/nativeaot/Runtime/amd64/ExceptionHandling.asm
+++ b/src/coreclr/nativeaot/Runtime/amd64/ExceptionHandling.asm
@@ -130,6 +130,10 @@ NESTED_ENTRY RhpThrowEx, _TEXT
alloc_stack SIZEOF_XmmSaves + 8h ;; reserve stack for the xmm saves (+8h to realign stack)
rdsspq r8 ;; nop if SSP is not implemented, 0 if not enabled
+ test r8, r8
+ je @f
+ add r8, 8 ;; Move SSP to match RSP of the throw site
+ @@:
push_vol_reg r8 ;; SSP
xor r8, r8
push_nonvol_reg r15
@@ -226,6 +230,10 @@ NESTED_ENTRY RhpRethrow, _TEXT
alloc_stack SIZEOF_XmmSaves + 8h ;; reserve stack for the xmm saves (+8h to realign stack)
rdsspq r8 ;; nop if SSP is not implemented, 0 if not enabled
+ test r8, r8
+ je @f
+ add r8, 8 ;; Move SSP to match RSP of the throw site
+ @@:
push_vol_reg r8 ;; SSP
xor r8, r8
push_nonvol_reg r15
diff --git a/src/coreclr/nativeaot/Runtime/thread.cpp b/src/coreclr/nativeaot/Runtime/thread.cpp
index 45b88d1cde2def..f0e369224a20ad 100644
--- a/src/coreclr/nativeaot/Runtime/thread.cpp
+++ b/src/coreclr/nativeaot/Runtime/thread.cpp
@@ -4,6 +4,7 @@
#include "common.h"
#include "gcenv.h"
#include "gcheaputilities.h"
+#include "gchandleutilities.h"
#include "CommonTypes.h"
#include "CommonMacros.h"
@@ -1278,6 +1279,49 @@ FCIMPL0(Object**, RhGetThreadStaticStorage)
}
FCIMPLEND
+#ifdef TARGET_UNIX
+#define NEWTHREAD_RETURN_TYPE size_t
+#else
+#define NEWTHREAD_RETURN_TYPE uint32_t
+#endif
+
+static NEWTHREAD_RETURN_TYPE RhThreadEntryPoint(void* pContext)
+{
+ // We will attach the thread early so that when the managed thread entrypoint
+ // starts running and performs its reverse p/invoke transition, the thread is
+ // already attached.
+ //
+ // This avoids potential deadlocks with module initializers that may be running
+ // as part of runtime initialization (in non-EXE scenario) and creating new
+ // threads. When RhThreadEntryPoint runs, the runtime must already be initialized
+ // enough to be able to run managed code so we don't need to wait for it to
+ // finish.
+
+ ThreadStore::AttachCurrentThread();
+
+ Thread * pThread = ThreadStore::GetCurrentThread();
+ pThread->SetDeferredTransitionFrameForNativeHelperThread();
+ pThread->DisablePreemptiveMode();
+
+ Object * pThreadObject = ObjectFromHandle((OBJECTHANDLE)pContext);
+ MethodTable* pMT = pThreadObject->GetMethodTable();
+
+ pThread->EnablePreemptiveMode();
+
+ NEWTHREAD_RETURN_TYPE (*pFn)(void*) = (NEWTHREAD_RETURN_TYPE (*)(void*))
+ pMT->GetTypeManagerPtr()
+ ->AsTypeManager()
+ ->GetClasslibFunction(ClasslibFunctionId::ThreadEntryPoint);
+
+ return pFn(pContext);
+}
+
+FCIMPL0(void*, RhGetThreadEntryPointAddress)
+{
+ return (void*)&RhThreadEntryPoint;
+}
+FCIMPLEND
+
InlinedThreadStaticRoot* Thread::GetInlinedThreadStaticList()
{
return m_pInlinedThreadLocalStatics;
diff --git a/src/coreclr/nativeaot/Runtime/unix/PalCreateDump.cpp b/src/coreclr/nativeaot/Runtime/unix/PalCreateDump.cpp
index 552dba78dd68d1..a8acc1b9f676c0 100644
--- a/src/coreclr/nativeaot/Runtime/unix/PalCreateDump.cpp
+++ b/src/coreclr/nativeaot/Runtime/unix/PalCreateDump.cpp
@@ -213,8 +213,8 @@ CreateCrashDump(
char* errorMessageBuffer,
int cbErrorMessageBuffer)
{
- int pipe_descs[2];
- if (pipe(pipe_descs) == -1)
+ int pipe_descs[4];
+ if (pipe(pipe_descs) == -1 || pipe(pipe_descs + 2) == -1)
{
if (errorMessageBuffer != nullptr)
{
@@ -222,9 +222,12 @@ CreateCrashDump(
}
return false;
}
- // [0] is read end, [1] is write end
- int parent_pipe = pipe_descs[0];
- int child_pipe = pipe_descs[1];
+ // from parent (write) to child (read), used to signal prctl(PR_SET_PTRACER, childpid) is done
+ int child_read_pipe = pipe_descs[0];
+ int parent_write_pipe = pipe_descs[1];
+ // from child (write) to parent (read), used to capture createdump's stderr
+ int parent_read_pipe = pipe_descs[2];
+ int child_write_pipe = pipe_descs[3];
// Fork the core dump child process.
pid_t childpid = fork();
@@ -236,19 +239,34 @@ CreateCrashDump(
{
snprintf(errorMessageBuffer, cbErrorMessageBuffer, "Problem launching createdump: fork() FAILED %s (%d)\n", strerror(errno), errno);
}
- close(pipe_descs[0]);
- close(pipe_descs[1]);
+ for (int i = 0; i < 4; i++)
+ {
+ close(pipe_descs[i]);
+ }
return false;
}
else if (childpid == 0)
{
- // Close the read end of the pipe, the child doesn't need it
- close(parent_pipe);
+ close(parent_read_pipe);
+ close(parent_write_pipe);
+
+ // Wait for prctl(PR_SET_PTRACER, childpid) in parent
+ char buffer;
+ int bytesRead;
+ while((bytesRead = read(child_read_pipe, &buffer, 1)) < 0 && errno == EINTR);
+ close(child_read_pipe);
+
+ if (bytesRead != 1)
+ {
+ fprintf(stderr, "Problem reading from createdump child_read_pipe: %s (%d)\n", strerror(errno), errno);
+ close(child_write_pipe);
+ exit(-1);
+ }
// Only dup the child's stderr if there is error buffer
if (errorMessageBuffer != nullptr)
{
- dup2(child_pipe, STDERR_FILENO);
+ dup2(child_write_pipe, STDERR_FILENO);
}
// Execute the createdump program
if (execv(argv[0], (char* const *)argv) == -1)
@@ -259,6 +277,8 @@ CreateCrashDump(
}
else
{
+ close(child_read_pipe);
+ close(child_write_pipe);
#if HAVE_PRCTL_H && HAVE_PR_SET_PTRACER
// Gives the child process permission to use /proc//mem and ptrace
if (prctl(PR_SET_PTRACER, childpid, 0, 0, 0) == -1)
@@ -270,7 +290,21 @@ CreateCrashDump(
#endif
}
#endif // HAVE_PRCTL_H && HAVE_PR_SET_PTRACER
- close(child_pipe);
+ // Signal child that prctl(PR_SET_PTRACER, childpid) is done
+ int bytesWritten;
+ while((bytesWritten = write(parent_write_pipe, "S", 1)) < 0 && errno == EINTR);
+ close(parent_write_pipe);
+
+ if (bytesWritten != 1)
+ {
+ fprintf(stderr, "Problem writing to createdump parent_write_pipe: %s (%d)\n", strerror(errno), errno);
+ close(parent_read_pipe);
+ if (errorMessageBuffer != nullptr)
+ {
+ errorMessageBuffer[0] = 0;
+ }
+ return false;
+ }
// Read createdump's stderr messages (if any)
if (errorMessageBuffer != nullptr)
@@ -278,7 +312,7 @@ CreateCrashDump(
// Read createdump's stderr
int bytesRead = 0;
int count = 0;
- while ((count = read(parent_pipe, errorMessageBuffer + bytesRead, cbErrorMessageBuffer - bytesRead)) > 0)
+ while ((count = read(parent_read_pipe, errorMessageBuffer + bytesRead, cbErrorMessageBuffer - bytesRead)) > 0)
{
bytesRead += count;
}
@@ -288,7 +322,7 @@ CreateCrashDump(
fputs(errorMessageBuffer, stderr);
}
}
- close(parent_pipe);
+ close(parent_read_pipe);
// Parent waits until the child process is done
int wstatus = 0;
diff --git a/src/coreclr/nativeaot/Runtime/unix/UnwindHelpers.cpp b/src/coreclr/nativeaot/Runtime/unix/UnwindHelpers.cpp
index 07c6c2135feeff..7f2d17b3f4376c 100644
--- a/src/coreclr/nativeaot/Runtime/unix/UnwindHelpers.cpp
+++ b/src/coreclr/nativeaot/Runtime/unix/UnwindHelpers.cpp
@@ -354,8 +354,8 @@ struct Registers_REGDISPLAY : REGDISPLAY
uint32_t getRegister(int num) const;
void setRegister(int num, uint32_t value, uint32_t location);
- double getFloatRegister(int num) const;
- void setFloatRegister(int num, double value);
+ unw_fpreg_t getFloatRegister(int num) const;
+ void setFloatRegister(int num, unw_fpreg_t value);
libunwind::v128 getVectorRegister(int num) const { abort(); }
void setVectorRegister(int num, libunwind::v128 value) { abort(); }
@@ -516,13 +516,13 @@ void Registers_REGDISPLAY::setRegister(int num, uint32_t value, uint32_t locatio
}
}
-double Registers_REGDISPLAY::getFloatRegister(int num) const
+unw_fpreg_t Registers_REGDISPLAY::getFloatRegister(int num) const
{
assert(validFloatRegister(num));
- return unwindhelpers_bitcast(D[num - UNW_ARM_D8]);
+ return unwindhelpers_bitcast(D[num - UNW_ARM_D8]);
}
-void Registers_REGDISPLAY::setFloatRegister(int num, double value)
+void Registers_REGDISPLAY::setFloatRegister(int num, unw_fpreg_t value)
{
assert(validFloatRegister(num));
D[num - UNW_ARM_D8] = unwindhelpers_bitcast(value);
diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.NativeAot.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.NativeAot.cs
index be875ba1731c52..541f62969ab526 100644
--- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.NativeAot.cs
+++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.NativeAot.cs
@@ -27,18 +27,6 @@ public static void InitializeArray(Array array, RuntimeFieldHandle fldHandle)
throw new PlatformNotSupportedException();
}
- private static unsafe ref byte GetSpanDataFrom(
- RuntimeFieldHandle fldHandle,
- RuntimeTypeHandle targetTypeHandle,
- out int count)
- {
- // We only support this intrinsic when it occurs within a well-defined IL sequence.
- // If a call to this method occurs within the recognized sequence, codegen must expand the IL sequence completely.
- // For any other purpose, the API is currently unsupported.
- // https://github.com/dotnet/corert/issues/364
- throw new PlatformNotSupportedException();
- }
-
[RequiresUnreferencedCode("Trimmer can't guarantee existence of class constructor")]
public static void RunClassConstructor(RuntimeTypeHandle type)
{
diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs
index 72a238b0bddde2..59ba6211e0b814 100644
--- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs
+++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs
@@ -26,6 +26,14 @@ internal static partial class RuntimeImports
{
internal const string RuntimeLibrary = "*";
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [RuntimeImport(RuntimeLibrary, "RhGetThreadEntryPointAddress")]
+#if TARGET_UNIX
+ internal static extern unsafe delegate* unmanaged RhGetThreadEntryPointAddress();
+#else
+ internal static extern unsafe delegate* unmanaged RhGetThreadEntryPointAddress();
+#endif
+
[MethodImplAttribute(MethodImplOptions.InternalCall)]
[RuntimeImport(RuntimeLibrary, "RhGetCrashInfoBuffer")]
internal static extern unsafe byte* RhGetCrashInfoBuffer(out int cbMaxSize);
diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Thread.NativeAot.Unix.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Thread.NativeAot.Unix.cs
index de77bc91b088e3..b30ffd62b08d9a 100644
--- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Thread.NativeAot.Unix.cs
+++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Thread.NativeAot.Unix.cs
@@ -101,7 +101,7 @@ private unsafe bool CreateThread(GCHandle thisThreadHandle)
stackSize = RuntimeImports.RhGetDefaultStackSize();
}
- if (!Interop.Sys.CreateThread(stackSize, &ThreadEntryPoint, GCHandle.ToIntPtr(thisThreadHandle)))
+ if (!Interop.Sys.CreateThread(stackSize, RuntimeImports.RhGetThreadEntryPointAddress(), GCHandle.ToIntPtr(thisThreadHandle)))
{
return false;
}
@@ -115,7 +115,7 @@ private unsafe bool CreateThread(GCHandle thisThreadHandle)
///
/// This is an entry point for managed threads created by application
///
- [UnmanagedCallersOnly]
+ [UnmanagedCallersOnly(EntryPoint = "ThreadEntryPoint")]
private static IntPtr ThreadEntryPoint(IntPtr parameter)
{
StartThread(parameter);
diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Thread.NativeAot.Windows.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Thread.NativeAot.Windows.cs
index f01fe0f86f38f7..9933c6309fb43d 100644
--- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Thread.NativeAot.Windows.cs
+++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Thread.NativeAot.Windows.cs
@@ -14,9 +14,6 @@ namespace System.Threading
{
public sealed partial class Thread
{
- [ThreadStatic]
- private static ApartmentType t_apartmentType;
-
[ThreadStatic]
private static ComState t_comState;
@@ -200,7 +197,7 @@ private unsafe bool CreateThread(GCHandle thisThreadHandle)
}
_osHandle = Interop.Kernel32.CreateThread(IntPtr.Zero, (IntPtr)stackSize,
- &ThreadEntryPoint, GCHandle.ToIntPtr(thisThreadHandle),
+ RuntimeImports.RhGetThreadEntryPointAddress(), GCHandle.ToIntPtr(thisThreadHandle),
Interop.Kernel32.CREATE_SUSPENDED | Interop.Kernel32.STACK_SIZE_PARAM_IS_A_RESERVATION,
out _);
@@ -219,7 +216,7 @@ private unsafe bool CreateThread(GCHandle thisThreadHandle)
///
/// This is an entry point for managed threads created by application
///
- [UnmanagedCallersOnly]
+ [UnmanagedCallersOnly(EntryPoint = "ThreadEntryPoint")]
private static uint ThreadEntryPoint(IntPtr parameter)
{
StartThread(parameter);
@@ -235,14 +232,15 @@ public ApartmentState GetApartmentState()
return _initialApartmentState;
}
- switch (GetCurrentApartmentType())
+ switch (GetCurrentApartmentState())
{
- case ApartmentType.STA:
+ case ApartmentState.STA:
return ApartmentState.STA;
- case ApartmentType.MTA:
+ case ApartmentState.MTA:
return ApartmentState.MTA;
default:
- return ApartmentState.Unknown;
+ // If COM is uninitialized on the current thread, it is assumed to be implicit MTA.
+ return ApartmentState.MTA;
}
}
@@ -275,14 +273,29 @@ private bool SetApartmentStateUnchecked(ApartmentState state, bool throwOnError)
}
else
{
+ // Compat: Setting ApartmentState to Unknown uninitializes COM
UninitializeCom();
}
- }
- // Clear the cache and check whether new state matches the desired state
- t_apartmentType = ApartmentType.Unknown;
+ // Clear the cache and check whether new state matches the desired state
+ t_comState &= ~(ComState.STA | ComState.MTA);
+
+ retState = GetCurrentApartmentState();
+ }
+ else
+ {
+ Debug.Assert((t_comState & ComState.MTA) != 0);
+ retState = ApartmentState.MTA;
+ }
+ }
- retState = GetApartmentState();
+ // Special case where we pass in Unknown and get back MTA.
+ // Once we CoUninitialize the thread, the OS will still
+ // report the thread as implicitly in the MTA if any
+ // other thread in the process is CoInitialized.
+ if ((state == ApartmentState.Unknown) && (retState == ApartmentState.MTA))
+ {
+ return true;
}
if (retState != state)
@@ -316,7 +329,7 @@ private static void InitializeComForThreadPoolThread()
// Process-wide COM is initialized very early before any managed code can run.
// Assume it is done.
// Prevent re-initialization of COM model on threadpool threads from the default one.
- t_comState |= ComState.Locked;
+ t_comState |= ComState.Locked | ComState.MTA;
}
private static void InitializeCom(ApartmentState state = ApartmentState.MTA)
@@ -396,24 +409,25 @@ internal static Thread EnsureThreadPoolThreadInitialized()
public void Interrupt() { throw new PlatformNotSupportedException(); }
internal static bool ReentrantWaitsEnabled =>
- GetCurrentApartmentType() == ApartmentType.STA;
+ GetCurrentApartmentState() == ApartmentState.STA;
- internal static ApartmentType GetCurrentApartmentType()
+ // Unlike the public API, this returns ApartmentState.Unknown when COM is uninitialized on the current thread
+ internal static ApartmentState GetCurrentApartmentState()
{
- ApartmentType currentThreadType = t_apartmentType;
- if (currentThreadType != ApartmentType.Unknown)
- return currentThreadType;
+ if ((t_comState & (ComState.MTA | ComState.STA)) != 0)
+ return ((t_comState & ComState.STA) != 0) ? ApartmentState.STA : ApartmentState.MTA;
Interop.APTTYPE aptType;
Interop.APTTYPEQUALIFIER aptTypeQualifier;
int result = Interop.Ole32.CoGetApartmentType(out aptType, out aptTypeQualifier);
- ApartmentType type = ApartmentType.Unknown;
+ ApartmentState state = ApartmentState.Unknown;
switch (result)
{
case HResults.CO_E_NOTINITIALIZED:
- type = ApartmentType.None;
+ Debug.Fail("COM is not initialized");
+ state = ApartmentState.Unknown;
break;
case HResults.S_OK:
@@ -421,24 +435,27 @@ internal static ApartmentType GetCurrentApartmentType()
{
case Interop.APTTYPE.APTTYPE_STA:
case Interop.APTTYPE.APTTYPE_MAINSTA:
- type = ApartmentType.STA;
+ state = ApartmentState.STA;
break;
case Interop.APTTYPE.APTTYPE_MTA:
- type = ApartmentType.MTA;
+ state = ApartmentState.MTA;
break;
case Interop.APTTYPE.APTTYPE_NA:
switch (aptTypeQualifier)
{
case Interop.APTTYPEQUALIFIER.APTTYPEQUALIFIER_NA_ON_MTA:
+ state = ApartmentState.MTA;
+ break;
+
case Interop.APTTYPEQUALIFIER.APTTYPEQUALIFIER_NA_ON_IMPLICIT_MTA:
- type = ApartmentType.MTA;
+ state = ApartmentState.Unknown;
break;
case Interop.APTTYPEQUALIFIER.APTTYPEQUALIFIER_NA_ON_STA:
case Interop.APTTYPEQUALIFIER.APTTYPEQUALIFIER_NA_ON_MAINSTA:
- type = ApartmentType.STA;
+ state = ApartmentState.STA;
break;
default:
@@ -454,17 +471,9 @@ internal static ApartmentType GetCurrentApartmentType()
break;
}
- if (type != ApartmentType.Unknown)
- t_apartmentType = type;
- return type;
- }
-
- internal enum ApartmentType : byte
- {
- Unknown = 0,
- None,
- STA,
- MTA
+ if (state != ApartmentState.Unknown)
+ t_comState |= (state == ApartmentState.STA) ? ComState.STA : ComState.MTA;
+ return state;
}
[Flags]
@@ -472,6 +481,8 @@ internal enum ComState : byte
{
InitializedByUs = 1,
Locked = 2,
+ MTA = 4,
+ STA = 8
}
}
}
diff --git a/src/coreclr/pal/inc/unixasmmacrosamd64.inc b/src/coreclr/pal/inc/unixasmmacrosamd64.inc
index 880a282813f738..1d3d11c7d24ab0 100644
--- a/src/coreclr/pal/inc/unixasmmacrosamd64.inc
+++ b/src/coreclr/pal/inc/unixasmmacrosamd64.inc
@@ -53,8 +53,13 @@ C_FUNC(\Name):
.endm
.macro LEAF_END_MARKED Name, Section
-C_FUNC(\Name\()_End):
+#if defined(__APPLE__)
+ .alt_entry C_FUNC(\Name\()_End)
+ .private_extern C_FUNC(\Name\()_End)
+#else
.global C_FUNC(\Name\()_End)
+#endif
+C_FUNC(\Name\()_End):
LEAF_END \Name, \Section
// make sure this symbol gets its own address
nop
diff --git a/src/coreclr/pal/inc/unixasmmacrosarm64.inc b/src/coreclr/pal/inc/unixasmmacrosarm64.inc
index ae5854a995c947..fa4265ab3fc9d2 100644
--- a/src/coreclr/pal/inc/unixasmmacrosarm64.inc
+++ b/src/coreclr/pal/inc/unixasmmacrosarm64.inc
@@ -64,8 +64,13 @@ C_FUNC(\Name):
.endm
.macro LEAF_END_MARKED Name, Section
-C_FUNC(\Name\()_End):
+#if defined(__APPLE__)
+ .alt_entry C_FUNC(\Name\()_End)
+ .private_extern C_FUNC(\Name\()_End)
+#else
.global C_FUNC(\Name\()_End)
+#endif
+C_FUNC(\Name\()_End):
LEAF_END \Name, \Section
// make sure this symbol gets its own address
nop
diff --git a/src/coreclr/pal/src/thread/process.cpp b/src/coreclr/pal/src/thread/process.cpp
index 9b779c0689c5c2..b2ecc36aec9624 100644
--- a/src/coreclr/pal/src/thread/process.cpp
+++ b/src/coreclr/pal/src/thread/process.cpp
@@ -2447,8 +2447,8 @@ PROCCreateCrashDump(
}
}
- int pipe_descs[2];
- if (pipe(pipe_descs) == -1)
+ int pipe_descs[4];
+ if (pipe(pipe_descs) == -1 || pipe(pipe_descs + 2) == -1)
{
if (errorMessageBuffer != nullptr)
{
@@ -2456,9 +2456,13 @@ PROCCreateCrashDump(
}
return false;
}
- // [0] is read end, [1] is write end
- int parent_pipe = pipe_descs[0];
- int child_pipe = pipe_descs[1];
+
+ // from parent (write) to child (read), used to signal prctl(PR_SET_PTRACER, childpid) is done
+ int child_read_pipe = pipe_descs[0];
+ int parent_write_pipe = pipe_descs[1];
+ // from child (write) to parent (read), used to capture createdump's stderr
+ int parent_read_pipe = pipe_descs[2];
+ int child_write_pipe = pipe_descs[3];
// Fork the core dump child process.
pid_t childpid = fork();
@@ -2470,20 +2474,36 @@ PROCCreateCrashDump(
{
sprintf_s(errorMessageBuffer, cbErrorMessageBuffer, "Problem launching createdump: fork() FAILED %s (%d)\n", strerror(errno), errno);
}
- close(pipe_descs[0]);
- close(pipe_descs[1]);
+ for (int i = 0; i < 4; i++)
+ {
+ close(pipe_descs[i]);
+ }
return false;
}
else if (childpid == 0)
{
- // Close the read end of the pipe, the child doesn't need it
int callbackResult = 0;
- close(parent_pipe);
+
+ close(parent_read_pipe);
+ close(parent_write_pipe);
+
+ // Wait for prctl(PR_SET_PTRACER, childpid) in parent
+ char buffer;
+ int bytesRead;
+ while((bytesRead = read(child_read_pipe, &buffer, 1)) < 0 && errno == EINTR);
+ close(child_read_pipe);
+
+ if (bytesRead != 1)
+ {
+ fprintf(stderr, "Problem reading from createdump child_read_pipe: %s (%d)\n", strerror(errno), errno);
+ close(child_write_pipe);
+ exit(-1);
+ }
// Only dup the child's stderr if there is error buffer
if (errorMessageBuffer != nullptr)
{
- dup2(child_pipe, STDERR_FILENO);
+ dup2(child_write_pipe, STDERR_FILENO);
}
if (g_createdumpCallback != nullptr)
{
@@ -2510,6 +2530,8 @@ PROCCreateCrashDump(
}
else
{
+ close(child_read_pipe);
+ close(child_write_pipe);
#if HAVE_PRCTL_H && HAVE_PR_SET_PTRACER
// Gives the child process permission to use /proc//mem and ptrace
if (prctl(PR_SET_PTRACER, childpid, 0, 0, 0) == -1)
@@ -2519,7 +2541,21 @@ PROCCreateCrashDump(
ERROR("PROCCreateCrashDump: prctl() FAILED %s (%d)\n", strerror(errno), errno);
}
#endif // HAVE_PRCTL_H && HAVE_PR_SET_PTRACER
- close(child_pipe);
+ // Signal child that prctl(PR_SET_PTRACER, childpid) is done
+ int bytesWritten;
+ while((bytesWritten = write(parent_write_pipe, "S", 1)) < 0 && errno == EINTR);
+ close(parent_write_pipe);
+
+ if (bytesWritten != 1)
+ {
+ fprintf(stderr, "Problem writing to createdump parent_write_pipe: %s (%d)\n", strerror(errno), errno);
+ close(parent_read_pipe);
+ if (errorMessageBuffer != nullptr)
+ {
+ errorMessageBuffer[0] = 0;
+ }
+ return false;
+ }
// Read createdump's stderr messages (if any)
if (errorMessageBuffer != nullptr)
@@ -2527,7 +2563,7 @@ PROCCreateCrashDump(
// Read createdump's stderr
int bytesRead = 0;
int count = 0;
- while ((count = read(parent_pipe, errorMessageBuffer + bytesRead, cbErrorMessageBuffer - bytesRead)) > 0)
+ while ((count = read(parent_read_pipe, errorMessageBuffer + bytesRead, cbErrorMessageBuffer - bytesRead)) > 0)
{
bytesRead += count;
}
@@ -2537,7 +2573,7 @@ PROCCreateCrashDump(
fputs(errorMessageBuffer, stderr);
}
}
- close(parent_pipe);
+ close(parent_read_pipe);
// Parent waits until the child process is done
int wstatus = 0;
@@ -2826,17 +2862,26 @@ InitializeFlushProcessWriteBuffers()
_ASSERTE(s_flushUsingMemBarrier == 0);
#if defined(__linux__) || HAVE_SYS_MEMBARRIER_H
- // Starting with Linux kernel 4.14, process memory barriers can be generated
- // using MEMBARRIER_CMD_PRIVATE_EXPEDITED.
- int mask = membarrier(MEMBARRIER_CMD_QUERY, 0, 0);
- if (mask >= 0 &&
- mask & MEMBARRIER_CMD_PRIVATE_EXPEDITED)
- {
- // Register intent to use the private expedited command.
- if (membarrier(MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED, 0, 0) == 0)
+
+#ifdef TARGET_ANDROID
+ // Avoid calling membarrier on older Android versions where membarrier
+ // may be barred by seccomp causing the process to be killed.
+ int apiLevel = android_get_device_api_level();
+ if (apiLevel >= __ANDROID_API_Q__)
+#endif
+ {
+ // Starting with Linux kernel 4.14, process memory barriers can be generated
+ // using MEMBARRIER_CMD_PRIVATE_EXPEDITED.
+ int mask = membarrier(MEMBARRIER_CMD_QUERY, 0, 0);
+ if (mask >= 0 &&
+ mask & MEMBARRIER_CMD_PRIVATE_EXPEDITED)
{
- s_flushUsingMemBarrier = TRUE;
- return TRUE;
+ // Register intent to use the private expedited command.
+ if (membarrier(MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED, 0, 0) == 0)
+ {
+ s_flushUsingMemBarrier = TRUE;
+ return TRUE;
+ }
}
}
#endif
diff --git a/src/coreclr/scripts/superpmi_collect_setup.py b/src/coreclr/scripts/superpmi_collect_setup.py
index c3a4d6e7348e12..0de14ce642d940 100644
--- a/src/coreclr/scripts/superpmi_collect_setup.py
+++ b/src/coreclr/scripts/superpmi_collect_setup.py
@@ -472,7 +472,7 @@ def main(main_args):
if arch == "arm64": # public osx_arm64
helix_queue = "osx.13.arm64.open"
else: # public osx_x64
- helix_queue = "OSX.1200.Amd64.Open"
+ helix_queue = "OSX.13.Amd64.Open"
else:
if platform_name == "windows":
if arch == "arm64": # internal windows_arm64
@@ -488,9 +488,9 @@ def main(main_args):
helix_queue = "azurelinux.3.amd64"
elif platform_name == "osx":
if arch == "arm64": # internal osx_arm64
- helix_queue = "OSX.1200.ARM64"
+ helix_queue = "OSX.13.ARM64"
else: # internal osx_x64
- helix_queue = "OSX.1200.Amd64"
+ helix_queue = "OSX.13.Amd64"
# Copy the superpmi scripts
diff --git a/src/coreclr/tools/Common/InstructionSetHelpers.cs b/src/coreclr/tools/Common/InstructionSetHelpers.cs
index 0fb2dd0f5c8c81..4778feeadbc3b9 100644
--- a/src/coreclr/tools/Common/InstructionSetHelpers.cs
+++ b/src/coreclr/tools/Common/InstructionSetHelpers.cs
@@ -57,7 +57,7 @@ public static InstructionSetSupport ConfigureInstructionSetSupport(string instru
}
string jitInterfaceLibrary = "jitinterface_" + RuntimeInformation.ProcessArchitecture.ToString().ToLowerInvariant();
- nint libHandle = NativeLibrary.Load(jitInterfaceLibrary, System.Reflection.Assembly.GetExecutingAssembly(), DllImportSearchPath.ApplicationDirectory);
+ nint libHandle = NativeLibrary.Load(jitInterfaceLibrary, System.Reflection.Assembly.GetExecutingAssembly(), DllImportSearchPath.AssemblyDirectory);
int cpuFeatures;
unsafe
{
diff --git a/src/coreclr/tools/Common/TypeSystem/IL/UnsafeAccessors.cs b/src/coreclr/tools/Common/TypeSystem/IL/UnsafeAccessors.cs
index b6be413b9baa14..9eabb99e61a84b 100644
--- a/src/coreclr/tools/Common/TypeSystem/IL/UnsafeAccessors.cs
+++ b/src/coreclr/tools/Common/TypeSystem/IL/UnsafeAccessors.cs
@@ -329,6 +329,12 @@ private static bool DoesMethodMatchUnsafeAccessorDeclaration(ref GenerationConte
return false;
}
+ // Validate generic parameter.
+ if (declSig.GenericParameterCount != maybeSig.GenericParameterCount)
+ {
+ return false;
+ }
+
// Validate argument count and return type
if (context.Kind == UnsafeAccessorKind.Constructor)
{
diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/FlowAnnotations.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/FlowAnnotations.cs
index 737d99d93be908..5333c2bd02af3d 100644
--- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/FlowAnnotations.cs
+++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/FlowAnnotations.cs
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System;
+using System.Diagnostics;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Reflection.Metadata;
@@ -523,7 +524,7 @@ protected override TypeAnnotations CreateValueFromKey(TypeDesc key)
// Look for the compiler generated backing field. If it doesn't work out simply move on. In such case we would still
// propagate the annotation to the setter/getter and later on when analyzing the setter/getter we will warn
// that the field (which ever it is) must be annotated as well.
- ScanMethodBodyForFieldAccess(methodBody, write: true, out backingFieldFromSetter);
+ backingFieldFromSetter = GetAutoPropertyCompilerGeneratedField(methodBody, isWriteAccessor: true);
}
MethodAnnotations? setterAnnotation = null;
@@ -560,16 +561,14 @@ protected override TypeAnnotations CreateValueFromKey(TypeDesc key)
MethodDesc getMethod = property.GetMethod;
if (getMethod != null)
{
-
- // Abstract property backing field propagation doesn't make sense, and any derived property will be validated
- // to have the exact same annotations on getter/setter, and thus if it has a detectable backing field that will be validated as well.
+ // Look only at compiler-generated accessors
MethodIL methodBody = _ilProvider.GetMethodIL(getMethod);
if (methodBody != null)
{
// Look for the compiler generated backing field. If it doesn't work out simply move on. In such case we would still
// propagate the annotation to the setter/getter and later on when analyzing the setter/getter we will warn
// that the field (which ever it is) must be annotated as well.
- ScanMethodBodyForFieldAccess(methodBody, write: false, out backingFieldFromGetter);
+ backingFieldFromGetter = GetAutoPropertyCompilerGeneratedField(methodBody, isWriteAccessor: false);
}
MethodAnnotations? getterAnnotation = null;
@@ -593,27 +592,23 @@ protected override TypeAnnotations CreateValueFromKey(TypeDesc key)
}
}
- FieldDesc? backingField;
- if (backingFieldFromGetter != null && backingFieldFromSetter != null &&
- backingFieldFromGetter != backingFieldFromSetter)
- {
- _logger.LogWarning(property, DiagnosticId.DynamicallyAccessedMembersCouldNotFindBackingField, property.GetDisplayName());
- backingField = null;
- }
- else
- {
- backingField = backingFieldFromGetter ?? backingFieldFromSetter;
- }
-
- if (backingField != null)
+ FieldDesc? backingField = backingFieldFromSetter ?? backingFieldFromGetter;
+ if (backingField is not null)
{
- if (annotatedFields.Any(a => a.Field == backingField))
+ bool validBackingFieldFound = backingFieldFromGetter is null
+ || backingFieldFromSetter is null
+ || backingFieldFromGetter == backingFieldFromSetter;
+ if (validBackingFieldFound)
{
- _logger.LogWarning(backingField, DiagnosticId.DynamicallyAccessedMembersOnPropertyConflictsWithBackingField, property.GetDisplayName(), backingField.GetDisplayName());
- }
- else
- {
- annotatedFields.Add(new FieldAnnotation(backingField, annotation));
+ if (annotatedFields.Any(a => a.Field == backingField && a.Annotation != annotation))
+ {
+ _logger.LogWarning(backingField, DiagnosticId.DynamicallyAccessedMembersOnPropertyConflictsWithBackingField, property.GetDisplayName(), backingField.GetDisplayName());
+ }
+ else
+ {
+ // Unique backing field with no conflicts with property or existing field
+ annotatedFields.Add(new FieldAnnotation(backingField, annotation));
+ }
}
}
}
@@ -651,13 +646,33 @@ protected override TypeAnnotations CreateValueFromKey(TypeDesc key)
return attrs;
}
- private static bool ScanMethodBodyForFieldAccess(MethodIL body, bool write, out FieldDesc? found)
+ ///
+ /// Returns true if the property has a single accessor which is compiler generated,
+ /// indicating that it is an auto-property.
+ ///
+ ///
+ /// Ideally this would be tightened to only return true if both accessors are auto-property accessors,
+ /// but it allows for either for back compatibility with existing behavior.
+ ///
+ private static bool IsAutoProperty(PropertyPseudoDesc property)
+ {
+ return property.SetMethod?.HasCustomAttribute("System.Runtime.CompilerServices", "CompilerGeneratedAttribute") == true
+ || property.GetMethod?.HasCustomAttribute("System.Runtime.CompilerServices", "CompilerGeneratedAttribute") == true;
+ }
+
+ private static FieldDesc? GetAutoPropertyCompilerGeneratedField(MethodIL body, bool isWriteAccessor)
{
// Tries to find the backing field for a property getter/setter.
// Returns true if this is a method body that we can unambiguously analyze.
// The found field could still be null if there's no backing store.
- found = null;
+ // Only analyze compiler-generated accessors
+ if (!body.OwningMethod.HasCustomAttribute("System.Runtime.CompilerServices", "CompilerGeneratedAttribute"))
+ {
+ return null;
+ }
+
+ FieldDesc? found = null;
ILReader ilReader = new ILReader(body.GetILBytes());
while (ilReader.HasNext)
@@ -665,45 +680,35 @@ private static bool ScanMethodBodyForFieldAccess(MethodIL body, bool write, out
ILOpcode opcode = ilReader.ReadILOpcode();
switch (opcode)
{
- case ILOpcode.ldsfld when !write:
- case ILOpcode.ldfld when !write:
- case ILOpcode.stsfld when write:
- case ILOpcode.stfld when write:
+ case ILOpcode.ldsfld when !isWriteAccessor:
+ case ILOpcode.ldfld when !isWriteAccessor:
+ case ILOpcode.stsfld when isWriteAccessor:
+ case ILOpcode.stfld when isWriteAccessor:
+ {
+ // Multiple field accesses - ambiguous, fail
+ if (found != null)
{
- // This writes/reads multiple fields - can't guess which one is the backing store.
- // Return failure.
- if (found != null)
- {
- found = null;
- return false;
- }
- found = (FieldDesc)body.GetObject(ilReader.ReadILToken());
+ return null;
}
+ found = (FieldDesc)body.GetObject(ilReader.ReadILToken());
break;
+ }
default:
ilReader.Skip(opcode);
break;
}
}
- if (found == null)
- {
- // Doesn't access any fields. Could be e.g. "Type Foo => typeof(Bar);"
- // Return success.
- return true;
- }
-
- if (found.OwningType != body.OwningMethod.OwningType ||
+ if (found is null ||
+ found.OwningType != body.OwningMethod.OwningType ||
found.IsStatic != body.OwningMethod.Signature.IsStatic ||
!found.HasCustomAttribute("System.Runtime.CompilerServices", "CompilerGeneratedAttribute"))
{
- // A couple heuristics to make sure we got the right field.
- // Return failure.
- found = null;
- return false;
+ // Heuristics failed - not a backing field
+ return null;
}
- return true;
+ return found;
}
}
diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs
index 45bfd1a2edbfee..a1dc79692155f5 100644
--- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs
+++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs
@@ -3117,8 +3117,8 @@ private void setEHcount(uint cEH)
private void setEHinfo(uint EHnumber, ref CORINFO_EH_CLAUSE clause)
{
- // Filters don't have class token in the clause.ClassTokenOrOffset
- if ((clause.Flags & CORINFO_EH_CLAUSE_FLAGS.CORINFO_EH_CLAUSE_FILTER) == 0)
+ // Filters, finallys, and faults don't have class token in the clause.ClassTokenOrOffset
+ if ((clause.Flags & (CORINFO_EH_CLAUSE_FLAGS.CORINFO_EH_CLAUSE_FILTER | CORINFO_EH_CLAUSE_FLAGS.CORINFO_EH_CLAUSE_FINALLY | CORINFO_EH_CLAUSE_FLAGS.CORINFO_EH_CLAUSE_FAULT)) == 0)
{
if (clause.ClassTokenOrOffset != 0)
{
diff --git a/src/coreclr/tools/aot/ILCompiler.Trimming.Tests/TestCasesRunner/ResultChecker.cs b/src/coreclr/tools/aot/ILCompiler.Trimming.Tests/TestCasesRunner/ResultChecker.cs
index 673df2e9a11500..ff012a7945fee0 100644
--- a/src/coreclr/tools/aot/ILCompiler.Trimming.Tests/TestCasesRunner/ResultChecker.cs
+++ b/src/coreclr/tools/aot/ILCompiler.Trimming.Tests/TestCasesRunner/ResultChecker.cs
@@ -202,6 +202,20 @@ private void VerifyLoggedMessages(AssemblyDefinition original, TrimmingTestLogge
List<(ICustomAttributeProvider, CustomAttribute)> expectedNoWarningsAttributes = new();
foreach (var attrProvider in GetAttributeProviders(original))
{
+ if (attrProvider is IMemberDefinition attrMember &&
+ attrMember is not TypeDefinition &&
+ attrMember.DeclaringType is TypeDefinition declaringType &&
+ declaringType.Name.StartsWith(""))
+ {
+ // Workaround: C# 14 extension members result in a compiler-generated type
+ // that has a member for each extension member (this is in addition to the type
+ // which contains the actual extension member implementation).
+ // The generated members inherit attributes from the extension members, but
+ // have empty implementations. We don't want to check inherited ExpectedWarningAttributes
+ // for these members.
+ continue;
+ }
+
foreach (var attr in attrProvider.CustomAttributes)
{
if (!IsProducedByNativeAOT(attr))
diff --git a/src/coreclr/vm/amd64/CachedInterfaceDispatchCoreCLR.S b/src/coreclr/vm/amd64/CachedInterfaceDispatchCoreCLR.S
index bc0edaccea0567..9b2345591947d6 100644
--- a/src/coreclr/vm/amd64/CachedInterfaceDispatchCoreCLR.S
+++ b/src/coreclr/vm/amd64/CachedInterfaceDispatchCoreCLR.S
@@ -23,7 +23,7 @@ LEAF_ENTRY RhpVTableOffsetDispatch, _TEXT
// to get the address in the vtable chunk list of what we want to dereference
#ifdef TARGET_APPLE
// Apple's linker has issues which break unwind info if
-// an ALTERNATE_ENTRY is present in the middle of a function see https://github.com/dotnet/runtime/pull/114982#discussion_r2083272768
+// an ALTERNATE_ENTRY is present in the middle of a function see https://github.com/dotnet/runtime/issues/119005
.cfi_endproc
#endif
ALTERNATE_ENTRY RhpVTableOffsetDispatchAVLocation
diff --git a/src/coreclr/vm/amd64/cgenamd64.cpp b/src/coreclr/vm/amd64/cgenamd64.cpp
index af27637759473b..f674b15bd302f4 100644
--- a/src/coreclr/vm/amd64/cgenamd64.cpp
+++ b/src/coreclr/vm/amd64/cgenamd64.cpp
@@ -206,6 +206,8 @@ void ResumableFrame::UpdateRegDisplay_Impl(const PREGDISPLAY pRD, bool updateFlo
CONTRACT_END;
CopyMemory(pRD->pCurrentContext, m_Regs, sizeof(CONTEXT));
+ // Clear the CONTEXT_XSTATE, since the REGDISPLAY contains just plain CONTEXT structure
+ pRD->pCurrentContext->ContextFlags &= ~(CONTEXT_XSTATE & CONTEXT_AREA_MASK);
pRD->ControlPC = m_Regs->Rip;
diff --git a/src/coreclr/vm/amd64/jithelpers_fastwritebarriers.S b/src/coreclr/vm/amd64/jithelpers_fastwritebarriers.S
index f987751bdcb358..cf9f149e374899 100644
--- a/src/coreclr/vm/amd64/jithelpers_fastwritebarriers.S
+++ b/src/coreclr/vm/amd64/jithelpers_fastwritebarriers.S
@@ -39,10 +39,10 @@ PATCH_LABEL JIT_WriteBarrier_PreGrow64_Patch_Label_CardTable
shr rdi, 0x0B
cmp byte ptr [rdi + rax], 0xFF
.byte 0x75, 0x02
- // jne UpdateCardTable_PreGrow64
+ // jne LOCAL_LABEL(UpdateCardTable_PreGrow64)
REPRET
- UpdateCardTable_PreGrow64:
+ LOCAL_LABEL(UpdateCardTable_PreGrow64):
mov byte ptr [rdi + rax], 0xFF
#ifdef FEATURE_MANUALLY_MANAGED_CARD_BUNDLES
@@ -57,17 +57,17 @@ PATCH_LABEL JIT_WriteBarrier_PreGrow64_Patch_Label_CardBundleTable
cmp byte ptr [rdi + rax], 0xFF
.byte 0x75, 0x02
- // jne UpdateCardBundle_PreGrow64
+ // jne LOCAL_LABEL(UpdateCardBundle_PreGrow64)
REPRET
- UpdateCardBundle_PreGrow64:
+ LOCAL_LABEL(UpdateCardBundle_PreGrow64):
mov byte ptr [rdi + rax], 0xFF
#endif
ret
.balign 16
- Exit_PreGrow64:
+PATCH_LABEL Exit_PreGrow64
REPRET
LEAF_END_MARKED JIT_WriteBarrier_PreGrow64, _TEXT
@@ -124,10 +124,10 @@ PATCH_LABEL JIT_WriteBarrier_PostGrow64_Patch_Label_CardTable
shr rdi, 0x0B
cmp byte ptr [rdi + rax], 0xFF
.byte 0x75, 0x02
- // jne UpdateCardTable_PostGrow64
+ // jne LOCAL_LABEL(UpdateCardTable_PostGrow64)
REPRET
- UpdateCardTable_PostGrow64:
+ LOCAL_LABEL(UpdateCardTable_PostGrow64):
mov byte ptr [rdi + rax], 0xFF
#ifdef FEATURE_MANUALLY_MANAGED_CARD_BUNDLES
@@ -142,17 +142,17 @@ PATCH_LABEL JIT_WriteBarrier_PostGrow64_Patch_Label_CardBundleTable
cmp byte ptr [rdi + rax], 0xFF
.byte 0x75, 0x02
- // jne UpdateCardBundle_PostGrow64
+ // jne LOCAL_LABEL(UpdateCardBundle_PostGrow64)
REPRET
- UpdateCardBundle_PostGrow64:
+ LOCAL_LABEL(UpdateCardBundle_PostGrow64):
mov byte ptr [rdi + rax], 0xFF
#endif
ret
.balign 16
- Exit_PostGrow64:
+PATCH_LABEL Exit_PostGrow64
REPRET
LEAF_END_MARKED JIT_WriteBarrier_PostGrow64, _TEXT
@@ -183,10 +183,10 @@ PATCH_LABEL JIT_WriteBarrier_SVR64_PatchLabel_CardTable
cmp byte ptr [rdi + rax], 0xFF
.byte 0x75, 0x02
- // jne UpdateCardTable_SVR64
+ // jne LOCAL_LABEL(UpdateCardTable_SVR64)
REPRET
- UpdateCardTable_SVR64:
+ LOCAL_LABEL(UpdateCardTable_SVR64):
mov byte ptr [rdi + rax], 0xFF
#ifdef FEATURE_MANUALLY_MANAGED_CARD_BUNDLES
@@ -200,10 +200,10 @@ PATCH_LABEL JIT_WriteBarrier_SVR64_PatchLabel_CardBundleTable
cmp byte ptr [rdi + rax], 0xFF
.byte 0x75, 0x02
- // jne UpdateCardBundle_SVR64
+ // jne LOCAL_LABEL(UpdateCardBundle_SVR64)
REPRET
- UpdateCardBundle_SVR64:
+ LOCAL_LABEL(UpdateCardBundle_SVR64):
mov byte ptr [rdi + rax], 0xFF
#endif
@@ -233,46 +233,46 @@ PATCH_LABEL JIT_WriteBarrier_Byte_Region64_Patch_Label_RegionShrDest
// Check whether the region we're storing into is gen 0 - nothing to do in this case
cmp byte ptr [rdi + rax], 0
.byte 0x75, 0x04
- //jne NotGen0_Byte_Region64
+ //jne LOCAL_LABEL(NotGen0_Byte_Region64)
REPRET
NOP_2_BYTE // padding for alignment of constant
- NotGen0_Byte_Region64:
+ LOCAL_LABEL(NotGen0_Byte_Region64):
PATCH_LABEL JIT_WriteBarrier_Byte_Region64_Patch_Label_Lower
movabs r9, 0xF0F0F0F0F0F0F0F0
cmp rsi, r9
.byte 0x73, 0x01
- // jae NotLow_Byte_Region64
+ // jae LOCAL_LABEL(NotLow_Byte_Region64)
ret
- NotLow_Byte_Region64:
+ LOCAL_LABEL(NotLow_Byte_Region64):
PATCH_LABEL JIT_WriteBarrier_Byte_Region64_Patch_Label_Upper
movabs r9, 0xF0F0F0F0F0F0F0F0
cmp rsi, r9
.byte 0x72, 0x02
- // jb NotHigh_Byte_Region64
+ // jb LOCAL_LABEL(NotHigh_Byte_Region64)
REPRET
- NotHigh_Byte_Region64:
+ LOCAL_LABEL(NotHigh_Byte_Region64):
PATCH_LABEL JIT_WriteBarrier_Byte_Region64_Patch_Label_RegionShrSrc
shr rsi, 0x16 // compute region index
mov dl, [rsi + rax]
cmp dl, [rdi + rax]
.byte 0x72, 0x03
- // jb IsOldToYoung_Byte_Region64
+ // jb LOCAL_LABEL(IsOldToYoung_Byte_Region64)
REPRET
nop
- IsOldToYoung_Byte_Region64:
+ LOCAL_LABEL(IsOldToYoung_Byte_Region64):
PATCH_LABEL JIT_WriteBarrier_Byte_Region64_Patch_Label_CardTable
movabs rax, 0xF0F0F0F0F0F0F0F0
shr r8, 0xB
cmp byte ptr [r8 + rax], 0xFF
.byte 0x75, 0x02
- // jne UpdateCardTable_Byte_Region64
+ // jne LOCAL_LABEL(UpdateCardTable_Byte_Region64)
REPRET
- UpdateCardTable_Byte_Region64:
+ LOCAL_LABEL(UpdateCardTable_Byte_Region64):
mov byte ptr [r8 + rax], 0xFF
#ifdef FEATURE_MANUALLY_MANAGED_CARD_BUNDLES
shr r8, 0x0A
@@ -280,10 +280,10 @@ PATCH_LABEL JIT_WriteBarrier_Byte_Region64_Patch_Label_CardBundleTable
movabs rax, 0xF0F0F0F0F0F0F0F0
cmp byte ptr [r8 + rax], 0xFF
.byte 0x75, 0x02
- // jne UpdateCardBundleTable_Byte_Region64
+ // jne LOCAL_LABEL(UpdateCardBundleTable_Byte_Region64)
REPRET
- UpdateCardBundleTable_Byte_Region64:
+ LOCAL_LABEL(UpdateCardBundleTable_Byte_Region64):
mov byte ptr [r8 + rax], 0xFF
#endif
ret
@@ -308,36 +308,36 @@ PATCH_LABEL JIT_WriteBarrier_Bit_Region64_Patch_Label_RegionShrDest
// Check whether the region we're storing into is gen 0 - nothing to do in this case
cmp byte ptr [rdi + rax], 0
.byte 0x75, 0x04
- //jne NotGen0_Bit_Region64
+ //jne LOCAL_LABEL(NotGen0_Bit_Region64)
REPRET
NOP_2_BYTE // padding for alignment of constant
- NotGen0_Bit_Region64:
+ LOCAL_LABEL(NotGen0_Bit_Region64):
PATCH_LABEL JIT_WriteBarrier_Bit_Region64_Patch_Label_Lower
movabs r9, 0xF0F0F0F0F0F0F0F0
cmp rsi, r9
.byte 0x73, 0x01
- // jae NotLow_Bit_Region64
+ // jae LOCAL_LABEL(NotLow_Bit_Region64)
ret
- NotLow_Bit_Region64:
+ LOCAL_LABEL(NotLow_Bit_Region64):
PATCH_LABEL JIT_WriteBarrier_Bit_Region64_Patch_Label_Upper
movabs r9, 0xF0F0F0F0F0F0F0F0
cmp rsi, r9
.byte 0x72, 0x02
- // jb NotHigh_Bit_Region64
+ // jb LOCAL_LABEL(NotHigh_Bit_Region64)
REPRET
- NotHigh_Bit_Region64:
+ LOCAL_LABEL(NotHigh_Bit_Region64):
PATCH_LABEL JIT_WriteBarrier_Bit_Region64_Patch_Label_RegionShrSrc
shr rsi, 0x16 // compute region index
mov dl, [rsi + rax]
cmp dl, [rdi + rax]
.byte 0x72, 0x03
- // jb IsOldToYoung_Bit_Region64
+ // jb LOCAL_LABEL(IsOldToYoung_Bit_Region64)
REPRET
nop
- IsOldToYoung_Bit_Region64:
+ LOCAL_LABEL(IsOldToYoung_Bit_Region64):
PATCH_LABEL JIT_WriteBarrier_Bit_Region64_Patch_Label_CardTable
movabs rax, 0xF0F0F0F0F0F0F0F0
@@ -349,10 +349,10 @@ PATCH_LABEL JIT_WriteBarrier_Bit_Region64_Patch_Label_CardTable
shl dl, cl
test byte ptr [r8 + rax], dl
.byte 0x74, 0x02
- // je UpdateCardTable_Bit_Region64
+ // je LOCAL_LABEL(UpdateCardTable_Bit_Region64)
REPRET
- UpdateCardTable_Bit_Region64:
+ LOCAL_LABEL(UpdateCardTable_Bit_Region64):
lock or byte ptr [r8 + rax], dl
#ifdef FEATURE_MANUALLY_MANAGED_CARD_BUNDLES
PATCH_LABEL JIT_WriteBarrier_Bit_Region64_Patch_Label_CardBundleTable
@@ -360,10 +360,10 @@ PATCH_LABEL JIT_WriteBarrier_Bit_Region64_Patch_Label_CardBundleTable
shr r8, 0x0A
cmp byte ptr [r8 + rax], 0xFF
.byte 0x75, 0x02
- // jne UpdateCardBundleTable_Bit_Region64
+ // jne LOCAL_LABEL(UpdateCardBundleTable_Bit_Region64)
REPRET
- UpdateCardBundleTable_Bit_Region64:
+ LOCAL_LABEL(UpdateCardBundleTable_Bit_Region64):
mov byte ptr [r8 + rax], 0xFF
#endif
ret
@@ -397,10 +397,10 @@ PATCH_LABEL JIT_WriteBarrier_WriteWatch_PreGrow64_Patch_Label_Lower
add rax, r10
cmp byte ptr [rax], 0x0
.byte 0x75, 0x03
- // jne CheckCardTable_WriteWatch_PreGrow64
+ // jne LOCAL_LABEL(CheckCardTable_WriteWatch_PreGrow64)
mov byte ptr [rax], 0xFF
- CheckCardTable_WriteWatch_PreGrow64:
+ LOCAL_LABEL(CheckCardTable_WriteWatch_PreGrow64):
// Check the lower ephemeral region bound.
cmp rsi, r11
@@ -419,10 +419,10 @@ PATCH_LABEL JIT_WriteBarrier_WriteWatch_PreGrow64_Patch_Label_CardTable
movabs rax, 0xF0F0F0F0F0F0F0F0
cmp byte ptr [rdi + rax], 0xFF
.byte 0x75, 0x02
- // jne UpdateCardTable_WriteWatch_PreGrow64
+ // jne LOCAL_LABEL(UpdateCardTable_WriteWatch_PreGrow64)
REPRET
- UpdateCardTable_WriteWatch_PreGrow64:
+ LOCAL_LABEL(UpdateCardTable_WriteWatch_PreGrow64):
mov byte ptr [rdi + rax], 0xFF
#ifdef FEATURE_MANUALLY_MANAGED_CARD_BUNDLES
@@ -434,17 +434,17 @@ PATCH_LABEL JIT_WriteBarrier_WriteWatch_PreGrow64_Patch_Label_CardBundleTable
cmp byte ptr [rdi + rax], 0xFF
.byte 0x75, 0x02
- // jne UpdateCardBundle_WriteWatch_PreGrow64
+ // jne LOCAL_LABEL(UpdateCardBundle_WriteWatch_PreGrow64)
REPRET
- UpdateCardBundle_WriteWatch_PreGrow64:
+ LOCAL_LABEL(UpdateCardBundle_WriteWatch_PreGrow64):
mov byte ptr [rdi + rax], 0xFF
#endif
ret
.balign 16
- Exit_WriteWatch_PreGrow64:
+PATCH_LABEL Exit_WriteWatch_PreGrow64
REPRET
LEAF_END_MARKED JIT_WriteBarrier_WriteWatch_PreGrow64, _TEXT
@@ -475,13 +475,13 @@ PATCH_LABEL JIT_WriteBarrier_WriteWatch_PostGrow64_Patch_Label_Lower
add rax, r10
cmp byte ptr [rax], 0x0
.byte 0x75, 0x06
- // jne CheckCardTable_WriteWatch_PostGrow64
+ // jne LOCAL_LABEL(CheckCardTable_WriteWatch_PostGrow64)
mov byte ptr [rax], 0xFF
NOP_3_BYTE // padding for alignment of constant
// Check the lower and upper ephemeral region bounds
- CheckCardTable_WriteWatch_PostGrow64:
+ LOCAL_LABEL(CheckCardTable_WriteWatch_PostGrow64):
cmp rsi, r11
#ifdef FEATURE_MANUALLY_MANAGED_CARD_BUNDLES
@@ -514,10 +514,10 @@ PATCH_LABEL JIT_WriteBarrier_WriteWatch_PostGrow64_Patch_Label_CardTable
shr rdi, 0x0B
cmp byte ptr [rdi + rax], 0xFF
.byte 0x75, 0x02
- // jne UpdateCardTable_WriteWatch_PostGrow64
+ // jne LOCAL_LABEL(UpdateCardTable_WriteWatch_PostGrow64)
REPRET
- UpdateCardTable_WriteWatch_PostGrow64:
+ LOCAL_LABEL(UpdateCardTable_WriteWatch_PostGrow64):
mov byte ptr [rdi + rax], 0xFF
#ifdef FEATURE_MANUALLY_MANAGED_CARD_BUNDLES
@@ -529,16 +529,16 @@ PATCH_LABEL JIT_WriteBarrier_WriteWatch_PostGrow64_Patch_Label_CardBundleTable
cmp byte ptr [rdi + rax], 0xFF
.byte 0x75, 0x02
- // jne UpdateCardBundle_WriteWatch_PostGrow64
+ // jne LOCAL_LABEL(UpdateCardBundle_WriteWatch_PostGrow64)
REPRET
- UpdateCardBundle_WriteWatch_PostGrow64:
+ LOCAL_LABEL(UpdateCardBundle_WriteWatch_PostGrow64):
mov byte ptr [rdi + rax], 0xFF
#endif
ret
.balign 16
- Exit_WriteWatch_PostGrow64:
+PATCH_LABEL Exit_WriteWatch_PostGrow64
REPRET
LEAF_END_MARKED JIT_WriteBarrier_WriteWatch_PostGrow64, _TEXT
@@ -578,17 +578,17 @@ PATCH_LABEL JIT_WriteBarrier_WriteWatch_SVR64_PatchLabel_CardTable
add rax, r10
cmp byte ptr [rax], 0x0
.byte 0x75, 0x03
- // jne CheckCardTable_WriteWatch_SVR64
+ // jne LOCAL_LABEL(CheckCardTable_WriteWatch_SVR64)
mov byte ptr [rax], 0xFF
- CheckCardTable_WriteWatch_SVR64:
+ LOCAL_LABEL(CheckCardTable_WriteWatch_SVR64):
shr rdi, 0x0B
cmp byte ptr [rdi + r11], 0xFF
.byte 0x75, 0x02
- // jne UpdateCardTable_WriteWatch_SVR64
+ // jne LOCAL_LABEL(UpdateCardTable_WriteWatch_SVR64)
REPRET
- UpdateCardTable_WriteWatch_SVR64:
+ LOCAL_LABEL(UpdateCardTable_WriteWatch_SVR64):
mov byte ptr [rdi + r11], 0xFF
#ifdef FEATURE_MANUALLY_MANAGED_CARD_BUNDLES
@@ -600,10 +600,10 @@ PATCH_LABEL JIT_WriteBarrier_WriteWatch_SVR64_PatchLabel_CardBundleTable
shr rdi, 0x0A
cmp byte ptr [rdi + r11], 0xFF
.byte 0x75, 0x02
- // jne UpdateCardBundle_WriteWatch_SVR64
+ // jne LOCAL_LABEL(UpdateCardBundle_WriteWatch_SVR64)
REPRET
- UpdateCardBundle_WriteWatch_SVR64:
+ LOCAL_LABEL(UpdateCardBundle_WriteWatch_SVR64):
mov byte ptr [rdi + r11], 0xFF
#endif
@@ -632,57 +632,57 @@ PATCH_LABEL JIT_WriteBarrier_WriteWatch_Byte_Region64_Patch_Label_RegionShrDest
shr rdi, 0x16 // compute region index
cmp byte ptr [rax], 0x0
.byte 0x75, 0x03
- // jne CheckGen0_WriteWatch_Byte_Region64
+ // jne LOCAL_LABEL(CheckGen0_WriteWatch_Byte_Region64)
mov byte ptr [rax], 0xFF
- CheckGen0_WriteWatch_Byte_Region64:
+ LOCAL_LABEL(CheckGen0_WriteWatch_Byte_Region64):
PATCH_LABEL JIT_WriteBarrier_WriteWatch_Byte_Region64_Patch_Label_RegionToGeneration
mov rax, 0xF0F0F0F0F0F0F0F0
// Check whether the region we're storing into is gen 0 - nothing to do in this case
cmp byte ptr [rdi + rax], 0
.byte 0x75, 0x08
- // jne NotGen0_WriteWatch_Byte_Region64
+ // jne LOCAL_LABEL(NotGen0_WriteWatch_Byte_Region64)
REPRET
NOP_2_BYTE // padding for alignment of constant
NOP_2_BYTE // padding for alignment of constant
NOP_2_BYTE // padding for alignment of constant
- NotGen0_WriteWatch_Byte_Region64:
+ LOCAL_LABEL(NotGen0_WriteWatch_Byte_Region64):
PATCH_LABEL JIT_WriteBarrier_WriteWatch_Byte_Region64_Patch_Label_Lower
movabs r9, 0xF0F0F0F0F0F0F0F0
cmp rsi, r9
.byte 0x73, 0x01
- // jae NotLow_WriteWatch_Byte_Region64
+ // jae LOCAL_LABEL(NotLow_WriteWatch_Byte_Region64)
ret
- NotLow_WriteWatch_Byte_Region64:
+ LOCAL_LABEL(NotLow_WriteWatch_Byte_Region64):
PATCH_LABEL JIT_WriteBarrier_WriteWatch_Byte_Region64_Patch_Label_Upper
mov r9, 0xF0F0F0F0F0F0F0F0
cmp rsi, r9
.byte 0x72, 0x02
- // jb NotHigh_WriteWatch_Byte_Region64
+ // jb LOCAL_LABEL(NotHigh_WriteWatch_Byte_Region64)
REPRET
- NotHigh_WriteWatch_Byte_Region64:
+ LOCAL_LABEL(NotHigh_WriteWatch_Byte_Region64):
PATCH_LABEL JIT_WriteBarrier_WriteWatch_Byte_Region64_Patch_Label_RegionShrSrc
shr rsi, 0x16 // compute region index
mov dl, [rsi + rax]
cmp dl, [rdi + rax]
.byte 0x72, 0x03
- // jb IsOldToYoung_WriteWatch_Byte_Region64
+ // jb LOCAL_LABEL(IsOldToYoung_WriteWatch_Byte_Region64)
REPRET
nop
- IsOldToYoung_WriteWatch_Byte_Region64:
+ LOCAL_LABEL(IsOldToYoung_WriteWatch_Byte_Region64):
PATCH_LABEL JIT_WriteBarrier_WriteWatch_Byte_Region64_Patch_Label_CardTable
mov rax, 0xF0F0F0F0F0F0F0F0
shr r8, 0xB
cmp byte ptr [r8 + rax], 0xFF
.byte 0x75, 0x02
- // jne UpdateCardTable_WriteWatch_Byte_Region64
+ // jne LOCAL_LABEL(UpdateCardTable_WriteWatch_Byte_Region64)
REPRET
- UpdateCardTable_WriteWatch_Byte_Region64:
+ LOCAL_LABEL(UpdateCardTable_WriteWatch_Byte_Region64):
mov byte ptr [r8 + rax], 0xFF
#ifdef FEATURE_MANUALLY_MANAGED_CARD_BUNDLES
shr r8, 0x0A
@@ -690,10 +690,10 @@ PATCH_LABEL JIT_WriteBarrier_WriteWatch_Byte_Region64_Patch_Label_CardBundleTabl
mov rax, 0xF0F0F0F0F0F0F0F0
cmp byte ptr [r8 + rax], 0xFF
.byte 0x75, 0x02
- // jne UpdateCardBundleTable_WriteWatch_Byte_Region64
+ // jne LOCAL_LABEL(UpdateCardBundleTable_WriteWatch_Byte_Region64)
REPRET
- UpdateCardBundleTable_WriteWatch_Byte_Region64:
+ LOCAL_LABEL(UpdateCardBundleTable_WriteWatch_Byte_Region64):
mov byte ptr [r8 + rax], 0xFF
#endif
ret
@@ -718,47 +718,47 @@ PATCH_LABEL JIT_WriteBarrier_WriteWatch_Bit_Region64_Patch_Label_RegionShrDest
shr rdi, 0x16 // compute region index
cmp byte ptr [rax], 0x0
.byte 0x75, 0x03
- // jne CheckGen0_WriteWatch_Bit_Region64
+ // jne LOCAL_LABEL(CheckGen0_WriteWatch_Bit_Region64)
mov byte ptr [rax], 0xFF
- CheckGen0_WriteWatch_Bit_Region64:
+ LOCAL_LABEL(CheckGen0_WriteWatch_Bit_Region64):
PATCH_LABEL JIT_WriteBarrier_WriteWatch_Bit_Region64_Patch_Label_RegionToGeneration
mov rax, 0xF0F0F0F0F0F0F0F0
// Check whether the region we're storing into is gen 0 - nothing to do in this case
cmp byte ptr [rdi + rax], 0
.byte 0x75, 0x08
- // jne NotGen0_WriteWatch_Bit_Region64
+ // jne LOCAL_LABEL(NotGen0_WriteWatch_Bit_Region64)
REPRET
NOP_2_BYTE // padding for alignment of constant
NOP_2_BYTE // padding for alignment of constant
NOP_2_BYTE // padding for alignment of constant
- NotGen0_WriteWatch_Bit_Region64:
+ LOCAL_LABEL(NotGen0_WriteWatch_Bit_Region64):
PATCH_LABEL JIT_WriteBarrier_WriteWatch_Bit_Region64_Patch_Label_Lower
movabs r9, 0xF0F0F0F0F0F0F0F0
cmp rsi, r9
.byte 0x73, 0x01
- // jae NotLow_WriteWatch_Bit_Region64
+ // jae LOCAL_LABEL(NotLow_WriteWatch_Bit_Region64)
ret
- NotLow_WriteWatch_Bit_Region64:
+ LOCAL_LABEL(NotLow_WriteWatch_Bit_Region64):
PATCH_LABEL JIT_WriteBarrier_WriteWatch_Bit_Region64_Patch_Label_Upper
mov r9, 0xF0F0F0F0F0F0F0F0
cmp rsi, r9
.byte 0x72, 0x02
- // jb NotHigh_WriteWatch_Bit_Region64
+ // jb LOCAL_LABEL(NotHigh_WriteWatch_Bit_Region64)
REPRET
- NotHigh_WriteWatch_Bit_Region64:
+ LOCAL_LABEL(NotHigh_WriteWatch_Bit_Region64):
PATCH_LABEL JIT_WriteBarrier_WriteWatch_Bit_Region64_Patch_Label_RegionShrSrc
shr rsi, 0x16 // compute region index
mov dl, [rsi + rax]
cmp dl, [rdi + rax]
.byte 0x72, 0x03
- // jb IsOldToYoung_WriteWatch_Bit_Region64
+ // jb LOCAL_LABEL(IsOldToYoung_WriteWatch_Bit_Region64)
REPRET
nop
- IsOldToYoung_WriteWatch_Bit_Region64:
+ LOCAL_LABEL(IsOldToYoung_WriteWatch_Bit_Region64):
PATCH_LABEL JIT_WriteBarrier_WriteWatch_Bit_Region64_Patch_Label_CardTable
mov rax, 0xF0F0F0F0F0F0F0F0
@@ -770,10 +770,10 @@ PATCH_LABEL JIT_WriteBarrier_WriteWatch_Bit_Region64_Patch_Label_CardTable
shl dl, cl
test byte ptr [r8 + rax], dl
.byte 0x74, 0x02
- // je UpdateCardTable_WriteWatch_Bit_Region64
+ // je LOCAL_LABEL(UpdateCardTable_WriteWatch_Bit_Region64)
REPRET
- UpdateCardTable_WriteWatch_Bit_Region64:
+ LOCAL_LABEL(UpdateCardTable_WriteWatch_Bit_Region64):
lock or byte ptr [r8 + rax], dl
#ifdef FEATURE_MANUALLY_MANAGED_CARD_BUNDLES
PATCH_LABEL JIT_WriteBarrier_WriteWatch_Bit_Region64_Patch_Label_CardBundleTable
@@ -781,10 +781,10 @@ PATCH_LABEL JIT_WriteBarrier_WriteWatch_Bit_Region64_Patch_Label_CardBundleTable
shr r8, 0x0A
cmp byte ptr [r8 + rax], 0xFF
.byte 0x75, 0x02
- // jne UpdateCardBundleTable_WriteWatch_Bit_Region64
+ // jne LOCAL_LABEL(UpdateCardBundleTable_WriteWatch_Bit_Region64)
REPRET
- UpdateCardBundleTable_WriteWatch_Bit_Region64:
+ LOCAL_LABEL(UpdateCardBundleTable_WriteWatch_Bit_Region64):
mov byte ptr [r8 + rax], 0xFF
#endif
ret
diff --git a/src/coreclr/vm/amd64/patchedcode.S b/src/coreclr/vm/amd64/patchedcode.S
index 9af4e3ce855b70..0c0173bf184e33 100644
--- a/src/coreclr/vm/amd64/patchedcode.S
+++ b/src/coreclr/vm/amd64/patchedcode.S
@@ -5,10 +5,63 @@
#include "unixasmmacros.inc"
#include "asmconstants.h"
+// On Apple platforms we emit the whole patched region as single function
+// with .alt_entry labels for individual write barrier helpers. This ensures
+// the linker doesn't relocate or split the code and treats it as single
+// atom. We also need to be careful to produce the correct unwinding
+// information.
+
+//-----------------------------------------------------------------------------
+// The following Macros help in WRITE_BARRIER Implementations
+// WRITE_BARRIER_ENTRY
+//
+// Declare the start of a write barrier function. Use similarly to NESTED_ENTRY. This is the only legal way
+// to declare a write barrier function.
+//
+.macro WRITE_BARRIER_ENTRY name
+#if defined(__APPLE__)
+ // .cfi_startproc/.cfi_endproc is workaround for https://github.com/dotnet/runtime/issues/119005
+ .cfi_endproc
+ .p2align 4
+ .alt_entry C_FUNC(\name)
+ .private_extern C_FUNC(\name)
+C_FUNC(\name):
+ .cfi_startproc
+#else
+ LEAF_ENTRY \name, _TEXT
+#endif
+.endm
+
+// WRITE_BARRIER_END
+//
+// The partner to WRITE_BARRIER_ENTRY, used like NESTED_END.
+//
+.macro WRITE_BARRIER_END name
+#if defined(__APPLE__)
+ // .cfi_startproc/.cfi_endproc is workaround for https://github.com/dotnet/runtime/issues/119005
+ .cfi_endproc
+ .alt_entry C_FUNC(\name\()_End)
+ .private_extern C_FUNC(\name\()_End)
+C_FUNC(\name\()_End):
+ .cfi_startproc
+ // make sure this symbol gets its own address
+ nop
+#else
+ LEAF_END_MARKED \name, _TEXT
+#endif
+.endm
+
// Mark start of the code region that we patch at runtime
+#if defined(__APPLE__)
+ .global C_FUNC(JIT_PatchedCodeStart)
+C_FUNC(JIT_PatchedCodeStart):
+ .cfi_startproc
+ ret
+#else
LEAF_ENTRY JIT_PatchedCodeStart, _TEXT
ret
LEAF_END JIT_PatchedCodeStart, _TEXT
+#endif
// There is an even more optimized version of these helpers possible which takes
@@ -24,7 +77,7 @@ LEAF_END JIT_PatchedCodeStart, _TEXT
// it needs to have it's card updated
//
// void JIT_CheckedWriteBarrier(Object** dst, Object* src)
-LEAF_ENTRY JIT_CheckedWriteBarrier, _TEXT
+WRITE_BARRIER_ENTRY JIT_CheckedWriteBarrier
// When WRITE_BARRIER_CHECK is defined _NotInHeap will write the reference
// but if it isn't then it will just return.
@@ -45,7 +98,7 @@ LEAF_ENTRY JIT_CheckedWriteBarrier, _TEXT
// See comment above about possible AV
mov [rdi], rsi
ret
-LEAF_END_MARKED JIT_CheckedWriteBarrier, _TEXT
+WRITE_BARRIER_END JIT_CheckedWriteBarrier
// This is used by the mechanism to hold either the JIT_WriteBarrier_PreGrow
@@ -54,7 +107,7 @@ LEAF_END_MARKED JIT_CheckedWriteBarrier, _TEXT
// larger of the two functions (JIT_WriteBarrier_PostGrow) to ensure we have created
// enough space to copy that code in.
.balign 16
-LEAF_ENTRY JIT_WriteBarrier, _TEXT
+WRITE_BARRIER_ENTRY JIT_WriteBarrier
#ifdef _DEBUG
// In debug builds, this just contains jump to the debug version of the write barrier by default
jmp C_FUNC(JIT_WriteBarrier_Debug)
@@ -237,9 +290,17 @@ LEAF_ENTRY JIT_WriteBarrier, _TEXT
// make sure this is bigger than any of the others
.balign 16
nop
-LEAF_END_MARKED JIT_WriteBarrier, _TEXT
+WRITE_BARRIER_END JIT_WriteBarrier
// Mark start of the code region that we patch at runtime
+#if defined(__APPLE__)
+ .private_extern C_FUNC(JIT_PatchedCodeLast)
+ .alt_entry C_FUNC(JIT_PatchedCodeLast)
+C_FUNC(JIT_PatchedCodeLast):
+ .cfi_endproc
+ ret
+#else
LEAF_ENTRY JIT_PatchedCodeLast, _TEXT
ret
LEAF_END JIT_PatchedCodeLast, _TEXT
+#endif
diff --git a/src/coreclr/vm/appdomain.cpp b/src/coreclr/vm/appdomain.cpp
index 7b247b2b8bfd02..f7d01fd809a59f 100644
--- a/src/coreclr/vm/appdomain.cpp
+++ b/src/coreclr/vm/appdomain.cpp
@@ -1871,7 +1871,7 @@ DispIDCache* AppDomain::SetupRefDispIDCache()
#endif // FEATURE_COMINTEROP
-FileLoadLock *FileLoadLock::Create(PEFileListLock *pLock, PEAssembly * pPEAssembly, Assembly *pAssembly)
+FileLoadLock* FileLoadLock::Create(PEFileListLock* pLock, PEAssembly* pPEAssembly)
{
CONTRACTL
{
@@ -1884,7 +1884,7 @@ FileLoadLock *FileLoadLock::Create(PEFileListLock *pLock, PEAssembly * pPEAssemb
}
CONTRACTL_END;
- NewHolder result(new FileLoadLock(pLock, pPEAssembly, pAssembly));
+ NewHolder result(new FileLoadLock(pLock, pPEAssembly));
pLock->AddElement(result);
result->AddRef(); // Add one ref on behalf of the ListLock's reference. The corresponding Release() happens in FileLoadLock::CompleteLoadLevel.
@@ -1910,6 +1910,14 @@ Assembly *FileLoadLock::GetAssembly()
return m_pAssembly;
}
+PEAssembly* FileLoadLock::GetPEAssembly()
+{
+ LIMITED_METHOD_CONTRACT;
+ // Underlying PEAssembly pointer is stored in the constructor in base ListLockEntry::m_data.
+ _ASSERTE(m_data != NULL);
+ return (PEAssembly*)m_data;
+}
+
FileLoadLevel FileLoadLock::GetLoadLevel()
{
LIMITED_METHOD_CONTRACT;
@@ -1958,6 +1966,7 @@ BOOL FileLoadLock::CanAcquire(FileLoadLevel targetLevel)
static const char *fileLoadLevelName[] =
{
"CREATE", // FILE_LOAD_CREATE
+ "ALLOCATE", // FILE_LOAD_ALLOCATE
"BEGIN", // FILE_LOAD_BEGIN
"BEFORE_TYPE_LOAD", // FILE_LOAD_BEFORE_TYPE_LOAD
"EAGER_FIXUPS", // FILE_LOAD_EAGER_FIXUPS
@@ -1983,7 +1992,9 @@ BOOL FileLoadLock::CompleteLoadLevel(FileLoadLevel level, BOOL success)
if (level > m_level)
{
// Must complete each level in turn, unless we have an error
- CONSISTENCY_CHECK(m_pAssembly->IsError() || (level == (m_level+1)));
+ CONSISTENCY_CHECK((level == (m_level+1)) || (m_pAssembly != nullptr && m_pAssembly->IsError()));
+ CONSISTENCY_CHECK(m_pAssembly != nullptr || level < FILE_LOAD_ALLOCATE);
+
// Remove the lock from the list if the load is completed
if (level >= FILE_ACTIVE)
{
@@ -2019,7 +2030,7 @@ BOOL FileLoadLock::CompleteLoadLevel(FileLoadLevel level, BOOL success)
{
m_level = (FileLoadLevel)level;
- if (success)
+ if (success && level >= FILE_LOAD_ALLOCATE)
m_pAssembly->SetLoadLevel(level);
}
@@ -2042,6 +2053,18 @@ BOOL FileLoadLock::CompleteLoadLevel(FileLoadLevel level, BOOL success)
return FALSE;
}
+void FileLoadLock::SetAssembly(Assembly* pAssembly)
+{
+ LIMITED_METHOD_CONTRACT;
+
+ _ASSERTE(HasLock());
+ _ASSERTE(m_level == FILE_LOAD_CREATE); // Only valid to set during CREATE -> ALLOCATE
+ _ASSERTE(m_pAssembly == nullptr);
+ _ASSERTE(pAssembly != nullptr && pAssembly->GetPEAssembly() == (PEAssembly *)m_data);
+
+ m_pAssembly = pAssembly;
+}
+
void FileLoadLock::SetError(Exception *ex)
{
CONTRACTL
@@ -2088,10 +2111,10 @@ UINT32 FileLoadLock::Release()
return count;
}
-FileLoadLock::FileLoadLock(PEFileListLock *pLock, PEAssembly * pPEAssembly, Assembly *pAssembly)
+FileLoadLock::FileLoadLock(PEFileListLock* pLock, PEAssembly* pPEAssembly)
: ListLockEntry(pLock, pPEAssembly, "File load lock"),
m_level((FileLoadLevel) (FILE_LOAD_CREATE)),
- m_pAssembly(pAssembly),
+ m_pAssembly(nullptr),
m_cachedHR(S_OK)
{
WRAPPER_NO_CONTRACT;
@@ -2420,23 +2443,6 @@ Assembly *AppDomain::LoadAssemblyInternal(AssemblySpec* pIdentity,
if (result == NULL)
{
- LoaderAllocator *pLoaderAllocator = NULL;
-
- AssemblyBinder *pAssemblyBinder = pPEAssembly->GetAssemblyBinder();
- // Assemblies loaded with CustomAssemblyBinder need to use a different LoaderAllocator if
- // marked as collectible
- pLoaderAllocator = pAssemblyBinder->GetLoaderAllocator();
- if (pLoaderAllocator == NULL)
- {
- pLoaderAllocator = this->GetLoaderAllocator();
- }
-
- // Allocate the DomainAssembly a bit early to avoid GC mode problems. We could potentially avoid
- // a rare redundant allocation by moving this closer to FileLoadLock::Create, but it's not worth it.
- AllocMemTracker amTracker;
- AllocMemTracker *pamTracker = &amTracker;
- NewHolder pDomainAssembly = new DomainAssembly(pPEAssembly, pLoaderAllocator, pamTracker);
-
LoadLockHolder lock(this);
// Find the list lock entry
@@ -2448,20 +2454,9 @@ Assembly *AppDomain::LoadAssemblyInternal(AssemblySpec* pIdentity,
result = FindAssembly(pPEAssembly, FindAssemblyOptions_IncludeFailedToLoad);
if (result == NULL)
{
- // We are the first one in - create the DomainAssembly
+ // We are the first one in - create the FileLoadLock. Creation of the Assembly will happen at FILE_LOAD_ALLOCATE stage
registerNewAssembly = true;
- fileLock = FileLoadLock::Create(lock, pPEAssembly, pDomainAssembly->GetAssembly());
- pDomainAssembly.SuppressRelease();
- pamTracker->SuppressRelease();
-
- // Set the assembly module to be tenured now that we know it won't be deleted
- pDomainAssembly->GetAssembly()->SetIsTenured();
- if (pDomainAssembly->GetAssembly()->IsCollectible())
- {
- // We add the assembly to the LoaderAllocator only when we are sure that it can be added
- // and won't be deleted in case of a concurrent load from the same ALC
- ((AssemblyLoaderAllocator *)pLoaderAllocator)->AddDomainAssembly(pDomainAssembly);
- }
+ fileLock = FileLoadLock::Create(lock, pPEAssembly);
}
}
else
@@ -2479,6 +2474,8 @@ Assembly *AppDomain::LoadAssemblyInternal(AssemblySpec* pIdentity,
// so it will not be removed until app domain unload. So there is no need
// to release our ref count.
result = LoadAssembly(fileLock, targetLevel);
+ // By now FILE_LOAD_ALLOCATE should have run and the Assembly should exist
+ _ASSERTE(result != NULL);
}
else
{
@@ -2487,7 +2484,7 @@ Assembly *AppDomain::LoadAssemblyInternal(AssemblySpec* pIdentity,
if (registerNewAssembly)
{
- pPEAssembly->GetAssemblyBinder()->AddLoadedAssembly(pDomainAssembly->GetAssembly());
+ pPEAssembly->GetAssemblyBinder()->AddLoadedAssembly(result);
}
}
else
@@ -2517,6 +2514,7 @@ Assembly *AppDomain::LoadAssembly(FileLoadLock *pLock, FileLoadLevel targetLevel
STANDARD_VM_CHECK;
PRECONDITION(CheckPointer(pLock));
PRECONDITION(AppDomain::GetCurrentDomain() == this);
+ PRECONDITION(targetLevel >= FILE_LOAD_ALLOCATE);
POSTCONDITION(RETVAL->GetLoadLevel() >= GetCurrentFileLoadLevel()
|| RETVAL->GetLoadLevel() >= targetLevel);
POSTCONDITION(RETVAL->CheckNoError(targetLevel));
@@ -2531,6 +2529,7 @@ Assembly *AppDomain::LoadAssembly(FileLoadLock *pLock, FileLoadLevel targetLevel
// Do a quick out check for the already loaded case.
if (pLock->GetLoadLevel() >= targetLevel)
{
+ _ASSERTE(pAssembly != nullptr);
pAssembly->ThrowIfError(targetLevel);
RETURN pAssembly;
@@ -2553,8 +2552,9 @@ Assembly *AppDomain::LoadAssembly(FileLoadLock *pLock, FileLoadLevel targetLevel
if (immediateTargetLevel > limit.GetLoadLevel())
immediateTargetLevel = limit.GetLoadLevel();
+ const char *simpleName = pLock->GetPEAssembly()->GetSimpleName();
LOG((LF_LOADER, LL_INFO100, "LOADER: ***%s*\t>>>Load initiated, %s/%s\n",
- pAssembly->GetSimpleName(),
+ simpleName,
fileLoadLevelName[immediateTargetLevel], fileLoadLevelName[targetLevel]));
// Now loop and do the load incrementally to the target level.
@@ -2577,30 +2577,32 @@ Assembly *AppDomain::LoadAssembly(FileLoadLock *pLock, FileLoadLevel targetLevel
LOG((LF_LOADER,
(workLevel == FILE_LOAD_BEGIN
- || workLevel == FILE_LOADED
- || workLevel == FILE_ACTIVE)
- ? LL_INFO10 : LL_INFO1000,
- "LOADER: %p:***%s*\t loading at level %s\n",
- this, pAssembly->GetSimpleName(), fileLoadLevelName[workLevel]));
+ || workLevel == FILE_LOADED
+ || workLevel == FILE_ACTIVE)
+ ? LL_INFO10 : LL_INFO1000,
+ "LOADER: %p:***%s*\t loading at level %s\n",
+ this, simpleName, fileLoadLevelName[workLevel]));
- TryIncrementalLoad(pAssembly, workLevel, fileLock);
+ TryIncrementalLoad(workLevel, fileLock);
}
}
if (pLock->GetLoadLevel() == immediateTargetLevel-1)
{
LOG((LF_LOADER, LL_INFO100, "LOADER: ***%s*\t<<GetSimpleName(),
+ simpleName,
fileLoadLevelName[immediateTargetLevel-1]));
}
}
LOG((LF_LOADER, LL_INFO100, "LOADER: ***%s*\t<<GetSimpleName(),
+ simpleName,
fileLoadLevelName[pLock->GetLoadLevel()]));
-
}
+ pAssembly = pLock->GetAssembly();
+ _ASSERTE(pAssembly != nullptr); // We should always be loading to at least FILE_LOAD_ALLOCATE, so the assembly should be created
+
// There may have been an error stored on the domain file by another thread, or from a previous load
pAssembly->ThrowIfError(targetLevel);
@@ -2624,7 +2626,7 @@ Assembly *AppDomain::LoadAssembly(FileLoadLock *pLock, FileLoadLevel targetLevel
RETURN pAssembly;
}
-void AppDomain::TryIncrementalLoad(Assembly *pAssembly, FileLoadLevel workLevel, FileLoadLockHolder &lockHolder)
+void AppDomain::TryIncrementalLoad(FileLoadLevel workLevel, FileLoadLockHolder& lockHolder)
{
STANDARD_VM_CONTRACT;
@@ -2632,11 +2634,41 @@ void AppDomain::TryIncrementalLoad(Assembly *pAssembly, FileLoadLevel workLevel,
BOOL released = FALSE;
FileLoadLock* pLoadLock = lockHolder.GetValue();
+ Assembly* pAssembly = pLoadLock->GetAssembly();
EX_TRY
{
- // Do the work
- BOOL success = pAssembly->DoIncrementalLoad(workLevel);
+ BOOL success;
+ if (workLevel == FILE_LOAD_ALLOCATE)
+ {
+ // FileLoadLock should not have an assembly yet
+ _ASSERTE(pAssembly == NULL);
+
+ // Allocate DomainAssembly & Assembly
+ PEAssembly *pPEAssembly = pLoadLock->GetPEAssembly();
+ AssemblyBinder *pAssemblyBinder = pPEAssembly->GetAssemblyBinder();
+ LoaderAllocator *pLoaderAllocator = pAssemblyBinder->GetLoaderAllocator();
+ if (pLoaderAllocator == NULL)
+ pLoaderAllocator = this->GetLoaderAllocator();
+
+ AllocMemTracker amTracker;
+ AllocMemTracker *pamTracker = &amTracker;
+ NewHolder pDomainAssembly = new DomainAssembly(pPEAssembly, pLoaderAllocator, pamTracker);
+ pLoadLock->SetAssembly(pDomainAssembly->GetAssembly());
+ pDomainAssembly->GetAssembly()->SetIsTenured();
+ if (pDomainAssembly->GetAssembly()->IsCollectible())
+ {
+ ((AssemblyLoaderAllocator *)pLoaderAllocator)->AddDomainAssembly(pDomainAssembly);
+ }
+ pDomainAssembly.SuppressRelease();
+ pamTracker->SuppressRelease();
+ pAssembly = pLoadLock->GetAssembly();
+ success = TRUE;
+ }
+ else
+ {
+ success = pAssembly->DoIncrementalLoad(workLevel);
+ }
// Complete the level.
if (pLoadLock->CompleteLoadLevel(workLevel, success) &&
@@ -2651,9 +2683,9 @@ void AppDomain::TryIncrementalLoad(Assembly *pAssembly, FileLoadLevel workLevel,
{
Exception *pEx = GET_EXCEPTION();
- //We will cache this error and wire this load to forever fail,
+ // We will cache this error and wire this load to forever fail,
// unless the exception is transient or the file is loaded OK but just cannot execute
- if (!pEx->IsTransient() && !pAssembly->IsLoaded())
+ if (pAssembly != nullptr && !pEx->IsTransient() && !pAssembly->IsLoaded())
{
if (released)
{
diff --git a/src/coreclr/vm/appdomain.hpp b/src/coreclr/vm/appdomain.hpp
index 8a42c4d7cd213f..a58a2314ee0225 100644
--- a/src/coreclr/vm/appdomain.hpp
+++ b/src/coreclr/vm/appdomain.hpp
@@ -293,14 +293,15 @@ class FileLoadLock : public ListLockEntry
{
private:
FileLoadLevel m_level;
- Assembly* m_pAssembly;
+ Assembly* m_pAssembly; // Will be null until FILE_LOAD_ALLOCATE is completed successfully
HRESULT m_cachedHR;
public:
- static FileLoadLock *Create(PEFileListLock *pLock, PEAssembly *pPEAssembly, Assembly *pAssembly);
+ static FileLoadLock* Create(PEFileListLock* pLock, PEAssembly* pPEAssembly);
~FileLoadLock();
Assembly *GetAssembly();
+ PEAssembly* GetPEAssembly();
FileLoadLevel GetLoadLevel();
// CanAcquire will return FALSE if Acquire will definitely not take the lock due
@@ -320,6 +321,9 @@ class FileLoadLock : public ListLockEntry
// returns TRUE if it updated load level, FALSE if the level was set already
BOOL CompleteLoadLevel(FileLoadLevel level, BOOL success);
+ // Associate an Assembly with this lock
+ void SetAssembly(Assembly* pAssembly);
+
void SetError(Exception *ex);
void AddRef();
@@ -327,7 +331,7 @@ class FileLoadLock : public ListLockEntry
private:
- FileLoadLock(PEFileListLock *pLock, PEAssembly *pPEAssembly, Assembly *pAssembly);
+ FileLoadLock(PEFileListLock* pLock, PEAssembly* pPEAssembly);
static void HolderLeave(FileLoadLock *pThis);
@@ -1098,7 +1102,7 @@ class AppDomain final
Assembly *LoadAssembly(FileLoadLock *pLock, FileLoadLevel targetLevel);
- void TryIncrementalLoad(Assembly *pFile, FileLoadLevel workLevel, FileLoadLockHolder &lockHolder);
+ void TryIncrementalLoad(FileLoadLevel workLevel, FileLoadLockHolder& lockHolder);
#ifndef DACCESS_COMPILE // needs AssemblySpec
public:
diff --git a/src/coreclr/vm/arm64/CachedInterfaceDispatchCoreCLR.S b/src/coreclr/vm/arm64/CachedInterfaceDispatchCoreCLR.S
index 068936ef5235e2..d4da67291443ab 100644
--- a/src/coreclr/vm/arm64/CachedInterfaceDispatchCoreCLR.S
+++ b/src/coreclr/vm/arm64/CachedInterfaceDispatchCoreCLR.S
@@ -6,6 +6,10 @@
#ifdef FEATURE_CACHED_INTERFACE_DISPATCH
+ // Workaround for Xcode 15 ld-classic linker which cannot deal with
+ // .alt_entry labels at beginning of section.
+ nop
+
//
// Stub dispatch routine for dispatch to a vtable slot
//
diff --git a/src/coreclr/vm/arm64/patchedcode.S b/src/coreclr/vm/arm64/patchedcode.S
index 2bea90942e66a4..248375142d2c49 100644
--- a/src/coreclr/vm/arm64/patchedcode.S
+++ b/src/coreclr/vm/arm64/patchedcode.S
@@ -5,6 +5,12 @@
#include "unixasmmacros.inc"
#include "patchedcodeconstants.h"
+// On Apple platforms we emit the whole patched region as single function
+// with .alt_entry labels for individual write barrier helpers. This ensures
+// the linker doesn't relocate or split the code and treats it as single
+// atom. We also need to be careful to produce the correct unwinding
+// information.
+
//-----------------------------------------------------------------------------
// The following Macros help in WRITE_BARRIER Implementations
// WRITE_BARRIER_ENTRY
@@ -13,7 +19,17 @@
// to declare a write barrier function.
//
.macro WRITE_BARRIER_ENTRY name
+#if defined(__APPLE__)
+ // .cfi_startproc/.cfi_endproc is workaround for https://github.com/dotnet/runtime/issues/119005
+ .cfi_endproc
+ .p2align 2
+ .alt_entry C_FUNC(\name)
+ .private_extern C_FUNC(\name)
+C_FUNC(\name):
+ .cfi_startproc
+#else
LEAF_ENTRY \name, _TEXT
+#endif
.endm
// WRITE_BARRIER_END
@@ -21,15 +37,33 @@
// The partner to WRITE_BARRIER_ENTRY, used like NESTED_END.
//
.macro WRITE_BARRIER_END name
+#if defined(__APPLE__)
+ // .cfi_startproc/.cfi_endproc is workaround for https://github.com/dotnet/runtime/issues/119005
+ .cfi_endproc
+ .alt_entry C_FUNC(\name\()_End)
+ .private_extern C_FUNC(\name\()_End)
+C_FUNC(\name\()_End):
+ .cfi_startproc
+ // make sure this symbol gets its own address
+ nop
+#else
LEAF_END_MARKED \name, _TEXT
+#endif
.endm
.balign 64 // Align to power of two at least as big as patchable literal pool so that it fits optimally in cache line
//------------------------------------------
// Start of the writeable code region
+#if defined(__APPLE__)
+ .global C_FUNC(JIT_PatchedCodeStart)
+C_FUNC(JIT_PatchedCodeStart):
+ .cfi_startproc
+ ret lr
+#else
LEAF_ENTRY JIT_PatchedCodeStart, _TEXT
ret lr
LEAF_END JIT_PatchedCodeStart, _TEXT
+#endif
//-----------------------------------------------------------------------------
// void JIT_ByRefWriteBarrier
@@ -145,10 +179,17 @@ WRITE_BARRIER_END JIT_WriteBarrier_Table
// ------------------------------------------------------------------
// End of the writeable code region
+#if defined(__APPLE__)
+ .private_extern C_FUNC(JIT_PatchedCodeLast)
+ .alt_entry C_FUNC(JIT_PatchedCodeLast)
+C_FUNC(JIT_PatchedCodeLast):
+ .cfi_endproc
+ ret lr
+#else
LEAF_ENTRY JIT_PatchedCodeLast, _TEXT
ret lr
LEAF_END JIT_PatchedCodeLast, _TEXT
-
+#endif
//-----------------------------------------------------------------------------
diff --git a/src/coreclr/vm/arm64/stubs.cpp b/src/coreclr/vm/arm64/stubs.cpp
index e26b8aac9ad5d0..533a9b1cf5afcc 100644
--- a/src/coreclr/vm/arm64/stubs.cpp
+++ b/src/coreclr/vm/arm64/stubs.cpp
@@ -350,6 +350,8 @@ void ResumableFrame::UpdateRegDisplay_Impl(const PREGDISPLAY pRD, bool updateFlo
CONTRACT_END;
CopyMemory(pRD->pCurrentContext, m_Regs, sizeof(T_CONTEXT));
+ // Clear the CONTEXT_XSTATE, since the REGDISPLAY contains just plain CONTEXT structure
+ pRD->pCurrentContext->ContextFlags &= ~(CONTEXT_XSTATE & CONTEXT_AREA_MASK);
pRD->ControlPC = m_Regs->Pc;
pRD->SP = m_Regs->Sp;
diff --git a/src/coreclr/vm/assembly.cpp b/src/coreclr/vm/assembly.cpp
index 470bbfd1e23c2d..7ec8d6b0db16e0 100644
--- a/src/coreclr/vm/assembly.cpp
+++ b/src/coreclr/vm/assembly.cpp
@@ -329,7 +329,10 @@ Assembly * Assembly::Create(
PRECONDITION(pLoaderAllocator != NULL);
PRECONDITION(pLoaderAllocator->IsCollectible() || pLoaderAllocator == SystemDomain::GetGlobalLoaderAllocator());
}
- CONTRACTL_END
+ CONTRACTL_END;
+
+ // Validate the assembly about to be created is suitable for execution.
+ pPEAssembly->ValidateForExecution();
NewHolder pAssembly (new Assembly(pPEAssembly, pLoaderAllocator));
@@ -540,21 +543,16 @@ Assembly *Assembly::CreateDynamic(AssemblyBinder* pBinder, NativeAssemblyNamePar
RETURN pRetVal;
} // Assembly::CreateDynamic
-
-
void Assembly::SetDomainAssembly(DomainAssembly *pDomainAssembly)
{
CONTRACTL
{
+ STANDARD_VM_CHECK;
PRECONDITION(CheckPointer(pDomainAssembly));
- THROWS;
- GC_TRIGGERS;
- INJECT_FAULT(COMPlusThrowOM(););
}
CONTRACTL_END;
GetModule()->SetDomainAssembly(pDomainAssembly);
-
} // Assembly::SetDomainAssembly
#endif // #ifndef DACCESS_COMPILE
diff --git a/src/coreclr/vm/assembly.hpp b/src/coreclr/vm/assembly.hpp
index 58e63b72a4d91e..9213cfaf98a88a 100644
--- a/src/coreclr/vm/assembly.hpp
+++ b/src/coreclr/vm/assembly.hpp
@@ -352,7 +352,10 @@ class Assembly
//****************************************************************************************
+private:
Assembly();
+
+public:
~Assembly();
BOOL GetResource(LPCSTR szName, DWORD *cbResource,
diff --git a/src/coreclr/vm/assemblyspec.hpp b/src/coreclr/vm/assemblyspec.hpp
index ea94c25dbbfc24..49446800fe7be2 100644
--- a/src/coreclr/vm/assemblyspec.hpp
+++ b/src/coreclr/vm/assemblyspec.hpp
@@ -27,7 +27,8 @@ enum FileLoadLevel
// Note that semantics here are description is the LAST step done, not what is
// currently being done.
- FILE_LOAD_CREATE,
+ FILE_LOAD_CREATE, // List entry + FileLoadLock created, no Assembly/DomainAssembly yet
+ FILE_LOAD_ALLOCATE, // DomainAssembly & Assembly object allocated and associated with the lock
FILE_LOAD_BEGIN,
FILE_LOAD_BEFORE_TYPE_LOAD,
FILE_LOAD_EAGER_FIXUPS,
diff --git a/src/coreclr/vm/asyncthunks.cpp b/src/coreclr/vm/asyncthunks.cpp
index 34777b22ad108e..bf2a385cd6d8ec 100644
--- a/src/coreclr/vm/asyncthunks.cpp
+++ b/src/coreclr/vm/asyncthunks.cpp
@@ -70,9 +70,6 @@ void MethodDesc::EmitTaskReturningThunk(MethodDesc* pAsyncOtherVariant, MetaSig&
bool isValueTask = thTaskRet.GetMethodTable()->IsValueType();
- LocalDesc returnLocalDesc(thTaskRet);
- DWORD returnLocal = pCode->NewLocal(returnLocalDesc);
-
TypeHandle thLogicalRetType;
DWORD logicalResultLocal = UINT_MAX;
if (thTaskRet.GetNumGenericArgs() > 0)
@@ -81,15 +78,14 @@ void MethodDesc::EmitTaskReturningThunk(MethodDesc* pAsyncOtherVariant, MetaSig&
logicalResultLocal = pCode->NewLocal(LocalDesc(thLogicalRetType));
}
- LocalDesc exceptionLocalDesc(CoreLibBinder::GetClass(CLASS__EXCEPTION));
- DWORD exceptionLocal = pCode->NewLocal(exceptionLocalDesc);
-
+ LocalDesc returnLocalDesc(thTaskRet);
+ DWORD returnTaskLocal = pCode->NewLocal(returnLocalDesc);
LocalDesc executionAndSyncBlockStoreLocalDesc(CoreLibBinder::GetClass(CLASS__EXECUTIONANDSYNCBLOCKSTORE));
DWORD executionAndSyncBlockStoreLocal = pCode->NewLocal(executionAndSyncBlockStoreLocalDesc);
- ILCodeLabel* pNoExceptionLabel = pCode->NewCodeLabel();
- ILCodeLabel* pReturnResultLabel = pCode->NewCodeLabel();
- ILCodeLabel* pSuspendedLabel = pCode->NewCodeLabel();
+ ILCodeLabel* returnTaskLabel = pCode->NewCodeLabel();
+ ILCodeLabel* suspendedLabel = pCode->NewCodeLabel();
+ ILCodeLabel* finishedLabel = pCode->NewCodeLabel();
pCode->EmitLDLOCA(executionAndSyncBlockStoreLocal);
pCode->EmitCALL(pCode->GetToken(CoreLibBinder::GetMethod(METHOD__EXECUTIONANDSYNCBLOCKSTORE__PUSH)), 1, 0);
@@ -172,7 +168,35 @@ void MethodDesc::EmitTaskReturningThunk(MethodDesc* pAsyncOtherVariant, MetaSig&
pCode->EmitSTLOC(logicalResultLocal);
pCode->EmitCALL(METHOD__STUBHELPERS__ASYNC_CALL_CONTINUATION, 0, 1);
pCode->EmitSTLOC(continuationLocal);
- pCode->EmitLEAVE(pNoExceptionLabel);
+ pCode->EmitLDLOC(continuationLocal);
+ pCode->EmitBRFALSE(finishedLabel);
+
+ pCode->EmitLEAVE(suspendedLabel);
+
+ pCode->EmitLabel(finishedLabel);
+ if (logicalResultLocal != UINT_MAX)
+ {
+ pCode->EmitLDLOC(logicalResultLocal);
+ MethodDesc* md;
+ if (isValueTask)
+ md = CoreLibBinder::GetMethod(METHOD__VALUETASK__FROM_RESULT_T);
+ else
+ md = CoreLibBinder::GetMethod(METHOD__TASK__FROM_RESULT_T);
+ md = FindOrCreateAssociatedMethodDesc(md, md->GetMethodTable(), FALSE, Instantiation(&thLogicalRetType, 1), FALSE);
+
+ int fromResultToken = GetTokenForGenericMethodCallWithAsyncReturnType(pCode, md);
+ pCode->EmitCALL(fromResultToken, 1, 1);
+ }
+ else
+ {
+ if (isValueTask)
+ pCode->EmitCALL(METHOD__VALUETASK__GET_COMPLETED_TASK, 0, 1);
+ else
+ pCode->EmitCALL(METHOD__TASK__GET_COMPLETED_TASK, 0, 1);
+ }
+ pCode->EmitSTLOC(returnTaskLocal);
+ pCode->EmitLEAVE(returnTaskLabel);
+
pCode->EndTryBlock();
}
// Catch
@@ -203,10 +227,39 @@ void MethodDesc::EmitTaskReturningThunk(MethodDesc* pAsyncOtherVariant, MetaSig&
fromExceptionToken = pCode->GetToken(fromExceptionMD);
}
pCode->EmitCALL(fromExceptionToken, 1, 1);
- pCode->EmitSTLOC(returnLocal);
- pCode->EmitLEAVE(pReturnResultLabel);
+ pCode->EmitSTLOC(returnTaskLocal);
+ pCode->EmitLEAVE(returnTaskLabel);
pCode->EndCatchBlock();
}
+
+ pCode->EmitLabel(suspendedLabel);
+
+ int finalizeTaskReturningThunkToken;
+ if (logicalResultLocal != UINT_MAX)
+ {
+ MethodDesc* md;
+ if (isValueTask)
+ md = CoreLibBinder::GetMethod(METHOD__ASYNC_HELPERS__FINALIZE_VALUETASK_RETURNING_THUNK_1);
+ else
+ md = CoreLibBinder::GetMethod(METHOD__ASYNC_HELPERS__FINALIZE_TASK_RETURNING_THUNK_1);
+
+ md = FindOrCreateAssociatedMethodDesc(md, md->GetMethodTable(), FALSE, Instantiation(&thLogicalRetType, 1), FALSE);
+ finalizeTaskReturningThunkToken = GetTokenForGenericMethodCallWithAsyncReturnType(pCode, md);
+ }
+ else
+ {
+ MethodDesc* md;
+ if (isValueTask)
+ md = CoreLibBinder::GetMethod(METHOD__ASYNC_HELPERS__FINALIZE_VALUETASK_RETURNING_THUNK);
+ else
+ md = CoreLibBinder::GetMethod(METHOD__ASYNC_HELPERS__FINALIZE_TASK_RETURNING_THUNK);
+ finalizeTaskReturningThunkToken = pCode->GetToken(md);
+ }
+ pCode->EmitLDLOC(continuationLocal);
+ pCode->EmitCALL(finalizeTaskReturningThunkToken, 1, 1);
+ pCode->EmitSTLOC(returnTaskLocal);
+ pCode->EmitLEAVE(returnTaskLabel);
+
pCode->EndTryBlock();
}
//
@@ -218,60 +271,8 @@ void MethodDesc::EmitTaskReturningThunk(MethodDesc* pAsyncOtherVariant, MetaSig&
pCode->EndFinallyBlock();
}
- pCode->EmitLabel(pNoExceptionLabel);
- pCode->EmitLDLOC(continuationLocal);
- pCode->EmitBRTRUE(pSuspendedLabel);
- if (logicalResultLocal != UINT_MAX)
- {
- pCode->EmitLDLOC(logicalResultLocal);
- MethodDesc* md;
- if (isValueTask)
- md = CoreLibBinder::GetMethod(METHOD__VALUETASK__FROM_RESULT_T);
- else
- md = CoreLibBinder::GetMethod(METHOD__TASK__FROM_RESULT_T);
- md = FindOrCreateAssociatedMethodDesc(md, md->GetMethodTable(), FALSE, Instantiation(&thLogicalRetType, 1), FALSE);
-
- int fromResultToken = GetTokenForGenericMethodCallWithAsyncReturnType(pCode, md);
- pCode->EmitCALL(fromResultToken, 1, 1);
- }
- else
- {
- if (isValueTask)
- pCode->EmitCALL(METHOD__VALUETASK__GET_COMPLETED_TASK, 0, 1);
- else
- pCode->EmitCALL(METHOD__TASK__GET_COMPLETED_TASK, 0, 1);
- }
-
- pCode->EmitSTLOC(returnLocal);
- pCode->EmitLabel(pReturnResultLabel);
- pCode->EmitLDLOC(returnLocal);
- pCode->EmitRET();
-
- pCode->EmitLabel(pSuspendedLabel);
-
- int finalizeTaskReturningThunkToken;
- if (logicalResultLocal != UINT_MAX)
- {
- MethodDesc* md;
- if (isValueTask)
- md = CoreLibBinder::GetMethod(METHOD__ASYNC_HELPERS__FINALIZE_VALUETASK_RETURNING_THUNK_1);
- else
- md = CoreLibBinder::GetMethod(METHOD__ASYNC_HELPERS__FINALIZE_TASK_RETURNING_THUNK_1);
-
- md = FindOrCreateAssociatedMethodDesc(md, md->GetMethodTable(), FALSE, Instantiation(&thLogicalRetType, 1), FALSE);
- finalizeTaskReturningThunkToken = GetTokenForGenericMethodCallWithAsyncReturnType(pCode, md);
- }
- else
- {
- MethodDesc* md;
- if (isValueTask)
- md = CoreLibBinder::GetMethod(METHOD__ASYNC_HELPERS__FINALIZE_VALUETASK_RETURNING_THUNK);
- else
- md = CoreLibBinder::GetMethod(METHOD__ASYNC_HELPERS__FINALIZE_TASK_RETURNING_THUNK);
- finalizeTaskReturningThunkToken = pCode->GetToken(md);
- }
- pCode->EmitLDLOC(continuationLocal);
- pCode->EmitCALL(finalizeTaskReturningThunkToken, 1, 1);
+ pCode->EmitLabel(returnTaskLabel);
+ pCode->EmitLDLOC(returnTaskLocal);
pCode->EmitRET();
}
@@ -337,6 +338,46 @@ SigPointer MethodDesc::GetAsyncThunkResultTypeSig()
return SigPointer(returnTypeSig, (DWORD)(returnTypeSigEnd - returnTypeSig));
}
+bool MethodDesc::IsValueTaskAsyncThunk()
+{
+ _ASSERTE(IsAsyncThunkMethod());
+ PCCOR_SIGNATURE pSigRaw;
+ DWORD cSig;
+ if (FAILED(GetMDImport()->GetSigOfMethodDef(GetMemberDef(), &cSig, &pSigRaw)))
+ {
+ _ASSERTE(!"Loaded MethodDesc should not fail to get signature");
+ pSigRaw = NULL;
+ cSig = 0;
+ }
+
+ SigPointer pSig(pSigRaw, cSig);
+ uint32_t callConvInfo;
+ IfFailThrow(pSig.GetCallingConvInfo(&callConvInfo));
+
+ if ((callConvInfo & IMAGE_CEE_CS_CALLCONV_GENERIC) != 0)
+ {
+ // GenParamCount
+ IfFailThrow(pSig.GetData(NULL));
+ }
+
+ // ParamCount
+ IfFailThrow(pSig.GetData(NULL));
+
+ // ReturnType comes now. Skip the modifiers.
+ IfFailThrow(pSig.SkipCustomModifiers());
+
+ // here we should have something Task, ValueTask, Task or ValueTask
+ BYTE bElementType;
+ IfFailThrow(pSig.GetByte(&bElementType));
+
+ // skip ELEMENT_TYPE_GENERICINST
+ if (bElementType == ELEMENT_TYPE_GENERICINST)
+ IfFailThrow(pSig.GetByte(&bElementType));
+
+ _ASSERTE(bElementType == ELEMENT_TYPE_VALUETYPE || bElementType == ELEMENT_TYPE_CLASS);
+ return bElementType == ELEMENT_TYPE_VALUETYPE;
+}
+
// Given a method Foo, return a MethodSpec token for Foo instantiated
// with the result type from the current async method's return type. For
// example, if "this" represents Task> Foo(), and "md" is
@@ -434,30 +475,32 @@ void MethodDesc::EmitAsyncMethodThunk(MethodDesc* pAsyncOtherVariant, MetaSig& m
MethodDesc* mdIsCompleted;
MethodDesc* mdGetResult;
+ bool isValueTask = IsValueTaskAsyncThunk();
+
if (msig.IsReturnTypeVoid())
{
- pMTTask = CoreLibBinder::GetClass(CLASS__TASK);
- thTaskAwaiter = CoreLibBinder::GetClass(CLASS__TASK_AWAITER);
- mdGetAwaiter = CoreLibBinder::GetMethod(METHOD__TASK__GET_AWAITER);
- mdIsCompleted = CoreLibBinder::GetMethod(METHOD__TASK_AWAITER__GET_ISCOMPLETED);
- mdGetResult = CoreLibBinder::GetMethod(METHOD__TASK_AWAITER__GET_RESULT);
+ pMTTask = CoreLibBinder::GetClass(isValueTask ? CLASS__VALUETASK : CLASS__TASK);
+ thTaskAwaiter = CoreLibBinder::GetClass(isValueTask ? CLASS__VALUETASK_AWAITER : CLASS__TASK_AWAITER);
+ mdGetAwaiter = CoreLibBinder::GetMethod(isValueTask ? METHOD__VALUETASK__GET_AWAITER : METHOD__TASK__GET_AWAITER);
+ mdIsCompleted = CoreLibBinder::GetMethod(isValueTask ? METHOD__VALUETASK_AWAITER__GET_ISCOMPLETED : METHOD__TASK_AWAITER__GET_ISCOMPLETED);
+ mdGetResult = CoreLibBinder::GetMethod(isValueTask ? METHOD__VALUETASK_AWAITER__GET_RESULT : METHOD__TASK_AWAITER__GET_RESULT);
}
else
{
TypeHandle thLogicalRetType = msig.GetRetTypeHandleThrowing();
- MethodTable* pMTTaskOpen = CoreLibBinder::GetClass(CLASS__TASK_1);
+ MethodTable* pMTTaskOpen = CoreLibBinder::GetClass(isValueTask ? CLASS__VALUETASK_1 : CLASS__TASK_1);
pMTTask = ClassLoader::LoadGenericInstantiationThrowing(pMTTaskOpen->GetModule(), pMTTaskOpen->GetCl(), Instantiation(&thLogicalRetType, 1)).GetMethodTable();
- MethodTable* pMTTaskAwaiterOpen = CoreLibBinder::GetClass(CLASS__TASK_AWAITER_1);
+ MethodTable* pMTTaskAwaiterOpen = CoreLibBinder::GetClass(isValueTask ? CLASS__VALUETASK_AWAITER_1 : CLASS__TASK_AWAITER_1);
thTaskAwaiter = ClassLoader::LoadGenericInstantiationThrowing(pMTTaskAwaiterOpen->GetModule(), pMTTaskAwaiterOpen->GetCl(), Instantiation(&thLogicalRetType, 1));
- mdGetAwaiter = CoreLibBinder::GetMethod(METHOD__TASK_1__GET_AWAITER);
+ mdGetAwaiter = CoreLibBinder::GetMethod(isValueTask ? METHOD__VALUETASK_1__GET_AWAITER : METHOD__TASK_1__GET_AWAITER);
mdGetAwaiter = MethodDesc::FindOrCreateAssociatedMethodDesc(mdGetAwaiter, pMTTask, FALSE, Instantiation(), FALSE);
- mdIsCompleted = CoreLibBinder::GetMethod(METHOD__TASK_AWAITER_1__GET_ISCOMPLETED);
+ mdIsCompleted = CoreLibBinder::GetMethod(isValueTask ? METHOD__VALUETASK_AWAITER_1__GET_ISCOMPLETED : METHOD__TASK_AWAITER_1__GET_ISCOMPLETED);
mdIsCompleted = MethodDesc::FindOrCreateAssociatedMethodDesc(mdIsCompleted, thTaskAwaiter.GetMethodTable(), FALSE, Instantiation(), FALSE);
- mdGetResult = CoreLibBinder::GetMethod(METHOD__TASK_AWAITER_1__GET_RESULT);
+ mdGetResult = CoreLibBinder::GetMethod(isValueTask ? METHOD__VALUETASK_AWAITER_1__GET_RESULT : METHOD__TASK_AWAITER_1__GET_RESULT);
mdGetResult = MethodDesc::FindOrCreateAssociatedMethodDesc(mdGetResult, thTaskAwaiter.GetMethodTable(), FALSE, Instantiation(), FALSE);
}
@@ -549,7 +592,19 @@ void MethodDesc::EmitAsyncMethodThunk(MethodDesc* pAsyncOtherVariant, MetaSig& m
getResultToken = pCode->GetToken(mdGetResult);
}
- pCode->EmitCALLVIRT(getAwaiterToken, 1, 1);
+ if (isValueTask)
+ {
+ LocalDesc valuetaskLocalDesc(pMTTask);
+ DWORD valuetaskLocal = pCode->NewLocal(valuetaskLocalDesc);
+ pCode->EmitSTLOC(valuetaskLocal);
+ pCode->EmitLDLOCA(valuetaskLocal);
+ pCode->EmitCALL(getAwaiterToken, 1, 1);
+ }
+ else
+ {
+ pCode->EmitCALLVIRT(getAwaiterToken, 1, 1);
+ }
+
pCode->EmitSTLOC(awaiterLocal);
pCode->EmitLDLOCA(awaiterLocal);
pCode->EmitCALL(getIsCompletedToken, 1, 1);
diff --git a/src/coreclr/vm/ceeload.cpp b/src/coreclr/vm/ceeload.cpp
index 29ea5a358fd2cd..adfe056bdbe20b 100644
--- a/src/coreclr/vm/ceeload.cpp
+++ b/src/coreclr/vm/ceeload.cpp
@@ -3744,10 +3744,19 @@ void SaveManagedCommandLine(LPCWSTR pwzAssemblyPath, int argc, LPCWSTR *argv)
#endif
}
+static bool g_fIJWLoaded = false;
+
void Module::SetIsIJWFixedUp()
{
LIMITED_METHOD_CONTRACT;
InterlockedOr((LONG*)&m_dwTransientFlags, IS_IJW_FIXED_UP);
+ g_fIJWLoaded = true;
+}
+
+bool Module::HasAnyIJWBeenLoaded()
+{
+ LIMITED_METHOD_CONTRACT;
+ return g_fIJWLoaded;
}
#endif // !DACCESS_COMPILE
diff --git a/src/coreclr/vm/ceeload.h b/src/coreclr/vm/ceeload.h
index 98853750cd44a9..3cea27da8fbcee 100644
--- a/src/coreclr/vm/ceeload.h
+++ b/src/coreclr/vm/ceeload.h
@@ -1513,6 +1513,8 @@ class Module : public ModuleBase
BOOL IsIJWFixedUp() { return m_dwTransientFlags & IS_IJW_FIXED_UP; }
void SetIsIJWFixedUp();
+ static bool HasAnyIJWBeenLoaded();
+
BOOL IsBeingUnloaded() { return m_dwTransientFlags & IS_BEING_UNLOADED; }
void SetBeingUnloaded();
void StartUnload();
diff --git a/src/coreclr/vm/ceemain.cpp b/src/coreclr/vm/ceemain.cpp
index 4ad3ae3cc78925..4be75dc9158969 100644
--- a/src/coreclr/vm/ceemain.cpp
+++ b/src/coreclr/vm/ceemain.cpp
@@ -1702,7 +1702,17 @@ static void OsAttachThread(void* thread)
if (t_flsState == FLS_STATE_INVOKED)
{
- _ASSERTE_ALL_BUILDS(!"Attempt to execute managed code after the .NET runtime thread state has been destroyed.");
+ // Managed C++ may run managed code in DllMain (e.g. during DLL_PROCESS_DETACH to run global destructors). This is
+ // not supported and unreliable. Historically, it happened to work most of the time. For backward compatibility,
+ // suppress this assert in release builds if we have encountered any mixed mode binaries.
+ if (Module::HasAnyIJWBeenLoaded())
+ {
+ _ASSERTE(!"Attempt to execute managed code after the .NET runtime thread state has been destroyed.");
+ }
+ else
+ {
+ _ASSERTE_ALL_BUILDS(!"Attempt to execute managed code after the .NET runtime thread state has been destroyed.");
+ }
}
t_flsState = FLS_STATE_ARMED;
diff --git a/src/coreclr/vm/corelib.h b/src/coreclr/vm/corelib.h
index 0b979353253f72..6de72c8918fa0a 100644
--- a/src/coreclr/vm/corelib.h
+++ b/src/coreclr/vm/corelib.h
@@ -344,12 +344,14 @@ DEFINE_CLASS(THREAD_START_EXCEPTION,Threading, ThreadStartException
DEFINE_METHOD(THREAD_START_EXCEPTION,EX_CTOR, .ctor, IM_Exception_RetVoid)
DEFINE_CLASS(VALUETASK_1, Tasks, ValueTask`1)
+DEFINE_METHOD(VALUETASK_1, GET_AWAITER, GetAwaiter, NoSig)
DEFINE_CLASS(VALUETASK, Tasks, ValueTask)
DEFINE_METHOD(VALUETASK, FROM_EXCEPTION, FromException, SM_Exception_RetValueTask)
DEFINE_METHOD(VALUETASK, FROM_EXCEPTION_1, FromException, GM_Exception_RetValueTaskOfT)
DEFINE_METHOD(VALUETASK, FROM_RESULT_T, FromResult, GM_T_RetValueTaskOfT)
DEFINE_METHOD(VALUETASK, GET_COMPLETED_TASK, get_CompletedTask, SM_RetValueTask)
+DEFINE_METHOD(VALUETASK, GET_AWAITER, GetAwaiter, NoSig)
DEFINE_CLASS(TASK_1, Tasks, Task`1)
DEFINE_METHOD(TASK_1, GET_AWAITER, GetAwaiter, NoSig)
@@ -369,6 +371,14 @@ DEFINE_CLASS(TASK_AWAITER, CompilerServices, TaskAwaiter)
DEFINE_METHOD(TASK_AWAITER, GET_ISCOMPLETED, get_IsCompleted, NoSig)
DEFINE_METHOD(TASK_AWAITER, GET_RESULT, GetResult, NoSig)
+DEFINE_CLASS(VALUETASK_AWAITER_1, CompilerServices, ValueTaskAwaiter`1)
+DEFINE_METHOD(VALUETASK_AWAITER_1, GET_ISCOMPLETED, get_IsCompleted, NoSig)
+DEFINE_METHOD(VALUETASK_AWAITER_1, GET_RESULT, GetResult, NoSig)
+
+DEFINE_CLASS(VALUETASK_AWAITER, CompilerServices, ValueTaskAwaiter)
+DEFINE_METHOD(VALUETASK_AWAITER, GET_ISCOMPLETED, get_IsCompleted, NoSig)
+DEFINE_METHOD(VALUETASK_AWAITER, GET_RESULT, GetResult, NoSig)
+
DEFINE_CLASS(TYPE_HANDLE, System, RuntimeTypeHandle)
DEFINE_CLASS(RT_TYPE_HANDLE, System, RuntimeTypeHandle)
DEFINE_METHOD(RT_TYPE_HANDLE, PVOID_CTOR, .ctor, IM_RuntimeType_RetVoid)
@@ -1347,7 +1357,6 @@ DEFINE_CLASS(EH, Runtime, EH)
DEFINE_METHOD(EH, RH_THROW_EX, RhThrowEx, SM_Obj_RefExInfo_RetVoid)
DEFINE_METHOD(EH, RH_THROWHW_EX, RhThrowHwEx, SM_UInt_RefExInfo_RetVoid)
DEFINE_METHOD(EH, RH_RETHROW, RhRethrow, SM_RefExInfo_RefExInfo_RetVoid)
-DEFINE_METHOD(EH, UNWIND_AND_INTERCEPT, RhUnwindAndIntercept, SM_RefExInfo_UIntPtr_RetVoid)
DEFINE_CLASS(EXCEPTIONSERVICES_INTERNALCALLS, ExceptionServices, InternalCalls)
DEFINE_CLASS(STACKFRAMEITERATOR, Runtime, StackFrameIterator)
#endif // FEATURE_EH_FUNCLETS
diff --git a/src/coreclr/vm/dbginterface.h b/src/coreclr/vm/dbginterface.h
index a72102ef62ad0b..2b352a9f3b4546 100644
--- a/src/coreclr/vm/dbginterface.h
+++ b/src/coreclr/vm/dbginterface.h
@@ -197,7 +197,7 @@ class DebugInterface
// Used by EditAndContinueModule::FixContextAndResume
- virtual void SendSetThreadContextNeeded(CONTEXT *context, DebuggerSteppingInfo *pDebuggerSteppingInfo = nullptr) = 0;
+ virtual void SendSetThreadContextNeeded(CONTEXT *context, DebuggerSteppingInfo *pDebuggerSteppingInfo = nullptr, bool HasActivePatchSkip = false, bool fClearSetIP = false) = 0;
virtual BOOL IsOutOfProcessSetContextEnabled() = 0;
#endif // FEATURE_METADATA_UPDATER
diff --git a/src/coreclr/vm/debuginfostore.cpp b/src/coreclr/vm/debuginfostore.cpp
index 9852d79e8324f2..2687329aea9862 100644
--- a/src/coreclr/vm/debuginfostore.cpp
+++ b/src/coreclr/vm/debuginfostore.cpp
@@ -1406,12 +1406,23 @@ void CompressDebugInfo::EnumMemoryRegions(CLRDataEnumMemoryFlags flags, PTR_BYTE
_ASSERTE(flagByte == 0);
}
- NibbleReader r(pDebugInfo, 12 /* maximum size of compressed 2 UINT32s */);
+ NibbleReader r(pDebugInfo, 24 /* maximum size of compressed 4 UINT32s */);
ULONG cbBounds = r.ReadEncodedU32();
+ ULONG cbUninstrumentedBounds = 0;
+ if (cbBounds == DebugInfoBoundsHasInstrumentedBounds)
+ {
+ // This means we have instrumented bounds.
+ cbBounds = r.ReadEncodedU32();
+ cbUninstrumentedBounds = r.ReadEncodedU32();
+ }
ULONG cbVars = r.ReadEncodedU32();
- pDebugInfo += r.GetNextByteIndex() + cbBounds + cbVars;
+ pDebugInfo += r.GetNextByteIndex() + cbBounds + cbUninstrumentedBounds + cbVars;
+
+ // NibbleReader reads in units of sizeof(NibbleChunkType)
+ // So we need to account for any partial chunk at the end.
+ pDebugInfo = AlignUp(dac_cast(pDebugInfo), sizeof(NibbleReader::NibbleChunkType));
DacEnumMemoryRegion(dac_cast(pStart), pDebugInfo - pStart);
}
diff --git a/src/coreclr/vm/domainassembly.cpp b/src/coreclr/vm/domainassembly.cpp
index 8a34fbe57be54e..bf851149116005 100644
--- a/src/coreclr/vm/domainassembly.cpp
+++ b/src/coreclr/vm/domainassembly.cpp
@@ -21,23 +21,17 @@ DomainAssembly::DomainAssembly(PEAssembly* pPEAssembly, LoaderAllocator* pLoader
{
CONTRACTL
{
+ STANDARD_VM_CHECK;
CONSTRUCTOR_CHECK;
- THROWS; // ValidateForExecution
- GC_TRIGGERS; // ValidateForExecution
- MODE_ANY;
}
CONTRACTL_END;
- pPEAssembly->AddRef();
- pPEAssembly->ValidateForExecution();
-
// Create the Assembly
NewHolder assembly = Assembly::Create(pPEAssembly, memTracker, pLoaderAllocator);
+ assembly->SetDomainAssembly(this);
m_pAssembly = assembly.Extract();
- m_pAssembly->SetDomainAssembly(this);
-
#ifndef PEIMAGE_FLAT_LAYOUT_ONLY
// Creating the Assembly should have ensured the PEAssembly is loaded
_ASSERT(GetPEAssembly()->IsLoaded());
diff --git a/src/coreclr/vm/excep.cpp b/src/coreclr/vm/excep.cpp
index 08620b3c715375..1829b5b16c8b2a 100644
--- a/src/coreclr/vm/excep.cpp
+++ b/src/coreclr/vm/excep.cpp
@@ -6191,7 +6191,10 @@ void HandleManagedFault(EXCEPTION_RECORD* pExceptionRecord, CONTEXT* pContext)
//Ex.RhThrowHwEx(exceptionCode, &exInfo)
CALL_MANAGED_METHOD_NORET(args)
+ DispatchExSecondPass(&exInfo);
+
GCPROTECT_END();
+ UNREACHABLE();
}
#endif // USE_FEF && !TARGET_UNIX
@@ -7276,42 +7279,6 @@ void UnwindAndContinueRethrowHelperInsideCatch(Frame* pEntryFrame, Exception* pE
#endif
}
-#ifdef FEATURE_EH_FUNCLETS
-//
-// This function continues exception interception unwind after it crossed native frames using
-// standard EH / SEH.
-//
-VOID DECLSPEC_NORETURN ContinueExceptionInterceptionUnwind()
-{
- STATIC_CONTRACT_THROWS;
- STATIC_CONTRACT_GC_TRIGGERS;
- STATIC_CONTRACT_MODE_ANY;
-
- GCX_COOP();
-
- Thread *pThread = GetThread();
- ThreadExceptionState* pExState = pThread->GetExceptionState();
- UINT_PTR uInterceptStackFrame = 0;
-
- pExState->GetDebuggerState()->GetDebuggerInterceptInfo(NULL, NULL,
- (PBYTE*)&uInterceptStackFrame,
- NULL, NULL);
-
- PREPARE_NONVIRTUAL_CALLSITE(METHOD__EH__UNWIND_AND_INTERCEPT);
- DECLARE_ARGHOLDER_ARRAY(args, 2);
- args[ARGNUM_0] = PTR_TO_ARGHOLDER((ExInfo*)pExState->GetCurrentExceptionTracker());
- args[ARGNUM_1] = PTR_TO_ARGHOLDER(uInterceptStackFrame);
- pThread->IncPreventAbort();
-
- //Ex.RhUnwindAndIntercept(throwable, &exInfo)
- CRITICAL_CALLSITE;
- CALL_MANAGED_METHOD_NORET(args)
-
- UNREACHABLE();
-}
-
-#endif // FEATURE_EH_FUNCLETS
-
//
// This does the work of the Unwind and Continue Hanlder after the catch clause of that handler. The stack has been
// unwound by the time this is called. Keep that in mind when deciding where to put new code :)
diff --git a/src/coreclr/vm/excep.h b/src/coreclr/vm/excep.h
index 9558c4c4f85bcb..50361b6fd18e2c 100644
--- a/src/coreclr/vm/excep.h
+++ b/src/coreclr/vm/excep.h
@@ -720,15 +720,10 @@ bool DebugIsEECxxException(EXCEPTION_RECORD* pExceptionRecord);
inline void CopyOSContext(T_CONTEXT* pDest, T_CONTEXT* pSrc)
{
- SIZE_T cbReadOnlyPost = 0;
-#ifdef TARGET_AMD64
- cbReadOnlyPost = sizeof(CONTEXT) - offsetof(CONTEXT, FltSave); // older OSes don't have the vector reg fields
-#endif // TARGET_AMD64
-
- memcpyNoGCRefs(pDest, pSrc, sizeof(T_CONTEXT) - cbReadOnlyPost);
-#ifdef TARGET_AMD64
- pDest->ContextFlags = (pDest->ContextFlags & ~(CONTEXT_XSTATE | CONTEXT_FLOATING_POINT)) | CONTEXT_AMD64;
-#endif // TARGET_AMD64
+ memcpyNoGCRefs(pDest, pSrc, sizeof(T_CONTEXT));
+#ifdef CONTEXT_XSTATE
+ pDest->ContextFlags &= ~(CONTEXT_XSTATE & CONTEXT_AREA_MASK);
+#endif
}
void SaveCurrentExceptionInfo(PEXCEPTION_RECORD pRecord, PT_CONTEXT pContext);
diff --git a/src/coreclr/vm/exceptionhandling.cpp b/src/coreclr/vm/exceptionhandling.cpp
index 818f5dbef72639..a4ccb5e1988b06 100644
--- a/src/coreclr/vm/exceptionhandling.cpp
+++ b/src/coreclr/vm/exceptionhandling.cpp
@@ -786,62 +786,6 @@ OBJECTREF ExInfo::CreateThrowable(
return oThrowable;
}
-#if defined(DEBUGGING_SUPPORTED)
-
-#ifdef DEBUGGER_EXCEPTION_INTERCEPTION_SUPPORTED
-//---------------------------------------------------------------------------------------
-//
-// This function is called by DefaultCatchHandler() to intercept an exception and start an unwind.
-//
-// Arguments:
-// pCurrentEstablisherFrame - unused on WIN64
-// pExceptionRecord - EXCEPTION_RECORD of the exception being intercepted
-//
-// Return Value:
-// ExceptionContinueSearch if the exception cannot be intercepted
-//
-// Notes:
-// If the exception is intercepted, this function never returns.
-//
-
-EXCEPTION_DISPOSITION ClrDebuggerDoUnwindAndIntercept(X86_FIRST_ARG(EXCEPTION_REGISTRATION_RECORD* pCurrentEstablisherFrame)
- EXCEPTION_RECORD* pExceptionRecord)
-{
- if (!CheckThreadExceptionStateForInterception())
- {
- return ExceptionContinueSearch;
- }
-
- Thread* pThread = GetThread();
- ThreadExceptionState* pExState = pThread->GetExceptionState();
-
- UINT_PTR uInterceptStackFrame = 0;
-
- pExState->GetDebuggerState()->GetDebuggerInterceptInfo(NULL, NULL,
- (PBYTE*)&uInterceptStackFrame,
- NULL, NULL);
-
-
- GCX_COOP();
-
- ExInfo* pExInfo = (ExInfo*)pExState->GetCurrentExceptionTracker();
- _ASSERTE(pExInfo != NULL);
-
- PREPARE_NONVIRTUAL_CALLSITE(METHOD__EH__UNWIND_AND_INTERCEPT);
- DECLARE_ARGHOLDER_ARRAY(args, 2);
- args[ARGNUM_0] = PTR_TO_ARGHOLDER(pExInfo);
- args[ARGNUM_1] = PTR_TO_ARGHOLDER(uInterceptStackFrame);
- pThread->IncPreventAbort();
-
- //Ex.RhUnwindAndIntercept(throwable, &exInfo)
- CRITICAL_CALLSITE;
- CALL_MANAGED_METHOD_NORET(args)
-
- UNREACHABLE();
-}
-#endif // DEBUGGER_EXCEPTION_INTERCEPTION_SUPPORTED
-#endif // DEBUGGING_SUPPORTED
-
#ifdef _DEBUG
//
// static
@@ -1512,6 +1456,8 @@ BOOL HandleHardwareException(PAL_SEHException* ex)
//Ex.RhThrowHwEx(exceptionCode, &exInfo)
CALL_MANAGED_METHOD_NORET(args)
+ DispatchExSecondPass(&exInfo);
+
GCPROTECT_END();
UNREACHABLE();
@@ -1653,6 +1599,8 @@ VOID DECLSPEC_NORETURN DispatchManagedException(OBJECTREF throwable, CONTEXT* pE
CRITICAL_CALLSITE;
CALL_MANAGED_METHOD_NORET(args)
+ DispatchExSecondPass(&exInfo);
+
GCPROTECT_END();
GCPROTECT_END();
@@ -1707,6 +1655,8 @@ VOID DECLSPEC_NORETURN DispatchRethrownManagedException(CONTEXT* pExceptionConte
//Ex.RhRethrow(ref ExInfo activeExInfo, ref ExInfo exInfo)
CALL_MANAGED_METHOD_NORET(args)
+ DispatchExSecondPass(&exInfo);
+
GCPROTECT_END();
UNREACHABLE();
@@ -2969,14 +2919,6 @@ void ExInfo::EnumMemoryRegions(CLRDataEnumMemoryFlags flags)
#endif // DACCESS_COMPILE
#ifndef DACCESS_COMPILE
-// Mark the pinvoke frame as invoking CallCatchFunclet (and similar) for collided unwind detection
-void MarkInlinedCallFrameAsFuncletCall(Frame* pFrame)
-{
- _ASSERTE(pFrame->GetFrameIdentifier() == FrameIdentifier::InlinedCallFrame);
- InlinedCallFrame* pInlinedCallFrame = (InlinedCallFrame*)pFrame;
- pInlinedCallFrame->m_Datum = (PTR_PInvokeMethodDesc)((TADDR)pInlinedCallFrame->m_Datum | (TADDR)InlinedCallFrameMarker::ExceptionHandlingHelper | (TADDR)InlinedCallFrameMarker::SecondPassFuncletCaller);
-}
-
// Mark the pinvoke frame as invoking any exception handling helper
void MarkInlinedCallFrameAsEHHelperCall(Frame* pFrame)
{
@@ -3120,18 +3062,19 @@ PropagateForeignExceptionThroughNativeFrames(IN PEXCEPTION_RECORD pExcepti
#endif // HOST_WINDOWS
-extern "C" void * QCALLTYPE CallCatchFunclet(QCall::ObjectHandleOnStack exceptionObj, BYTE* pHandlerIP, REGDISPLAY* pvRegDisplay, ExInfo* exInfo)
+void CallCatchFunclet(OBJECTREF throwable, BYTE* pHandlerIP, REGDISPLAY* pvRegDisplay, ExInfo* exInfo)
{
- QCALL_CONTRACT;
-
- BEGIN_QCALL;
- GCX_COOP_NO_DTOR();
-
+ CONTRACTL
+ {
+ MODE_COOPERATIVE;
+ GC_TRIGGERS;
+ THROWS;
+ }
+ CONTRACTL_END;
+
Thread* pThread = GET_THREAD();
pThread->DecPreventAbort();
- Frame* pFrame = pThread->GetFrame();
- MarkInlinedCallFrameAsFuncletCall(pFrame);
exInfo->m_ScannedStackRange.ExtendUpperBound(exInfo->m_frameIter.m_crawl.GetRegisterSet()->SP);
DWORD_PTR dwResumePC = 0;
UINT_PTR callerTargetSp = 0;
@@ -3157,7 +3100,6 @@ extern "C" void * QCALLTYPE CallCatchFunclet(QCall::ObjectHandleOnStack exceptio
pCodeManager->EnsureCallerContextIsValid(pvRegDisplay);
_ASSERTE(exInfo->m_sfCallerOfActualHandlerFrame == GetSP(pvRegDisplay->pCallerContext));
#endif
- OBJECTREF throwable = exceptionObj.Get();
throwable = PossiblyUnwrapThrowable(throwable, exInfo->m_frameIter.m_crawl.GetAssembly());
exInfo->m_csfEnclosingClause = CallerStackFrame::FromRegDisplay(exInfo->m_frameIter.m_crawl.GetRegisterSet());
@@ -3303,22 +3245,17 @@ extern "C" void * QCALLTYPE CallCatchFunclet(QCall::ObjectHandleOnStack exceptio
#endif
{
STRESS_LOG2(LF_EH, LL_INFO100, "Resuming propagation of managed exception through native frames at IP=%p, SP=%p\n", GetIP(pvRegDisplay->pCurrentContext), GetSP(pvRegDisplay->pCurrentContext));
- ExecuteFunctionBelowContext((PCODE)PropagateExceptionThroughNativeFrames, pvRegDisplay->pCurrentContext, targetSSP, (size_t)OBJECTREFToObject(exceptionObj.Get()));
+ ExecuteFunctionBelowContext((PCODE)PropagateExceptionThroughNativeFrames, pvRegDisplay->pCurrentContext, targetSSP, (size_t)OBJECTREFToObject(throwable));
}
#undef FIRST_ARG_REG
}
- END_QCALL;
- return NULL;
}
-extern "C" void QCALLTYPE ResumeAtInterceptionLocation(REGDISPLAY* pvRegDisplay)
+void ResumeAtInterceptionLocation(REGDISPLAY* pvRegDisplay)
{
Thread* pThread = GET_THREAD();
pThread->DecPreventAbort();
- Frame* pFrame = pThread->GetFrame();
- MarkInlinedCallFrameAsFuncletCall(pFrame);
-
UINT_PTR targetSp = GetSP(pvRegDisplay->pCurrentContext);
ExInfo *pExInfo = (PTR_ExInfo)pThread->GetExceptionState()->GetCurrentExceptionTracker();
@@ -3363,19 +3300,16 @@ extern "C" void QCALLTYPE ResumeAtInterceptionLocation(REGDISPLAY* pvRegDisplay)
ClrRestoreNonvolatileContext(pvRegDisplay->pCurrentContext, targetSSP);
}
-extern "C" void QCALLTYPE CallFinallyFunclet(BYTE* pHandlerIP, REGDISPLAY* pvRegDisplay, ExInfo* exInfo)
+void CallFinallyFunclet(BYTE* pHandlerIP, REGDISPLAY* pvRegDisplay, ExInfo* exInfo)
{
- QCALL_CONTRACT;
+ STATIC_CONTRACT_THROWS;
+ STATIC_CONTRACT_GC_TRIGGERS;
+ STATIC_CONTRACT_MODE_COOPERATIVE;
- BEGIN_QCALL;
- GCX_COOP();
Thread* pThread = GET_THREAD();
pThread->DecPreventAbort();
- Frame* pFrame = pThread->GetFrame();
- MarkInlinedCallFrameAsFuncletCall(pFrame);
exInfo->m_csfEnclosingClause = CallerStackFrame::FromRegDisplay(exInfo->m_frameIter.m_crawl.GetRegisterSet());
- exInfo->m_ScannedStackRange.ExtendUpperBound(exInfo->m_frameIter.m_crawl.GetRegisterSet()->SP);
MethodDesc *pMD = exInfo->m_frameIter.m_crawl.GetFunction();
// Profiler, debugger and ETW events
@@ -3383,13 +3317,14 @@ extern "C" void QCALLTYPE CallFinallyFunclet(BYTE* pHandlerIP, REGDISPLAY* pvReg
exInfo->MakeCallbacksRelatedToHandler(true, pThread, pMD, &exInfo->m_CurrentClause, (DWORD_PTR)pHandlerIP, spForDebugger);
EH_LOG((LL_INFO100, "Calling finally funclet at %p\n", pHandlerIP));
+ ENDFORBIDGC();
exInfo->m_frameIter.m_crawl.GetCodeManager()->CallFunclet(NULL, pHandlerIP, pvRegDisplay, exInfo, false /* isFilterFunclet */);
+ BEGINFORBIDGC();
pThread->IncPreventAbort();
// Profiler, debugger and ETW events
exInfo->MakeCallbacksRelatedToHandler(false, pThread, pMD, &exInfo->m_CurrentClause, (DWORD_PTR)pHandlerIP, spForDebugger);
- END_QCALL;
}
extern "C" CLR_BOOL QCALLTYPE CallFilterFunclet(QCall::ObjectHandleOnStack exceptionObj, BYTE* pFilterIP, REGDISPLAY* pvRegDisplay)
@@ -3465,16 +3400,12 @@ extern "C" CLR_BOOL QCALLTYPE EHEnumInitFromStackFrameIterator(StackFrameIterato
return TRUE;
}
-extern "C" CLR_BOOL QCALLTYPE EHEnumNext(EH_CLAUSE_ENUMERATOR* pEHEnum, RhEHClause* pEHClause)
+// The doNotCalculateCatchType option makes the function skip calculation of the catch type. It is used in
+// the 2nd pass of EH to avoid possible GC stemming from a call to ResolveEHClause.
+CLR_BOOL EHEnumNextWorker(EH_CLAUSE_ENUMERATOR* pEHEnum, RhEHClause* pEHClause, bool doNotCalculateCatchType = false)
{
- QCALL_CONTRACT;
CLR_BOOL result = FALSE;
- BEGIN_QCALL;
- Thread* pThread = GET_THREAD();
- Frame* pFrame = pThread->GetFrame();
- MarkInlinedCallFrameAsEHHelperCall(pFrame);
-
ExtendedEHClauseEnumerator *pExtendedEHEnum = (ExtendedEHClauseEnumerator*)pEHEnum;
StackFrameIterator *pFrameIter = pExtendedEHEnum->pFrameIter;
@@ -3513,9 +3444,17 @@ extern "C" CLR_BOOL QCALLTYPE EHEnumNext(EH_CLAUSE_ENUMERATOR* pEHEnum, RhEHClau
if (flags == COR_ILEXCEPTION_CLAUSE_NONE)
{
pEHClause->_clauseKind = RH_EH_CLAUSE_TYPED;
- pEHClause->_pTargetType = pJitMan->ResolveEHClause(&EHClause, &pFrameIter->m_crawl).AsMethodTable();
- EH_LOG((LL_INFO100, " typed clause, target type=%p (%s)\n",
- pEHClause->_pTargetType, ((MethodTable*)pEHClause->_pTargetType)->GetDebugClassName()));
+ if (!doNotCalculateCatchType)
+ {
+ pEHClause->_pTargetType = pJitMan->ResolveEHClause(&EHClause, &pFrameIter->m_crawl).AsMethodTable();
+ EH_LOG((LL_INFO100, " typed clause, target type=%p (%s)\n",
+ pEHClause->_pTargetType, ((MethodTable*)pEHClause->_pTargetType)->GetDebugClassName()));
+ }
+ else
+ {
+ pEHClause->_pTargetType = NULL;
+ EH_LOG((LL_INFO100, " typed clause, target type not calculated\n"));
+ }
}
else if (flags & COR_ILEXCEPTION_CLAUSE_FILTER)
{
@@ -3529,8 +3468,8 @@ extern "C" CLR_BOOL QCALLTYPE EHEnumNext(EH_CLAUSE_ENUMERATOR* pEHEnum, RhEHClau
}
else if (flags & COR_ILEXCEPTION_CLAUSE_FAULT)
{
- EH_LOG((LL_INFO100, " fault clause\n"));
pEHClause->_clauseKind = RH_EH_CLAUSE_FAULT;
+ EH_LOG((LL_INFO100, " fault clause\n"));
}
else
{
@@ -3551,6 +3490,23 @@ extern "C" CLR_BOOL QCALLTYPE EHEnumNext(EH_CLAUSE_ENUMERATOR* pEHEnum, RhEHClau
}
#endif // HOST_WINDOWS
}
+
+ return result;
+}
+
+extern "C" CLR_BOOL QCALLTYPE EHEnumNext(EH_CLAUSE_ENUMERATOR* pEHEnum, RhEHClause* pEHClause)
+{
+ QCALL_CONTRACT;
+
+ CLR_BOOL result = FALSE;
+
+ BEGIN_QCALL;
+
+ Thread* pThread = GET_THREAD();
+ Frame* pFrame = pThread->GetFrame();
+ MarkInlinedCallFrameAsEHHelperCall(pFrame);
+
+ result = EHEnumNextWorker(pEHEnum, pEHClause);
END_QCALL;
return result;
@@ -3738,24 +3694,26 @@ static void NotifyFunctionEnter(StackFrameIterator *pThis, Thread *pThread, ExIn
END_PROFILER_CALLBACK();
}
-extern "C" CLR_BOOL QCALLTYPE SfiInit(StackFrameIterator* pThis, CONTEXT* pStackwalkCtx, CLR_BOOL instructionFault, CLR_BOOL* pfIsExceptionIntercepted)
+CLR_BOOL SfiInitWorker(StackFrameIterator* pThis, CONTEXT* pStackwalkCtx, CLR_BOOL instructionFault, CLR_BOOL* pfIsExceptionIntercepted)
{
- QCALL_CONTRACT;
+ CONTRACTL
+ {
+ MODE_COOPERATIVE;
+ THROWS;
+ GC_TRIGGERS;
+ }
+ CONTRACTL_END;
CLR_BOOL result = FALSE;
Thread* pThread = GET_THREAD();
ExInfo* pExInfo = (ExInfo*)pThread->GetExceptionState()->GetCurrentExceptionTracker();
+ Frame* pFrame = pThread->GetFrame();
if (pExInfo->m_passNumber == 1)
{
pThread->ResetThreadStateNC(Thread::TSNC_SkipManagedPersonalityRoutine);
}
- BEGIN_QCALL;
-
- Frame* pFrame = pThread->GetFrame();
- MarkInlinedCallFrameAsEHHelperCall(pFrame);
-
// we already fixed the context in HijackHandler, so let's
// just clear the thread state.
pThread->ResetThrowControlForThread();
@@ -3833,8 +3791,6 @@ extern "C" CLR_BOOL QCALLTYPE SfiInit(StackFrameIterator* pThis, CONTEXT* pStack
_ASSERTE(!result || pThis->GetFrameState() == StackFrameIterator::SFITER_FRAMELESS_METHOD);
- END_QCALL;
-
if (result)
{
TADDR controlPC = pThis->m_crawl.GetRegisterSet()->ControlPC;
@@ -3878,6 +3834,24 @@ extern "C" CLR_BOOL QCALLTYPE SfiInit(StackFrameIterator* pThis, CONTEXT* pStack
return result;
}
+extern "C" CLR_BOOL QCALLTYPE SfiInit(StackFrameIterator* pThis, CONTEXT* pStackwalkCtx, CLR_BOOL instructionFault, CLR_BOOL* pfIsExceptionIntercepted)
+{
+ QCALL_CONTRACT;
+
+ CLR_BOOL result = FALSE;
+ BEGIN_QCALL;
+
+ Thread* pThread = GET_THREAD();
+ Frame* pFrame = pThread->GetFrame();
+ MarkInlinedCallFrameAsEHHelperCall(pFrame);
+
+ GCX_COOP();
+ result = SfiInitWorker(pThis, pStackwalkCtx, instructionFault, pfIsExceptionIntercepted);
+ END_QCALL;
+
+ return result;
+}
+
static StackWalkAction MoveToNextNonSkippedFrame(StackFrameIterator* pStackFrameIterator)
{
StackWalkAction retVal;
@@ -3895,19 +3869,22 @@ static StackWalkAction MoveToNextNonSkippedFrame(StackFrameIterator* pStackFrame
return retVal;
}
-extern "C" CLR_BOOL QCALLTYPE SfiNext(StackFrameIterator* pThis, uint* uExCollideClauseIdx, CLR_BOOL* fUnwoundReversePInvoke, CLR_BOOL* pfIsExceptionIntercepted)
+CLR_BOOL SfiNextWorker(StackFrameIterator* pThis, uint* uExCollideClauseIdx, CLR_BOOL* fUnwoundReversePInvoke, CLR_BOOL* pfIsExceptionIntercepted)
{
- QCALL_CONTRACT;
+ CONTRACTL
+ {
+ MODE_COOPERATIVE;
+ THROWS;
+ GC_TRIGGERS;
+ }
+ CONTRACTL_END;
StackWalkAction retVal = SWA_FAILED;
CLR_BOOL isPropagatingToNativeCode = FALSE;
Thread* pThread = GET_THREAD();
ExInfo* pTopExInfo = (ExInfo*)pThread->GetExceptionState()->GetCurrentExceptionTracker();
- BEGIN_QCALL;
-
Frame* pFrame = pThread->GetFrame();
- MarkInlinedCallFrameAsEHHelperCall(pFrame);
// we already fixed the context in HijackHandler, so let's
// just clear the thread state.
@@ -4028,6 +4005,7 @@ extern "C" CLR_BOOL QCALLTYPE SfiNext(StackFrameIterator* pThis, uint* uExCollid
{
#ifdef HOST_WINDOWS
GetThread()->SetThreadStateNC(Thread::TSNC_SkipManagedPersonalityRoutine);
+ GCX_PREEMP_NO_DTOR();
RaiseException(pTopExInfo->m_ExceptionCode, EXCEPTION_NONCONTINUABLE, pTopExInfo->m_ptrs.ExceptionRecord->NumberParameters, pTopExInfo->m_ptrs.ExceptionRecord->ExceptionInformation);
#else
CrashDumpAndTerminateProcess(pTopExInfo->m_ExceptionCode);
@@ -4053,74 +4031,53 @@ extern "C" CLR_BOOL QCALLTYPE SfiNext(StackFrameIterator* pThis, uint* uExCollid
goto Exit;
}
- if (!pThis->m_crawl.IsFrameless())
+ if (doingFuncletUnwind && pThis->GetNextExInfo() != NULL && GetRegdisplaySP(pThis->m_crawl.GetRegisterSet()) > (TADDR)pTopExInfo)
{
- // Detect collided unwind
- pFrame = pThis->m_crawl.GetFrame();
-
- if (InlinedCallFrame::FrameHasActiveCall(pFrame))
+ // Detected collided unwind
+ if ((pThis->GetNextExInfo()->m_passNumber == 1) ||
+ (pThis->GetNextExInfo()->m_idxCurClause == 0xFFFFFFFF))
{
- InlinedCallFrame* pInlinedCallFrame = (InlinedCallFrame*)pFrame;
- if (((TADDR)pInlinedCallFrame->m_Datum & (TADDR)InlinedCallFrameMarker::Mask) == ((TADDR)InlinedCallFrameMarker::ExceptionHandlingHelper | (TADDR)InlinedCallFrameMarker::SecondPassFuncletCaller))
- {
- // passing through CallCatchFunclet et al
- if (doingFuncletUnwind)
- {
- // Unwind the CallCatchFunclet
- retVal = MoveToNextNonSkippedFrame(pThis);
-
- if (retVal == SWA_FAILED)
- {
- _ASSERTE_MSG(FALSE, "StackFrameIterator::Next failed");
- break;
- }
-
- if ((pThis->GetNextExInfo()->m_passNumber == 1) ||
- (pThis->GetNextExInfo()->m_idxCurClause == 0xFFFFFFFF))
- {
- _ASSERTE_MSG(FALSE, "did not expect to collide with a 1st-pass ExInfo during a EH stackwalk");
- EEPOLICY_HANDLE_FATAL_ERROR(COR_E_EXECUTIONENGINE);
- }
- else
- {
- *uExCollideClauseIdx = pExInfo->m_idxCurClause;
- isCollided = true;
- pExInfo->m_kind = (ExKind)((uint8_t)pExInfo->m_kind | (uint8_t)ExKind::SupersededFlag);
-
- // Unwind to the frame of the prevExInfo
- ExInfo* pPrevExInfo = pThis->GetNextExInfo();
- EH_LOG((LL_INFO100, "SfiNext: collided with previous exception handling, skipping from IP=%p, SP=%p to IP=%p, SP=%p\n",
- GetControlPC(&pTopExInfo->m_regDisplay), GetRegdisplaySP(&pTopExInfo->m_regDisplay),
- GetControlPC(&pPrevExInfo->m_regDisplay), GetRegdisplaySP(&pPrevExInfo->m_regDisplay)));
-
- pThis->SkipTo(&pPrevExInfo->m_frameIter);
- pThis->ResetNextExInfoForSP(pThis->m_crawl.GetRegisterSet()->SP);
- _ASSERTE_MSG(pThis->GetFrameState() == StackFrameIterator::SFITER_FRAMELESS_METHOD, "Collided unwind should have reached a frameless method");
- break;
- }
- }
- }
+ _ASSERTE_MSG(FALSE, "did not expect to collide with a 1st-pass ExInfo during a EH stackwalk");
+ EEPOLICY_HANDLE_FATAL_ERROR(COR_E_EXECUTIONENGINE);
}
else
{
- if (pTopExInfo->m_passNumber == 1)
+ *uExCollideClauseIdx = pExInfo->m_idxCurClause;
+ isCollided = true;
+ pExInfo->m_kind = (ExKind)((uint8_t)pExInfo->m_kind | (uint8_t)ExKind::SupersededFlag);
+
+ // Unwind to the frame of the prevExInfo
+ ExInfo* pPrevExInfo = pThis->GetNextExInfo();
+ EH_LOG((LL_INFO100, "SfiNext: collided with previous exception handling, skipping from IP=%p, SP=%p to IP=%p, SP=%p\n",
+ GetControlPC(&pTopExInfo->m_regDisplay), GetRegdisplaySP(&pTopExInfo->m_regDisplay),
+ GetControlPC(&pPrevExInfo->m_regDisplay), GetRegdisplaySP(&pPrevExInfo->m_regDisplay)));
+
+ pThis->SkipTo(&pPrevExInfo->m_frameIter);
+ pThis->ResetNextExInfoForSP(pThis->m_crawl.GetRegisterSet()->SP);
+ _ASSERTE_MSG(pThis->GetFrameState() == StackFrameIterator::SFITER_FRAMELESS_METHOD, "Collided unwind should have reached a frameless method");
+ break;
+ }
+ }
+
+ if (!pThis->m_crawl.IsFrameless())
+ {
+ if (pTopExInfo->m_passNumber == 1)
+ {
+ MethodDesc *pMD = pFrame->GetFunction();
+ if (pMD != NULL)
{
- MethodDesc *pMD = pFrame->GetFunction();
- if (pMD != NULL)
- {
- GCX_COOP();
- StackTraceInfo::AppendElement(pTopExInfo->m_hThrowable, 0, GetRegdisplaySP(pTopExInfo->m_frameIter.m_crawl.GetRegisterSet()), pMD, &pTopExInfo->m_frameIter.m_crawl);
+ GCX_COOP();
+ StackTraceInfo::AppendElement(pTopExInfo->m_hThrowable, 0, GetRegdisplaySP(pTopExInfo->m_frameIter.m_crawl.GetRegisterSet()), pMD, &pTopExInfo->m_frameIter.m_crawl);
#if defined(DEBUGGING_SUPPORTED)
- if (NotifyDebuggerOfStub(pThread, pFrame))
+ if (NotifyDebuggerOfStub(pThread, pFrame))
+ {
+ if (!pTopExInfo->DeliveredFirstChanceNotification())
{
- if (!pTopExInfo->DeliveredFirstChanceNotification())
- {
- ExceptionNotifications::DeliverFirstChanceNotification();
- }
+ ExceptionNotifications::DeliverFirstChanceNotification();
}
-#endif // DEBUGGING_SUPPORTED
}
+#endif // DEBUGGING_SUPPORTED
}
}
@@ -4143,7 +4100,6 @@ extern "C" CLR_BOOL QCALLTYPE SfiNext(StackFrameIterator* pThis, uint* uExCollid
}
Exit:;
- END_QCALL;
if (retVal != SWA_FAILED)
{
@@ -4173,6 +4129,300 @@ Exit:;
return FALSE;
}
+extern "C" CLR_BOOL QCALLTYPE SfiNext(StackFrameIterator* pThis, uint* uExCollideClauseIdx, CLR_BOOL* fUnwoundReversePInvoke, CLR_BOOL* pfIsExceptionIntercepted)
+{
+ QCALL_CONTRACT;
+
+ CLR_BOOL result = FALSE;
+
+ BEGIN_QCALL;
+
+ Thread* pThread = GET_THREAD();
+ Frame* pFrame = pThread->GetFrame();
+ MarkInlinedCallFrameAsEHHelperCall(pFrame);
+
+ GCX_COOP();
+ result = SfiNextWorker(pThis, uExCollideClauseIdx, fUnwoundReversePInvoke, pfIsExceptionIntercepted);
+
+ END_QCALL;
+
+ return result;
+}
+
+static uint32_t CalculateCodeOffset(PCODE pbControlPC, IJitManager::MethodRegionInfo *pMethodRegionInfo)
+{
+ STATIC_CONTRACT_LEAF;
+
+ uint codeOffset = (uint)(pbControlPC - pMethodRegionInfo->hotStartAddress);
+ // If the PC is in the cold region, adjust the offset to be relative to the start of the method.
+ if ((pMethodRegionInfo->coldSize != 0) && (codeOffset >= pMethodRegionInfo->hotSize))
+ {
+ codeOffset = (uint32_t)(pMethodRegionInfo->hotSize + (size_t)(pbControlPC - pMethodRegionInfo->coldStartAddress));
+ }
+
+ return codeOffset;
+}
+
+const uint32_t MaxTryRegionIdx = 0xFFFFFFFFu;
+
+// This function is a copy of the code in ExceptionHandling.cs converted to native code.
+// The only difference is the ehClause._isSameTry check that is coreclr specific.
+static void InvokeSecondPass(ExInfo *pExInfo, uint idxStart, uint idxLimit)
+{
+ CONTRACTL
+ {
+ MODE_COOPERATIVE;
+ GC_TRIGGERS;
+ }
+ CONTRACTL_END;
+
+ ExtendedEHClauseEnumerator ehEnum;
+ IJitManager::MethodRegionInfo methodRegionInfo;
+
+ // We need to forbid any GC to happen between successive funclet invocations.
+ BEGINFORBIDGC();
+
+ pExInfo->m_ScannedStackRange.ExtendUpperBound(pExInfo->m_frameIter.m_crawl.GetRegisterSet()->SP);
+
+ if (!EHEnumInitFromStackFrameIterator(&pExInfo->m_frameIter, &methodRegionInfo, &ehEnum))
+ {
+ ENDFORBIDGC();
+ return;
+ }
+
+ PCODE pbControlPC = pExInfo->m_frameIter.GetAdjustedControlPC();
+
+ uint codeOffset = CalculateCodeOffset(pbControlPC, &methodRegionInfo);
+
+ uint lastTryStart = 0, lastTryEnd = 0;
+
+ // Search the clauses for one that contains the current offset.
+ RhEHClause ehClause;
+ for (uint curIdx = 0; EHEnumNextWorker(&ehEnum, &ehClause, /* doNotCalculateCatchType */ true) && curIdx < idxLimit; curIdx++)
+ {
+ //
+ // Skip to the starting try region. This is used by collided unwinds and rethrows to pickup where
+ // the previous dispatch left off.
+ //
+ if (idxStart != MaxTryRegionIdx)
+ {
+ if (curIdx <= idxStart)
+ {
+ lastTryStart = ehClause._tryStartOffset; lastTryEnd = ehClause._tryEndOffset;
+ continue;
+ }
+
+ // Now, we continue skipping while the try region is identical to the one that invoked the
+ // previous dispatch.
+ if ((ehClause._tryStartOffset == lastTryStart) && (ehClause._tryEndOffset == lastTryEnd)
+ && (ehClause._isSameTry)
+ )
+ continue;
+
+ // We are done skipping. This is required to handle empty finally block markers that are used
+ // to separate runs of different try blocks with same native code offsets.
+ idxStart = MaxTryRegionIdx;
+ }
+
+ RhEHClauseKind clauseKind = ehClause._clauseKind;
+
+ if ((clauseKind != RH_EH_CLAUSE_FAULT) || !ehClause.ContainsCodeOffset(codeOffset))
+ {
+ continue;
+ }
+
+ // Found a containing clause. Because of the order of the clauses, we know this is the
+ // most containing.
+
+ byte* pFinallyHandler = ehClause._handlerAddress;
+ pExInfo->m_idxCurClause = curIdx;
+ CallFinallyFunclet(pFinallyHandler, pExInfo->m_frameIter.m_crawl.GetRegisterSet(), pExInfo);
+ pExInfo->m_idxCurClause = MaxTryRegionIdx;
+ }
+
+ ENDFORBIDGC();
+}
+
+static void InvokeSecondPass(ExInfo *pExInfo, uint idxStart)
+{
+ CONTRACTL
+ {
+ MODE_COOPERATIVE;
+ GC_TRIGGERS;
+ }
+ CONTRACTL_END;
+
+ InvokeSecondPass(pExInfo, idxStart, MaxTryRegionIdx);
+}
+
+void DECLSPEC_NORETURN DispatchExSecondPass(ExInfo *pExInfo)
+{
+ CONTRACTL
+ {
+ MODE_COOPERATIVE;
+ GC_TRIGGERS;
+ }
+ CONTRACTL_END;
+
+ TADDR handlingFrameSP = pExInfo->m_handlingFrameSP;
+#ifdef TARGET_ARM64
+ PCODE handlingFramePC = pExInfo->m_handlingFramePC;
+#endif
+ PCODE pCatchHandler = pExInfo->m_pCatchHandler;
+
+ StackFrameIterator *pFrameIter = &pExInfo->m_frameIter;
+ pExInfo->m_passNumber = 2;
+ uint startIdx = MaxTryRegionIdx;
+ uint catchingTryRegionIdx = pExInfo->m_idxCurClause;
+ CLR_BOOL unwoundReversePInvoke = false;
+ CLR_BOOL isExceptionIntercepted = false;
+ CLR_BOOL isValid = SfiInitWorker(pFrameIter, pExInfo->m_pExContext, ((uint8_t)pExInfo->m_kind & (uint8_t)ExKind::InstructionFaultFlag) != 0, &isExceptionIntercepted);
+ for (; isValid && (GetRegdisplaySP(pFrameIter->m_crawl.GetRegisterSet()) <= handlingFrameSP); isValid = SfiNextWorker(pFrameIter, &startIdx, &unwoundReversePInvoke, &isExceptionIntercepted))
+ {
+ _ASSERTE_MSG(isValid, "second-pass EH unwind failed unexpectedly");
+ _ASSERTE_MSG(GetControlPC(pFrameIter->m_crawl.GetRegisterSet()) != 0, "IP address must not be null");
+
+ if (isExceptionIntercepted)
+ {
+ pCatchHandler = 0;
+ break;
+ }
+
+ if (unwoundReversePInvoke)
+ {
+ _ASSERTE_MSG(GetRegdisplaySP(pFrameIter->m_crawl.GetRegisterSet()) == handlingFrameSP, "Encountered a different reverse P/Invoke frame in the second pass.");
+ // Found the native frame that called the reverse P/invoke.
+ // It is not possible to run managed second pass handlers on a native frame.
+ break;
+ }
+
+ if ((GetRegdisplaySP(pFrameIter->m_crawl.GetRegisterSet()) == handlingFrameSP)
+#if TARGET_ARM64
+ && (GetControlPC(pFrameIter->m_crawl.GetRegisterSet()) == handlingFramePC)
+#endif
+ )
+ {
+ // invoke only a partial second-pass here...
+ InvokeSecondPass(pExInfo, startIdx, catchingTryRegionIdx);
+ break;
+ }
+
+ InvokeSecondPass(pExInfo, startIdx);
+ }
+
+ // ------------------------------------------------
+ //
+ // Call the handler and resume execution
+ //
+ // ------------------------------------------------
+ pExInfo->m_idxCurClause = catchingTryRegionIdx;
+
+ CallCatchFunclet(pExInfo->m_exception, (BYTE *)pCatchHandler, pFrameIter->m_crawl.GetRegisterSet(), pExInfo);
+ // CallCatchFunclet will resume after the catch and never return here.
+ UNREACHABLE();
+}
+
+//
+// This function continues exception interception unwind after it crossed native frames using
+// standard EH / SEH.
+//
+VOID DECLSPEC_NORETURN ContinueExceptionInterceptionUnwind()
+{
+ STATIC_CONTRACT_THROWS;
+ STATIC_CONTRACT_GC_TRIGGERS;
+ STATIC_CONTRACT_MODE_ANY;
+
+ Thread* pThread = GetThread();
+ ThreadExceptionState* pExState = pThread->GetExceptionState();
+
+ UINT_PTR uInterceptStackFrame = 0;
+
+ pExState->GetDebuggerState()->GetDebuggerInterceptInfo(NULL, NULL,
+ (PBYTE*)&uInterceptStackFrame,
+ NULL, NULL);
+
+
+ GCX_COOP();
+
+ ExInfo* pExInfo = (ExInfo*)pExState->GetCurrentExceptionTracker();
+ _ASSERTE(pExInfo != NULL);
+ StackFrameIterator *pFrameIter = &pExInfo->m_frameIter;
+
+ pExInfo->m_passNumber = 2;
+ pExInfo->m_idxCurClause = MaxTryRegionIdx;
+ uint32_t startIdx = MaxTryRegionIdx;
+ CLR_BOOL unwoundReversePInvoke = false;
+ CLR_BOOL isExceptionIntercepted = false;
+ CLR_BOOL isValid = SfiInitWorker(pFrameIter, pExInfo->m_pExContext, ((uint8_t)pExInfo->m_kind & (uint8_t)ExKind::InstructionFaultFlag) != 0, &isExceptionIntercepted);
+ for (; isValid && (GetRegdisplaySP(pFrameIter->m_crawl.GetRegisterSet()) <= uInterceptStackFrame); isValid = SfiNextWorker(pFrameIter, &startIdx, &unwoundReversePInvoke, &isExceptionIntercepted))
+ {
+ _ASSERTE_MSG(isValid, "Unwind and intercept failed unexpectedly");
+ _ASSERTE_MSG(GetControlPC(pFrameIter->m_crawl.GetRegisterSet()) != 0, "IP address must not be null");
+
+ if (unwoundReversePInvoke)
+ {
+ // Found the native frame that called the reverse P/invoke.
+ // It is not possible to run managed second pass handlers on a native frame.
+ break;
+ }
+
+ if (GetRegdisplaySP(pFrameIter->m_crawl.GetRegisterSet()) == uInterceptStackFrame)
+ {
+ break;
+ }
+
+ InvokeSecondPass(pExInfo, startIdx);
+ if (isExceptionIntercepted)
+ {
+ _ASSERTE(FALSE);
+ break;
+ }
+ }
+
+ // ------------------------------------------------
+ //
+ // Call the interception code
+ //
+ // ------------------------------------------------
+ if (unwoundReversePInvoke)
+ {
+ CallCatchFunclet(pExInfo->m_exception, NULL, pExInfo->m_frameIter.m_crawl.GetRegisterSet(), pExInfo);
+ }
+ else
+ {
+ ResumeAtInterceptionLocation(pExInfo->m_frameIter.m_crawl.GetRegisterSet());
+ }
+
+ UNREACHABLE();
+}
+
+//---------------------------------------------------------------------------------------
+//
+// This function is called by DefaultCatchHandler() to intercept an exception and start an unwind.
+//
+// Arguments:
+// pCurrentEstablisherFrame - unused on WIN64
+// pExceptionRecord - EXCEPTION_RECORD of the exception being intercepted
+//
+// Return Value:
+// ExceptionContinueSearch if the exception cannot be intercepted
+//
+// Notes:
+// If the exception is intercepted, this function never returns.
+//
+
+EXCEPTION_DISPOSITION ClrDebuggerDoUnwindAndIntercept(X86_FIRST_ARG(EXCEPTION_REGISTRATION_RECORD* pCurrentEstablisherFrame)
+ EXCEPTION_RECORD* pExceptionRecord)
+{
+ if (!CheckThreadExceptionStateForInterception())
+ {
+ return ExceptionContinueSearch;
+ }
+
+ ContinueExceptionInterceptionUnwind();
+ UNREACHABLE();
+}
+
namespace AsmOffsetsAsserts
{
// Verify that the offsets into CONTEXT, REGDISPLAY, ExInfo and StackFrameIterator that the new managed exception handling
diff --git a/src/coreclr/vm/exceptionhandling.h b/src/coreclr/vm/exceptionhandling.h
index 0199b7d26e692a..20503d2f83db99 100644
--- a/src/coreclr/vm/exceptionhandling.h
+++ b/src/coreclr/vm/exceptionhandling.h
@@ -34,6 +34,9 @@ VOID DECLSPEC_NORETURN DispatchManagedException(RuntimeExceptionKind reKind);
VOID DECLSPEC_NORETURN DispatchRethrownManagedException();
VOID DECLSPEC_NORETURN DispatchRethrownManagedException(CONTEXT* pExceptionContext);
+struct ExInfo;
+void DECLSPEC_NORETURN DispatchExSecondPass(ExInfo *pExInfo);
+
enum CLRUnwindStatus { UnwindPending, FirstPassComplete, SecondPassComplete };
enum TrackerMemoryType
@@ -58,12 +61,10 @@ enum class InlinedCallFrameMarker
{
#ifdef HOST_64BIT
ExceptionHandlingHelper = 2,
- SecondPassFuncletCaller = 4,
#else // HOST_64BIT
ExceptionHandlingHelper = 1,
- SecondPassFuncletCaller = 2,
#endif // HOST_64BIT
- Mask = ExceptionHandlingHelper | SecondPassFuncletCaller
+ Mask = ExceptionHandlingHelper
};
#ifdef FEATURE_INTERPRETER
diff --git a/src/coreclr/vm/exceptionhandlingqcalls.h b/src/coreclr/vm/exceptionhandlingqcalls.h
index fd1feccef6cb91..c9dd9ba353250b 100644
--- a/src/coreclr/vm/exceptionhandlingqcalls.h
+++ b/src/coreclr/vm/exceptionhandlingqcalls.h
@@ -12,10 +12,7 @@ struct ExInfo;
#ifndef DACCESS_COMPILE
-extern "C" void * QCALLTYPE CallCatchFunclet(QCall::ObjectHandleOnStack exceptionObj, BYTE* pHandlerIP, REGDISPLAY* pvRegDisplay, ExInfo* exInfo);
-extern "C" void QCALLTYPE CallFinallyFunclet(BYTE* pHandlerIP, REGDISPLAY* pvRegDisplay, ExInfo* exInfo);
extern "C" CLR_BOOL QCALLTYPE CallFilterFunclet(QCall::ObjectHandleOnStack exceptionObj, BYTE* pFilterP, REGDISPLAY* pvRegDisplay);
-extern "C" void QCALLTYPE ResumeAtInterceptionLocation(REGDISPLAY* pvRegDisplay);
extern "C" void QCALLTYPE AppendExceptionStackFrame(QCall::ObjectHandleOnStack exceptionObj, SIZE_T ip, SIZE_T sp, int flags, ExInfo *pExInfo);
extern "C" CLR_BOOL QCALLTYPE EHEnumInitFromStackFrameIterator(StackFrameIterator *pFrameIter, IJitManager::MethodRegionInfo *pMethodRegionInfo, EH_CLAUSE_ENUMERATOR * pEHEnum);
extern "C" CLR_BOOL QCALLTYPE EHEnumNext(EH_CLAUSE_ENUMERATOR* pEHEnum, RhEHClause* pEHClause);
diff --git a/src/coreclr/vm/exinfo.cpp b/src/coreclr/vm/exinfo.cpp
index 41c90561aa5b06..916910fb77e187 100644
--- a/src/coreclr/vm/exinfo.cpp
+++ b/src/coreclr/vm/exinfo.cpp
@@ -324,8 +324,7 @@ ExInfo::ExInfo(Thread *pThread, EXCEPTION_RECORD *pExceptionRecord, CONTEXT *pEx
m_propagateExceptionContext(NULL),
#endif // HOST_UNIX
m_CurrentClause({}),
- m_pMDToReportFunctionLeave(NULL),
- m_lastReportedFunclet({0, 0, 0})
+ m_pMDToReportFunctionLeave(NULL)
#ifdef HOST_WINDOWS
, m_pLongJmpBuf(NULL),
m_longJmpReturnValue(0)
diff --git a/src/coreclr/vm/exinfo.h b/src/coreclr/vm/exinfo.h
index 6c17d51cd2c289..16c99a6ad70c64 100644
--- a/src/coreclr/vm/exinfo.h
+++ b/src/coreclr/vm/exinfo.h
@@ -182,6 +182,12 @@ struct RhEHClause
BYTE *_handlerAddress;
void *_pTargetType;
BOOL _isSameTry;
+
+ bool ContainsCodeOffset(unsigned codeOffset)
+ {
+ LIMITED_METHOD_CONTRACT;
+ return (codeOffset >= _tryStartOffset) && (codeOffset < _tryEndOffset);
+ }
};
enum class ExKind : uint8_t
@@ -315,6 +321,15 @@ struct ExInfo
// The exception handling clause for the catch handler that was identified during pass 1
EE_ILEXCEPTION_CLAUSE m_ClauseForCatch;
+ // Catch handler address
+ PCODE m_pCatchHandler;
+ // SP of the frame handling the exception
+ TADDR m_handlingFrameSP;
+#ifdef TARGET_ARM64
+ // PC of the frame handling the exception
+ PCODE m_handlingFramePC;
+#endif
+
#ifdef TARGET_UNIX
// Set to TRUE to take ownership of the EXCEPTION_RECORD and CONTEXT_RECORD in the m_ptrs. When set, the
// memory of those records is freed using PAL_FreeExceptionRecords when the ExInfo is destroyed.
@@ -333,8 +348,6 @@ struct ExInfo
REGDISPLAY m_regDisplay;
// Initial explicit frame for stack walking
Frame *m_pInitialFrame;
- // Info on the last reported funclet used to report references in the parent frame
- LastReportedFuncletInfo m_lastReportedFunclet;
#ifdef TARGET_WINDOWS
// Longjmp buffer used to restart longjmp after a block of managed frames when
diff --git a/src/coreclr/vm/finalizerthread.cpp b/src/coreclr/vm/finalizerthread.cpp
index 0ad3d680bcd8bc..ef5949ec055404 100644
--- a/src/coreclr/vm/finalizerthread.cpp
+++ b/src/coreclr/vm/finalizerthread.cpp
@@ -176,6 +176,26 @@ OBJECTREF FinalizerThread::GetNextFinalizableObject()
if (fQuitFinalizer)
return NULL;
+#ifdef _DEBUG
+ if (g_pConfig->GetGCStressLevel() > 1)
+ {
+ // Throttle finalizing to one item per msec, or so, when running GC stress.
+ // This is to prevent cases where finalizers rearm themselves and
+ // do allocations or whatever else that triggers GC under stress.
+ // As a result couple of such things can occupy finalizer loop continuously
+ // while rearming and finalizing the same objects, which adds little
+ // to the coverage, but makes everything else move slower.
+ // NOTE: under GC stress most allocations of finalizable objects
+ // would trigger a GC, thus 1 item/msec should not be too slow for
+ // regular not re-arming finalizables.
+ GetFinalizerThread()->m_GCOnTransitionsOK = FALSE;
+ GetFinalizerThread()->EnablePreemptiveGC();
+ ClrSleepEx(1, false);
+ GetFinalizerThread()->DisablePreemptiveGC();
+ GetFinalizerThread()->m_GCOnTransitionsOK = TRUE;
+ }
+#endif //_DEBUG
+
OBJECTREF obj = ObjectToOBJECTREF(GCHeapUtilities::GetGCHeap()->GetNextFinalizable());
if (obj == NULL)
return NULL;
@@ -432,27 +452,6 @@ VOID FinalizerThread::FinalizerThreadWorker(void *args)
GetFinalizerThread()->DisablePreemptiveGC();
-#ifdef _DEBUG
- // workaround. make finalization very lazy for gcstress 3 or 4.
- // only do finalization if the system is quiescent
- if (g_pConfig->GetGCStressLevel() > 1)
- {
- size_t last_gc_count;
- DWORD dwSwitchCount = 0;
-
- do
- {
- last_gc_count = GCHeapUtilities::GetGCHeap()->CollectionCount(0);
- GetFinalizerThread()->m_GCOnTransitionsOK = FALSE;
- GetFinalizerThread()->EnablePreemptiveGC();
- __SwitchToThread (0, ++dwSwitchCount);
- GetFinalizerThread()->DisablePreemptiveGC();
- // If no GCs happened, then we assume we are quiescent
- GetFinalizerThread()->m_GCOnTransitionsOK = TRUE;
- } while (GCHeapUtilities::GetGCHeap()->CollectionCount(0) - last_gc_count > 0);
- }
-#endif //_DEBUG
-
// we might want to do some extra work on the finalizer thread
// check and do it
if (HaveExtraWorkForFinalizer())
diff --git a/src/coreclr/vm/gcenv.ee.common.cpp b/src/coreclr/vm/gcenv.ee.common.cpp
index 0df511d2eadcbe..a1ea5fbf365f83 100644
--- a/src/coreclr/vm/gcenv.ee.common.cpp
+++ b/src/coreclr/vm/gcenv.ee.common.cpp
@@ -259,54 +259,8 @@ StackWalkAction GcStackCrawlCallBack(CrawlFrame* pCF, VOID* pData)
// We may have unwound this crawlFrame and thus, shouldn't report the invalid
// references it may contain.
fReportGCReferences = pCF->ShouldCrawlframeReportGCReferences();
-
- Thread *pThread = pCF->GetThread();
- ExInfo *pExInfo = (ExInfo *)pThread->GetExceptionState()->GetCurrentExceptionTracker();
-
- if (pCF->ShouldSaveFuncletInfo())
- {
- STRESS_LOG3(LF_GCROOTS, LL_INFO1000, "Saving info on funclet at SP: %p, PC: %p, FP: %p\n",
- GetRegdisplaySP(pCF->GetRegisterSet()), GetControlPC(pCF->GetRegisterSet()), GetFP(pCF->GetRegisterSet()->pCurrentContext));
-
- _ASSERTE(pExInfo);
- REGDISPLAY *pRD = pCF->GetRegisterSet();
- pExInfo->m_lastReportedFunclet.IP = GetControlPC(pRD);
- pExInfo->m_lastReportedFunclet.FP = GetFP(pRD->pCurrentContext);
- pExInfo->m_lastReportedFunclet.Flags = pCF->GetCodeManagerFlags();
- }
-
- if (pCF->ShouldParentToFuncletReportSavedFuncletSlots())
- {
- STRESS_LOG4(LF_GCROOTS, LL_INFO1000, "Reporting slots in funclet parent frame method at SP: %p, PC: %p using original FP: %p, PC: %p\n",
- GetRegdisplaySP(pCF->GetRegisterSet()), GetControlPC(pCF->GetRegisterSet()), pExInfo->m_lastReportedFunclet.FP, pExInfo->m_lastReportedFunclet.IP);
-
- _ASSERTE(!pCF->ShouldParentToFuncletUseUnwindTargetLocationForGCReporting());
- _ASSERTE(pExInfo);
-
- ICodeManager * pCM = pCF->GetCodeManager();
- _ASSERTE(pCM != NULL);
-
- CONTEXT context = {};
- REGDISPLAY partialRD;
- SetIP(&context, pExInfo->m_lastReportedFunclet.IP);
- SetFP(&context, pExInfo->m_lastReportedFunclet.FP);
- SetSP(&context, 0);
-
- context.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;
- FillRegDisplay(&partialRD, &context);
-
- EECodeInfo codeInfo(pExInfo->m_lastReportedFunclet.IP);
- _ASSERTE(codeInfo.IsValid());
-
- pCM->EnumGcRefs(&partialRD,
- &codeInfo,
- pExInfo->m_lastReportedFunclet.Flags | ReportFPBasedSlotsOnly,
- GcEnumObject,
- pData,
- NO_OVERRIDE_OFFSET);
- }
- else
#endif // defined(FEATURE_EH_FUNCLETS)
+
if (fReportGCReferences)
{
if (pCF->IsFrameless())
diff --git a/src/coreclr/vm/gcheaputilities.cpp b/src/coreclr/vm/gcheaputilities.cpp
index 7525be410b99a3..987e75fc22a0f6 100644
--- a/src/coreclr/vm/gcheaputilities.cpp
+++ b/src/coreclr/vm/gcheaputilities.cpp
@@ -188,8 +188,12 @@ HMODULE LoadStandaloneGc(LPCWSTR libFileName, LPCWSTR libFilePath)
return nullptr;
}
+ // The APP_CONTEXT_BASE_DIRECTORY is always set by the host. In cases
+ // where the runtime is activated as a component, the base directory
+ // will be an empty string. If the base directory is an empty string, skip it.
SString appBase;
- if (HostInformation::GetProperty("APP_CONTEXT_BASE_DIRECTORY", appBase))
+ if (HostInformation::GetProperty("APP_CONTEXT_BASE_DIRECTORY", appBase)
+ && u16_strlen(appBase.GetUnicode()) != 0)
{
PathString libPath = appBase.GetUnicode();
libPath.Append(libFileName);
diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp
index c15c2f6f81f4fe..74bab557b4416d 100644
--- a/src/coreclr/vm/jitinterface.cpp
+++ b/src/coreclr/vm/jitinterface.cpp
@@ -8613,18 +8613,18 @@ bool CEEInfo::resolveVirtualMethodHelper(CORINFO_DEVIRTUALIZATION_INFO * info)
if (pObjMT->IsArray())
{
+ if (pBaseMT->IsSharedByGenericInstantiations())
+ {
+ info->detail = CORINFO_DEVIRTUALIZATION_FAILED_CANON;
+ return false;
+ }
+
// Does the array implicitly implement this interface?
//
isArrayImplicitInterface = pBaseMT->HasInstantiation() && IsImplicitInterfaceOfSZArray(pBaseMT);
if (!isArrayImplicitInterface)
{
- if (pBaseMT->IsSharedByGenericInstantiations())
- {
- info->detail = CORINFO_DEVIRTUALIZATION_FAILED_CANON;
- return false;
- }
-
// Ensure we can cast the array to the interface type
//
if (!TypeHandle(pObjMT).CanCastTo(TypeHandle(pBaseMT)))
@@ -8650,15 +8650,12 @@ bool CEEInfo::resolveVirtualMethodHelper(CORINFO_DEVIRTUALIZATION_INFO * info)
{
_ASSERTE(pObjMT->IsArray());
- // We cannot devirtualize unless we know the exact array element type
- //
- TypeHandle elemType = pObjMT->GetArrayElementTypeHandle();
- if (elemType.IsCanonicalSubtype())
- {
- info->detail = CORINFO_DEVIRTUALIZATION_FAILED_LOOKUP;
- return false;
- }
- pDevirtMD = GetActualImplementationForArrayGenericIListOrIReadOnlyListMethod(pBaseMD, elemType);
+ // The instantiation we want is based on the interface element type, not the
+ // array element type.
+ TypeHandle resultElemType = pBaseMT->GetInstantiation()[0];
+ // We should have ruled this out above.
+ _ASSERTE(!resultElemType.IsCanonicalSubtype());
+ pDevirtMD = GetActualImplementationForArrayGenericIListOrIReadOnlyListMethod(pBaseMD, resultElemType);
}
else if (pObjMT->IsSharedByGenericInstantiations() || pBaseMT->IsSharedByGenericInstantiations())
{
@@ -12734,7 +12731,7 @@ void CEECodeGenInfo::setEHinfoWorker(
LOG((LF_EH, LL_INFO1000000, " FilterOffset : 0x%08lx -> 0x%08lx\n", clause->FilterOffset, pEHClause->FilterOffset));
if (IsDynamicScope(m_MethodInfo.scope) &&
- ((pEHClause->Flags & COR_ILEXCEPTION_CLAUSE_FILTER) == 0) &&
+ ((pEHClause->Flags & (COR_ILEXCEPTION_CLAUSE_FILTER | COR_ILEXCEPTION_CLAUSE_FINALLY | COR_ILEXCEPTION_CLAUSE_FAULT)) == 0) &&
(clause->ClassToken != mdTokenNil))
{
ResolvedToken resolved{};
diff --git a/src/coreclr/vm/loaderallocator.cpp b/src/coreclr/vm/loaderallocator.cpp
index 58740770b2b644..4e94ddc8680327 100644
--- a/src/coreclr/vm/loaderallocator.cpp
+++ b/src/coreclr/vm/loaderallocator.cpp
@@ -13,6 +13,8 @@
#endif
#include "comcallablewrapper.h"
+//#define ENABLE_LOG_LOADER_ALLOCATOR_CLEANUP 1
+
#define STUBMANAGER_RANGELIST(stubManager) (stubManager::g_pManager->GetRangeList())
UINT64 LoaderAllocator::cLoaderAllocatorsCreated = 1;
@@ -125,6 +127,9 @@ void LoaderAllocator::AddReference()
_ASSERTE((m_cReferences > (UINT32)0) && (m_cReferences != (UINT32)-1));
InterlockedIncrement((LONG *)&m_cReferences);
+#ifdef ENABLE_LOG_LOADER_ALLOCATOR_CLEANUP
+ minipal_log_print_info("LoaderAllocator::AddReference LA %d(%p) %d\n", m_nLoaderAllocator, this, (int)m_cReferences.Load());
+#endif
}
#endif //!DACCESS_COMPILE
@@ -162,6 +167,9 @@ BOOL LoaderAllocator::AddReferenceIfAlive()
if (cOriginalReferences == cReferencesLocalSnapshot)
{ // The exchange happened
+#ifdef ENABLE_LOG_LOADER_ALLOCATOR_CLEANUP
+ minipal_log_print_info("LoaderAllocator::AddReferenceIfAlive LA %d(%p) %d\n", this->m_nLoaderAllocator, this, (int)m_cReferences.Load());
+#endif
return TRUE;
}
// Let's spin till we are the only thread to modify this value
@@ -191,6 +199,9 @@ BOOL LoaderAllocator::Release()
_ASSERTE((m_cReferences > (UINT32)0) && (m_cReferences != (UINT32)-1));
LONG cNewReferences = InterlockedDecrement((LONG *)&m_cReferences);
+#ifdef ENABLE_LOG_LOADER_ALLOCATOR_CLEANUP
+ minipal_log_print_info("LoaderAllocator::Release LA %d(%p) %d\n", this->m_nLoaderAllocator, this, (int)m_cReferences.Load());
+#endif
return (cNewReferences == 0);
#else //DACCESS_COMPILE
@@ -226,6 +237,10 @@ BOOL LoaderAllocator::CheckAddReference_Unlocked(LoaderAllocator *pOtherLA)
m_LoaderAllocatorReferences.Add(pOtherLA);
// Notify the other LoaderAllocator that a reference exists
+#ifdef ENABLE_LOG_LOADER_ALLOCATOR_CLEANUP
+ minipal_log_print_info("LoaderAllocator::CheckAddReference_Unlocked LA %d(%p) to LA %d(%p)\n", m_nLoaderAllocator, this, pOtherLA->m_nLoaderAllocator, pOtherLA, (int)pOtherLA->m_cReferences.Load());
+#endif
+
pOtherLA->AddReference();
return TRUE;
}
@@ -358,45 +373,42 @@ LoaderAllocator * LoaderAllocator::GCLoaderAllocators_RemoveAssemblies(AppDomain
// List of LoaderAllocators being deleted
LoaderAllocator * pFirstDestroyedLoaderAllocator = NULL;
-#if 0
- // Debug logic for debugging the loader allocator gc.
+ AppDomain::AssemblyIterator i;
{
+ // Iterate through every loader allocator, marking as we go
+ CrstHolder chLoaderAllocatorReferencesLock(pAppDomain->GetLoaderAllocatorReferencesLock());
+ CrstHolder chAssemblyListLock(pAppDomain->GetAssemblyListLock());
+
+ CollectibleAssemblyHolder pAssembly;
+
+#ifdef ENABLE_LOG_LOADER_ALLOCATOR_CLEANUP
+ // Debug logic for debugging the loader allocator gc.
/* Iterate through every loader allocator, and print its current state */
- AppDomain::AssemblyIterator iData;
- iData = pAppDomain->IterateAssembliesEx((AssemblyIterationFlags)(
+ i = pAppDomain->IterateAssembliesEx((AssemblyIterationFlags)(
kIncludeExecution | kIncludeLoaded | kIncludeCollected));
- CollectibleAssemblyHolder pAssembly;
- while (iData.Next_Unlocked(pAssembly.This()))
+ while (i.Next_Unlocked(pAssembly.This()))
{
if (pAssembly != NULL)
{
LoaderAllocator * pLoaderAllocator = pAssembly->GetLoaderAllocator();
if (pLoaderAllocator->IsCollectible())
{
- minipal_log_print_info("LA %p ReferencesTo %d\n", pLoaderAllocator, pLoaderAllocator->m_cReferences);
+ minipal_log_print_info("LA %d(%p) ReferencesTo %d\n", pLoaderAllocator->m_nLoaderAllocator, pLoaderAllocator, (int)pLoaderAllocator->m_cReferences.Load());
LoaderAllocatorSet::Iterator iter = pLoaderAllocator->m_LoaderAllocatorReferences.Begin();
while (iter != pLoaderAllocator->m_LoaderAllocatorReferences.End())
{
LoaderAllocator * pAllocator = *iter;
- minipal_log_print_info("LARefTo: %p\n", pAllocator);
+ minipal_log_print_info("LARefTo: %d(%p)\n", pAllocator->m_nLoaderAllocator, pAllocator);
iter++;
}
}
}
}
- }
-#endif //0
-
- AppDomain::AssemblyIterator i;
- {
- // Iterate through every loader allocator, marking as we go
- CrstHolder chLoaderAllocatorReferencesLock(pAppDomain->GetLoaderAllocatorReferencesLock());
- CrstHolder chAssemblyListLock(pAppDomain->GetAssemblyListLock());
+#endif // ENABLE_LOG_LOADER_ALLOCATOR_CLEANUP
i = pAppDomain->IterateAssembliesEx((AssemblyIterationFlags)(
kIncludeExecution | kIncludeLoaded | kIncludeCollected));
- CollectibleAssemblyHolder pAssembly;
while (i.Next_Unlocked(pAssembly.This()))
{
@@ -406,7 +418,12 @@ LoaderAllocator * LoaderAllocator::GCLoaderAllocators_RemoveAssemblies(AppDomain
if (pLoaderAllocator->IsCollectible())
{
if (pLoaderAllocator->IsAlive())
+ {
+ // This mark is a deep mark, it will mark all LoaderAllocators that this one references too (recursively),
+ // even ones that are not alive. Note that the caller of the current function has decremented reference count
+ // of the loader allocator we are going to release and also all of its dependencies.
pLoaderAllocator->Mark();
+ }
}
}
}
@@ -508,13 +525,16 @@ void LoaderAllocator::GCLoaderAllocators(LoaderAllocator* pOriginalLoaderAllocat
}
CONTRACTL_END;
+#ifdef ENABLE_LOG_LOADER_ALLOCATOR_CLEANUP
+ minipal_log_print_info("-------LoaderAllocator::GCLoaderAllocators LA %d(%p) %d\n", pOriginalLoaderAllocator->m_nLoaderAllocator, pOriginalLoaderAllocator, pOriginalLoaderAllocator->m_cReferences.Load());
+#endif
// List of LoaderAllocators being deleted
LoaderAllocator * pFirstDestroyedLoaderAllocator = NULL;
AppDomain* pAppDomain = AppDomain::GetCurrentDomain();
// Collect all LoaderAllocators that don't have anymore DomainAssemblies alive
- // Note: that it may not collect our pOriginalLoaderAllocator in case this
+ // Note: that it will not collect our pOriginalLoaderAllocator in case this
// LoaderAllocator hasn't loaded any DomainAssembly. We handle this case in the next loop.
// Note: The removed LoaderAllocators are not reachable outside of this function anymore, because we
// removed them from the assembly list
@@ -550,10 +570,13 @@ void LoaderAllocator::GCLoaderAllocators(LoaderAllocator* pOriginalLoaderAllocat
pDomainLoaderAllocatorDestroyIterator = pDomainLoaderAllocatorDestroyIterator->m_pLoaderAllocatorDestroyNext;
}
- // If the original LoaderAllocator was not processed, it is most likely a LoaderAllocator without any loaded DomainAssembly
+ // If the original LoaderAllocator was not processed, it is a LoaderAllocator without any loaded DomainAssembly
// But we still want to collect it so we add it to the list of LoaderAllocator to destroy
- if (!isOriginalLoaderAllocatorFound && !pOriginalLoaderAllocator->IsAlive())
+ if (!isOriginalLoaderAllocatorFound && !pOriginalLoaderAllocator->Id()->HasAttachedDynamicAssemblies() && !pOriginalLoaderAllocator->IsAlive())
{
+#ifdef ENABLE_LOG_LOADER_ALLOCATOR_CLEANUP
+ minipal_log_print_info("LoaderAllocator::GCLoaderAllocators FORCED unload due to no DomainAssembly LA %d(%p) %d\n", pOriginalLoaderAllocator->m_nLoaderAllocator, pOriginalLoaderAllocator, (int)pOriginalLoaderAllocator->m_cReferences.Load());
+#endif
pOriginalLoaderAllocator->m_pLoaderAllocatorDestroyNext = pFirstDestroyedLoaderAllocator;
pFirstDestroyedLoaderAllocator = pOriginalLoaderAllocator;
}
@@ -562,6 +585,9 @@ void LoaderAllocator::GCLoaderAllocators(LoaderAllocator* pOriginalLoaderAllocat
pDomainLoaderAllocatorDestroyIterator = pFirstDestroyedLoaderAllocator;
while (pDomainLoaderAllocatorDestroyIterator != NULL)
{
+#ifdef ENABLE_LOG_LOADER_ALLOCATOR_CLEANUP
+ minipal_log_print_info("LoaderAllocator::GCLoaderAllocators DESTROY LA %d(%p) %d\n", pDomainLoaderAllocatorDestroyIterator->m_nLoaderAllocator, pDomainLoaderAllocatorDestroyIterator, (int)pDomainLoaderAllocatorDestroyIterator->m_cReferences.Load());
+#endif
_ASSERTE(!pDomainLoaderAllocatorDestroyIterator->IsAlive());
DomainAssemblyIterator domainAssemblyIt(pDomainLoaderAllocatorDestroyIterator->m_pFirstDomainAssemblyFromSameALCToDelete);
@@ -642,6 +668,9 @@ BOOL LoaderAllocator::Destroy(QCall::LoaderAllocatorHandle pLoaderAllocator)
{
STRESS_LOG1(LF_CLASSLOADER, LL_INFO100, "Begin LoaderAllocator::Destroy for loader allocator %p\n", reinterpret_cast(static_cast(pLoaderAllocator)));
LoaderAllocatorID *pID = pLoaderAllocator->Id();
+#ifdef ENABLE_LOG_LOADER_ALLOCATOR_CLEANUP
+ minipal_log_print_info("LoaderAllocator::Destroy LA %d(%p) %d\n", pLoaderAllocator->m_nLoaderAllocator, pLoaderAllocator, pLoaderAllocator->m_cReferences.Load());
+#endif
{
GCX_COOP();
@@ -1044,6 +1073,9 @@ void LoaderAllocator::ActivateManagedTracking()
// There is now one external reference to this LoaderAllocator (the managed scout)
_ASSERTE(m_cReferences == (UINT32)-1);
m_cReferences = (UINT32)1;
+#ifdef ENABLE_LOG_LOADER_ALLOCATOR_CLEANUP
+ minipal_log_print_info("LoaderAllocator::ActivateManagedTracking LA %d(%p) %d\n", m_nLoaderAllocator, this, (int)m_cReferences.Load());
+#endif
LOADERALLOCATORREF loaderAllocator = (LOADERALLOCATORREF)ObjectFromHandle(m_hLoaderAllocatorObjectHandle);
loaderAllocator->SetNativeLoaderAllocator(this);
diff --git a/src/coreclr/vm/loaderallocator.hpp b/src/coreclr/vm/loaderallocator.hpp
index 4e8de0ffa6470c..6c876fde167574 100644
--- a/src/coreclr/vm/loaderallocator.hpp
+++ b/src/coreclr/vm/loaderallocator.hpp
@@ -232,6 +232,14 @@ class LoaderAllocatorID
m_pValue = value;
};
VOID Init();
+ bool HasAttachedDynamicAssemblies()
+ {
+ if (m_type == LAT_Assembly && m_pDomainAssembly != NULL)
+ {
+ return true;
+ }
+ return false;
+ }
LoaderAllocatorType GetType();
VOID AddDomainAssembly(DomainAssembly* pDomainAssembly);
DomainAssemblyIterator GetDomainAssemblyIterator();
diff --git a/src/coreclr/vm/metasig.h b/src/coreclr/vm/metasig.h
index 4d6e8666749c2b..ddb9b5ea403e63 100644
--- a/src/coreclr/vm/metasig.h
+++ b/src/coreclr/vm/metasig.h
@@ -186,7 +186,6 @@ DEFINE_METASIG(SM(Obj_IntPtr_IntPtr_Int_RetIntPtr, j I I i, I))
DEFINE_METASIG(SM(IntPtr_IntPtr_RefIntPtr_RetObj, I I r(I), j))
DEFINE_METASIG_T(SM(Obj_RefExInfo_RetVoid, j r(g(EXINFO)), v))
DEFINE_METASIG_T(SM(UInt_RefExInfo_RetVoid, K r(g(EXINFO)), v))
-DEFINE_METASIG_T(SM(RefExInfo_UIntPtr_RetVoid, r(g(EXINFO)) U, v))
DEFINE_METASIG_T(SM(RefExInfo_RefExInfo_RetVoid, r(g(EXINFO)) r(g(EXINFO)), v))
#ifdef FEATURE_COMINTEROP
DEFINE_METASIG(SM(Obj_IntPtr_RefIntPtr_RefBool_RetIntPtr, j I r(I) r(F), I))
diff --git a/src/coreclr/vm/method.cpp b/src/coreclr/vm/method.cpp
index 349a05ec3c5396..3d27905122ce01 100644
--- a/src/coreclr/vm/method.cpp
+++ b/src/coreclr/vm/method.cpp
@@ -3699,6 +3699,7 @@ MethodDesc::EnumMemoryRegions(CLRDataEnumMemoryFlags flags)
{
EX_TRY
{
+ ilVersion.GetModule()->LookupMethodDef(ilVersion.GetMethodDef());
ilVersion.GetActiveNativeCodeVersion(dac_cast(this));
ilVersion.GetVersionId();
ilVersion.GetRejitState();
diff --git a/src/coreclr/vm/method.hpp b/src/coreclr/vm/method.hpp
index 1438276e35b42c..7a23d0cd0b6325 100644
--- a/src/coreclr/vm/method.hpp
+++ b/src/coreclr/vm/method.hpp
@@ -2093,6 +2093,7 @@ class MethodDesc
void EmitTaskReturningThunk(MethodDesc* pAsyncOtherVariant, MetaSig& thunkMsig, ILStubLinker* pSL);
void EmitAsyncMethodThunk(MethodDesc* pAsyncOtherVariant, MetaSig& msig, ILStubLinker* pSL);
SigPointer GetAsyncThunkResultTypeSig();
+ bool IsValueTaskAsyncThunk();
int GetTokenForGenericMethodCallWithAsyncReturnType(ILCodeStream* pCode, MethodDesc* md);
int GetTokenForGenericTypeMethodCallWithAsyncReturnType(ILCodeStream* pCode, MethodDesc* md);
int GetTokenForAwaitAwaiterInstantiatedOverTaskAwaiterType(ILCodeStream* pCode, TypeHandle taskAwaiterType);
diff --git a/src/coreclr/vm/proftoeeinterfaceimpl.cpp b/src/coreclr/vm/proftoeeinterfaceimpl.cpp
index effd3b73b37441..c1ad32fdb03401 100644
--- a/src/coreclr/vm/proftoeeinterfaceimpl.cpp
+++ b/src/coreclr/vm/proftoeeinterfaceimpl.cpp
@@ -10666,9 +10666,7 @@ void __stdcall ProfilerUnmanagedToManagedTransitionMD(MethodDesc *pMD,
// These do a lot of work for us, setting up Frames, gathering arg info and resolving generics.
//*******************************************************************************************
-HCIMPL2_RAW(EXTERN_C void, ProfileEnter, UINT_PTR clientData, void * platformSpecificHandle)
-GCX_COOP_THREAD_EXISTS(GET_THREAD());
-HCIMPL_PROLOG(ProfileEnter)
+HCIMPL2(EXTERN_C void, ProfileEnter, UINT_PTR clientData, void * platformSpecificHandle)
{
FCALL_CONTRACT;
@@ -10844,12 +10842,12 @@ HCIMPL_PROLOG(ProfileEnter)
}
HCIMPLEND
-HCIMPL2_RAW(EXTERN_C void, ProfileLeave, UINT_PTR clientData, void * platformSpecificHandle)
-GCX_COOP();
-HCIMPL_PROLOG(ProfileLeave)
+HCIMPL2(EXTERN_C void, ProfileLeave, UINT_PTR clientData, void * platformSpecificHandle)
{
FCALL_CONTRACT;
+ GCX_COOP();
+
#ifdef PROFILING_SUPPORTED
#ifdef PROF_TEST_ONLY_FORCE_ELT
diff --git a/src/coreclr/vm/qcallentrypoints.cpp b/src/coreclr/vm/qcallentrypoints.cpp
index e2dd498b8b483a..19cb4a2a58c500 100644
--- a/src/coreclr/vm/qcallentrypoints.cpp
+++ b/src/coreclr/vm/qcallentrypoints.cpp
@@ -532,10 +532,7 @@ static const Entry s_QCall[] =
#ifdef FEATURE_EH_FUNCLETS
DllImportEntry(SfiInit)
DllImportEntry(SfiNext)
- DllImportEntry(CallCatchFunclet)
- DllImportEntry(ResumeAtInterceptionLocation)
DllImportEntry(CallFilterFunclet)
- DllImportEntry(CallFinallyFunclet)
DllImportEntry(EHEnumInitFromStackFrameIterator)
DllImportEntry(EHEnumNext)
DllImportEntry(AppendExceptionStackFrame)
diff --git a/src/coreclr/vm/stackwalk.cpp b/src/coreclr/vm/stackwalk.cpp
index 3376d945e0ca91..c43821f875a2d2 100644
--- a/src/coreclr/vm/stackwalk.cpp
+++ b/src/coreclr/vm/stackwalk.cpp
@@ -1049,9 +1049,6 @@ void StackFrameIterator::CommonCtor(Thread * pThread, PTR_Frame pFrame, ULONG32
m_fDidFuncletReportGCReferences = true;
m_isRuntimeWrappedExceptions = false;
#endif // FEATURE_EH_FUNCLETS
- m_forceReportingWhileSkipping = ForceGCReportingStage::Off;
- m_movedPastFirstExInfo = false;
- m_fFuncletNotSeen = false;
m_fFoundFirstFunclet = false;
#if defined(RECORD_RESUMABLE_FRAME_SP)
m_pvResumableFrameTargetSP = NULL;
@@ -1399,8 +1396,6 @@ void StackFrameIterator::ResetCrawlFrame()
m_crawl.isFilterFuncletCached = false;
m_crawl.fShouldParentToFuncletSkipReportingGCReferences = false;
m_crawl.fShouldParentFrameUseUnwindTargetPCforGCReporting = false;
- m_crawl.fShouldSaveFuncletInfo = false;
- m_crawl.fShouldParentToFuncletReportSavedFuncletSlots = false;
#endif // FEATURE_EH_FUNCLETS
m_crawl.pThread = this->m_pThread;
@@ -1624,33 +1619,6 @@ StackWalkAction StackFrameIterator::Filter(void)
SIZE_T frameSP = (m_frameState == SFITER_FRAME_FUNCTION) ? (SIZE_T)dac_cast(m_crawl.pFrame) : m_crawl.GetRegisterSet()->SP;
- if ((m_flags & GC_FUNCLET_REFERENCE_REPORTING) && (pExInfo != NULL) && (frameSP > (SIZE_T)pExInfo))
- {
- if (!m_movedPastFirstExInfo)
- {
- if ((pExInfo->m_passNumber == 2) && !pExInfo->m_csfEnclosingClause.IsNull() && m_sfFuncletParent.IsNull() && pExInfo->m_lastReportedFunclet.IP != 0)
- {
- // We are in the 2nd pass and we have already called an exceptionally called
- // finally funclet and reported that to GC in a previous GC run. But we have
- // not seen any funclet on the call stack yet.
- // Simulate that we have actualy seen a finally funclet during this pass and
- // that it didn't report GC references to ensure that the references will be
- // reported by the parent correctly.
- m_sfFuncletParent = (StackFrame)pExInfo->m_csfEnclosingClause;
- m_sfParent = m_sfFuncletParent;
- m_fProcessNonFilterFunclet = true;
- m_fDidFuncletReportGCReferences = false;
- m_fFuncletNotSeen = true;
- STRESS_LOG3(LF_GCROOTS, LL_INFO100,
- "STACKWALK: Moved over first ExInfo @ %p in second pass, SP: %p, Enclosing clause: %p\n",
- pExInfo, (void*)m_crawl.GetRegisterSet()->SP, (void*)m_sfFuncletParent.SP);
- }
- m_movedPastFirstExInfo = true;
- }
- }
-
- m_crawl.fShouldParentToFuncletReportSavedFuncletSlots = false;
-
// by default, there is no funclet for the current frame
// that reported GC references
m_crawl.fShouldParentToFuncletSkipReportingGCReferences = false;
@@ -1659,8 +1627,6 @@ StackWalkAction StackFrameIterator::Filter(void)
// CrawlFrame
m_crawl.fShouldCrawlframeReportGCReferences = true;
- m_crawl.fShouldSaveFuncletInfo = false;
-
// By default, assume that parent frame is going to report GC references from
// the actual location reported by the stack walk.
m_crawl.fShouldParentFrameUseUnwindTargetPCforGCReporting = false;
@@ -1770,14 +1736,6 @@ StackWalkAction StackFrameIterator::Filter(void)
// can use it.
m_sfParent = m_sfIntermediaryFuncletParent;
fSkipFuncletCallback = false;
-
- if (!ExecutionManager::IsManagedCode(GetIP(m_crawl.GetRegisterSet()->pCallerContext)))
- {
- // Initiate force reporting of references in the new managed exception handling code frames.
- // These frames are still alive when we are in a finally funclet.
- m_forceReportingWhileSkipping = ForceGCReportingStage::LookForManagedFrame;
- STRESS_LOG0(LF_GCROOTS, LL_INFO100, "STACKWALK: Setting m_forceReportingWhileSkipping = ForceGCReportingStage::LookForManagedFrame while processing filter funclet\n");
- }
}
}
}
@@ -1817,26 +1775,6 @@ StackWalkAction StackFrameIterator::Filter(void)
// can use it.
m_sfParent = m_sfFuncletParent;
- if (!m_fFoundFirstFunclet && (pExInfo > (void*)GetRegdisplaySP(m_crawl.GetRegisterSet())) && ((void*)m_sfParent.SP > pExInfo))
- {
- // For the first funclet we encounter below the topmost ExInfo that has a parent above that ExInfo
- // (so it is an exceptionally called funclet for the exception represented by the ExInfo),
- // we instruct the GC scanning of the frame
- // to save information on the funclet so that we can use it to report references in the parent frame if
- // no such funclet is found in future GC scans for the same exception.
- _ASSERTE(pExInfo != NULL);
- m_crawl.fShouldSaveFuncletInfo = true;
- m_fFoundFirstFunclet = true;
- }
-
- if (!fFrameWasUnwound && !ExecutionManager::IsManagedCode(GetIP(m_crawl.GetRegisterSet()->pCallerContext)))
- {
- // Initiate force reporting of references in the new managed exception handling code frames.
- // These frames are still alive when we are in a finally funclet.
- m_forceReportingWhileSkipping = ForceGCReportingStage::LookForManagedFrame;
- STRESS_LOG0(LF_GCROOTS, LL_INFO100, "STACKWALK: Setting m_forceReportingWhileSkipping = ForceGCReportingStage::LookForManagedFrame\n");
- }
-
// For non-filter funclets, we will make the callback for the funclet
// but skip all the frames until we reach the parent method. When we do,
// we will make a callback for it as well and then continue to make callbacks
@@ -2029,14 +1967,6 @@ StackWalkAction StackFrameIterator::Filter(void)
}
else if (!m_crawl.IsFunclet())
{
- if (m_fFuncletNotSeen)
- {
- // We have reached a real parent of a funclet that would be on the stack if GC didn't
- // kick in between the calls to funclets in the second pass. We instruct GC to report
- // roots using the info of the saved funclet we've seen during a previous GC.
- m_crawl.fShouldParentToFuncletReportSavedFuncletSlots = true;
- m_fFuncletNotSeen = false;
- }
// we've reached the parent and it's not handling an exception, it's also not
// a funclet so reset our state. note that we cannot reset the state when the
// parent is a funclet since the leaf funclet didn't report any references and
@@ -2104,7 +2034,7 @@ StackWalkAction StackFrameIterator::Filter(void)
}
else if (fSkipFuncletCallback && (m_flags & GC_FUNCLET_REFERENCE_REPORTING))
{
- if (!m_sfParent.IsNull() && (m_forceReportingWhileSkipping == ForceGCReportingStage::Off))
+ if (!m_sfParent.IsNull())
{
STRESS_LOG4(LF_GCROOTS, LL_INFO100,
"STACKWALK: %s: not making callback for this frame, SPOfParent = %p, \
@@ -2117,22 +2047,6 @@ StackWalkAction StackFrameIterator::Filter(void)
// don't stop here
break;
}
-
- if (m_forceReportingWhileSkipping == ForceGCReportingStage::LookForManagedFrame)
- {
- // State indicating that the next marker frame should turn off the reporting again. That would be the caller of the managed RhThrowEx
- m_forceReportingWhileSkipping = ForceGCReportingStage::LookForMarkerFrame;
- STRESS_LOG0(LF_GCROOTS, LL_INFO100, "STACKWALK: Setting m_forceReportingWhileSkipping = ForceGCReportingStage::LookForMarkerFrame\n");
- }
-
-#ifdef _DEBUG
- if (m_forceReportingWhileSkipping != ForceGCReportingStage::Off)
- {
- STRESS_LOG3(LF_GCROOTS, LL_INFO100,
- "STACKWALK: Force callback for skipped function m_crawl.pFunc = %pM (%s.%s)\n", m_crawl.pFunc, m_crawl.pFunc->m_pszDebugClassName, m_crawl.pFunc->m_pszDebugMethodName);
- _ASSERTE((m_crawl.pFunc->GetMethodTable() == g_pEHClass) || (strcmp(m_crawl.pFunc->m_pszDebugClassName, "ILStubClass") == 0) || (strcmp(m_crawl.pFunc->m_pszDebugMethodName, "CallFinallyFunclet") == 0) || (m_crawl.pFunc->GetMethodTable() == g_pExceptionServicesInternalCallsClass));
- }
-#endif
}
}
}
@@ -2226,11 +2140,6 @@ StackWalkAction StackFrameIterator::Filter(void)
fStop = true;
}
}
- if (m_forceReportingWhileSkipping == ForceGCReportingStage::LookForMarkerFrame)
- {
- m_forceReportingWhileSkipping = ForceGCReportingStage::Off;
- STRESS_LOG0(LF_GCROOTS, LL_INFO100, "STACKWALK: Setting m_forceReportingWhileSkipping = ForceGCReportingStage::Off\n");
- }
break;
case SFITER_INITIAL_NATIVE_CONTEXT:
diff --git a/src/coreclr/vm/stackwalk.h b/src/coreclr/vm/stackwalk.h
index 6b650a277137e3..ddf7158a62eee9 100644
--- a/src/coreclr/vm/stackwalk.h
+++ b/src/coreclr/vm/stackwalk.h
@@ -411,18 +411,6 @@ class CrawlFrame
return fShouldParentFrameUseUnwindTargetPCforGCReporting;
}
- bool ShouldParentToFuncletReportSavedFuncletSlots()
- {
- LIMITED_METHOD_CONTRACT;
- return fShouldParentToFuncletReportSavedFuncletSlots;
- }
-
- bool ShouldSaveFuncletInfo()
- {
- LIMITED_METHOD_CONTRACT;
- return fShouldSaveFuncletInfo;
- }
-
const EE_ILEXCEPTION_CLAUSE& GetEHClauseForCatch()
{
return ehClauseForCatch;
@@ -473,8 +461,6 @@ class CrawlFrame
bool fShouldParentToFuncletSkipReportingGCReferences;
bool fShouldCrawlframeReportGCReferences;
bool fShouldParentFrameUseUnwindTargetPCforGCReporting;
- bool fShouldSaveFuncletInfo;
- bool fShouldParentToFuncletReportSavedFuncletSlots;
EE_ILEXCEPTION_CLAUSE ehClauseForCatch;
#endif //FEATURE_EH_FUNCLETS
Thread* pThread;
@@ -611,6 +597,11 @@ class StackFrameIterator
m_AdjustedControlPC = pc;
}
+ TADDR GetAdjustedControlPC()
+ {
+ return m_AdjustedControlPC;
+ }
+
void UpdateIsRuntimeWrappedExceptions()
{
CONTRACTL
@@ -651,23 +642,6 @@ class StackFrameIterator
private:
- // For the new exception handling that uses managed code to dispatch the
- // exceptions, we need to force the stack walker to report GC references
- // in the exception handling code frames, since they are alive. This is
- // different from the old exception handling where no frames below the
- // funclets upto the parent frame are alive.
- enum class ForceGCReportingStage : BYTE
- {
- Off = 0,
- // The stack walker has hit a funclet, we are looking for the first managed
- // frame that would be one of the managed exception handling code frames
- LookForManagedFrame = 1,
- // The stack walker has already hit a managed exception handling code frame,
- // we are looking for a marker frame which indicates the native caller of
- // the managed exception handling code
- LookForMarkerFrame = 2
- };
-
// This is a helper for the two constructors.
void CommonCtor(Thread * pThread, PTR_Frame pFrame, ULONG32 flags);
@@ -760,12 +734,6 @@ class StackFrameIterator
bool m_fDidFuncletReportGCReferences;
bool m_isRuntimeWrappedExceptions;
#endif // FEATURE_EH_FUNCLETS
- // State of forcing of GC reference reporting for managed exception handling methods (RhExThrow, RhDispatchEx etc)
- ForceGCReportingStage m_forceReportingWhileSkipping;
- // The stack walk has moved past the first ExInfo location on the stack
- bool m_movedPastFirstExInfo;
- // Indicates that no funclet was seen during the current stack walk yet
- bool m_fFuncletNotSeen;
// Indicates that the stack walk has moved past a funclet
bool m_fFoundFirstFunclet;
#ifdef FEATURE_INTERPRETER
diff --git a/src/coreclr/vm/threads.cpp b/src/coreclr/vm/threads.cpp
index 92344beb931331..3fed0d695ba456 100644
--- a/src/coreclr/vm/threads.cpp
+++ b/src/coreclr/vm/threads.cpp
@@ -7686,6 +7686,7 @@ void ClrRestoreNonvolatileContext(PCONTEXT ContextRecord, size_t targetSSP)
// Falling back to RtlRestoreContext() for now, though it should be possible to have simpler variants for these cases
RtlRestoreContext(ContextRecord, NULL);
#endif
+ UNREACHABLE();
}
#ifdef FEATURE_INTERPRETER
diff --git a/src/coreclr/vm/threads.h b/src/coreclr/vm/threads.h
index 3dd41dfd5f8b54..e156f2b4bc1df8 100644
--- a/src/coreclr/vm/threads.h
+++ b/src/coreclr/vm/threads.h
@@ -3561,6 +3561,12 @@ class Thread
_ASSERTE(!m_debuggerActivePatchSkipper.Load());
}
+ bool HasActivePatchSkip() const
+ {
+ LIMITED_METHOD_DAC_CONTRACT;
+ return m_debuggerActivePatchSkipper.Load() != NULL;
+ }
+
private:
static BOOL EnterWorkingOnThreadContext(Thread *pThread)
diff --git a/src/coreclr/vm/threadsuspend.cpp b/src/coreclr/vm/threadsuspend.cpp
index fd6bbdaede369a..8bb327a17ae0d5 100644
--- a/src/coreclr/vm/threadsuspend.cpp
+++ b/src/coreclr/vm/threadsuspend.cpp
@@ -2712,6 +2712,11 @@ void __stdcall Thread::RedirectedHandledJITCase(RedirectReason reason)
GCX_PREEMP_NO_DTOR_END();
}
+#if defined(FEATURE_HIJACK) && !defined(TARGET_UNIX)
+ // Make sure that this is cleared to enable redirects again
+ pThread->ResetThreadState(Thread::TS_GCSuspendRedirected);
+#endif
+
// Once we get here the suspension is over!
// We will restore the state as it was at the point of redirection
// and continue normal execution.
diff --git a/src/coreclr/vm/unsafeaccessors.cpp b/src/coreclr/vm/unsafeaccessors.cpp
index 6b039f780ec629..b82c3e6800a3dc 100644
--- a/src/coreclr/vm/unsafeaccessors.cpp
+++ b/src/coreclr/vm/unsafeaccessors.cpp
@@ -424,14 +424,26 @@ namespace
return false;
}
- // Handle generic param count
- DWORD declGenericCount = 0;
- DWORD methodGenericCount = 0;
+ // Handle generic signature
if (callConvDecl & IMAGE_CEE_CS_CALLCONV_GENERIC)
+ {
+ if (!(callConvMethod & IMAGE_CEE_CS_CALLCONV_GENERIC))
+ return false;
+
+ DWORD declGenericCount = 0;
+ DWORD methodGenericCount = 0;
IfFailThrow(CorSigUncompressData_EndPtr(pSig1, pEndSig1, &declGenericCount));
- if (callConvMethod & IMAGE_CEE_CS_CALLCONV_GENERIC)
IfFailThrow(CorSigUncompressData_EndPtr(pSig2, pEndSig2, &methodGenericCount));
+ if (declGenericCount != methodGenericCount)
+ return false;
+ }
+ else if (callConvMethod & IMAGE_CEE_CS_CALLCONV_GENERIC)
+ {
+ // Method is generic but declaration is not
+ return false;
+ }
+
DWORD declArgCount;
DWORD methodArgCount;
IfFailThrow(CorSigUncompressData_EndPtr(pSig1, pEndSig1, &declArgCount));
diff --git a/src/installer/managed/Microsoft.NET.HostModel/AppHost/HostWriter.cs b/src/installer/managed/Microsoft.NET.HostModel/AppHost/HostWriter.cs
index 47f64f4669c60c..777fab812578b0 100644
--- a/src/installer/managed/Microsoft.NET.HostModel/AppHost/HostWriter.cs
+++ b/src/installer/managed/Microsoft.NET.HostModel/AppHost/HostWriter.cs
@@ -124,7 +124,7 @@ void RewriteAppHost(MemoryMappedFile mappedFile, MemoryMappedViewAccessor access
if (File.Exists(appHostDestinationFilePath))
File.Delete(appHostDestinationFilePath);
- long appHostSourceLength = new FileInfo(appHostSourceFilePath).Length;
+ long appHostSourceLength = HostModelUtils.GetFileLength(appHostSourceFilePath);
string destinationFileName = Path.GetFileName(appHostDestinationFilePath);
// Memory-mapped files cannot be resized, so calculate
// the maximum length of the destination file upfront.
diff --git a/src/installer/managed/Microsoft.NET.HostModel/Bundle/Bundler.cs b/src/installer/managed/Microsoft.NET.HostModel/Bundle/Bundler.cs
index a5e8b593484198..f59e9c941ab053 100644
--- a/src/installer/managed/Microsoft.NET.HostModel/Bundle/Bundler.cs
+++ b/src/installer/managed/Microsoft.NET.HostModel/Bundle/Bundler.cs
@@ -293,7 +293,7 @@ public string GenerateBundle(IReadOnlyList fileSpecs)
// We will memory map a larger file than needed, but we'll take that trade-off.
foreach (var (spec, type) in relativePathToSpec)
{
- bundledFilesSize += new FileInfo(spec.SourcePath).Length;
+ bundledFilesSize += HostModelUtils.GetFileLength(spec.SourcePath);
if (type == FileType.Assembly)
{
// Alignment could be as much as AssemblyAlignment - 1 bytes.
@@ -314,7 +314,7 @@ public string GenerateBundle(IReadOnlyList fileSpecs)
{
Directory.CreateDirectory(destinationDirectory);
}
- var hostLength = new FileInfo(hostSource).Length;
+ var hostLength = HostModelUtils.GetFileLength(hostSource);
var bundleManifestLength = Manifest.GetManifestLength(BundleManifest.BundleMajorVersion, relativePathToSpec.Select(x => x.Spec.BundleRelativePath));
long bundleTotalSize = hostLength + bundledFilesSize + bundleManifestLength;
if (_target.IsOSX && _macosCodesign)
@@ -386,7 +386,7 @@ public string GenerateBundle(IReadOnlyList fileSpecs)
}
if (_macosCodesign)
{
- endOfBundle = (ulong)machFile.AdHocSignFile(machFileReader!, _hostName, signatureBlob);
+ endOfBundle = (ulong)machFile.AdHocSignFile(machFileReader!, _hostName);
}
}
diff --git a/src/installer/managed/Microsoft.NET.HostModel/HostModelUtils.cs b/src/installer/managed/Microsoft.NET.HostModel/HostModelUtils.cs
index 85724bef64c026..8fcb58da9b899a 100644
--- a/src/installer/managed/Microsoft.NET.HostModel/HostModelUtils.cs
+++ b/src/installer/managed/Microsoft.NET.HostModel/HostModelUtils.cs
@@ -2,9 +2,14 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System.Diagnostics;
+#if NETFRAMEWORK
+using Microsoft.IO;
+#else
using System.IO;
+#endif
using System.Runtime.InteropServices;
+
namespace Microsoft.NET.HostModel
{
internal static class HostModelUtils
@@ -32,5 +37,11 @@ public static (int ExitCode, string StdErr) RunCodesign(string args, string appH
return (p.ExitCode, p.StandardError.ReadToEnd());
}
}
+
+ public static long GetFileLength(string path)
+ {
+ var info = new FileInfo(path);
+ return ((FileInfo)info.ResolveLinkTarget(true) ?? info).Length;
+ }
}
}
diff --git a/src/installer/managed/Microsoft.NET.HostModel/MachO/BinaryFormat/Blobs/BlobParser.cs b/src/installer/managed/Microsoft.NET.HostModel/MachO/BinaryFormat/Blobs/BlobParser.cs
index b8157940bd04a1..d26200d583d4b3 100644
--- a/src/installer/managed/Microsoft.NET.HostModel/MachO/BinaryFormat/Blobs/BlobParser.cs
+++ b/src/installer/managed/Microsoft.NET.HostModel/MachO/BinaryFormat/Blobs/BlobParser.cs
@@ -26,8 +26,6 @@ public static IBlob ParseBlob(IMachOFileReader reader, long offset)
BlobMagic.Requirements => new RequirementsBlob(SuperBlob.Read(reader, offset)),
BlobMagic.CmsWrapper => new CmsWrapperBlob(SimpleBlob.Read(reader, offset)),
BlobMagic.EmbeddedSignature => new EmbeddedSignatureBlob(SuperBlob.Read(reader, offset)),
- BlobMagic.Entitlements => new EntitlementsBlob(SimpleBlob.Read(reader, offset)),
- BlobMagic.DerEntitlements => new DerEntitlementsBlob(SimpleBlob.Read(reader, offset)),
_ => CreateUnknownBlob(magic, reader, offset),
};
diff --git a/src/installer/managed/Microsoft.NET.HostModel/MachO/BinaryFormat/Blobs/CodeDirectoryBlob.cs b/src/installer/managed/Microsoft.NET.HostModel/MachO/BinaryFormat/Blobs/CodeDirectoryBlob.cs
index b56c60b02e70eb..8de8a0b7fdde36 100644
--- a/src/installer/managed/Microsoft.NET.HostModel/MachO/BinaryFormat/Blobs/CodeDirectoryBlob.cs
+++ b/src/installer/managed/Microsoft.NET.HostModel/MachO/BinaryFormat/Blobs/CodeDirectoryBlob.cs
@@ -119,17 +119,11 @@ public static CodeDirectoryBlob Create(
long signatureStart,
string identifier,
RequirementsBlob requirementsBlob,
- EntitlementsBlob? entitlementsBlob = null,
- DerEntitlementsBlob? derEntitlementsBlob = null,
HashType hashType = HashType.SHA256,
uint pageSize = MachObjectFile.DefaultPageSize)
{
uint codeSlotCount = GetCodeSlotCount((uint)signatureStart, pageSize);
- uint specialCodeSlotCount = (uint)(derEntitlementsBlob != null
- ? CodeDirectorySpecialSlot.DerEntitlements
- : entitlementsBlob != null
- ? CodeDirectorySpecialSlot.Entitlements
- : CodeDirectorySpecialSlot.Requirements);
+ uint specialCodeSlotCount = (uint)CodeDirectorySpecialSlot.Requirements;
var specialSlotHashes = new byte[specialCodeSlotCount][];
var codeHashes = new byte[codeSlotCount][];
@@ -144,29 +138,12 @@ public static CodeDirectoryBlob Create(
// Fill in the CodeDirectory hashes
// Special slot hashes
- // -7 is the der entitlements blob hash
- if (derEntitlementsBlob != null)
- {
- using var derStream = new MemoryStreamWriter((int)derEntitlementsBlob.Size);
- derEntitlementsBlob.Write(derStream, 0);
- specialSlotHashes[(int)CodeDirectorySpecialSlot.DerEntitlements - 1] = hasher.ComputeHash(derStream.GetBuffer());
- }
-
- // -5 is the entitlements blob hash
- if (entitlementsBlob != null)
- {
- using var entStream = new MemoryStreamWriter((int)entitlementsBlob.Size);
- entitlementsBlob.Write(entStream, 0);
- specialSlotHashes[(int)CodeDirectorySpecialSlot.Entitlements - 1] = hasher.ComputeHash(entStream.GetBuffer());
- }
-
// -2 is the requirements blob hash
using (var reqStream = new MemoryStreamWriter((int)requirementsBlob.Size))
{
requirementsBlob.Write(reqStream, 0);
specialSlotHashes[(int)CodeDirectorySpecialSlot.Requirements - 1] = hasher.ComputeHash(reqStream.GetBuffer());
}
-
// -1 is the CMS blob hash (which is empty -- nothing to hash)
// Reverse special slot hashes
diff --git a/src/installer/managed/Microsoft.NET.HostModel/MachO/BinaryFormat/Blobs/DerEntitlementsBlob.cs b/src/installer/managed/Microsoft.NET.HostModel/MachO/BinaryFormat/Blobs/DerEntitlementsBlob.cs
deleted file mode 100644
index 4b0a13b94252d0..00000000000000
--- a/src/installer/managed/Microsoft.NET.HostModel/MachO/BinaryFormat/Blobs/DerEntitlementsBlob.cs
+++ /dev/null
@@ -1,35 +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.IO;
-
-namespace Microsoft.NET.HostModel.MachO;
-
-internal sealed class DerEntitlementsBlob : IBlob
-{
- private SimpleBlob _inner;
-
- public DerEntitlementsBlob(SimpleBlob blob)
- {
- _inner = blob;
- if (blob.Size > MaxSize)
- {
- throw new InvalidDataException($"DerEntitlementsBlob size exceeds maximum allowed size: {blob.Data.Length} > {MaxSize}");
- }
- if (blob.Magic != BlobMagic.DerEntitlements)
- {
- throw new InvalidDataException($"Invalid magic for DerEntitlementsBlob: {blob.Magic}");
- }
- }
-
- public static uint MaxSize => 1024;
-
- ///
- public BlobMagic Magic => ((IBlob)_inner).Magic;
-
- ///
- public uint Size => ((IBlob)_inner).Size;
-
- ///
- public int Write(IMachOFileWriter writer, long offset) => ((IBlob)_inner).Write(writer, offset);
-}
diff --git a/src/installer/managed/Microsoft.NET.HostModel/MachO/BinaryFormat/Blobs/EmbeddedSignatureBlob.cs b/src/installer/managed/Microsoft.NET.HostModel/MachO/BinaryFormat/Blobs/EmbeddedSignatureBlob.cs
index 0d9174d3a203c8..529cdc547c3144 100644
--- a/src/installer/managed/Microsoft.NET.HostModel/MachO/BinaryFormat/Blobs/EmbeddedSignatureBlob.cs
+++ b/src/installer/managed/Microsoft.NET.HostModel/MachO/BinaryFormat/Blobs/EmbeddedSignatureBlob.cs
@@ -5,7 +5,6 @@
using System;
using System.Collections.Immutable;
-using System.Diagnostics;
using System.IO;
namespace Microsoft.NET.HostModel.MachO;
@@ -36,38 +35,20 @@ public EmbeddedSignatureBlob(SuperBlob superBlob)
public EmbeddedSignatureBlob(
CodeDirectoryBlob codeDirectoryBlob,
RequirementsBlob requirementsBlob,
- CmsWrapperBlob cmsWrapperBlob,
- EntitlementsBlob? entitlementsBlob = null,
- DerEntitlementsBlob? derEntitlementsBlob = null)
+ CmsWrapperBlob cmsWrapperBlob)
{
- int blobCount = 3 + (entitlementsBlob is not null ? 1 : 0) + (derEntitlementsBlob is not null ? 1 : 0);
+ int blobCount = 3;
var blobs = ImmutableArray.CreateBuilder(blobCount);
var blobIndices = ImmutableArray.CreateBuilder(blobCount);
- uint nextBlobOffset = (uint)(sizeof(uint) * 3 + (BlobIndex.Size * blobCount));
-
+ uint expectedOffset = (uint)(sizeof(uint) * 3 + (BlobIndex.Size * blobCount));
blobs.Add(codeDirectoryBlob);
- blobIndices.Add(new BlobIndex(CodeDirectorySpecialSlot.CodeDirectory, nextBlobOffset));
- nextBlobOffset += codeDirectoryBlob.Size;
-
+ blobIndices.Add(new BlobIndex(CodeDirectorySpecialSlot.CodeDirectory, expectedOffset));
+ expectedOffset += codeDirectoryBlob.Size;
blobs.Add(requirementsBlob);
- blobIndices.Add(new BlobIndex(CodeDirectorySpecialSlot.Requirements, nextBlobOffset));
- nextBlobOffset += requirementsBlob.Size;
-
+ blobIndices.Add(new BlobIndex(CodeDirectorySpecialSlot.Requirements, expectedOffset));
+ expectedOffset += requirementsBlob.Size;
blobs.Add(cmsWrapperBlob);
- blobIndices.Add(new BlobIndex(CodeDirectorySpecialSlot.CmsWrapper, nextBlobOffset));
- nextBlobOffset += cmsWrapperBlob.Size;
-
- if (entitlementsBlob is not null)
- {
- blobs.Add(entitlementsBlob);
- blobIndices.Add(new BlobIndex(CodeDirectorySpecialSlot.Entitlements, nextBlobOffset));
- nextBlobOffset += entitlementsBlob.Size;
- }
- if (derEntitlementsBlob is not null)
- {
- blobs.Add(derEntitlementsBlob);
- blobIndices.Add(new BlobIndex(CodeDirectorySpecialSlot.DerEntitlements, nextBlobOffset));
- }
+ blobIndices.Add(new BlobIndex(CodeDirectorySpecialSlot.CmsWrapper, expectedOffset));
_inner = new SuperBlob(BlobMagic.EmbeddedSignature, blobIndices.MoveToImmutable(), blobs.MoveToImmutable());
}
@@ -90,16 +71,6 @@ public EmbeddedSignatureBlob(
///
public CmsWrapperBlob? CmsWrapperBlob => GetBlob(BlobMagic.CmsWrapper) as CmsWrapperBlob;
- ///
- /// The EntitlementsBlob. This is only included in created signatures if present in the original signature.
- ///
- public EntitlementsBlob? EntitlementsBlob => GetBlob(BlobMagic.Entitlements) as EntitlementsBlob;
-
- ///
- /// The DerEntitlementsBlob. This is only included in created signatures if present in the original signature.
- ///
- public DerEntitlementsBlob? DerEntitlementsBlob => GetBlob(BlobMagic.DerEntitlements) as DerEntitlementsBlob;
-
public uint GetSpecialSlotHashCount()
{
uint maxSlot = 0;
@@ -113,7 +84,6 @@ public uint GetSpecialSlotHashCount()
maxSlot = slot;
}
}
- Debug.Assert((CodeDirectorySpecialSlot)maxSlot is 0 or CodeDirectorySpecialSlot.Requirements or CodeDirectorySpecialSlot.Entitlements or CodeDirectorySpecialSlot.DerEntitlements);
return maxSlot;
}
@@ -134,7 +104,7 @@ public static unsafe long GetLargestSizeEstimate(uint fileSize, string identifie
size += sizeof(BlobMagic);
size += sizeof(uint); // Blob size
size += sizeof(uint); // Blob count
- size += sizeof(BlobIndex) * 5; // 5 sub-blobs: CodeDirectory, Requirements, CmsWrapper, Entitlements, DerEntitlements
+ size += sizeof(BlobIndex) * 3; // 3 sub-blobs: CodeDirectory, Requirements, CmsWrapper
// CodeDirectoryBlob
size += sizeof(BlobMagic);
@@ -142,45 +112,22 @@ public static unsafe long GetLargestSizeEstimate(uint fileSize, string identifie
size += sizeof(CodeDirectoryBlob.CodeDirectoryHeader); // CodeDirectory header
size += CodeDirectoryBlob.GetIdentifierLength(identifier); // Identifier
size += (long)CodeDirectoryBlob.GetCodeSlotCount(fileSize) * usedHashSize; // Code hashes
- size += (long)(uint)CodeDirectorySpecialSlot.DerEntitlements * usedHashSize; // Special code hashes. The highest special slot is DerEntitlements.
+ size += (long)(uint)CodeDirectorySpecialSlot.Requirements * usedHashSize; // Special code hashes
size += RequirementsBlob.Empty.Size; // Requirements is always written as an empty blob
size += CmsWrapperBlob.Empty.Size; // CMS blob is always written as an empty blob
- size += EntitlementsBlob.MaxSize;
- size += DerEntitlementsBlob.MaxSize;
return size;
}
///
/// Returns the size of a signature used to replace an existing one.
/// If the existing signature is null, it will assume sizing using the default signature, which includes the Requirements and CMS blobs.
- /// If the existing signature is not null, it will preserve the Entitlements and DER Entitlements blobs if they exist.
///
- internal static unsafe long GetSignatureSize(uint fileSize, string identifier, EmbeddedSignatureBlob? existingSignature = null, byte? hashSize = null)
+ internal static unsafe long GetSignatureSize(uint fileSize, string identifier, byte? hashSize = null)
{
byte usedHashSize = hashSize ?? CodeDirectoryBlob.DefaultHashType.GetHashSize();
- // CodeDirectory, Requirements, CMS Wrapper are always present
uint specialCodeSlotCount = (uint)CodeDirectorySpecialSlot.Requirements;
- uint embeddedSignatureSubBlobCount = 3;
- uint entitlementsBlobSize = 0;
- uint derEntitlementsBlobSize = 0;
-
- if (existingSignature != null)
- {
- // We preserve Entitlements and DER Entitlements blobs if they exist in the old signature.
- // We need to update the relevant sizes and counts to reflect this.
- specialCodeSlotCount = Math.Max((uint)CodeDirectorySpecialSlot.Requirements, existingSignature.GetSpecialSlotHashCount());
- if (existingSignature.EntitlementsBlob is not null)
- {
- entitlementsBlobSize = existingSignature.EntitlementsBlob.Size;
- embeddedSignatureSubBlobCount += 1;
- }
- if (existingSignature.DerEntitlementsBlob is not null)
- {
- derEntitlementsBlobSize = existingSignature.DerEntitlementsBlob.Size;
- embeddedSignatureSubBlobCount += 1;
- }
- }
+ uint embeddedSignatureSubBlobCount = 3; // CodeDirectory, Requirements, CMS Wrapper are always present
// Calculate the size of the new signature
long size = 0;
@@ -190,21 +137,16 @@ internal static unsafe long GetSignatureSize(uint fileSize, string identifier, E
size += sizeof(uint); // Blob count
size += sizeof(BlobIndex) * embeddedSignatureSubBlobCount; // EmbeddedSignature sub-blobs
// CodeDirectory
- size += sizeof(BlobMagic); // CodeDirectory Magic number
- size += sizeof(uint); // CodeDirectory Size field
+ size += sizeof(BlobMagic); // CD Magic number
+ size += sizeof(uint); // CD Size field
size += sizeof(CodeDirectoryBlob.CodeDirectoryHeader); // CodeDirectory header
size += CodeDirectoryBlob.GetIdentifierLength(identifier); // Identifier
size += specialCodeSlotCount * usedHashSize; // Special code hashes
size += CodeDirectoryBlob.GetCodeSlotCount(fileSize) * usedHashSize; // Code hashes
- // RequirementsBlob is always empty
+ // RequirementsBlob
size += RequirementsBlob.Empty.Size;
- // EntitlementsBlob
- size += entitlementsBlobSize;
- // DER EntitlementsBlob
- size += derEntitlementsBlobSize;
- // CMSWrapperBlob is always empty
+ // CmsWrapperBlob
size += CmsWrapperBlob.Empty.Size;
-
return size;
}
@@ -243,11 +185,5 @@ public static void AssertEquivalent(EmbeddedSignatureBlob? a, EmbeddedSignatureB
if (a.CmsWrapperBlob?.Size != b.CmsWrapperBlob?.Size)
throw new ArgumentException("CMS Wrapper blobs are not equivalent");
-
- if (a.EntitlementsBlob?.Size != b.EntitlementsBlob?.Size)
- throw new ArgumentException("Entitlements blobs are not equivalent");
-
- if (a.DerEntitlementsBlob?.Size != b.DerEntitlementsBlob?.Size)
- throw new ArgumentException("DER Entitlements blobs are not equivalent");
}
}
diff --git a/src/installer/managed/Microsoft.NET.HostModel/MachO/BinaryFormat/Blobs/EntitlementsBlob.cs b/src/installer/managed/Microsoft.NET.HostModel/MachO/BinaryFormat/Blobs/EntitlementsBlob.cs
deleted file mode 100644
index fa0f8c0c41329a..00000000000000
--- a/src/installer/managed/Microsoft.NET.HostModel/MachO/BinaryFormat/Blobs/EntitlementsBlob.cs
+++ /dev/null
@@ -1,39 +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.IO;
-
-namespace Microsoft.NET.HostModel.MachO;
-
-///
-/// See https://github.com/apple-oss-distributions/Security/blob/3dab46a11f45f2ffdbd70e2127cc5a8ce4a1f222/OSX/libsecurity_utilities/lib/blob.h
-/// Code signature data is always big endian / network order.
-///
-internal sealed class EntitlementsBlob : IBlob
-{
- private SimpleBlob _inner;
-
- public EntitlementsBlob(SimpleBlob blob)
- {
- _inner = blob;
- if (blob.Magic != BlobMagic.Entitlements)
- {
- throw new InvalidDataException($"Invalid magic for EntitlementsBlob: {blob.Magic}");
- }
- if (blob.Size > MaxSize)
- {
- throw new InvalidDataException($"EntitlementsBlob data exceeds maximum size of {MaxSize} bytes.");
- }
- }
-
- public static uint MaxSize => 2048;
-
- ///
- public BlobMagic Magic => ((IBlob)_inner).Magic;
-
- ///
- public uint Size => ((IBlob)_inner).Size;
-
- ///
- public int Write(IMachOFileWriter writer, long offset) => ((IBlob)_inner).Write(writer, offset);
-}
diff --git a/src/installer/managed/Microsoft.NET.HostModel/MachO/Enums/BlobMagic.cs b/src/installer/managed/Microsoft.NET.HostModel/MachO/Enums/BlobMagic.cs
index b2c4f245e418f0..8a709e7c066bea 100644
--- a/src/installer/managed/Microsoft.NET.HostModel/MachO/Enums/BlobMagic.cs
+++ b/src/installer/managed/Microsoft.NET.HostModel/MachO/Enums/BlobMagic.cs
@@ -11,7 +11,5 @@ internal enum BlobMagic : uint
EmbeddedSignature = 0xfade0cc0,
CodeDirectory = 0xfade0c02,
Requirements = 0xfade0c01,
- Entitlements = 0xfade7171,
- DerEntitlements = 0xfade7172,
CmsWrapper = 0xfade0b01,
}
diff --git a/src/installer/managed/Microsoft.NET.HostModel/MachO/Enums/CodeDirectorySpecialSlot.cs b/src/installer/managed/Microsoft.NET.HostModel/MachO/Enums/CodeDirectorySpecialSlot.cs
index 231083e272615b..18603dda63c778 100644
--- a/src/installer/managed/Microsoft.NET.HostModel/MachO/Enums/CodeDirectorySpecialSlot.cs
+++ b/src/installer/managed/Microsoft.NET.HostModel/MachO/Enums/CodeDirectorySpecialSlot.cs
@@ -10,7 +10,5 @@ internal enum CodeDirectorySpecialSlot
{
CodeDirectory = 0,
Requirements = 2,
- Entitlements = 5,
- DerEntitlements = 7,
CmsWrapper = 0x10000,
}
diff --git a/src/installer/managed/Microsoft.NET.HostModel/MachO/MachObjectFile.cs b/src/installer/managed/Microsoft.NET.HostModel/MachO/MachObjectFile.cs
index ecb7e3d96165c1..0129a3d00cbe94 100644
--- a/src/installer/managed/Microsoft.NET.HostModel/MachO/MachObjectFile.cs
+++ b/src/installer/managed/Microsoft.NET.HostModel/MachO/MachObjectFile.cs
@@ -112,50 +112,35 @@ public static MachObjectFile Create(IMachOFileReader file)
///
/// The file to write the signature to.
/// The identifier to use for the code signature.
- ///
- /// An optional old signature to preserve entitlements metadata.
- /// If not provided, the existing code signature blob will be used.
- /// If the existing code signature blob is not present, a new signature will be created without entitlements.
- ///
- public long AdHocSignFile(IMachOFileAccess file, string identifier, EmbeddedSignatureBlob? oldSignature = null)
+ public long AdHocSignFile(IMachOFileAccess file, string identifier)
{
- oldSignature ??= _codeSignatureBlob;
- AllocateCodeSignatureLoadCommand(identifier, oldSignature);
+ AllocateCodeSignatureLoadCommand(identifier);
_codeSignatureBlob = null;
// The code signature includes hashes of the entire file up to the code signature.
// In order to calculate the hashes correctly, everything up to the code signature must be written before the signature is built.
Write(file);
- _codeSignatureBlob = CreateSignature(this, file, identifier, oldSignature);
+ _codeSignatureBlob = CreateSignature(this, file, identifier);
Validate();
_codeSignatureBlob.Write(file, _codeSignatureLoadCommand.Command.GetDataOffset(_header));
return GetFileSize();
}
- private static EmbeddedSignatureBlob CreateSignature(MachObjectFile machObject, IMachOFileReader file, string identifier, EmbeddedSignatureBlob? oldSignature)
+ private static EmbeddedSignatureBlob CreateSignature(MachObjectFile machObject, IMachOFileReader file, string identifier)
{
- var oldSignatureBlob = oldSignature;
-
Debug.Assert(!machObject._codeSignatureLoadCommand.Command.IsDefault);
uint signatureStart = machObject._codeSignatureLoadCommand.Command.GetDataOffset(machObject._header);
RequirementsBlob requirementsBlob = RequirementsBlob.Empty;
CmsWrapperBlob cmsWrapperBlob = CmsWrapperBlob.Empty;
- EntitlementsBlob? entitlementsBlob = oldSignatureBlob?.EntitlementsBlob;
- DerEntitlementsBlob? derEntitlementsBlob = oldSignatureBlob?.DerEntitlementsBlob;
-
var codeDirectory = CodeDirectoryBlob.Create(
file,
signatureStart,
identifier,
- requirementsBlob,
- entitlementsBlob,
- derEntitlementsBlob);
+ requirementsBlob);
return new EmbeddedSignatureBlob(
codeDirectoryBlob: codeDirectory,
requirementsBlob: requirementsBlob,
- cmsWrapperBlob: cmsWrapperBlob,
- entitlementsBlob: entitlementsBlob,
- derEntitlementsBlob: derEntitlementsBlob);
+ cmsWrapperBlob: cmsWrapperBlob);
}
///
@@ -448,11 +433,11 @@ private static void ReadCommands(
///
/// Clears the old signature and sets the codeSignatureLC to the proper size and offset for a new signature.
///
- private void AllocateCodeSignatureLoadCommand(string identifier, EmbeddedSignatureBlob? oldSignature)
+ private void AllocateCodeSignatureLoadCommand(string identifier)
{
uint csOffset = GetSignatureStart();
uint csPtr = (uint)(_codeSignatureLoadCommand.Command.IsDefault ? NextLoadCommandOffset : _codeSignatureLoadCommand.FileOffset);
- uint csSize = (uint)EmbeddedSignatureBlob.GetSignatureSize(csOffset, identifier, oldSignature);
+ uint csSize = (uint)EmbeddedSignatureBlob.GetSignatureSize(csOffset, identifier);
if (_codeSignatureLoadCommand.Command.IsDefault)
{
diff --git a/src/installer/managed/Microsoft.NET.HostModel/Microsoft.NET.HostModel.csproj b/src/installer/managed/Microsoft.NET.HostModel/Microsoft.NET.HostModel.csproj
index 92a763f7032414..af27dd32dcc9a8 100644
--- a/src/installer/managed/Microsoft.NET.HostModel/Microsoft.NET.HostModel.csproj
+++ b/src/installer/managed/Microsoft.NET.HostModel/Microsoft.NET.HostModel.csproj
@@ -24,6 +24,7 @@
+
diff --git a/src/installer/managed/Microsoft.NET.HostModel/ResourceUpdater.cs b/src/installer/managed/Microsoft.NET.HostModel/ResourceUpdater.cs
index e4791a6bb14e99..1873e38956038e 100644
--- a/src/installer/managed/Microsoft.NET.HostModel/ResourceUpdater.cs
+++ b/src/installer/managed/Microsoft.NET.HostModel/ResourceUpdater.cs
@@ -13,7 +13,7 @@ namespace Microsoft.NET.HostModel
///
/// Provides methods for modifying the embedded native resources in a PE image.
///
- public class ResourceUpdater : IDisposable
+ public sealed class ResourceUpdater : IDisposable
{
private readonly FileStream stream;
private readonly PEReader _reader;
@@ -331,12 +331,15 @@ public void Dispose()
GC.SuppressFinalize(this);
}
- public void Dispose(bool disposing)
+ private void Dispose(bool disposing)
{
- if (disposing && !leaveOpen)
+ if (disposing)
{
_reader.Dispose();
- stream.Dispose();
+ if (!leaveOpen)
+ {
+ stream.Dispose();
+ }
}
}
}
diff --git a/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props b/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props
index 44625877c6561d..e1cc2c0e0110fa 100644
--- a/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props
+++ b/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props
@@ -5,6 +5,7 @@
$(MicrosoftNetCoreAppFrameworkName)
.NET Runtime
+ true
+
+
+
+
+
+
+
diff --git a/src/installer/pkg/sfx/Microsoft.NETCore.App/PackageOverrides.txt b/src/installer/pkg/sfx/Microsoft.NETCore.App/PackageOverrides.txt
index ebb64b23369a45..29f3ee5cb4140d 100644
--- a/src/installer/pkg/sfx/Microsoft.NETCore.App/PackageOverrides.txt
+++ b/src/installer/pkg/sfx/Microsoft.NETCore.App/PackageOverrides.txt
@@ -253,6 +253,7 @@ System.Text.Encodings.Web|${ProductVersion}
System.Text.Json|${ProductVersion}
System.Text.RegularExpressions|4.3.1
System.Threading|4.3.0
+System.Threading.AccessControl|${ProductVersion}
System.Threading.Channels|${ProductVersion}
System.Threading.Overlapped|4.3.0
System.Threading.Tasks|4.3.0
diff --git a/src/installer/pkg/sfx/bundle/Microsoft.NETCore.App.Bundle.bundleproj b/src/installer/pkg/sfx/bundle/Microsoft.NETCore.App.Bundle.bundleproj
index bceda8cc30cfe3..ca964ce663a88b 100644
--- a/src/installer/pkg/sfx/bundle/Microsoft.NETCore.App.Bundle.bundleproj
+++ b/src/installer/pkg/sfx/bundle/Microsoft.NETCore.App.Bundle.bundleproj
@@ -15,9 +15,18 @@
$(MSBuildProjectDirectory)/shared-framework-distribution-template-$(TargetArchitecture).xml
com.microsoft.dotnet.Microsoft.NETCore.App.$(ProductVersion).osx.$(TargetArchitecture)
osx_resources
+ true
+
+
+
+
+
+
+
+
diff --git a/src/installer/pkg/sfx/bundle/bundle.thm b/src/installer/pkg/sfx/bundle/bundle.thm
index df6c7fc9600e3c..9dd8f98e35b829 100644
--- a/src/installer/pkg/sfx/bundle/bundle.thm
+++ b/src/installer/pkg/sfx/bundle/bundle.thm
@@ -1,114 +1,144 @@
-
-
- #(loc.Caption)
- Segoe UI
- Segoe UI
- Segoe UI
- Segoe UI
- Segoe UI
- Segoe UI
-
- #(loc.Title)
+
+
+
+ Segoe UI
+ Segoe UI
+
+
+ Segoe UI
+
+
+
+
+
+
+
+
-
+
+
- #(loc.HelpHeader)
- #(loc.HelpText)
-
-
+
-
-
-
-
- #(loc.WelcomeHeaderMessage)
- #(loc.WelcomeDescription)
- #(loc.LicenseAssent)
- #(loc.PrivacyStatementLink)
- #(loc.EulaLink)
-
-
-
-
-
-
-
- #(loc.OptionsHeader)
- #(loc.OptionsLocationLabel)
-
-
-
-
-
-
-
+
+
+
- #(loc.FilesInUseHeader)
- #(loc.FilesInUseLabel)
-
+
+
-
-
+
+ #(loc.PrivacyStatementLink)
+ #(loc.EulaLink)
-
-
-
+
+
-
-
-
- #(loc.ProgressHeader)
- #(loc.ProgressLabel)
- #(loc.OverallProgressPackageText)
-
-
+
+
+
+
+
+
+
-
-
+
- #(loc.ModifyHeader)
-
-
-
+
+
+
+
+
-
-
-
- #(loc.SuccessHeader)
- #(loc.SuccessInstallHeader)
- #(loc.SuccessRepairHeader)
- #(loc.SuccessUninstallHeader)
-
- #(loc.SuccessRestartText)
-
- #(loc.SuccessInstallLocation)
- #(loc.SuccessInstallProductName)
- #(loc.ResourcesHeader)
- #(loc.DocumentationLink)
- #(loc.ReleaseNotesLink)
- #(loc.TutorialLink)
- #(loc.TelemetryLink)
-
-
-
+
+
+
+
+
+
+ #(loc.DocumentationLink)
+ #(loc.ReleaseNotesLink)
+ #(loc.TutorialLink)
+ #(loc.TelemetryLink)
+
+
+
+
+
+
-
-
-
- #(loc.FailureHeader)
- #(loc.FailureInstallHeader)
- #(loc.FailureUninstallHeader)
- #(loc.FailureRepairHeader)
- #(loc.FailureHyperlinkLogText)
-
- #(loc.FailureRestartText)
-
-
+
+
+
+ #(loc.FailureHyperlinkLogText)
+
+
+
+
+
+
+
+
-
+
+
\ No newline at end of file
diff --git a/src/installer/pkg/sfx/bundle/theme/1028/bundle.wxl b/src/installer/pkg/sfx/bundle/theme/1028/bundle.wxl
index 62c9abbbeb43a9..bf1f17d6b79873 100644
--- a/src/installer/pkg/sfx/bundle/theme/1028/bundle.wxl
+++ b/src/installer/pkg/sfx/bundle/theme/1028/bundle.wxl
@@ -1,74 +1,79 @@
-
-
- [WixBundleName] 安裝程式
- [BUNDLEMONIKER]
- 您只需要殼層、文字編輯器和 10 分鐘的時間。
+
+
+
+ 確定要取消嗎?
- 前一版
-
- /install | /repair | /uninstall | /layout [directory] - 在目錄中安裝、修復、解除安裝或
- 建立搭售方案的完整本機複本。預設為安裝。
+準備好了嗎?設定好了嗎?開始吧!"/>
+
+
+
+ 關閉(&C)
- 我同意授權條款及條件(&A)
- 選項(&O)
- 安裝(&I)
- 關閉(&C)
-
- 安裝位置:
- 瀏覽(&B)
- 確定(&O)
- 取消(&C)
-
- 處理中:
- 正在初始化...
- 取消(&C)
-
- 修復(&R)
- 解除安裝(&U)
- 關閉(&C)
-
-
-
-
- 啟動(&L)
- 必須重新啟動電腦,才能使用此軟體。
- 重新啟動(&R)
- 關閉(&C)
-
-
-
-
- 有一個或多個問題導致安裝程式失敗。請解決問題,然後重試一次安裝。如需詳細資訊,請參閱<a href="#">記錄檔</a>。
- 必須重新啟動電腦,才能完成軟體的復原。
- 重新啟動(&R)
- 關閉(&C)
- 此作業系統不支援 [PRODUCT_NAME]。如需詳細資訊,請參閱 [LINK_PREREQ_PAGE]。
- x86 作業系統不支援 [PRODUCT_NAME]。請使用對應的 x86 安裝程式來安裝。
-
- 以下應用程式正在使用需要進行更新的檔案:
- 關閉應用程式並嘗試重新啟動(&A)
- 不關閉應用程式,需要重新啟動(&D)
- 確定(&O)
- 取消(&C)
-
- .NET Runtime 可用於在您的 Windows 電腦上執行 .NET 應用程式。.NET 為開放原始碼形式,且可跨平台運作,同時受到 Microsoft 支援。希望您會喜歡!
- 深入了解 .NET
- 下列項目已安裝在 [DOTNETHOME]
- - [BUNDLEMONIKER]
-
- <A HREF="https://aka.ms/dotnet-docs">文件</A>
- <A HREF="https://aka.ms/20-p2-rel-notes">版本資訊</A>
- <A HREF="https://aka.ms/dotnet-tutorials">教學課程</A>
- <A HREF="https://aka.ms/dotnet-cli-telemetry">.NET 遙測</A>
- <A HREF="https://aka.ms/dev-privacy">隱私權聲明</A>
- <A HREF="https://aka.ms/dotnet-license-windows">.NET 的授權資訊</A>
- 按一下 [\[]安裝[\[] 即表示您同意下列條款。
+/norestart - 抑制任何重新啟動嘗試。根據預設,UI 在重新啟動前會先提示。
+/log log.txt - 記錄到特定檔案。預設會在 %TEMP% 中建立記錄檔。"/>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/installer/pkg/sfx/bundle/theme/1029/bundle.wxl b/src/installer/pkg/sfx/bundle/theme/1029/bundle.wxl
index 9def6b3f9676fc..dfcd451e65171f 100644
--- a/src/installer/pkg/sfx/bundle/theme/1029/bundle.wxl
+++ b/src/installer/pkg/sfx/bundle/theme/1029/bundle.wxl
@@ -1,74 +1,79 @@
-
-
- Instalační program pro [WixBundleName]
- [BUNDLEMONIKER]
- Potřebujete jenom prostředí, textový editor a 10 minut času.
+
+
+
+ Opravdu chcete akci zrušit?
- Předchozí verze
-
- /install | /repair | /uninstall | /layout [adresář] – Nainstaluje, opraví, odinstaluje nebo
- vytvoří úplnou místní kopii svazku v adresáři. Výchozí možností je instalace.
+Jste připraveni? Připraveni? Jdeme na to!"/>
+
+
+
+ &Zavřít
- Souhl&asím s licenčními podmínkami
- M&ožnosti
- &Instalovat
- &Zavřít
-
- Umístění instalace:
- &Procházet
- &OK
- &Storno
-
- Probíhá zpracování:
- Inicializace...
- &Storno
-
- Op&ravit
- O&dinstalovat
- &Zavřít
-
-
-
-
- &Spustit
- Před použitím tohoto softwaru musíte restartovat počítač.
- &Restartovat
- &Zavřít
-
-
-
-
- Jeden nebo více problémů způsobilo selhání instalace. Opravte tyto problémy a znovu spusťte instalaci. Pro více informací se podívejte do <a href="#">souboru protokolu</a>.
- Pro dokončení vrácení změn tohoto softwaru je potřeba restartovat počítač.
- &Restartovat
- &Zavřít
- [PRODUCT_NAME] se tomto operačním systému nepodporuje. Další informace: [LINK_PREREQ_PAGE]
- [PRODUCT_NAME] se v operačních systémech pro platformu x86 nepodporuje. Použijte prosím k instalaci odpovídající instalační program pro platformu x86.
-
- Následující aplikace používají soubory, které je potřeba aktualizovat:
- Zavřete &aplikace a zkuste je restartovat.
- A&plikace nezavírejte. Bude potřeba provést restart.
- &OK
- &Zrušit
-
- Modul .NET Runtime se používá ke spouštění aplikací .NET na počítači s Windows. .NET je open source, k dispozici pro více platforem a podporovaný Microsoftem. Doufáme, že se vám bude líbit!
- Další informace o .NET
- Do [DOTNETHOME] se nainstalovaly následující položky.
- - [BUNDLEMONIKER]
-
- <A HREF="https://aka.ms/dotnet-docs">Dokumentace</A>
- <A HREF="https://aka.ms/20-p2-rel-notes">Zpráva k vydání verze</A>
- <A HREF="https://aka.ms/dotnet-tutorials">Kurzy</A>
- <A HREF="https://aka.ms/dotnet-cli-telemetry">Telemetrie pro platformu .NET</A>
- <A HREF="https://aka.ms/dev-privacy">Prohlášení o zásadách ochrany osobních údajů</A>
- <A HREF="https://aka.ms/dotnet-license-windows">Informace o licencování pro .NET</A>
- Kliknutím na Nainstalovat vyjadřujete souhlas s následujícími podmínkami.
+/norestart – Potlačí všechny pokusy o restartování. Ve výchozím nastavení uživatelské rozhraní zobrazí před restartováním výzvu.
+/log log.txt – Zapíše protokol do konkrétního souboru. Ve výchozím nastavení bude soubor protokolu vytvořen v adresáři %TEMP%."/>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/installer/pkg/sfx/bundle/theme/1031/bundle.wxl b/src/installer/pkg/sfx/bundle/theme/1031/bundle.wxl
index 397dfe8e51ce95..cbb5b265eed13d 100644
--- a/src/installer/pkg/sfx/bundle/theme/1031/bundle.wxl
+++ b/src/installer/pkg/sfx/bundle/theme/1031/bundle.wxl
@@ -1,74 +1,79 @@
-
-
- [WixBundleName]-Installationsprogramm
- [BUNDLEMONIKER]
- Sie benötigen nur eine Shell, einen Text-Editor und 10 Minuten Zeit.
+
+
+
+ Möchten Sie den Vorgang wirklich abbrechen?
- Vorherige Version
-
- /install | /repair | /uninstall | /layout [Verzeichnis] - installiert, repariert, deinstalliert oder
- erstellt eine vollständige lokale Kopie des Bundles im Verzeichnis. Installieren ist die Standardeinstellung.
+Auf die Plätze? Fertig? Los geht's!"/>
+
+
+
+ S&chließen
- Ich &stimme den Bedingungen des Lizenzvertrags zu
- &Optionen
- &Installieren
- S&chließen
-
- Installationspfad:
- &Durchsuchen
- &OK
- &Abbrechen
-
- Wird verarbeitet:
- Wird initialisiert...
- &Abbrechen
-
- &Reparieren
- &Deinstallieren
- S&chließen
-
-
-
-
- &Starten
- Sie müssen den Computer neu starten, bevor Sie die Software verwenden können.
- &Neustart
- S&chließen
-
-
-
-
- Setup ist aufgrund eines oder mehrerer Probleme fehlgeschlagen. Beheben Sie die Probleme, und führen Sie Setup erneut aus. Weitere Informationen finden Sie in der <a href="#">Protokolldatei</a>.
- Sie müssen den Computer neu starten, um das Zurücksetzen der Software abzuschließen.
- &Neustart
- S&chließen
- [PRODUCT_NAME] wird auf diesem Betriebssystem nicht unterstützt. Weitere Informationen finden Sie unter [LINK_PREREQ_PAGE].
- [PRODUCT_NAME] wird auf x86-Betriebssystemen nicht unterstützt. Installieren Sie das entsprechende x86-Installationsprogramm.
-
- Die folgenden Anwendungen verwenden Dateien, die aktualisiert werden müssen:
- Schließen Sie die &Anwendungen, und versuchen Sie sie erneut zu starten.
- &Anwendungen nicht schließen. Ein Neustart ist erforderlich.
- &OK
- &Abbrechen
-
- Die .NET-Runtime wird zum Ausführen von .NET-Anwendungen auf Ihrem Windows-Computer verwendet. .NET ist ein plattformübergreifendes Open-Source-Framework, das von Microsoft unterstützt wird. Wir wünschen Ihnen viel Spaß damit!
- Weitere Informationen zu .NET
- Folgendes wurde unter [DOTNETHOME] installiert.
- - [BUNDLEMONIKER]
-
- <A HREF="https://aka.ms/dotnet-docs">Dokumentation</A>
- <A HREF="https://aka.ms/20-p2-rel-notes">Versionshinweise</A>
- <A HREF="https://aka.ms/dotnet-tutorials">Tutorials</A>
- <A HREF="https://aka.ms/dotnet-cli-telemetry">.NET-Telemetrie</A>
- <A HREF="https://aka.ms/dev-privacy">Datenschutzerklärung</A>
- <A HREF="https://aka.ms/dotnet-license-windows">Lizenzierungsinformationen für .NET</A>
- Durch Klicken auf "Installieren" stimmen Sie den nachstehenden Bedingungen zu.
+/norestart: Unterdrückt alle Neustartversuche. Standardmäßig wird die Benutzeroberfläche vor dem Neustart aufgefordert.
+/log log.txt: Protokolliert eine bestimmte Datei. Standardmäßig wird die Protokolldatei in %TEMP% erstellt."/>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/installer/pkg/sfx/bundle/theme/1033/bundle.wxl b/src/installer/pkg/sfx/bundle/theme/1033/bundle.wxl
index d73fc75220bfa8..8641340a1b8371 100644
--- a/src/installer/pkg/sfx/bundle/theme/1033/bundle.wxl
+++ b/src/installer/pkg/sfx/bundle/theme/1033/bundle.wxl
@@ -1,74 +1,79 @@
-
-
- [WixBundleName] Installer
- [BUNDLEMONIKER]
- You just need a shell, a text editor and 10 minutes of your time.
+
+
+
+ Are you sure you want to cancel?
- Previous version
-
- /install | /repair | /uninstall | /layout [directory] - installs, repairs, uninstalls or
+Ready? Set? Let's go!" />
+
+
+
+ &Close
- I &agree to the license terms and conditions
- &Options
- &Install
- &Close
-
- Install location:
- &Browse
- &OK
- &Cancel
-
- Processing:
- Initializing...
- &Cancel
-
- &Repair
- &Uninstall
- &Close
-
-
-
-
- &Launch
- You must restart your computer before you can use the software.
- &Restart
- &Close
-
-
-
-
- One or more issues caused the setup to fail. Please fix the issues and then retry setup. For more information see the <a href="#">log file</a>.
- You must restart your computer to complete the rollback of the software.
- &Restart
- &Close
- The [PRODUCT_NAME] is not supported on this operating system. For more information, see [LINK_PREREQ_PAGE].
- The [PRODUCT_NAME] isn't supported on x86 operating systems. Please install using the corresponding x86 installer.
-
- The following applications are using files that need to be updated:
- Close the &applications and attempt to restart them.
- &Do not close applications. A reboot will be required.
- &OK
- &Cancel
-
- The .NET Runtime is used to run .NET applications, on your Windows computer. .NET is open source, cross platform, and supported by Microsoft. We hope you enjoy it!
- Learn more about .NET
- The following was installed at [DOTNETHOME]
- - [BUNDLEMONIKER]
-
- <A HREF="https://aka.ms/dotnet-docs">Documentation</A>
- <A HREF="https://aka.ms/20-p2-rel-notes">Release Notes</A>
- <A HREF="https://aka.ms/dotnet-tutorials">Tutorials</A>
- <A HREF="https://aka.ms/dotnet-cli-telemetry">.NET Telemetry</A>
- <A HREF="https://aka.ms/dev-privacy">Privacy Statement</A>
- <A HREF="https://aka.ms/dotnet-license-windows">Licensing Information for .NET</A>
- By clicking Install, you agree to the following terms.
+/log log.txt - logs to a specific file. By default a log file is created in %TEMP%." />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/installer/pkg/sfx/bundle/theme/1036/bundle.wxl b/src/installer/pkg/sfx/bundle/theme/1036/bundle.wxl
index a6921f8fdc3309..0719b4a3cab415 100644
--- a/src/installer/pkg/sfx/bundle/theme/1036/bundle.wxl
+++ b/src/installer/pkg/sfx/bundle/theme/1036/bundle.wxl
@@ -1,74 +1,79 @@
-
-
- Programme d’installation de [WixBundleName]
- [BUNDLEMONIKER]
- Vous avez juste besoin d'un interpréteur de commandes, d'un éditeur de texte et de 10 minutes.
+
+
+
+ Voulez-vous vraiment annuler ?
- Version précédente
-
- /install | /repair | /uninstall | /layout [répertoire] - installe, répare, désinstalle ou
- crée une copie locale complète du bundle dans le répertoire. Install est l'option par défaut.
+À vos marques ? Prêt ? C’est parti !"/>
+
+
+
+ &Fermer
- J'&accepte les conditions générales de la licence
- &Options
- &Installer
- &Fermer
-
- Emplacement de l'installation :
- &Parcourir
- &OK
- &Annuler
-
- En cours :
- Initialisation...
- &Annuler
-
- &Réparer
- &Désinstaller
- &Fermer
-
-
-
-
- &Démarrer
- Vous devez redémarrer votre ordinateur avant de pouvoir utiliser le logiciel.
- &Redémarrer
- &Fermer
-
-
-
-
- Le programme d’installation a échoué en raison d’un ou de plusieurs problèmes. Veuillez corriger ces problèmes, puis relancez le programme d’installation. Pour plus d’informations, consultez le <a href="#">fichier journal</a>.
- Vous devez redémarrer votre ordinateur pour terminer l'opération de restauration du logiciel.
- &Redémarrer
- &Fermer
- [PRODUCT_NAME] n'est pas pris en charge sur ce système d'exploitation. Pour plus d'informations, consultez [LINK_PREREQ_PAGE].
- [PRODUCT_NAME] n'est pas pris en charge sur les systèmes d'exploitation x86. Effectuez l'installation à l'aide du programme d'installation x86 correspondant.
-
- Les applications suivantes utilisent des fichiers nécessitant une mise à jour :
- &Fermer les applications essayer de les ouvrir de nouveau.
- &Ne pas fermer les applications. Un redémarrage sera nécessaire.
- &OK
- &Annuler
-
- Le runtime .NET vous permet d'exécuter les applications .NET sur votre ordinateur Windows. .NET est open source, multiplateforme et pris en charge par Microsoft. Nous espérons que vous l'apprécierez !
- En savoir plus sur .NET
- L'élément suivant a été installé sur [DOTNETHOME]
- - [BUNDLEMONIKER]
-
- <A HREF="https://aka.ms/dotnet-docs">Documentation</A>
- <A HREF="https://aka.ms/20-p2-rel-notes">Notes de publication</A>
- <A HREF="https://aka.ms/dotnet-tutorials">Tutoriels</A>
- <A HREF="https://aka.ms/dotnet-cli-telemetry">Télémétrie .NET</A>
- <A HREF="https://aka.ms/dev-privacy">Déclaration de confidentialité</A>
- <A HREF="https://aka.ms/dotnet-license-windows">Informations de licence pour .NET</A>
- En cliquant sur Installer, vous acceptez les conditions suivantes.
+/norestart – supprime toute tentative de redémarrage. Par défaut, l’interface utilisateur vous invite à redémarrer.
+/log log.txt – enregistre dans un fichier spécifique. Par défaut, un fichier journal est créé dans %TEMP%."/>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/installer/pkg/sfx/bundle/theme/1040/bundle.wxl b/src/installer/pkg/sfx/bundle/theme/1040/bundle.wxl
index d06e2078812c7e..7d7c4897abb70a 100644
--- a/src/installer/pkg/sfx/bundle/theme/1040/bundle.wxl
+++ b/src/installer/pkg/sfx/bundle/theme/1040/bundle.wxl
@@ -1,74 +1,79 @@
-
-
- Programma di installazione di [WixBundleName]
- [BUNDLEMONIKER]
- Bastano solo una shell, un editor di testo e 10 minuti di tempo.
+
+
+
+ Annullare?
- Versione precedente
-
- /install | /repair | /uninstall | /layout [directory] - installa, ripara, disinstalla o
- crea una copia locale completa del bundle nella directory. L'opzione predefinita è install.
+Pronti? Partenza? Via!"/>
+
+
+
+ &Chiudi
- &Accetto i termini e le condizioni di licenza
- &Opzioni
- &Installa
- &Chiudi
-
- Percorso di installazione:
- &Sfoglia
- &OK
- Ann&ulla
-
- Elaborazione di:
- Inizializzazione in corso...
- Ann&ulla
-
- &Ripristina
- &Disinstalla
- &Chiudi
-
-
-
-
- &Avvia
- È necessario riavviare il computer prima di utilizzare il software.
- &Riavvia
- &Chiudi
-
-
-
-
- Installazione non riuscita a causa di uno o più problemi. Risolvere i problemi e ritentare l'installazione. Per ulteriori informazioni, vedere il <a href="#">file di log</a>.
- È necessario riavviare il computer per completare il rollback del software.
- &Riavvia
- &Chiudi
- [PRODUCT_NAME] non è supportato in questo sistema operativo. Per altre informazioni, vedere [LINK_PREREQ_PAGE].
- [PRODUCT_NAME] non è supportato in sistemi operativi x86. Eseguire l'installazione usando il programma di installazione x86 corrispondente.
-
- Le applicazioni seguenti usano file che necessitano di aggiornamento:
- Chiudere le &applicazioni e provare a riavviarle.
- &Non chiudere le applicazioni; sarà necessario riavviare il sistema
- &OK
- &Annulla
-
- Runtime di .NET consente di eseguire applicazioni .NET nel computer Windows. .NET è open source, multipiattaforma e supportato da Microsoft.
- Altre informazioni su .NET
- I componenti seguenti sono stati installati in [DOTNETHOME]
- - [BUNDLEMONIKER]
-
- <A HREF="https://aka.ms/dotnet-docs">Documentazione</A>
- <A HREF="https://aka.ms/20-p2-rel-notes">Note sulla versione</A>
- <A HREF="https://aka.ms/dotnet-tutorials">Esercitazioni</A>
- <A HREF="https://aka.ms/dotnet-cli-telemetry">Telemetria di .NET</A>
- <A HREF="https://aka.ms/dev-privacy">Informativa sulla privacy</A>
- <A HREF="https://aka.ms/dotnet-license-windows">Informazioni sulla licenza per .NET</A>
- Facendo clic su Installa, si accettano le condizioni seguenti.
+/norestart - Consente di sopprimere qualsiasi tentativo di riavvio. Per impostazione predefinita, prima del riavvio verrà visualizzata una richiesta nell'interfaccia utente.
+/log log.txt - Esegue la registrazione in un file specifico. Per impostazione predefinita, viene creato un file di log in %TEMP%."/>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/installer/pkg/sfx/bundle/theme/1041/bundle.wxl b/src/installer/pkg/sfx/bundle/theme/1041/bundle.wxl
index 1aaf18c5356252..94371315b6aa41 100644
--- a/src/installer/pkg/sfx/bundle/theme/1041/bundle.wxl
+++ b/src/installer/pkg/sfx/bundle/theme/1041/bundle.wxl
@@ -1,74 +1,79 @@
-
-
- [WixBundleName] インストーラー
- [BUNDLEMONIKER]
- 必要なのは、シェル、テキスト エディター、それに時間が 10 分のみです。
+
+
+
+ 取り消しますか?
- 以前のバージョン
-
- /install | /repair | /uninstall | /layout [directory] - バンドルの完全なローカル コピーに対する
- ディレクトリへのインストール、修復、ディレクトリからのアンインストール、またはディレクトリ内への作成を行います。既定の設定はインストールです。
+準備はいいですか?準備はできましたか?始めましょう。"/>
+
+
+
+ 閉じる(&C)
- ライセンス条項および使用条件に同意する(&A)
- オプション(&O)
- インストール(&I)
- 閉じる(&C)
-
- インストール場所:
- 参照(&B)
- OK(&O)
- キャンセル(&C)
-
- 処理中:
- 初期化しています...
- キャンセル(&C)
-
- 修復(&R)
- アンインストール(&U)
- 閉じる(&C)
-
-
-
-
- 起動(&L)
- ソフトウェアを使用する前にコンピューターを再起動する必要があります。
- 再起動(&R)
- 閉じる(&C)
-
-
-
-
- 1 つまたは複数の問題により、セットアップが失敗しました。問題を解決してからセットアップを再試行してください。詳細については、<a href="#">ログ ファイル</a>を参照してください。
- ソフトウェアのロールバックを完了するには、コンピューターを再起動する必要があります。
- 再起動(&R)
- 閉じる(&C)
- [PRODUCT_NAME] は、このオペレーティング システムではサポートされていません。詳細については、[LINK_PREREQ_PAGE] を参照してください。
- x86 オペレーティング システムでは、[PRODUCT_NAME] はサポートされていません。対応する x86 インストーラーを使用してインストールしてください。
-
- 次のアプリケーションは、更新の必要があるファイルを使用しています:
- アプリケーションを閉じて再起動を試みる。(&A)
- アプリケーションを終了させない (コンピューターの再起動が必要になります)(&D)
- OK(&O)
- キャンセル(&C)
-
- .NET Runtime は、Windows コンピューターで .NET アプリケーションを実行するために使用されます。.NET はオープン ソースのクロス プラットフォームで、Microsoft によってサポートされています。ぜひご利用ください。
- .Net の詳細情報
- [DOTNETHOME] に以下がインストールされました
- - [BUNDLEMONIKER]
-
- <A HREF="https://aka.ms/dotnet-docs">ドキュメント</A>
- <A HREF="https://aka.ms/20-p2-rel-notes">リリース ノート</A>
- <A HREF="https://aka.ms/dotnet-tutorials">チュートリアル</A>
- <A HREF="https://aka.ms/dotnet-cli-telemetry">.NET テレメトリ</A>
- <A HREF="https://aka.ms/dev-privacy">プライバシーに関する声明</A>
- <A HREF="https://aka.ms/dotnet-license-windows">.NET のライセンス情報</A>
- インストール をクリックすると、次の条項に同意したものと見なされます。
+/norestart - 再起動の試行をすべて抑止します。既定では、再起動の前に UI が表示されます。
+/log log.txt - 特定のファイルにログを出力します。既定では、ログ ファイルは %TEMP% に作成されます。"/>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/installer/pkg/sfx/bundle/theme/1042/bundle.wxl b/src/installer/pkg/sfx/bundle/theme/1042/bundle.wxl
index de7139b850c213..9d6114db47280d 100644
--- a/src/installer/pkg/sfx/bundle/theme/1042/bundle.wxl
+++ b/src/installer/pkg/sfx/bundle/theme/1042/bundle.wxl
@@ -1,74 +1,79 @@
-
-
- [WixBundleName] 설치 관리자
- [BUNDLEMONIKER]
- 셸, 텍스트 편집기, 10분의 시간만 있으면 됩니다.
+
+
+
+ 취소하시겠습니까?
- 이전 버전
-
- /install | /repair | /uninstall | /layout [directory] - 디렉터리에 번들의 전체 로컬 복사본을 설치, 복구, 제거 또는
- 작성합니다. 설치가 기본값입니다.
+준비되셨나요? 준비하시고, 시작!"/>
+
+
+
+ 닫기(&C)
- 동의함(&A)
- 옵션(&O)
- 설치(&I)
- 닫기(&C)
-
- 설치 위치:
- 찾아보기(&B)
- 확인(&O)
- 취소(&C)
-
- 처리 중:
- 초기화하는 중...
- 취소(&C)
-
- 복구(&R)
- 제거(&U)
- 닫기(&C)
-
-
-
-
- 시작(&L)
- 소프트웨어를 사용하려면 먼저 컴퓨터를 다시 시작해야 합니다.
- 다시 시작(&R)
- 닫기(&C)
-
-
-
-
- 하나 이상의 문제가 발생하여 설치하지 못했습니다. 문제를 해결한 다음 설치를 다시 시도하십시오. 자세한 내용은 <a href="#">로그 파일</a>을 참조하십시오.
- 소프트웨어 롤백을 완료하려면 컴퓨터를 다시 시작해야 합니다.
- 다시 시작(&R)
- 닫기(&C)
- 이 운영 체제에서는 [PRODUCT_NAME]이(가) 지원되지 않습니다. 자세한 내용은 [LINK_PREREQ_PAGE]을(를) 참조하세요.
- x86 운영 체제에서는 [PRODUCT_NAME]이(가) 지원되지 않습니다. 해당 x86 설치 관리자를 사용하여 설치하세요.
-
- 다음의 응용 프로그램이 업데이트해야 할 파일을 사용 중입니다.
- 응용 프로그램을 닫고 다시 시작합니다(&A).
- 응용 프로그램을 닫지 않습니다(&D). 다시 부팅해야 합니다.
- 확인(&O)
- 취소(&C)
-
- .NET 런타임은 Windows 컴퓨터에서 .NET 애플리케이션을 실행하는 데 사용됩니다. .NET은 오픈 소스 및 플랫폼 간이며 Microsoft에서 지원합니다. .NET을 유용하게 사용하시길 바랍니다.
- .NET에 대한 자세한 정보
- 다음이 [DOTNETHOME]에 설치되었습니다.
- - [BUNDLEMONIKER]
-
- <A HREF="https://aka.ms/dotnet-docs">설명서</A>
- <A HREF="https://aka.ms/20-p2-rel-notes">릴리스 정보</A>
- <A HREF="https://aka.ms/dotnet-tutorials">자습서</A>
- <A HREF="https://aka.ms/dotnet-cli-telemetry">.NET 원격 분석</A>
- <A HREF="https://aka.ms/dev-privacy">개인정보처리방침</A>
- <A HREF="https://aka.ms/dotnet-license-windows">.NET에 대한 라이선스 정보</A>
- 설치를 클릭하면 다음 사용 약관에 동의하는 것입니다.
+/norestart - 다시 시작 시도를 억제합니다. 기본적으로 UI는 다시 시작하기 전에 메시지를 표시합니다.
+/log log.txt - 특정 파일에 로그합니다. 기본적으로 로그 파일은 %TEMP%에 만들어집니다."/>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/installer/pkg/sfx/bundle/theme/1045/bundle.wxl b/src/installer/pkg/sfx/bundle/theme/1045/bundle.wxl
index 7588ea7062e206..8ec725859372ca 100644
--- a/src/installer/pkg/sfx/bundle/theme/1045/bundle.wxl
+++ b/src/installer/pkg/sfx/bundle/theme/1045/bundle.wxl
@@ -1,74 +1,79 @@
-
-
- Instalator pakietu [WixBundleName]
- [BUNDLEMONIKER]
- Potrzebujemy tylko powłoki, edytora tekstu i 10 minut czasu.
+
+
+
+ Czy na pewno chcesz anulować?
- Poprzednia wersja
-
- /install | /repair | /uninstall | /layout [katalog] - Instaluje, naprawia, odinstalowuje
- lub tworzy pełną lokalną kopię pakietu w katalogu. Domyślnie jest używany przełącznik install.
+Wszystko gotowe? Gotowe? Zaczynajmy!"/>
+
+
+
+ &Zamknij
- Zg&adzam się na warunki licencji
- &Opcje
- Za&instaluj
- &Zamknij
-
- Lokalizacja instalacji:
- &Przeglądaj
- &OK
- &Anuluj
-
- Przetwarzanie:
- Trwa inicjowanie...
- &Anuluj
-
- Nap&raw
- O&dinstaluj
- &Zamknij
-
-
-
-
- &Uruchom
- Aby korzystać z oprogramowania, należy ponownie uruchomić komputer.
- &Uruchom ponownie
- &Zamknij
-
-
-
-
- Jeden lub więcej problemów spowodował niepowodzenie instalacji. Napraw błędy, a następnie uruchom ponownie instalację. Aby uzyskać więcej informacji zobacz <a href="#">plik dziennika</a>.
- Należy ponownie uruchomić komputer, aby dokończyć wycofywanie oprogramowania.
- &Uruchom ponownie
- &Zamknij
- Produkt [PRODUCT_NAME] nie jest obsługiwany w tym systemie operacyjnym. Aby uzyskać więcej informacji, zobacz [LINK_PREREQ_PAGE].
- Produkt [PRODUCT_NAME] nie jest obsługiwany w systemach operacyjnych x86. Przeprowadź instalację przy użyciu odpowiedniego instalatora x86.
-
- Następujące aplikacje korzystają z plików, które muszą zostać zaktualizowane:
- Zamknij &aplikacje i spróbuj je ponownie uruchomić.
- &Nie zamykaj aplikacji. Będzie konieczne ponowne uruchomienie.
- &OK
- &Anuluj
-
- Środowisko uruchomieniowe platformy .NET służy do uruchamiania aplikacji platformy .NET na komputerze z systemem Windows. Platforma .NET jest oprogramowaniem typu open source, działa na różnych platformach i jest obsługiwana przez firmę Microsoft. Mamy nadzieję, że Ci się podoba!
- Dowiedz się więcej o platformie .NET
- Następujące elementy zainstalowano w [DOTNETHOME]
- - [BUNDLEMONIKER]
-
- <A HREF="https://aka.ms/dotnet-docs">Dokumentacja</A>
- <A HREF="https://aka.ms/20-p2-rel-notes">Informacje o wersji</A>
- <A HREF="https://aka.ms/dotnet-tutorials">Samouczki</A>
- <A HREF="https://aka.ms/dotnet-cli-telemetry">Telemetria platformy .NET</A>
- <A HREF="https://aka.ms/dev-privacy">Zasady zachowania poufności informacji</A>
- <A HREF="https://aka.ms/dotnet-license-windows">Informacje o licencjonowaniu dla platformy .NET</A>
- Klikając pozycję Zainstaluj, wyrażasz zgodę na następujące warunki.
+/norestart — powstrzymuje przed ewentualnymi próbami ponownego uruchomienia. Domyślnie interfejs użytkownika będzie monitować przed ponownym uruchomieniem.
+/log log.txt — rejestruje w określonym pliku. Domyślnie plik dziennika jest tworzony w folderze %TEMP%."/>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/installer/pkg/sfx/bundle/theme/1046/bundle.wxl b/src/installer/pkg/sfx/bundle/theme/1046/bundle.wxl
index 8bf76b5d78617e..da50001273b809 100644
--- a/src/installer/pkg/sfx/bundle/theme/1046/bundle.wxl
+++ b/src/installer/pkg/sfx/bundle/theme/1046/bundle.wxl
@@ -1,74 +1,79 @@
-
-
- Instalador do [WixBundleName]
- [BUNDLEMONIKER]
- Você só precisa de um shell, um editor de texto e 10 minutos de seu tempo.
+
+
+
+ Tem certeza de que deseja cancelar?
- Versão anterior
-
- /install | /repair | /uninstall | /layout [diretório] - instala, repara, desinstala ou
- cria uma cópia local completa do pacote no diretório. Install é o padrão
+Pronto? Preparar? Vamos lá!"/>
+
+
+
+ &Fechar
- Eu &concordo com os termos e condições da licença
- &Opções
- &Instalar
- &Fechar
-
- Local de instalação:
- &Procurar
- &OK
- &Cancelar
-
- Processando:
- Inicializando...
- &Cancelar
-
- &Reparar
- &Desinstalar
- &Fechar
-
-
-
-
- &Iniciar
- Reinicie o computador para poder usar o software.
- &Reiniciar
- &Fechar
-
-
-
-
- Um ou mais problemas causaram falha na instalação. Corrija-os e tente instalar novamente. Para obter mais informações, consulte o <a href="#">arquivo de log</a>.
- Reinicie o computador para concluir a reversão do software.
- &Reiniciar
- &Fechar
- Não há suporte para o [PRODUCT_NAME] neste sistema operacional. Para obter mais informações, confira [LINK_PREREQ_PAGE].
- O [PRODUCT_NAME] não tem suporte em sistemas operacionais x86. Instale usando o instalador x86 correspondente.
-
- Os aplicativos a seguir estão usando arquivos que precisam ser atualizados:
- Feche os &aplicativos e tente reiniciá-los.
- &Não feche os aplicativos. Uma reinicialização será necessária.
- &OK
- &Cancelar
-
- O Runtime do .NET é usado para executar aplicativos .NET no seu computador com Windows. O .NET é um software de código aberto, com plataforma cruzada e possui o suporte da Microsoft. Esperamos que você goste!
- Saiba mais sobre o .NET
- O seguinte foi instalado em [DOTNETHOME]
- - [BUNDLEMONIKER]
-
- <A HREF="https://aka.ms/dotnet-docs">Documentação</A>
- <A HREF="https://aka.ms/20-p2-rel-notes">Notas sobre a Versão</A>
- <A HREF="https://aka.ms/dotnet-tutorials">Tutoriais</A>
- <A HREF="https://aka.ms/dotnet-cli-telemetry">Telemetria do .NET</A>
- <A HREF="https://aka.ms/dev-privacy">Política de Privacidade</A>
- <A HREF="https://aka.ms/dotnet-license-windows">Informações de licenciamento para .NET</A>
- Ao clicar em instalar, você concorda com os termos a seguir.
+/norestart - suprimir qualquer tentativa de reinicialização. Por padrão, a interface do usuário solicitará confirmação antes de reiniciar.
+/log log.txt - registrar em um arquivo específico. Por padrão, um arquivo de log é criado em %TEMP%."/>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/installer/pkg/sfx/bundle/theme/1049/bundle.wxl b/src/installer/pkg/sfx/bundle/theme/1049/bundle.wxl
index 1b2f2e2146204d..ee074d187040f2 100644
--- a/src/installer/pkg/sfx/bundle/theme/1049/bundle.wxl
+++ b/src/installer/pkg/sfx/bundle/theme/1049/bundle.wxl
@@ -1,74 +1,79 @@
-
-
- Установщик [WixBundleName]
- [BUNDLEMONIKER]
- Вам требуется только оболочка, текстовый редактор и 10 минут времени.
+
+
+
+ Отменить?
- Предыдущая версия
-
- /install | /repair | /uninstall | /layout [каталог] — установка, восстановление, удаление или
- создание полной локальной копии пакета в каталоге. По умолчанию — установка.
+Готовы? Уверены? Приступим!"/>
+
+
+
+ &Закрыть
- Я &принимаю условия лицензии
- &Параметры
- &Установить
- &Закрыть
-
- Расположение установки:
- &Обзор
- &ОК
- Отм&ена
-
- Обработка:
- Инициализация...
- Отм&ена
-
- &Исправить
- &Удалить
- &Закрыть
-
-
-
-
- &Запустить
- Перед использованием программного обеспечения необходимо перезапустить компьютер.
- &Перезапустить
- &Закрыть
-
-
-
-
- Одна или несколько проблем вызывали сбой программы установки. Исправьте эти проблемы и попробуйте повторить установку. Дополнительные сведения см. в <a href="#">файле журнала</a>.
- Необходимо перезагрузить компьютер, чтобы завершить откат программного обеспечения.
- &Перезапустить
- &Закрыть
- Продукт [PRODUCT_NAME] не поддерживается в этой операционной системе. Дополнительные сведения: [LINK_PREREQ_PAGE].
- Продукт [PRODUCT_NAME] не поддерживается в операционных системах x86. Установите с помощью соответствующего установщика x86.
-
- Следующие приложения используют файлы, которые следует обновить:
- Закройте &приложения и попробуйте перезапустить их.
- &Не закрывайте приложения. Потребуется перезагрузка компьютера.
- &ОК
- &Отменить
-
- Среда выполнения .NET используется для запуска приложений .NET на компьютерах с Windows. Среда .NET является открытой, кроссплатформенной и поддерживается Майкрософт. Надеемся, вам понравится!
- Дополнительные сведения о .NET
- Следующее было установлено в [DOTNETHOME]
- - [BUNDLEMONIKER]
-
- <A HREF="https://aka.ms/dotnet-docs">Документация</A>
- <A HREF="https://aka.ms/20-p2-rel-notes">Заметки о выпуске</A>
- <A HREF="https://aka.ms/dotnet-tutorials">Руководства</A>
- <A HREF="https://aka.ms/dotnet-cli-telemetry">Телеметрия .NET</A>
- <A HREF="https://aka.ms/dev-privacy">Заявление о конфиденциальности</A>
- <A HREF="https://aka.ms/dotnet-license-windows">Сведения о лицензировании .NET</A>
- Нажимая кнопку "Установить", вы принимаете следующие условия.
+/norestart — подавлять все попытки перезапуска. По умолчанию пользовательский интерфейс запрашивает подтверждение перед перезагрузкой.
+/log log.txt — журналы в определенном файле. По умолчанию файл журнала создается в папке %TEMP%."/>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/installer/pkg/sfx/bundle/theme/1055/bundle.wxl b/src/installer/pkg/sfx/bundle/theme/1055/bundle.wxl
index 12bd9ae8f83a1c..3e94ba4f609de6 100644
--- a/src/installer/pkg/sfx/bundle/theme/1055/bundle.wxl
+++ b/src/installer/pkg/sfx/bundle/theme/1055/bundle.wxl
@@ -1,74 +1,79 @@
-
-
- [WixBundleName] Yükleyicisi
- [BUNDLEMONIKER]
- Yalnızca bir kabuğa, bir metin düzenleyicisine ve 10 dakikalık bir zamana ihtiyacınız var.
+
+
+
+ İptal etmek istediğinizden emin misiniz?
- Önceki sürüm
-
- /install | /repair | /uninstall | /layout [dizin] - yükler, onarır, kaldırır ya da
- dizindeki paketin tam bir yerel kopyasını oluşturur. Varsayılan install değeridir.
+Hazır mısınız? Ayarlar tamam mı? Hadi başlayalım!"/>
+
+
+
+ &Kapat
- Lisans hüküm ve koşullarını &kabul ediyorum
- &Seçenekler
- Yü&kle
- &Kapat
-
- Yükleme konumu:
- &Gözat
- &Tamam
- İ&ptal
-
- İşleniyor:
- Başlatılıyor...
- İ&ptal
-
- &Onar
- &Kaldır
- &Kapat
-
-
-
-
- &Başlat
- Yazılımı kullanabilmeniz için bilgisayarınızı yeniden başlatmanız gerekiyor.
- &Yeniden Başlat
- &Kapat
-
-
-
-
- Bir ya da daha fazla sorun nedeniyle kurulum başarısız oldu. Lütfen bu sorunları düzeltin ve kurulumu yeniden deneyin. Daha fazla bilgi için <a href="#">günlük dosyasına</a> bakın.
- Yazılımın geri alınmasını tamamlamak için bilgisayarınızı yeniden başlatmanız gerekiyor.
- &Yeniden Başlat
- &Kapat
- [PRODUCT_NAME] bu işletim sisteminde desteklenmiyor. Daha fazla bilgi için bkz. [LINK_PREREQ_PAGE].
- [PRODUCT_NAME], x86 işletim sistemlerinde desteklenmiyor. Lütfen karşılık gelen x86 yükleyicisini kullanarak yükleyin.
-
- Şu uygulamalar güncelleştirilmesi gereken dosyaları kullanıyor:
- &Uygulamaları kapatın ve yeniden başlatmayı deneyin.
- &Uygulamaları kapatmayın. Sistemi yeniden başlatmanız gerekir.
- &Tamam
- İ&ptal
-
- .NET Çalışma Zamanı, Windows bilgisayarınızda .NET uygulamalarını çalıştırmak için kullanılır. .NET açık kaynaktır, platformlar arasında kullanılabilir ve Microsoft tarafından desteklenmektedir. Beğeneceğinizi umuyoruz!
- .NET hakkında daha fazla bilgi edinin
- Aşağıdakiler [DOTNETHOME] konumunda yüklendi
- - [BUNDLEMONIKER]
-
- <A HREF="https://aka.ms/dotnet-docs">Belgeler</A>
- <A HREF="https://aka.ms/20-p2-rel-notes">Sürüm Notları</A>
- <A HREF="https://aka.ms/dotnet-tutorials">Öğreticiler</A>
- <A HREF="https://aka.ms/dotnet-cli-telemetry">.NET Telemetrisi</A>
- <A HREF="https://aka.ms/dev-privacy">Gizlilik Bildirimi</A>
- <A HREF="https://aka.ms/dotnet-license-windows">.NET için Lisans Bilgileri</A>
- Yükle'ye tıklayarak aşağıdaki koşulları kabul etmiş olursunuz.
+/norestart - yeniden başlatma girişimlerini durdur. Varsayılan olarak kullanıcı arabirimi yeniden başlatmadan önce soracaktır.
+/log log.txt - belirli bir dosyaya kaydeder. Varsayılan olarak %TEMP% içinde bir günlük dosyası oluşturulur."/>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/installer/pkg/sfx/bundle/theme/2052/bundle.wxl b/src/installer/pkg/sfx/bundle/theme/2052/bundle.wxl
index 89017ef18407b7..f23661716ec60e 100644
--- a/src/installer/pkg/sfx/bundle/theme/2052/bundle.wxl
+++ b/src/installer/pkg/sfx/bundle/theme/2052/bundle.wxl
@@ -1,74 +1,79 @@
-
-
- [WixBundleName] 安装程序
- [BUNDLEMONIKER]
- 你只需要一个 shell、一个文本编辑器,还需花 10 分钟即可。
+
+
+
+ 是否确实要取消?
- 上一版本
-
- /install | /repair | /uninstall | /layout [目录] - 安装、修复、卸载
- 目录中的安装包或创建其完整本地副本。Install 为默认选择。
+准备好了吗?预备?开始!"/>
+
+
+
+ 关闭(&C)
- 我同意许可条款和条件(&A)
- 选项(&O)
- 安装(&I)
- 关闭(&C)
-
- 安装位置:
- 浏览(&B)
- 确定(&O)
- 取消(&C)
-
- 正在处理:
- 正在初始化...
- 取消(&C)
-
- 修复(&R)
- 卸载(&U)
- 关闭(&C)
-
-
-
-
- 启动(&L)
- 您必须先重新启动计算机,然后才能使用该软件。
- 重新启动(&R)
- 关闭(&C)
-
-
-
-
- 一个或多个问题导致了安装失败。请修复这些问题,然后重试安装。有关详细信息,请参阅<a href="#">日志文件</a>。
- 必须重新启动计算机才能完成软件回退。
- 重新启动(&R)
- 关闭(&C)
- 此操作系统不支持 [PRODUCT_NAME]。有关详细信息,请参阅[LINK_PREREQ_PAGE]。
- x86 操作系统不支持该 [PRODUCT_NAME]。请使用相应的 x86 安装程序进行安装。
-
- 以下应用程序正在使用的文件需要更新:
- 关闭应用程序并尝试重启(&A)。
- 不关闭应用程序(&D)。需要重启。
- 确定(&O)
- 取消(&C)
-
- .NET 运行时用于在 Windows 计算机上运行 .NET 应用程序。.NET 是开源、跨平台的,且由 Microsoft 提供支持。希望你喜欢它!
- 了解有关 .NET 的详细信息
- 以下项已安装到 [DOTNETHOME]
- - [BUNDLEMONIKER]
-
- <A HREF="https://aka.ms/dotnet-docs">文档</A>
- <A HREF="https://aka.ms/20-p2-rel-notes">发行说明</A>
- <A HREF="https://aka.ms/dotnet-tutorials">教程</A>
- <A HREF="https://aka.ms/dotnet-cli-telemetry">.NET 遥测</A>
- <A HREF="https://aka.ms/dev-privacy">隐私声明</A>
- <A HREF="https://aka.ms/dotnet-license-windows">.NET 的许可信息</A>
- 单击“安装”即表示你同意以下条款。
+/norestart - 禁止任何重启尝试。默认情况下,UI 将在重启前提示。
+/log log.txt - 记录到特定文件。默认在 %TEMP% 中创建日志文件。"/>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/installer/pkg/sfx/bundle/theme/3082/bundle.wxl b/src/installer/pkg/sfx/bundle/theme/3082/bundle.wxl
index 00b207781bd62b..9f33d35243aba9 100644
--- a/src/installer/pkg/sfx/bundle/theme/3082/bundle.wxl
+++ b/src/installer/pkg/sfx/bundle/theme/3082/bundle.wxl
@@ -1,74 +1,79 @@
-
-
- Instalador de [WixBundleName]
- [BUNDLEMONIKER]
- Solo necesita un shell, un editor de texto y 10 minutos.
+
+
+
+ ¿Está seguro de que desea cancelar la operación?
- Versión anterior
-
- /install | /repair | /uninstall | /layout [directory] - instala, repara, desinstala o
- crea una copia local completa del paquete en el directorio. Install es la opción predeterminada.
+¿Preparados? ¿Listos? ¡Adelante!"/>
+
+
+
+ &Cerrar
- &Acepto los términos y condiciones de licencia
- &Opciones
- &Instalar
- &Cerrar
-
- Ubicación de instalación:
- E&xaminar
- &Aceptar
- &Cancelar
-
- Procesando:
- Inicializando...
- &Cancelar
-
- &Reparar
- &Desinstalar
- &Cerrar
-
-
-
-
- &Iniciar
- Debe reiniciar el equipo para poder usar el software.
- &Reiniciar
- &Cerrar
-
-
-
-
- Error de instalación debido a uno o varios problemas. Corrija los problemas e intente de nuevo la instalación. Para obtener más información, consulte el <a href="#">archivo de registro</a>.
- Debe reiniciar el equipo para completar la reversión del software.
- &Reiniciar
- &Cerrar
- [PRODUCT_NAME] no se admite en este sistema operativo. Para obtener más información, consulte [LINK_PREREQ_PAGE].
- [PRODUCT_NAME] no es compatible con los sistemas operativos x86. Instálelo con el instalador x86 correspondiente.
-
- Las siguientes aplicaciones usan archivos que se deben actualizar:
- Cerrar las &aplicaciones e intentar reiniciarlas.
- &No cerrar las aplicaciones. Será necesario un reinicio.
- &Aceptar
- &Cancelar
-
- .NET Runtime se usa para ejecutar aplicaciones .NET en un equipo con Windows. Microsoft admite .NET, un código abierto multiplataforma. Esperamos que lo disfrute.
- Más información sobre .NET
- Lo siguiente se instaló en [DOTNETHOME]
- - [BUNDLEMONIKER]
-
- <A HREF="https://aka.ms/dotnet-docs">Documentación</A>
- <A HREF="https://aka.ms/20-p2-rel-notes">Notas de la versión</A>
- <A HREF="https://aka.ms/dotnet-tutorials">Tutoriales</A>
- <A HREF="https://aka.ms/dotnet-cli-telemetry">Telemetría de .NET</A>
- <A HREF="https://aka.ms/dev-privacy">Declaración de privacidad</A>
- <A HREF="https://aka.ms/dotnet-license-windows">Información de licencias de .NET</A>
- Al hacer clic en Instalar, acepta los términos siguientes.
+/norestart : suprime los intentos de reinicio. De manera predeterminada, la interfaz de usuario le avisará antes del reinicio.
+/log log.txt: registra en un archivo específico. De manera predeterminada, se crea un archivo de registro en %TEMP%."/>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/installer/pkg/sfx/installers/Directory.Build.props b/src/installer/pkg/sfx/installers/Directory.Build.props
index 02255f07efd3ce..d86caf2a353eb1 100644
--- a/src/installer/pkg/sfx/installers/Directory.Build.props
+++ b/src/installer/pkg/sfx/installers/Directory.Build.props
@@ -4,5 +4,6 @@
true
true
+ true
\ No newline at end of file
diff --git a/src/installer/pkg/sfx/installers/Directory.Build.targets b/src/installer/pkg/sfx/installers/Directory.Build.targets
index d108af94975de8..dded62b7d746f1 100644
--- a/src/installer/pkg/sfx/installers/Directory.Build.targets
+++ b/src/installer/pkg/sfx/installers/Directory.Build.targets
@@ -2,6 +2,17 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/installer/pkg/sfx/installers/dotnet-host.proj b/src/installer/pkg/sfx/installers/dotnet-host.proj
index 64282f8de95808..f834af089e1ac1 100644
--- a/src/installer/pkg/sfx/installers/dotnet-host.proj
+++ b/src/installer/pkg/sfx/installers/dotnet-host.proj
@@ -13,10 +13,7 @@
Dotnet_CLI_SharedHost
HostSrc
-
- afterInstallInitialize
+ afterInstallExecute
false
true
sharedhost
@@ -30,7 +27,7 @@
-
+
diff --git a/src/installer/pkg/sfx/installers/host.wxs b/src/installer/pkg/sfx/installers/host.wxs
index 893520ff557275..2f53e3ba54c1f8 100644
--- a/src/installer/pkg/sfx/installers/host.wxs
+++ b/src/installer/pkg/sfx/installers/host.wxs
@@ -1,5 +1,5 @@
-
-
+
@@ -20,38 +20,51 @@
1. the legacy SDK can be subsequently installed
2. the user runs 'dotnet' commands directly against 'ProgramFiles'\dotnet\dotnet.exe -->
-
+
-
+
-
+
-
-
-
- NOT NON_NATIVE_ARCHITECTURE
-
-
- NOT VersionNT64
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -62,51 +75,22 @@
-
-
+
-
+
-
-
-
-
-
-
-
-
-
-
-
- "#1" AND NOT NON_NATIVE_ARCHITECTURE]]>
-
-
- "#1" AND NOT VersionNT64]]>
-
-
-
-
-
-
-
- "#1"]]>
-
-
-
-
- NON_NATIVE_ARCHITECTURE
-
+
\ No newline at end of file
diff --git a/src/installer/tests/HostActivation.Tests/FrameworkResolution/FrameworkResolution.cs b/src/installer/tests/HostActivation.Tests/FrameworkResolution/FrameworkResolution.cs
index 42e724c8ad5356..b5e993a100a31d 100644
--- a/src/installer/tests/HostActivation.Tests/FrameworkResolution/FrameworkResolution.cs
+++ b/src/installer/tests/HostActivation.Tests/FrameworkResolution/FrameworkResolution.cs
@@ -103,6 +103,64 @@ public void FrameworkResolutionError_ListOtherArchitectures()
}
}
+ [Theory]
+ [InlineData("6.1.0", "", "6.1.3")] // Roll forward to 6.1.3 - empty value has no effect on resolution
+ [InlineData("6.1.0", " ", "6.1.3")] // Roll forward to 6.1.3 - whitespace value has no effect on resolution
+ [InlineData("6.1.0", "6.1.2", "6.1.3")] // Roll forward to 6.1.3 when 6.1.2 is disabled
+ [InlineData("6.1.0", "6.1.3", "6.1.2")] // Roll forward to 6.1.2 when 6.1.3 is disabled
+ [InlineData("6.1.3", "6.1.3", ResolvedFramework.NotFound)] // Fail when the only matching version is disabled
+ [InlineData("7.2.0", "7.2.3", ResolvedFramework.NotFound)] // Fail when the only matching version is disabled
+ [InlineData("6.1.0", "6.1.2;6.1.3", ResolvedFramework.NotFound)] // Fail when all matching versions are disabled
+ [InlineData("6.1.0", "invalid;6.1.3", "6.1.2")] // Roll forward to 6.1.2 - invalid value ignored, 6.1.3 disabled
+ [InlineData("6.1.0", "v6.1.3;;6.1.0", "6.1.3")] // Roll forward to 6.1.3 - invalid or non-existent versions have no effect on resolution
+ public void DisabledVersions(string requestedVersion, string disabledVersions, string expectedResolution)
+ {
+ CommandResult result = RunTest(
+ new TestSettings()
+ .WithRuntimeConfigCustomizer(rc => rc.WithFramework(MicrosoftNETCoreApp, requestedVersion))
+ .WithEnvironment(Constants.DisableRuntimeVersions.EnvironmentVariable, disabledVersions));
+
+ result.ShouldHaveResolvedFrameworkOrFailToFind(MicrosoftNETCoreApp, expectedResolution);
+ if (string.IsNullOrWhiteSpace(disabledVersions))
+ {
+ result.Should().NotHaveStdErrContaining($"Ignoring disabled version");
+ }
+ else
+ {
+ foreach (string value in disabledVersions.Split(';'))
+ {
+ if (SharedState.InstalledVersions.Contains(value))
+ {
+ result.Should().HaveStdErrContaining($"Ignoring disabled version [{value}]");
+ if (expectedResolution == ResolvedFramework.NotFound)
+ {
+ result.Should().HaveStdErrContaining(
+ $"""
+ {value} at [{SharedState.InstalledDotNet.SharedFxPath}]
+ Disabled via {Constants.DisableRuntimeVersions.EnvironmentVariable} environment variable
+ """);
+
+ }
+ }
+ }
+ }
+ }
+
+ [Fact]
+ public void DisabledVersions_NoRollForward()
+ {
+ string disabledVersion = "6.1.2";
+ CommandResult result = RunTest(
+ new TestSettings()
+ .WithRuntimeConfigCustomizer(rc => rc
+ .WithFramework(MicrosoftNETCoreApp, disabledVersion)
+ .WithRollForward(Constants.RollForwardSetting.Disable))
+ .WithEnvironment(Constants.DisableRuntimeVersions.EnvironmentVariable, disabledVersion));
+
+ result.ShouldFailToFindCompatibleFrameworkVersion(MicrosoftNETCoreApp, disabledVersion)
+ .And.HaveStdErrContaining($"Ignoring disabled version [{disabledVersion}]");
+ }
+
private CommandResult RunTest(TestSettings testSettings, [CallerMemberName] string caller = "")
{
return RunTest(
diff --git a/src/installer/tests/HostActivation.Tests/HostCommands.cs b/src/installer/tests/HostActivation.Tests/HostCommands.cs
index d7fb6d30cfd83a..5e5d03ba7f2282 100644
--- a/src/installer/tests/HostActivation.Tests/HostCommands.cs
+++ b/src/installer/tests/HostActivation.Tests/HostCommands.cs
@@ -241,6 +241,22 @@ public void ListRuntimes()
.And.HaveStdOut(expectedOutput);
}
+ [Fact]
+ public void ListRuntimes_DisabledVersions()
+ {
+ // Verify exact match of command output. The output of --list-runtimes is intended to be machine-readable
+ // and must not change in a way that breaks existing parsing.
+ string disabledVersion = SharedState.InstalledVersions[0];
+ string[] expectedVersions = SharedState.InstalledVersions[1..];
+ string expectedOutput = GetListRuntimesOutput(SharedState.DotNet.BinPath, expectedVersions);
+ SharedState.DotNet.Exec("--list-runtimes")
+ .CaptureStdOut()
+ .EnvironmentVariable(Constants.DisableRuntimeVersions.EnvironmentVariable, disabledVersion)
+ .Execute()
+ .Should().Pass()
+ .And.HaveStdOut(expectedOutput);
+ }
+
[Theory]
[InlineData(true)]
[InlineData(false)]
diff --git a/src/installer/tests/HostActivation.Tests/NativeHostApis.cs b/src/installer/tests/HostActivation.Tests/NativeHostApis.cs
index 89854dab4934e7..b0fb2777fbb2ec 100644
--- a/src/installer/tests/HostActivation.Tests/NativeHostApis.cs
+++ b/src/installer/tests/HostActivation.Tests/NativeHostApis.cs
@@ -353,26 +353,10 @@ public void Hostfxr_get_dotnet_environment_info_dotnet_root_only()
string expectedSdkVersions = string.Join(";", f.LocalSdks);
string expectedSdkPaths = string.Join(';', f.LocalSdkPaths);
- string expectedFrameworkNames = string.Join(';', new[]
- {
- "HostFxr.Test.B",
- "HostFxr.Test.B",
- "HostFxr.Test.C"
- });
-
- string expectedFrameworkVersions = string.Join(';', new[]
- {
- "4.0.0",
- "5.6.7-A",
- "3.0.0"
- });
-
- string expectedFrameworkPaths = string.Join(';', new[]
- {
- Path.Combine(f.LocalFrameworksDir, "HostFxr.Test.B"),
- Path.Combine(f.LocalFrameworksDir, "HostFxr.Test.B"),
- Path.Combine(f.LocalFrameworksDir, "HostFxr.Test.C")
- });
+ IEnumerable<(string Name, string Version)> frameworks = f.LocalFrameworks.SelectMany(fw => fw.fwVersions.Select(v => (fw.fwName, v)));
+ string expectedFrameworkNames = string.Join(';', frameworks.Select(fw => fw.Name));
+ string expectedFrameworkVersions = string.Join(';', frameworks.Select(fw => fw.Version));
+ string expectedFrameworkPaths = string.Join(';', frameworks.Select(fw => Path.Combine(f.LocalFrameworksDir, fw.Name)));
string api = ApiNames.hostfxr_get_dotnet_environment_info;
TestContext.BuiltDotNet.Exec(sharedTestState.HostApiInvokerApp.AppDll, api, f.ExeDir)
@@ -431,6 +415,41 @@ public void Hostfxr_get_dotnet_environment_info_with_multilevel_lookup_with_dotn
.And.HaveStdOutContaining($"{api} framework paths:[{expectedFrameworkPaths}]");
}
+ [Fact]
+ public void Hostfxr_get_dotnet_environment_info_DisabledVersions()
+ {
+ var f = sharedTestState.SdkAndFrameworkFixture;
+ string expectedSdkVersions = string.Join(";", f.LocalSdks);
+ string expectedSdkPaths = string.Join(';', f.LocalSdkPaths);
+
+ string[] disabledVersions = ["4.0.0", "3.0.0"];
+ IEnumerable<(string Name, string Version)> frameworks = f.LocalFrameworks
+ .SelectMany(fw => fw.fwVersions
+ .Where(v => !disabledVersions.Contains(v))
+ .Select(v => (fw.fwName, v)));
+ string expectedFrameworkNames = string.Join(';', frameworks.Select(fw => fw.Name));
+ string expectedFrameworkVersions = string.Join(';', frameworks.Select(fw => fw.Version));
+ string expectedFrameworkPaths = string.Join(';', frameworks.Select(fw => Path.Combine(f.LocalFrameworksDir, fw.Name)));
+
+ string api = ApiNames.hostfxr_get_dotnet_environment_info;
+ var result = TestContext.BuiltDotNet.Exec(sharedTestState.HostApiInvokerApp.AppDll, api, f.ExeDir)
+ .EnableTracingAndCaptureOutputs()
+ .EnvironmentVariable(Constants.DisableRuntimeVersions.EnvironmentVariable, string.Join(';', disabledVersions))
+ .Execute();
+ result.Should().Pass()
+ .And.ReturnStatusCode(api, Constants.ErrorCode.Success)
+ .And.HaveStdOutContaining($"{api} sdk versions:[{expectedSdkVersions}]")
+ .And.HaveStdOutContaining($"{api} sdk paths:[{expectedSdkPaths}]")
+ .And.HaveStdOutContaining($"{api} framework names:[{expectedFrameworkNames}]")
+ .And.HaveStdOutContaining($"{api} framework versions:[{expectedFrameworkVersions}]")
+ .And.HaveStdOutContaining($"{api} framework paths:[{expectedFrameworkPaths}]");
+
+ foreach (string version in disabledVersions)
+ {
+ result.Should().HaveStdErrContaining($"Ignoring disabled version [{version}]");
+ }
+ }
+
[Fact]
[PlatformSpecific(TestPlatforms.Windows)] // The test setup only works on Windows (and MLL was Windows-only anyway)
public void Hostfxr_get_dotnet_environment_info_with_multilevel_lookup_only()
diff --git a/src/installer/tests/Microsoft.NET.HostModel.Tests/Bundle/BundlerConsistencyTests.cs b/src/installer/tests/Microsoft.NET.HostModel.Tests/Bundle/BundlerConsistencyTests.cs
index 44cfdfd95358cf..fe6e122d46b68c 100644
--- a/src/installer/tests/Microsoft.NET.HostModel.Tests/Bundle/BundlerConsistencyTests.cs
+++ b/src/installer/tests/Microsoft.NET.HostModel.Tests/Bundle/BundlerConsistencyTests.cs
@@ -98,6 +98,24 @@ public void ExactDuplicateEntries()
bundler.BundleManifest.Files.Where(entry => entry.RelativePath.Equals("rel/system.repeat.dll")).Single().Type.Should().Be(FileType.Assembly);
}
+ [Fact]
+ public void ResolveLinkTargets()
+ {
+ string appPath = Path.Combine(
+ Path.GetDirectoryName(sharedTestState.App.AppDll),
+ Path.GetFileNameWithoutExtension(sharedTestState.App.AppDll)
+ + ".link" + Path.GetExtension(sharedTestState.App.AppDll));
+ File.CreateSymbolicLink(appPath, sharedTestState.App.AppDll);
+ // File specification with duplicate entries with matching source paths
+ var fileSpecs = new FileSpec[]
+ {
+ new FileSpec(Binaries.AppHost.FilePath, BundlerHostName),
+ new FileSpec(appPath, "rel/app.repeat.dll")
+ };
+ Bundler bundler = CreateBundlerInstance();
+ bundler.GenerateBundle(fileSpecs);
+ }
+
[Fact]
public void DuplicateBundleRelativePath_Fails()
{
diff --git a/src/installer/tests/Microsoft.NET.HostModel.Tests/MachObjectSigning/SigningTests.cs b/src/installer/tests/Microsoft.NET.HostModel.Tests/MachObjectSigning/SigningTests.cs
index 452fe8a8a1b32e..b1ed8eada30fcd 100644
--- a/src/installer/tests/Microsoft.NET.HostModel.Tests/MachObjectSigning/SigningTests.cs
+++ b/src/installer/tests/Microsoft.NET.HostModel.Tests/MachObjectSigning/SigningTests.cs
@@ -90,7 +90,7 @@ void MatchesCodesignOutput(string filePath, TestArtifact _)
// Codesigned file
File.Copy(filePath, codesignFilePath);
Assert.True(Codesign.IsAvailable, "Could not find codesign tool");
- var (exitCode, stdErr) = Codesign.Run("-s - -f --preserve-metadata=entitlements -i" + fileName, codesignFilePath);
+ var (exitCode, stdErr) = Codesign.Run("-s - -f -i " + fileName, codesignFilePath);
Assert.Equal(0, exitCode);
// Managed signed file
@@ -140,41 +140,6 @@ void ReadSignedMachIsTheSameAsReadAndResigned(string filePath, TestArtifact _)
}
}
- [Fact]
- [PlatformSpecific(TestPlatforms.OSX)]
- public void SigningAppHostPreservesEntitlements()
- {
- using var testDirectory = TestArtifact.Create(nameof(SigningAppHostPreservesEntitlements));
- var testAppHostPath = Path.Combine(testDirectory.Location, Path.GetFileName(Binaries.AppHost.FilePath));
- File.Copy(Binaries.AppHost.FilePath, testAppHostPath);
- string signedHostPath = testAppHostPath + ".signed";
-
- HostWriter.CreateAppHost(testAppHostPath, signedHostPath, testAppHostPath + ".dll", enableMacOSCodeSign: true);
-
- Assert.True(SigningTests.HasEntitlementsBlob(testAppHostPath));
- Assert.True(SigningTests.HasEntitlementsBlob(signedHostPath));
- Assert.True(SigningTests.HasDerEntitlementsBlob(testAppHostPath));
- Assert.True(SigningTests.HasDerEntitlementsBlob(signedHostPath));
- }
-
- [Fact]
- [PlatformSpecific(TestPlatforms.OSX)]
- public void BundledAppHostHasEntitlements()
- {
- using var testDirectory = TestArtifact.Create(nameof(BundledAppHostHasEntitlements));
- var testAppHostPath = Path.Combine(testDirectory.Location, Path.GetFileName(Binaries.SingleFileHost.FilePath));
- File.Copy(Binaries.SingleFileHost.FilePath, testAppHostPath);
- string signedHostPath = testAppHostPath + ".signed";
-
- HostWriter.CreateAppHost(testAppHostPath, signedHostPath, testAppHostPath + ".dll", enableMacOSCodeSign: true);
- var bundlePath = new Bundler(Path.GetFileName(signedHostPath), testAppHostPath + ".bundle").GenerateBundle([new(signedHostPath, Path.GetFileName(signedHostPath))]);
-
- Assert.True(SigningTests.HasEntitlementsBlob(testAppHostPath));
- Assert.True(SigningTests.HasEntitlementsBlob(bundlePath));
- Assert.True(SigningTests.HasDerEntitlementsBlob(testAppHostPath));
- Assert.True(SigningTests.HasDerEntitlementsBlob(bundlePath));
- }
-
[Fact]
[PlatformSpecific(TestPlatforms.OSX)]
public void OverwritingExistingBundleClearsMacOsSignatureCache()
@@ -326,26 +291,6 @@ public static bool IsSigned(string filePath)
public static bool IsMachOImage(string filePath) => MachObjectFile.IsMachOImage(filePath);
- public static bool HasEntitlementsBlob(string filePath)
- {
- using (MemoryMappedFile memoryMappedFile = MemoryMappedFile.CreateFromFile(filePath, FileMode.Open))
- using (MemoryMappedViewAccessor memoryMappedViewAccessor = memoryMappedFile.CreateViewAccessor(0, 0, MemoryMappedFileAccess.Read))
- {
- var machObjectFile = MachObjectFile.Create(memoryMappedViewAccessor);
- return machObjectFile.EmbeddedSignatureBlob?.EntitlementsBlob != null;
- }
- }
-
- public static bool HasDerEntitlementsBlob(string filePath)
- {
- using (MemoryMappedFile memoryMappedFile = MemoryMappedFile.CreateFromFile(filePath, FileMode.Open))
- using (MemoryMappedViewAccessor memoryMappedViewAccessor = memoryMappedFile.CreateViewAccessor(0, 0, MemoryMappedFileAccess.Read))
- {
- var machObjectFile = MachObjectFile.Create(memoryMappedViewAccessor);
- return machObjectFile.EmbeddedSignatureBlob?.DerEntitlementsBlob != null;
- }
- }
-
static readonly string[] liveBuiltHosts = new string[] { Binaries.AppHost.FilePath, Binaries.SingleFileHost.FilePath };
public static Object[][] GetTestFilePaths(string testArtifactName)
diff --git a/src/installer/tests/Microsoft.NET.HostModel.Tests/ResourceUpdaterTests.cs b/src/installer/tests/Microsoft.NET.HostModel.Tests/ResourceUpdaterTests.cs
index 30e3efdf1027db..2f25839507bbfa 100644
--- a/src/installer/tests/Microsoft.NET.HostModel.Tests/ResourceUpdaterTests.cs
+++ b/src/installer/tests/Microsoft.NET.HostModel.Tests/ResourceUpdaterTests.cs
@@ -23,7 +23,7 @@ class TempFile : IDisposable
public TempFile()
{
_path = Path.GetTempFileName();
- Stream = new FileStream(_path, FileMode.Open);
+ Stream = new FileStream(_path, FileMode.Open, FileAccess.ReadWrite, FileShare.None);
}
public void Dispose()
@@ -169,6 +169,25 @@ void AddResource_AddTwoSameUShortTypeWithDifferName()
}
}
+ [Fact]
+ void DisposeWithLeaveOpenDisposesPEReader()
+ {
+ using var tempFile = GetCurrentAssemblyMemoryStream();
+ PEReader? peReader = null;
+
+ using (var updater = new ResourceUpdater(tempFile.Stream, leaveOpen: true))
+ {
+ FieldInfo? readerField = typeof(ResourceUpdater).GetField("_reader", BindingFlags.Instance | BindingFlags.NonPublic);
+ Assert.NotNull(readerField);
+ peReader = Assert.IsType(readerField.GetValue(updater));
+ _ = peReader.PEHeaders;
+ }
+
+ Assert.NotNull(peReader);
+
+ Assert.Throws(() => _ = peReader!.PEHeaders);
+ }
+
[Fact]
void AddResourcesFromPEImage()
{
diff --git a/src/installer/tests/TestUtils/CommandExtensions.cs b/src/installer/tests/TestUtils/CommandExtensions.cs
index bc5303a1593b30..70c18ab08ae25d 100644
--- a/src/installer/tests/TestUtils/CommandExtensions.cs
+++ b/src/installer/tests/TestUtils/CommandExtensions.cs
@@ -46,9 +46,13 @@ public static Command DotNetRoot(this Command command, string dotNetRoot, string
if (!string.IsNullOrEmpty(architecture))
return command.EnvironmentVariable(Constants.DotnetRoot.ArchitectureEnvironmentVariablePrefix + architecture.ToUpper(), dotNetRoot);
+ // If we are clearing out the variable, make sure we clear out any architecture-specific one too
+ if (string.IsNullOrEmpty(dotNetRoot))
+ command = command.EnvironmentVariable($"{Constants.DotnetRoot.ArchitectureEnvironmentVariablePrefix}{TestContext.BuildArchitecture.ToUpperInvariant()}", dotNetRoot);
+
return command
- .EnvironmentVariable(Constants.DotnetRoot.EnvironmentVariable, dotNetRoot)
- .EnvironmentVariable(Constants.DotnetRoot.WindowsX86EnvironmentVariable, dotNetRoot);
+ .EnvironmentVariable(Constants.DotnetRoot.EnvironmentVariable, dotNetRoot)
+ .EnvironmentVariable(Constants.DotnetRoot.WindowsX86EnvironmentVariable, dotNetRoot);
}
public static Command MultilevelLookup(this Command command, bool? enable)
diff --git a/src/installer/tests/TestUtils/Constants.cs b/src/installer/tests/TestUtils/Constants.cs
index 4d3be90319ad15..e965aa55e7c03a 100644
--- a/src/installer/tests/TestUtils/Constants.cs
+++ b/src/installer/tests/TestUtils/Constants.cs
@@ -35,6 +35,11 @@ public static class RollForwardSetting
public const string Disable = "Disable";
}
+ public static class DisableRuntimeVersions
+ {
+ public const string EnvironmentVariable = "DOTNET_DISABLE_RUNTIME_VERSIONS";
+ }
+
public static class FxVersion
{
public const string CommandLineArgument = "--fx-version";
diff --git a/src/libraries/Common/src/System/Diagnostics/NetFrameworkUtils.cs b/src/libraries/Common/src/System/Diagnostics/NetFrameworkUtils.cs
index 87f56dcdc242f4..e30106f020012a 100644
--- a/src/libraries/Common/src/System/Diagnostics/NetFrameworkUtils.cs
+++ b/src/libraries/Common/src/System/Diagnostics/NetFrameworkUtils.cs
@@ -22,14 +22,17 @@ internal static void EnterMutex(string name, ref Mutex mutex)
internal static void EnterMutexWithoutGlobal(string mutexName, ref Mutex mutex)
{
- Mutex tmpMutex = new Mutex(false, mutexName, out _);
-
- // Specify a SID in case the mutex has not yet been created; this prevents it from using the SID from the current thread.
- // This SID (AuthenticatedUserSid) is the same one used by .NET Framework.
- MutexSecurity sec = new MutexSecurity();
- SecurityIdentifier authenticatedUserSid = new SecurityIdentifier(WellKnownSidType.AuthenticatedUserSid, null);
- sec.AddAccessRule(new MutexAccessRule(authenticatedUserSid, MutexRights.Synchronize | MutexRights.Modify, AccessControlType.Allow));
- tmpMutex.SetAccessControl(sec);
+ Mutex tmpMutex = new Mutex(false, mutexName, out bool createdNew);
+
+ if (createdNew)
+ {
+ // Specify a SID in case the mutex has not yet been created; this prevents it from using the SID from the current thread.
+ // This SID (AuthenticatedUserSid) is the same one used by .NET Framework.
+ MutexSecurity sec = new MutexSecurity();
+ SecurityIdentifier authenticatedUserSid = new SecurityIdentifier(WellKnownSidType.AuthenticatedUserSid, null);
+ sec.AddAccessRule(new MutexAccessRule(authenticatedUserSid, MutexRights.Synchronize | MutexRights.Modify, AccessControlType.Allow));
+ tmpMutex.SetAccessControl(sec);
+ }
SafeWaitForMutex(tmpMutex, ref mutex);
}
diff --git a/src/libraries/Common/src/System/Security/Cryptography/CompositeMLDsa.cs b/src/libraries/Common/src/System/Security/Cryptography/CompositeMLDsa.cs
index 6b7cd722e3ecd5..78eb7b5415376d 100644
--- a/src/libraries/Common/src/System/Security/Cryptography/CompositeMLDsa.cs
+++ b/src/libraries/Common/src/System/Security/Cryptography/CompositeMLDsa.cs
@@ -866,19 +866,13 @@ static void PrivateKeyReader(
out CompositeMLDsa dsa)
{
CompositeMLDsaAlgorithm algorithm = GetAlgorithmIdentifier(in algorithmIdentifier);
- AsnValueReader reader = new AsnValueReader(privateKeyContents.Span, AsnEncodingRules.BER);
- if (!reader.TryReadPrimitiveOctetString(out ReadOnlySpan key) || reader.HasData)
- {
- throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding);
- }
-
- if (!algorithm.IsValidPrivateKeySize(key.Length))
+ if (!algorithm.IsValidPrivateKeySize(privateKeyContents.Length))
{
throw new CryptographicException(SR.Argument_PrivateKeyWrongSizeForAlgorithm);
}
- dsa = CompositeMLDsaImplementation.ImportCompositeMLDsaPrivateKeyImpl(algorithm, key);
+ dsa = CompositeMLDsaImplementation.ImportCompositeMLDsaPrivateKeyImpl(algorithm, privateKeyContents.Span);
}
}
@@ -1863,9 +1857,7 @@ private AsnWriter WriteSubjectPublicKeyToAsnWriter()
ReadOnlySpan publicKey = buffer.AsSpan(0, written);
- // TODO verify overhead
-
- // TODO: The ASN.1 overhead of a SubjectPublicKeyInfo encoding a public key is ___ bytes.
+ // The ASN.1 overhead of a SubjectPublicKeyInfo encoding a public key is around 24 bytes.
// Round it off to 32. This checked operation should never throw because the inputs are not
// user provided.
int capacity = checked(32 + publicKey.Length);
diff --git a/src/libraries/Common/src/System/Security/Cryptography/CompositeMLDsaAlgorithm.cs b/src/libraries/Common/src/System/Security/Cryptography/CompositeMLDsaAlgorithm.cs
index bd5d12f6d6cbdd..3656e070ff7dd6 100644
--- a/src/libraries/Common/src/System/Security/Cryptography/CompositeMLDsaAlgorithm.cs
+++ b/src/libraries/Common/src/System/Security/Cryptography/CompositeMLDsaAlgorithm.cs
@@ -12,8 +12,6 @@ namespace System.Security.Cryptography
[Experimental(Experimentals.PostQuantumCryptographyDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
public sealed class CompositeMLDsaAlgorithm : IEquatable
{
- internal const int RandomizerSizeInBytes = 32;
-
///
/// Gets the name of the algorithm.
///
@@ -454,8 +452,8 @@ private static CompositeMLDsaAlgorithm CreateRsa(
mldsaAlgorithm.PrivateSeedSizeInBytes + maxRsaPrivateKeySizeInBytes,
mldsaAlgorithm.PublicKeySizeInBytes + keySizeInBytes, // Private key contains at least n
mldsaAlgorithm.PublicKeySizeInBytes + maxRsaPublicKeySizeInBytes,
- RandomizerSizeInBytes + mldsaAlgorithm.SignatureSizeInBytes + keySizeInBytes,
- RandomizerSizeInBytes + mldsaAlgorithm.SignatureSizeInBytes + keySizeInBytes,
+ mldsaAlgorithm.SignatureSizeInBytes + keySizeInBytes,
+ mldsaAlgorithm.SignatureSizeInBytes + keySizeInBytes,
oid);
}
@@ -465,29 +463,8 @@ private static CompositeMLDsaAlgorithm CreateECDsa(
int keySizeInBits,
string oid)
{
- // The key size calculation depends on the size of the curve algorithm's OID, and only includes the curves
- // supported at the time of writing this code. If more curves are added, ensure the OID length is accounted for in the calculation.
- Debug.Assert(oid is
- Oids.MLDsa44WithECDsaP256PreHashSha256 or
- Oids.MLDsa65WithECDsaP256PreHashSha512 or
- Oids.MLDsa65WithECDsaP384PreHashSha512 or
- Oids.MLDsa87WithECDsaP384PreHashSha512 or
- Oids.MLDsa87WithECDsaP521PreHashSha512 or
- Oids.MLDsa65WithECDsaBrainpoolP256r1PreHashSha512 or
- Oids.MLDsa87WithECDsaBrainpoolP384r1PreHashSha512);
-
int keySizeInBytes = (keySizeInBits + 7) / 8;
- const int MaxUniversalTagLength = 1;
-
- // long form prefix and 4 bytes for length. CLR arrays and spans only support length up to int.MaxValue.
- // Padding with leading zero bytes is allowed, but we still limit the length to 4 bytes since the only
- // plausible scenario would be encoding a 4-byte numeric data type without trimming.
- // Note this bound also covers indefinite length encodings which require only 1 + 2 bytes of overhead.
- const int MaxLengthLength = 1 + 4;
-
- const int MaxPrefixLength = MaxUniversalTagLength + MaxLengthLength;
-
// RFC 5915, Section 3
// ECPrivateKey ::= SEQUENCE {
// version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
@@ -496,51 +473,32 @@ Oids.MLDsa65WithECDsaBrainpoolP256r1PreHashSha512 or
// publicKey [1] BIT STRING OPTIONAL
// }
- int maxPrivateKeySizeInBytes =
- MaxPrefixLength +
- (
- // version
- MaxPrefixLength + 1 + // Version should always be 1
-
- // privateKey
- MaxPrefixLength + keySizeInBytes +
-
- // parameters
- 1 + MaxLengthLength + // Explicit tag
- (
- // RFC5480, Section 2.1.1
- // ECParameters ::= CHOICE {
- // namedCurve OBJECT IDENTIFIER
- // -- implicitCurve NULL
- // -- specifiedCurve SpecifiedECDomain
- // }
- // -- implicitCurve and specifiedCurve MUST NOT be used in PKIX.
- //
- // So this is a CHOICE with with the only option being a namedCurve OBJECT IDENTIFIER.
- //
- // Curve | OID | DER Encoding with prefix | Length without prefix
- // ----------------|-----------------------|----------------------------------|----------------------
- // secp256r1 | 1.2.840.10045.3.1.7 | 06 08 2A 86 48 CE 3D 03 01 07 | 8
- // secp384r1 | 1.3.132.0.34 | 06 05 2B 81 04 00 22 | 5
- // secp521r1 | 1.3.132.0.35 | 06 05 2B 81 04 00 23 | 5
- // brainpoolP256r1 | 1.3.36.3.3.2.8.1.1.7 | 06 09 2B 24 03 03 02 08 01 01 07 | 9
- // brainpoolP384r1 | 1.3.36.3.3.2.8.1.1.11 | 06 09 2B 24 03 03 02 08 01 01 0B | 9
- MaxPrefixLength + 9 // This doesn't need to be exact, but it does need to consider all supported curves.
- ) +
-
- // publicKey
- 1 + MaxLengthLength + // Explicit tag
- 1 + 2 * keySizeInBytes
- );
+ int versionSizeInBytes =
+ 1 + // Tag for INTEGER
+ 1 + // Length field
+ 1; // Value (always 1)
+
+ int privateKeySizeInBytes =
+ 1 + // Tag for OCTET STRING
+ GetDerLengthLength(keySizeInBytes) + // Length field
+ keySizeInBytes; // Value
+
+ // parameters and publicKey must be omitted for Composite ML-DSA
+
+ int ecPrivateKeySizeInBytes =
+ 1 + // Tag for SEQUENCE
+ GetDerLengthLength(versionSizeInBytes + privateKeySizeInBytes) + // Length field
+ versionSizeInBytes + // Version
+ privateKeySizeInBytes;
return new CompositeMLDsaAlgorithm(
name,
- mldsaAlgorithm.PrivateSeedSizeInBytes + keySizeInBytes, // ECPrivateKey has at least the private key
- mldsaAlgorithm.PrivateSeedSizeInBytes + maxPrivateKeySizeInBytes,
+ mldsaAlgorithm.PrivateSeedSizeInBytes + ecPrivateKeySizeInBytes,
+ mldsaAlgorithm.PrivateSeedSizeInBytes + ecPrivateKeySizeInBytes,
mldsaAlgorithm.PublicKeySizeInBytes + 1 + 2 * keySizeInBytes,
mldsaAlgorithm.PublicKeySizeInBytes + 1 + 2 * keySizeInBytes,
- RandomizerSizeInBytes + mldsaAlgorithm.SignatureSizeInBytes + 2 + 3 * 2, // 2 non-zero INTEGERS and overhead for 3 ASN.1 values
- RandomizerSizeInBytes + mldsaAlgorithm.SignatureSizeInBytes + AsymmetricAlgorithmHelpers.GetMaxDerSignatureSize(keySizeInBits),
+ mldsaAlgorithm.SignatureSizeInBytes + 2 + 3 * 2, // 2 non-zero INTEGERS and overhead for 3 ASN.1 values
+ mldsaAlgorithm.SignatureSizeInBytes + AsymmetricAlgorithmHelpers.GetMaxDerSignatureSize(keySizeInBits),
oid);
}
@@ -559,9 +517,28 @@ private static CompositeMLDsaAlgorithm CreateEdDsa(
mldsaAlgorithm.PrivateSeedSizeInBytes + keySizeInBytes,
mldsaAlgorithm.PublicKeySizeInBytes + keySizeInBytes,
mldsaAlgorithm.PublicKeySizeInBytes + keySizeInBytes,
- RandomizerSizeInBytes + mldsaAlgorithm.SignatureSizeInBytes + 2 * keySizeInBytes,
- RandomizerSizeInBytes + mldsaAlgorithm.SignatureSizeInBytes + 2 * keySizeInBytes,
+ mldsaAlgorithm.SignatureSizeInBytes + 2 * keySizeInBytes,
+ mldsaAlgorithm.SignatureSizeInBytes + 2 * keySizeInBytes,
oid);
}
+
+ private static int GetDerLengthLength(int payloadLength)
+ {
+ Debug.Assert(payloadLength >= 0);
+
+ if (payloadLength <= 0x7F)
+ return 1;
+
+ if (payloadLength <= 0xFF)
+ return 2;
+
+ if (payloadLength <= 0xFFFF)
+ return 3;
+
+ if (payloadLength <= 0xFFFFFF)
+ return 4;
+
+ return 5;
+ }
}
}
diff --git a/src/libraries/Common/src/System/Security/Cryptography/CompositeMLDsaManaged.ECDsa.cs b/src/libraries/Common/src/System/Security/Cryptography/CompositeMLDsaManaged.ECDsa.cs
index 55e2448d538f62..d832c1cf9e87e7 100644
--- a/src/libraries/Common/src/System/Security/Cryptography/CompositeMLDsaManaged.ECDsa.cs
+++ b/src/libraries/Common/src/System/Security/Cryptography/CompositeMLDsaManaged.ECDsa.cs
@@ -71,30 +71,13 @@ public static unsafe ECDsaComponent ImportPrivateKey(ECDsaAlgorithm algorithm, R
{
ECPrivateKey ecPrivateKey = ECPrivateKey.Decode(manager.Memory, AsnEncodingRules.BER);
- if (ecPrivateKey.Version != 1)
+ if (ecPrivateKey.Version != 1 ||
+ ecPrivateKey.Parameters is not null ||
+ ecPrivateKey.PublicKey is not null)
{
throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding);
}
- // If domain parameters are present, validate that they match the composite ML-DSA algorithm.
- if (ecPrivateKey.Parameters is ECDomainParameters domainParameters)
- {
- if (domainParameters.Named is not string curveOid || curveOid != algorithm.CurveOidValue)
- {
- // The curve specified must be named and match the required curve for the composite ML-DSA algorithm.
- throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding);
- }
- }
-
- byte[]? x = null;
- byte[]? y = null;
-
- // If public key is present, add it to the parameters.
- if (ecPrivateKey.PublicKey is ReadOnlyMemory publicKey)
- {
- EccKeyFormatHelper.GetECPointFromUncompressedPublicKey(publicKey.Span, algorithm.KeySizeInBytes, out x, out y);
- }
-
byte[] d = new byte[ecPrivateKey.PrivateKey.Length];
using (PinAndClear.Track(d))
@@ -107,8 +90,8 @@ public static unsafe ECDsaComponent ImportPrivateKey(ECDsaAlgorithm algorithm, R
Curve = algorithm.Curve,
Q = new ECPoint
{
- X = x,
- Y = y,
+ X = null,
+ Y = null,
},
D = d
};
@@ -121,14 +104,10 @@ public static unsafe ECDsaComponent ImportPrivateKey(ECDsaAlgorithm algorithm, R
#error ECDsa.Create(ECParameters) is avaliable in .NET Framework 4.7.2 and later, so this workaround is not needed anymore.
#endif
Debug.Assert(!string.IsNullOrEmpty(algorithm.CurveOid.FriendlyName));
- Debug.Assert(x is null == y is null);
- if (x is null)
- {
- byte[] zero = new byte[d.Length];
- x = zero;
- y = zero;
- }
+ byte[] zero = new byte[d.Length];
+ byte[] x = zero;
+ byte[] y = zero;
if (!TryValidateNamedCurve(x, y, d))
{
@@ -227,7 +206,7 @@ internal override bool TryExportPrivateKey(Span destination, out int bytes
try
{
- WriteKey(ecParameters.D, ecParameters.Q.X, ecParameters.Q.Y, _algorithm.CurveOidValue, writer);
+ WriteKey(ecParameters.D, writer);
return writer.TryEncode(destination, out bytesWritten);
}
finally
@@ -260,7 +239,7 @@ internal override bool TryExportPrivateKey(Span destination, out int bytes
throw new CryptographicException();
}
- WriteKey(d, x, y, _algorithm.CurveOidValue, writer);
+ WriteKey(d, writer);
return true;
});
});
@@ -273,7 +252,7 @@ internal override bool TryExportPrivateKey(Span destination, out int bytes
}
#endif
- static void WriteKey(byte[] d, byte[]? x, byte[]? y, string curveOid, AsnWriter writer)
+ static void WriteKey(byte[] d, AsnWriter writer)
{
// ECPrivateKey
using (writer.PushSequence())
@@ -283,23 +262,6 @@ static void WriteKey(byte[] d, byte[]? x, byte[]? y, string curveOid, AsnWriter
// privateKey
writer.WriteOctetString(d);
-
- // domainParameters
- using (writer.PushSequence(new Asn1Tag(TagClass.ContextSpecific, 0, isConstructed: true)))
- {
- writer.WriteObjectIdentifier(curveOid);
- }
-
- // publicKey
- if (x != null)
- {
- Debug.Assert(y != null);
-
- using (writer.PushSequence(new Asn1Tag(TagClass.ContextSpecific, 1, isConstructed: true)))
- {
- EccKeyFormatHelper.WriteUncompressedPublicKey(x, y, writer);
- }
- }
}
}
}
diff --git a/src/libraries/Common/src/System/Security/Cryptography/CompositeMLDsaManaged.cs b/src/libraries/Common/src/System/Security/Cryptography/CompositeMLDsaManaged.cs
index 5bb63453387841..c2ec4c1d073563 100644
--- a/src/libraries/Common/src/System/Security/Cryptography/CompositeMLDsaManaged.cs
+++ b/src/libraries/Common/src/System/Security/Cryptography/CompositeMLDsaManaged.cs
@@ -5,6 +5,7 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
+using System.Formats.Asn1;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using Internal.Cryptography;
@@ -61,23 +62,21 @@ internal static CompositeMLDsa GenerateKeyImpl(CompositeMLDsaAlgorithm algorithm
AlgorithmMetadata metadata = s_algorithmMetadata[algorithm];
- // draft-ietf-lamps-pq-composite-sigs-latest (July 7, 2025), 4.1
- // 1. Generate component keys
+ // draft-ietf-lamps-pq-composite-sigs-08, 4.1
+ // 1. Generate component keys
//
- // mldsaSeed = Random(32)
- // (mldsaPK, _) = ML-DSA.KeyGen(mldsaSeed)
- // (tradPK, tradSK) = Trad.KeyGen()
+ // mldsaSeed = Random(32)
+ // (mldsaPK, mldsaSK) = ML-DSA.KeyGen(mldsaSeed)
+ // (tradPK, tradSK) = Trad.KeyGen()
+ //
+ // 2. Check for component key gen failure
+ //
+ // if NOT (mldsaPK, mldsaSK) or NOT (tradPK, tradSK):
+ // output "Key generation error"
- MLDsa? mldsaKey = null;
- ComponentAlgorithm? tradKey = null;
+ MLDsa mldsaKey = MLDsaImplementation.GenerateKey(metadata.MLDsaAlgorithm);
- try
- {
- mldsaKey = MLDsaImplementation.GenerateKey(metadata.MLDsaAlgorithm);
- }
- catch (CryptographicException)
- {
- }
+ ComponentAlgorithm? tradKey;
try
{
@@ -85,49 +84,27 @@ internal static CompositeMLDsa GenerateKeyImpl(CompositeMLDsaAlgorithm algorithm
{
RsaAlgorithm rsaAlgorithm => RsaComponent.GenerateKey(rsaAlgorithm),
ECDsaAlgorithm ecdsaAlgorithm => ECDsaComponent.GenerateKey(ecdsaAlgorithm),
- _ => FailAndGetNull(),
+ _ => throw FailAndGetException(),
};
- static ComponentAlgorithm? FailAndGetNull()
+ static CryptographicException FailAndGetException()
{
Debug.Fail("Only supported algorithms should reach here.");
- return null;
+ return new CryptographicException();
}
}
catch (CryptographicException)
{
- }
-
- // 2. Check for component key gen failure
- //
- // if NOT (mldsaPK, mldsaSK) or NOT (tradPK, tradSK):
- // output "Key generation error"
-
- [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
- static bool KeyGenFailed([NotNullWhen(false)] MLDsa? mldsaKey, [NotNullWhen(false)] ComponentAlgorithm? tradKey) =>
- (mldsaKey is null) | (tradKey is null);
-
- if (KeyGenFailed(mldsaKey, tradKey))
- {
- try
- {
- Debug.Assert(mldsaKey is null || tradKey is null);
+ mldsaKey.Dispose();
- mldsaKey?.Dispose();
- tradKey?.Dispose();
- }
- catch (CryptographicException)
- {
- }
-
- throw new CryptographicException();
+ throw;
}
- // 3. Output the composite public and private keys
+ // 3. Output the composite public and private keys
//
- // pk = SerializePublicKey(mldsaPK, tradPK)
- // sk = SerializePrivateKey(mldsaSeed, tradSK)
- // return (pk, sk)
+ // pk = SerializePublicKey(mldsaPK, tradPK)
+ // sk = SerializePrivateKey(mldsaSeed, tradSK)
+ // return (pk, sk)
return new CompositeMLDsaManaged(algorithm, mldsaKey, tradKey);
}
@@ -138,29 +115,31 @@ internal static CompositeMLDsa ImportCompositeMLDsaPublicKeyImpl(CompositeMLDsaA
AlgorithmMetadata metadata = s_algorithmMetadata[algorithm];
- // draft-ietf-lamps-pq-composite-sigs-latest (June 20, 2025), 5.1
- // 1. Parse each constituent encoded public key.
- // The length of the mldsaKey is known based on the size of
- // the ML-DSA component key length specified by the Object ID.
+ // draft-ietf-lamps-pq-composite-sigs-08, 5.1
+ // 1. Parse each constituent encoded public key.
+ // The length of the mldsaKey is known based on the
+ // size of the ML-DSA component key length specified
+ // by the Object ID.
//
- // switch ML-DSA do
- // case ML-DSA-44:
- // mldsaPK = bytes[:1312]
- // tradPK = bytes[1312:]
- // case ML-DSA-65:
- // mldsaPK = bytes[:1952]
- // tradPK = bytes[1952:]
- // case ML-DSA-87:
- // mldsaPK = bytes[:2592]
- // tradPK = bytes[2592:]
+ // switch ML-DSA do
+ // case ML-DSA-44:
+ // mldsaPK = bytes[:1312]
+ // tradPK = bytes[1312:]
+ // case ML-DSA-65:
+ // mldsaPK = bytes[:1952]
+ // tradPK = bytes[1952:]
+ // case ML-DSA-87:
+ // mldsaPK = bytes[:2592]
+ // tradPK = bytes[2592:]
//
- // Note that while ML-DSA has fixed-length keys, RSA and ECDSA
- // may not, depending on encoding, so rigorous length - checking
- // of the overall composite key is not always possible.
+ // Note that while ML-DSA has fixed-length keys, RSA and
+ // ECDSA may not, depending on encoding, so rigorous
+ // length-checking of the overall composite key is not
+ // always possible.
//
- // 2. Output the component public keys
+ // 2. Output the component public keys
//
- // output(mldsaPK, tradPK)
+ // output (mldsaPK, tradPK)
ReadOnlySpan mldsaKey = source.Slice(0, metadata.MLDsaAlgorithm.PublicKeySizeInBytes);
ReadOnlySpan tradKey = source.Slice(metadata.MLDsaAlgorithm.PublicKeySizeInBytes);
@@ -188,21 +167,19 @@ internal static CompositeMLDsa ImportCompositeMLDsaPrivateKeyImpl(CompositeMLDsa
AlgorithmMetadata metadata = s_algorithmMetadata[algorithm];
- // draft-ietf-lamps-pq-composite-sigs-latest (June 20, 2025), 5.2
- // 1. Parse each constituent encoded key.
- // The length of an ML-DSA private key is always a 32 byte seed
- // for all parameter sets.
+ // draft-ietf-lamps-pq-composite-sigs-08, 5.2
+ // 1. Parse each constituent encoded key.
//
- // mldsaSeed = bytes[:32]
- // tradSK = bytes[32:]
+ // mldsaSeed = bytes[:32]
+ // tradSK = bytes[32:]
//
- // Note that while ML-DSA has fixed-length keys, RSA and ECDSA
- // may not, depending on encoding, so rigorous length-checking
- // of the overall composite key is not always possible.
+ // Note that while ML-DSA has fixed-length keys, RSA and ECDSA
+ // may not, depending on encoding, so rigorous length-checking
+ // of the overall composite key is not always possible.
//
- // 2. Output the component private keys
+ // 2. Output the component private keys
//
- // output (mldsaSeed, tradSK)
+ // output (mldsaSeed, tradSK)
ReadOnlySpan mldsaKey = source.Slice(0, metadata.MLDsaAlgorithm.PrivateSeedSizeInBytes);
ReadOnlySpan tradKey = source.Slice(metadata.MLDsaAlgorithm.PrivateSeedSizeInBytes);
@@ -226,54 +203,48 @@ static CryptographicException FailAndGetException()
protected override int SignDataCore(ReadOnlySpan data, ReadOnlySpan context, Span destination)
{
- // draft-ietf-lamps-pq-composite-sigs-latest (June 20, 2025), 4.2
- // 1. If len(ctx) > 255:
- // return error
+ // draft-ietf-lamps-pq-composite-sigs-08, 4.2
+ // 1. If len(ctx) > 255:
+ // return error
Debug.Assert(context.Length <= 255, $"Caller should have checked context.Length, got {context.Length}");
- // 2. Compute the Message representative M'.
- // As in FIPS 204, len(ctx) is encoded as a single unsigned byte.
- // Randomize the message representative
+ // 2. Compute the Message representative M'.
+ // As in FIPS 204, len(ctx) is encoded as a single unsigned byte.
//
- // r = Random(32)
- // M' := Prefix || Domain || len(ctx) || ctx || r
- // || PH( M )
-
- Span r = stackalloc byte[CompositeMLDsaAlgorithm.RandomizerSizeInBytes];
- RandomNumberGenerator.Fill(r);
+ // M' := Prefix || Label || len(ctx) || ctx || PH( M )
- byte[] M_prime = GetMessageRepresentative(AlgorithmDetails, context, r, data);
+ byte[] M_prime = GetMessageRepresentative(AlgorithmDetails, context, data);
- // 3. Separate the private key into component keys
- // and re-generate the ML-DSA key from seed.
+ // 3. Separate the private key into component keys
+ // and re-generate the ML-DSA key from seed.
//
- // (mldsaSeed, tradSK) = DeserializePrivateKey(sk)
- // (_, mldsaSK) = ML-DSA.KeyGen(mldsaSeed)
+ // (mldsaSeed, tradSK) = DeserializePrivateKey(sk)
+ // (_, mldsaSK) = ML-DSA.KeyGen(mldsaSeed)
/* no-op */
- // 4. Generate the two component signatures independently by calculating
- // the signature over M' according to their algorithm specifications.
+ // 4. Generate the two component signatures independently by
+ // calculating the signature over M' according to their algorithm
+ // specifications.
//
- // mldsaSig = ML-DSA.Sign( mldsaSK, M', ctx=Domain )
- // tradSig = Trad.Sign( tradSK, M' )
+ // mldsaSig = ML-DSA.Sign( mldsaSK, M', ctx=Label )
+ // tradSig = Trad.Sign( tradSK, M' )
// Note that in step 4 above, both component signature processes are
// invoked, and no indication is given about which one failed.This
// SHOULD be done in a timing-invariant way to prevent side-channel
// attackers from learning which component algorithm failed.
- Span randomizer = destination.Slice(0, CompositeMLDsaAlgorithm.RandomizerSizeInBytes);
- Span mldsaSig = destination.Slice(CompositeMLDsaAlgorithm.RandomizerSizeInBytes, AlgorithmDetails.MLDsaAlgorithm.SignatureSizeInBytes);
- Span tradSig = destination.Slice(CompositeMLDsaAlgorithm.RandomizerSizeInBytes + AlgorithmDetails.MLDsaAlgorithm.SignatureSizeInBytes);
+ Span mldsaSig = destination.Slice(0, AlgorithmDetails.MLDsaAlgorithm.SignatureSizeInBytes);
+ Span tradSig = destination.Slice(AlgorithmDetails.MLDsaAlgorithm.SignatureSizeInBytes);
bool mldsaSigned = false;
bool tradSigned = false;
try
{
- _mldsa.SignData(M_prime, mldsaSig, AlgorithmDetails.DomainSeparator);
+ _mldsa.SignData(M_prime, mldsaSig, AlgorithmDetails.Label);
mldsaSigned = true;
}
catch (CryptographicException)
@@ -291,11 +262,11 @@ protected override int SignDataCore(ReadOnlySpan data, ReadOnlySpan
{
}
- // 5. If either ML-DSA.Sign() or Trad.Sign() return an error, then this
- // process MUST return an error.
+ // 5. If either ML-DSA.Sign() or Trad.Sign() return an error, then
+ // this process MUST return an error.
//
- // if NOT mldsaSig or NOT tradSig:
- // output "Signature generation error"
+ // if NOT mldsaSig or NOT tradSig:
+ // output "Signature generation error"
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
static bool Or(bool x, bool y) => x | y;
@@ -306,57 +277,54 @@ protected override int SignDataCore(ReadOnlySpan data, ReadOnlySpan
throw new CryptographicException(SR.Cryptography_CompositeSignDataError);
}
- // 6. Output the encoded composite signature value.
+ // 6. Output the encoded composite signature value.
//
- // s = SerializeSignatureValue(r, mldsaSig, tradSig)
- // return s
+ // s = SerializeSignatureValue(mldsaSig, tradSig)
+ // return s
- r.CopyTo(randomizer);
- return randomizer.Length + mldsaSig.Length + tradBytesWritten;
+ return mldsaSig.Length + tradBytesWritten;
}
protected override bool VerifyDataCore(ReadOnlySpan data, ReadOnlySpan context, ReadOnlySpan signature)
{
- // draft-ietf-lamps-pq-composite-sigs-latest (June 20, 2025), 4.3
- // 1. If len(ctx) > 255
- // return error
+ // draft-ietf-lamps-pq-composite-sigs-08, 4.3
+ // 1. If len(ctx) > 255
+ // return error
Debug.Assert(context.Length <= 255, $"Caller should have checked context.Length, got {context.Length}");
- // 2. Separate the keys and signatures
+ // 2. Separate the keys and signatures
//
- // (mldsaPK, tradPK) = DeserializePublicKey(pk)
- // (r, mldsaSig, tradSig) = DeserializeSignatureValue(s)
+ // (mldsaPK, tradPK) = DeserializePublicKey(pk)
+ // (mldsaSig, tradSig) = DeserializeSignatureValue(s)
//
- // If Error during deserialization, or if any of the component
- // keys or signature values are not of the correct type or
- // length for the given component algorithm then output
- // "Invalid signature" and stop.
+ // If Error during deserialization, or if any of the component
+ // keys or signature values are not of the correct type or
+ // length for the given component algorithm then output
+ // "Invalid signature" and stop.
- ReadOnlySpan r = signature.Slice(0, CompositeMLDsaAlgorithm.RandomizerSizeInBytes);
- ReadOnlySpan mldsaSig = signature.Slice(CompositeMLDsaAlgorithm.RandomizerSizeInBytes, AlgorithmDetails.MLDsaAlgorithm.SignatureSizeInBytes);
- ReadOnlySpan tradSig = signature.Slice(CompositeMLDsaAlgorithm.RandomizerSizeInBytes + AlgorithmDetails.MLDsaAlgorithm.SignatureSizeInBytes);
+ ReadOnlySpan mldsaSig = signature.Slice(0, AlgorithmDetails.MLDsaAlgorithm.SignatureSizeInBytes);
+ ReadOnlySpan tradSig = signature.Slice(AlgorithmDetails.MLDsaAlgorithm.SignatureSizeInBytes);
- // 3. Compute a Hash of the Message.
- // As in FIPS 204, len(ctx) is encoded as a single unsigned byte.
+ // 3. Compute a Hash of the Message.
+ // As in FIPS 204, len(ctx) is encoded as a single unsigned byte.
//
- // M' = Prefix || Domain || len(ctx) || ctx || r
- // || PH( M )
+ // M' = Prefix || Label || len(ctx) || ctx || PH( M )
- byte[] M_prime = GetMessageRepresentative(AlgorithmDetails, context, r, data);
+ byte[] M_prime = GetMessageRepresentative(AlgorithmDetails, context, data);
- // 4. Check each component signature individually, according to its
- // algorithm specification.
- // If any fail, then the entire signature validation fails.
+ // 4. Check each component signature individually, according to its
+ // algorithm specification.
+ // If any fail, then the entire signature validation fails.
//
- // if not ML-DSA.Verify( mldsaPK, M', mldsaSig, ctx=Domain ) then
- // output "Invalid signature"
+ // if not ML-DSA.Verify( mldsaPK, M', mldsaSig, ctx=Label ) then
+ // output "Invalid signature"
//
- // if not Trad.Verify( tradPK, M', tradSig ) then
- // output "Invalid signature"
+ // if not Trad.Verify( tradPK, M', tradSig ) then
+ // output "Invalid signature"
//
- // if all succeeded, then
- // output "Valid signature"
+ // if all succeeded, then
+ // output "Valid signature"
// We don't short circuit here because we want to avoid revealing which component signature failed.
// This is not required in the spec, but it is a good practice to avoid timing attacks.
@@ -364,18 +332,53 @@ protected override bool VerifyDataCore(ReadOnlySpan data, ReadOnlySpan x & y;
- return And(_mldsa.VerifyData(M_prime, mldsaSig, AlgorithmDetails.DomainSeparator), _componentAlgorithm.VerifyData(M_prime, tradSig));
+ return And(_mldsa.VerifyData(M_prime, mldsaSig, AlgorithmDetails.Label), _componentAlgorithm.VerifyData(M_prime, tradSig));
}
- protected override bool TryExportPkcs8PrivateKeyCore(Span destination, out int bytesWritten) =>
- throw new PlatformNotSupportedException();
+ protected override bool TryExportPkcs8PrivateKeyCore(Span destination, out int bytesWritten)
+ {
+ AsnWriter? writer = null;
+
+ try
+ {
+ using (CryptoPoolLease lease = CryptoPoolLease.Rent(Algorithm.MaxPrivateKeySizeInBytes))
+ {
+ int privateKeySize = ExportCompositeMLDsaPrivateKeyCore(lease.Span);
+
+ // Add some overhead for the ASN.1 structure.
+ int initialCapacity = 32 + privateKeySize;
+
+ writer = new AsnWriter(AsnEncodingRules.DER, initialCapacity);
+
+ using (writer.PushSequence())
+ {
+ writer.WriteInteger(0); // Version
+
+ using (writer.PushSequence())
+ {
+ writer.WriteObjectIdentifier(Algorithm.Oid);
+ }
+
+ writer.WriteOctetString(lease.Span.Slice(0, privateKeySize));
+ }
+
+ Debug.Assert(writer.GetEncodedLength() <= initialCapacity);
+ }
+
+ return writer.TryEncode(destination, out bytesWritten);
+ }
+ finally
+ {
+ writer?.Reset();
+ }
+ }
protected override int ExportCompositeMLDsaPublicKeyCore(Span destination)
{
- // draft-ietf-lamps-pq-composite-sigs-latest (June 20, 2025), 5.1
- // 1. Combine and output the encoded public key
+ // draft-ietf-lamps-pq-composite-sigs-08, 5.1
+ // 1. Combine and output the encoded public key
//
- // output mldsaPK || tradPK
+ // output mldsaPK || tradPK
int bytesWritten = 0;
@@ -394,10 +397,10 @@ protected override int ExportCompositeMLDsaPublicKeyCore(Span destination)
protected override int ExportCompositeMLDsaPrivateKeyCore(Span destination)
{
- // draft-ietf-lamps-pq-composite-sigs-latest (June 20, 2025), 5.2
- // 1. Combine and output the encoded private key
+ // draft-ietf-lamps-pq-composite-sigs-08, 5.2
+ // 1. Combine and output the encoded private key.
//
- // output mldsaSeed || tradSK
+ // output mldsaSeed || tradSK
try
{
@@ -439,14 +442,11 @@ protected override void Dispose(bool disposing)
private static byte[] GetMessageRepresentative(
AlgorithmMetadata metadata,
ReadOnlySpan context,
- ReadOnlySpan r,
ReadOnlySpan message)
{
checked
{
- Debug.Assert(r.Length is CompositeMLDsaAlgorithm.RandomizerSizeInBytes);
-
- // M' = Prefix || Domain || len(ctx) || ctx || r || PH( M )
+ // M' = Prefix || Label || len(ctx) || ctx || PH( M )
using (IncrementalHash hash = IncrementalHash.CreateHash(metadata.HashAlgorithmName))
{
@@ -458,10 +458,9 @@ private static byte[] GetMessageRepresentative(
int length =
MessageRepresentativePrefix.Length + // Prefix
- metadata.DomainSeparator.Length + // Domain
+ metadata.Label.Length + // Label
1 + // len(ctx)
context.Length + // ctx
- r.Length + // r
hashLength; // PH( M )
// The representative message will often be < 256 bytes so we can stackalloc with a callback.
@@ -474,9 +473,9 @@ private static byte[] GetMessageRepresentative(
MessageRepresentativePrefix.CopyTo(M_prime.AsSpan(offset, MessageRepresentativePrefix.Length));
offset += MessageRepresentativePrefix.Length;
- // Domain
- metadata.DomainSeparator.AsSpan().CopyTo(M_prime.AsSpan(offset, metadata.DomainSeparator.Length));
- offset += metadata.DomainSeparator.Length;
+ // Label
+ metadata.Label.AsSpan().CopyTo(M_prime.AsSpan(offset, metadata.Label.Length));
+ offset += metadata.Label.Length;
// len(ctx)
M_prime[offset] = (byte)context.Length;
@@ -486,10 +485,6 @@ private static byte[] GetMessageRepresentative(
context.CopyTo(M_prime.AsSpan(offset, context.Length));
offset += context.Length;
- // r
- r.CopyTo(M_prime.AsSpan(offset, r.Length));
- offset += r.Length;
-
// PH( M )
hash.AppendData(message);
#if NET
@@ -567,7 +562,7 @@ private static Dictionary CreateAlgo
new AlgorithmMetadata(
MLDsaAlgorithm.MLDsa44,
new RsaAlgorithm(2048, HashAlgorithmName.SHA256, RSASignaturePadding.Pss),
- [0x06, 0x0B, 0x60, 0x86, 0x48, 0x01, 0x86, 0xFA, 0x6B, 0x50, 0x09, 0x01, 0x00],
+ [.."COMPSIG-MLDSA44-RSA2048-PSS-SHA256"u8],
HashAlgorithmName.SHA256)
},
{
@@ -575,7 +570,7 @@ private static Dictionary CreateAlgo
new AlgorithmMetadata(
MLDsaAlgorithm.MLDsa44,
new RsaAlgorithm(2048, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1),
- [0x06, 0x0B, 0x60, 0x86, 0x48, 0x01, 0x86, 0xFA, 0x6B, 0x50, 0x09, 0x01, 0x01],
+ [.."COMPSIG-MLDSA44-RSA2048-PKCS15-SHA256"u8],
HashAlgorithmName.SHA256)
},
{
@@ -583,7 +578,7 @@ private static Dictionary CreateAlgo
new AlgorithmMetadata(
MLDsaAlgorithm.MLDsa44,
new EdDsaAlgorithm(),
- [0x06, 0x0B, 0x60, 0x86, 0x48, 0x01, 0x86, 0xFA, 0x6B, 0x50, 0x09, 0x01, 0x02],
+ [.. "COMPSIG-MLDSA44-Ed25519-SHA512"u8],
HashAlgorithmName.SHA512)
},
{
@@ -591,7 +586,7 @@ private static Dictionary CreateAlgo
new AlgorithmMetadata(
MLDsaAlgorithm.MLDsa44,
ECDsaAlgorithm.CreateP256(HashAlgorithmName.SHA256),
- [0x06, 0x0B, 0x60, 0x86, 0x48, 0x01, 0x86, 0xFA, 0x6B, 0x50, 0x09, 0x01, 0x03],
+ [.."COMPSIG-MLDSA44-ECDSA-P256-SHA256"u8],
HashAlgorithmName.SHA256)
},
{
@@ -599,7 +594,7 @@ private static Dictionary CreateAlgo
new AlgorithmMetadata(
MLDsaAlgorithm.MLDsa65,
new RsaAlgorithm(3072, HashAlgorithmName.SHA256, RSASignaturePadding.Pss),
- [0x06, 0x0B, 0x60, 0x86, 0x48, 0x01, 0x86, 0xFA, 0x6B, 0x50, 0x09, 0x01, 0x04],
+ [.."COMPSIG-MLDSA65-RSA3072-PSS-SHA512"u8],
HashAlgorithmName.SHA512)
},
{
@@ -607,7 +602,7 @@ private static Dictionary CreateAlgo
new AlgorithmMetadata(
MLDsaAlgorithm.MLDsa65,
new RsaAlgorithm(3072, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1),
- [0x06, 0x0B, 0x60, 0x86, 0x48, 0x01, 0x86, 0xFA, 0x6B, 0x50, 0x09, 0x01, 0x05],
+ [.."COMPSIG-MLDSA65-RSA3072-PKCS15-SHA512"u8],
HashAlgorithmName.SHA512)
},
{
@@ -615,7 +610,7 @@ private static Dictionary CreateAlgo
new AlgorithmMetadata(
MLDsaAlgorithm.MLDsa65,
new RsaAlgorithm(4096, HashAlgorithmName.SHA384, RSASignaturePadding.Pss),
- [0x06, 0x0B, 0x60, 0x86, 0x48, 0x01, 0x86, 0xFA, 0x6B, 0x50, 0x09, 0x01, 0x06],
+ [.."COMPSIG-MLDSA65-RSA4096-PSS-SHA512"u8],
HashAlgorithmName.SHA512)
},
{
@@ -623,7 +618,7 @@ private static Dictionary CreateAlgo
new AlgorithmMetadata(
MLDsaAlgorithm.MLDsa65,
new RsaAlgorithm(4096, HashAlgorithmName.SHA384, RSASignaturePadding.Pkcs1),
- [0x06, 0x0B, 0x60, 0x86, 0x48, 0x01, 0x86, 0xFA, 0x6B, 0x50, 0x09, 0x01, 0x07],
+ [.."COMPSIG-MLDSA65-RSA4096-PKCS15-SHA512"u8],
HashAlgorithmName.SHA512)
},
{
@@ -631,7 +626,7 @@ private static Dictionary CreateAlgo
new AlgorithmMetadata(
MLDsaAlgorithm.MLDsa65,
ECDsaAlgorithm.CreateP256(HashAlgorithmName.SHA256),
- [0x06, 0x0B, 0x60, 0x86, 0x48, 0x01, 0x86, 0xFA, 0x6B, 0x50, 0x09, 0x01, 0x08],
+ [.."COMPSIG-MLDSA65-P256-SHA512"u8],
HashAlgorithmName.SHA512)
},
{
@@ -639,7 +634,7 @@ private static Dictionary CreateAlgo
new AlgorithmMetadata(
MLDsaAlgorithm.MLDsa65,
ECDsaAlgorithm.CreateP384(HashAlgorithmName.SHA384),
- [0x06, 0x0B, 0x60, 0x86, 0x48, 0x01, 0x86, 0xFA, 0x6B, 0x50, 0x09, 0x01, 0x09],
+ [.."COMPSIG-MLDSA65-P384-SHA512"u8],
HashAlgorithmName.SHA512)
},
{
@@ -647,7 +642,7 @@ private static Dictionary CreateAlgo
new AlgorithmMetadata(
MLDsaAlgorithm.MLDsa65,
ECDsaAlgorithm.CreateBrainpoolP256r1(HashAlgorithmName.SHA256),
- [0x06, 0x0B, 0x60, 0x86, 0x48, 0x01, 0x86, 0xFA, 0x6B, 0x50, 0x09, 0x01, 0x0A],
+ [.."COMPSIG-MLDSA65-BP256-SHA512"u8],
HashAlgorithmName.SHA512)
},
{
@@ -655,7 +650,7 @@ private static Dictionary CreateAlgo
new AlgorithmMetadata(
MLDsaAlgorithm.MLDsa65,
new EdDsaAlgorithm(),
- [0x06, 0x0B, 0x60, 0x86, 0x48, 0x01, 0x86, 0xFA, 0x6B, 0x50, 0x09, 0x01, 0x0B],
+ [.."COMPSIG-MLDSA65-Ed25519-SHA512"u8],
HashAlgorithmName.SHA512)
},
{
@@ -663,7 +658,7 @@ private static Dictionary CreateAlgo
new AlgorithmMetadata(
MLDsaAlgorithm.MLDsa87,
ECDsaAlgorithm.CreateP384(HashAlgorithmName.SHA384),
- [0x06, 0x0B, 0x60, 0x86, 0x48, 0x01, 0x86, 0xFA, 0x6B, 0x50, 0x09, 0x01, 0x0C],
+ [.."COMPSIG-MLDSA87-P384-SHA512"u8],
HashAlgorithmName.SHA512)
},
{
@@ -671,7 +666,7 @@ private static Dictionary CreateAlgo
new AlgorithmMetadata(
MLDsaAlgorithm.MLDsa87,
ECDsaAlgorithm.CreateBrainpoolP384r1(HashAlgorithmName.SHA384),
- [0x06, 0x0B, 0x60, 0x86, 0x48, 0x01, 0x86, 0xFA, 0x6B, 0x50, 0x09, 0x01, 0x0D],
+ [.."COMPSIG-MLDSA87-BP384-SHA512"u8],
HashAlgorithmName.SHA512)
},
{
@@ -679,7 +674,7 @@ private static Dictionary CreateAlgo
new AlgorithmMetadata(
MLDsaAlgorithm.MLDsa87,
new EdDsaAlgorithm(),
- [0x06, 0x0B, 0x60, 0x86, 0x48, 0x01, 0x86, 0xFA, 0x6B, 0x50, 0x09, 0x01, 0x0E],
+ [.."COMPSIG-MLDSA87-Ed448-SHAKE256"u8],
new HashAlgorithmName("SHAKE256"))
},
{
@@ -687,7 +682,7 @@ private static Dictionary CreateAlgo
new AlgorithmMetadata(
MLDsaAlgorithm.MLDsa87,
new RsaAlgorithm(3072, HashAlgorithmName.SHA256, RSASignaturePadding.Pss),
- [0x06, 0x0B, 0x60, 0x86, 0x48, 0x01, 0x86, 0xFA, 0x6B, 0x50, 0x09, 0x01, 0x0F],
+ [.."COMPSIG-MLDSA87-RSA3072-PSS-SHA512"u8],
HashAlgorithmName.SHA512)
},
{
@@ -695,7 +690,7 @@ private static Dictionary CreateAlgo
new AlgorithmMetadata(
MLDsaAlgorithm.MLDsa87,
new RsaAlgorithm(4096, HashAlgorithmName.SHA384, RSASignaturePadding.Pss),
- [0x06, 0x0B, 0x60, 0x86, 0x48, 0x01, 0x86, 0xFA, 0x6B, 0x50, 0x09, 0x01, 0x10],
+ [.."COMPSIG-MLDSA87-RSA4096-PSS-SHA512"u8],
HashAlgorithmName.SHA512)
},
{
@@ -703,7 +698,7 @@ private static Dictionary CreateAlgo
new AlgorithmMetadata(
MLDsaAlgorithm.MLDsa87,
ECDsaAlgorithm.CreateP521(HashAlgorithmName.SHA512),
- [0x06, 0x0B, 0x60, 0x86, 0x48, 0x01, 0x86, 0xFA, 0x6B, 0x50, 0x09, 0x01, 0x11],
+ [.."COMPSIG-MLDSA87-P521-SHA512"u8],
HashAlgorithmName.SHA512)
}
};
@@ -716,12 +711,12 @@ private static Dictionary CreateAlgo
private sealed class AlgorithmMetadata(
MLDsaAlgorithm mldsaAlgorithm,
object traditionalAlgorithm,
- byte[] domainSeparator,
+ byte[] label,
HashAlgorithmName hashAlgorithmName)
{
internal MLDsaAlgorithm MLDsaAlgorithm { get; } = mldsaAlgorithm;
internal object TraditionalAlgorithm { get; } = traditionalAlgorithm;
- internal byte[] DomainSeparator { get; } = domainSeparator;
+ internal byte[] Label { get; } = label;
internal HashAlgorithmName HashAlgorithmName { get; } = hashAlgorithmName;
}
diff --git a/src/libraries/Common/src/System/Security/Cryptography/EccKeyFormatHelper.cs b/src/libraries/Common/src/System/Security/Cryptography/EccKeyFormatHelper.cs
deleted file mode 100644
index 72df332a19fade..00000000000000
--- a/src/libraries/Common/src/System/Security/Cryptography/EccKeyFormatHelper.cs
+++ /dev/null
@@ -1,62 +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.Formats.Asn1;
-
-namespace System.Security.Cryptography
-{
- internal static partial class EccKeyFormatHelper
- {
- internal static void GetECPointFromUncompressedPublicKey(ReadOnlySpan publicKey, int fieldWidthInBytes, out byte[] x, out byte[] y)
- {
- if (publicKey.Length == 0)
- {
- throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding);
- }
-
- // Implementation limitation
- // 04 (Uncompressed ECPoint) is almost always used.
- if (publicKey[0] != 0x04)
- {
- throw new CryptographicException(SR.Cryptography_NotValidPublicOrPrivateKey);
- }
-
- // https://www.secg.org/sec1-v2.pdf, 2.3.4, #3 (M has length 2 * CEIL(log2(q)/8) + 1)
- if (publicKey.Length != 2 * fieldWidthInBytes + 1)
- {
- throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding);
- }
-
- x = publicKey.Slice(1, fieldWidthInBytes).ToArray();
- y = publicKey.Slice(1 + fieldWidthInBytes).ToArray();
- }
-
- internal static void WriteUncompressedPublicKey(byte[] x, byte[] y, AsnWriter writer)
- {
- int publicKeyLength = x.Length * 2 + 1;
-
- // A NIST P-521 Q will encode to 133 bytes: (521 + 7)/8 * 2 + 1.
- // 256 should be plenty for all but very atypical uses.
- const int MaxStackAllocSize = 256;
- Span publicKeyBytes = stackalloc byte[MaxStackAllocSize];
- byte[]? rented = null;
-
- if (publicKeyLength > MaxStackAllocSize)
- {
- publicKeyBytes = rented = CryptoPool.Rent(publicKeyLength);
- }
-
- publicKeyBytes[0] = 0x04;
- x.CopyTo(publicKeyBytes.Slice(1));
- y.CopyTo(publicKeyBytes.Slice(1 + x.Length));
-
- writer.WriteBitString(publicKeyBytes.Slice(0, publicKeyLength));
-
- if (rented is not null)
- {
- // Q contains public EC parameters that are not sensitive.
- CryptoPool.Return(rented, clearSize: 0);
- }
- }
- }
-}
diff --git a/src/libraries/Common/src/System/Security/Cryptography/MLDsa.cs b/src/libraries/Common/src/System/Security/Cryptography/MLDsa.cs
index 662addf92386e8..a774719bc668ff 100644
--- a/src/libraries/Common/src/System/Security/Cryptography/MLDsa.cs
+++ b/src/libraries/Common/src/System/Security/Cryptography/MLDsa.cs
@@ -24,7 +24,6 @@ namespace System.Security.Cryptography
/// cryptographic libraries.
///
///
- [Experimental(Experimentals.PostQuantumCryptographyDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
public abstract partial class MLDsa : IDisposable
#if DESIGNTIMEINTERFACES
#pragma warning disable SA1001
@@ -299,6 +298,7 @@ public bool VerifyData(byte[] data, byte[] signature, byte[]? context = default)
/// -or-
/// An error occurred while signing the hash.
///
+ [Experimental(Experimentals.PostQuantumCryptographyDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
public void SignPreHash(ReadOnlySpan hash, Span destination, string hashAlgorithmOid, ReadOnlySpan context = default)
{
ArgumentNullException.ThrowIfNull(hashAlgorithmOid);
@@ -364,6 +364,7 @@ public void SignPreHash(ReadOnlySpan hash, Span destination, string
/// -or-
/// An error occurred while signing the hash.
///
+ [Experimental(Experimentals.PostQuantumCryptographyDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
public byte[] SignPreHash(byte[] hash, string hashAlgorithmOid, byte[]? context = default)
{
ArgumentNullException.ThrowIfNull(hash);
@@ -410,6 +411,7 @@ public byte[] SignPreHash(byte[] hash, string hashAlgorithmOid, byte[]? context
/// -or-
/// An error occurred while verifying the hash.
///
+ [Experimental(Experimentals.PostQuantumCryptographyDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
public bool VerifyPreHash(ReadOnlySpan hash, ReadOnlySpan signature, string hashAlgorithmOid, ReadOnlySpan context = default)
{
ArgumentNullException.ThrowIfNull(hashAlgorithmOid);
@@ -481,6 +483,7 @@ public bool VerifyPreHash(ReadOnlySpan hash, ReadOnlySpan signature,
///
/// A context is treated as empty.
///
+ [Experimental(Experimentals.PostQuantumCryptographyDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
public bool VerifyPreHash(byte[] hash, byte[] signature, string hashAlgorithmOid, byte[]? context = null)
{
ArgumentNullException.ThrowIfNull(hash);
@@ -496,6 +499,7 @@ public bool VerifyPreHash(byte[] hash, byte[] signature, string hashAlgorithmOid
///
/// is .
+ [Experimental(Experimentals.PostQuantumCryptographyDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
public byte[] SignMu(byte[] externalMu)
{
ArgumentNullException.ThrowIfNull(externalMu);
@@ -527,6 +531,7 @@ public byte[] SignMu(byte[] externalMu)
/// The current platform does not support signing with an externally computed mu value.
///
///
+ [Experimental(Experimentals.PostQuantumCryptographyDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
public byte[] SignMu(ReadOnlySpan externalMu)
{
byte[] destination = new byte[Algorithm.SignatureSizeInBytes];
@@ -566,6 +571,7 @@ public byte[] SignMu(ReadOnlySpan externalMu)
/// The current platform does not support signing with an externally computed mu value.
///
///
+ [Experimental(Experimentals.PostQuantumCryptographyDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
public void SignMu(ReadOnlySpan externalMu, Span destination)
{
if (externalMu.Length != Algorithm.MuSizeInBytes)
@@ -590,12 +596,14 @@ public void SignMu(ReadOnlySpan externalMu, Span destination)
///
/// An error occurred while computing the signature.
///
+ [Experimental(Experimentals.PostQuantumCryptographyDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
protected abstract void SignMuCore(ReadOnlySpan externalMu, Span destination);
///
///
/// or is .
///
+ [Experimental(Experimentals.PostQuantumCryptographyDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
public bool VerifyMu(byte[] externalMu, byte[] signature)
{
ArgumentNullException.ThrowIfNull(externalMu);
@@ -620,6 +628,7 @@ public bool VerifyMu(byte[] externalMu, byte[] signature)
///
/// The current platform does not support verification with an externally computed mu value.
///
+ [Experimental(Experimentals.PostQuantumCryptographyDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
public bool VerifyMu(ReadOnlySpan externalMu, ReadOnlySpan signature)
{
if (externalMu.Length != Algorithm.MuSizeInBytes || signature.Length != Algorithm.SignatureSizeInBytes)
@@ -641,6 +650,7 @@ public bool VerifyMu(ReadOnlySpan externalMu, ReadOnlySpan signature
///
/// if the mu value is valid; otherwise, .
///
+ [Experimental(Experimentals.PostQuantumCryptographyDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
protected abstract bool VerifyMuCore(ReadOnlySpan externalMu, ReadOnlySpan signature);
///
@@ -655,6 +665,7 @@ public bool VerifyMu(ReadOnlySpan externalMu, ReadOnlySpan signature
///
/// An error occurred while exporting the key.
///
+ [Experimental(Experimentals.PostQuantumCryptographyDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
public byte[] ExportSubjectPublicKeyInfo()
{
ThrowIfDisposed();
@@ -684,6 +695,7 @@ public byte[] ExportSubjectPublicKeyInfo()
///
/// An error occurred while exporting the key.
///
+ [Experimental(Experimentals.PostQuantumCryptographyDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
public bool TryExportSubjectPublicKeyInfo(Span destination, out int bytesWritten)
{
ThrowIfDisposed();
@@ -706,6 +718,7 @@ public bool TryExportSubjectPublicKeyInfo(Span destination, out int bytesW
///
/// An error occurred while exporting the key.
///
+ [Experimental(Experimentals.PostQuantumCryptographyDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
public string ExportSubjectPublicKeyInfoPem()
{
ThrowIfDisposed();
@@ -732,6 +745,7 @@ public string ExportSubjectPublicKeyInfoPem()
/// -or-
/// An error occurred while exporting the key.
///
+ [Experimental(Experimentals.PostQuantumCryptographyDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
public byte[] ExportPkcs8PrivateKey()
{
ThrowIfDisposed();
@@ -760,6 +774,7 @@ public byte[] ExportPkcs8PrivateKey()
///
/// An error occurred while exporting the key.
///
+ [Experimental(Experimentals.PostQuantumCryptographyDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
public bool TryExportPkcs8PrivateKey(Span destination, out int bytesWritten)
{
ThrowIfDisposed();
@@ -803,6 +818,7 @@ public bool TryExportPkcs8PrivateKey(Span destination, out int bytesWritte
///
/// An error occurred while exporting the key.
///
+ [Experimental(Experimentals.PostQuantumCryptographyDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
protected abstract bool TryExportPkcs8PrivateKeyCore(Span destination, out int bytesWritten);
///
@@ -818,6 +834,7 @@ public bool TryExportPkcs8PrivateKey(Span destination, out int bytesWritte
///
/// An error occurred while exporting the key.
///
+ [Experimental(Experimentals.PostQuantumCryptographyDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
public string ExportPkcs8PrivateKeyPem()
{
ThrowIfDisposed();
@@ -852,6 +869,7 @@ public string ExportPkcs8PrivateKeyPem()
/// -or-
/// An error occurred while exporting the key.
///
+ [Experimental(Experimentals.PostQuantumCryptographyDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
public byte[] ExportEncryptedPkcs8PrivateKey(ReadOnlySpan password, PbeParameters pbeParameters)
{
ArgumentNullException.ThrowIfNull(pbeParameters);
@@ -899,6 +917,7 @@ public byte[] ExportEncryptedPkcs8PrivateKey(ReadOnlySpan password, PbePar
/// -or-
/// An error occurred while exporting the key.
///
+ [Experimental(Experimentals.PostQuantumCryptographyDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
public byte[] ExportEncryptedPkcs8PrivateKey(ReadOnlySpan passwordBytes, PbeParameters pbeParameters)
{
ArgumentNullException.ThrowIfNull(pbeParameters);
@@ -921,6 +940,7 @@ public byte[] ExportEncryptedPkcs8PrivateKey(ReadOnlySpan passwordBytes, P
///
/// or is .
///
+ [Experimental(Experimentals.PostQuantumCryptographyDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
public byte[] ExportEncryptedPkcs8PrivateKey(string password, PbeParameters pbeParameters)
{
ArgumentNullException.ThrowIfNull(password);
@@ -964,6 +984,7 @@ public byte[] ExportEncryptedPkcs8PrivateKey(string password, PbeParameters pbeP
/// -or-
/// An error occurred while exporting the key.
///
+ [Experimental(Experimentals.PostQuantumCryptographyDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
public bool TryExportEncryptedPkcs8PrivateKey(
ReadOnlySpan password,
PbeParameters pbeParameters,
@@ -1024,6 +1045,7 @@ public bool TryExportEncryptedPkcs8PrivateKey(
/// -or-
/// An error occurred while exporting the key.
///
+ [Experimental(Experimentals.PostQuantumCryptographyDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
public bool TryExportEncryptedPkcs8PrivateKey(
ReadOnlySpan passwordBytes,
PbeParameters pbeParameters,
@@ -1050,6 +1072,7 @@ public bool TryExportEncryptedPkcs8PrivateKey(
///
/// or is .
///
+ [Experimental(Experimentals.PostQuantumCryptographyDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
public bool TryExportEncryptedPkcs8PrivateKey(
string password,
PbeParameters pbeParameters,
@@ -1089,6 +1112,7 @@ public bool TryExportEncryptedPkcs8PrivateKey(
/// -or-
/// An error occurred while exporting the key.
///
+ [Experimental(Experimentals.PostQuantumCryptographyDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
public string ExportEncryptedPkcs8PrivateKeyPem(
ReadOnlySpan password,
PbeParameters pbeParameters)
@@ -1133,6 +1157,7 @@ public string ExportEncryptedPkcs8PrivateKeyPem(
/// -or-
/// An error occurred while exporting the key.
///
+ [Experimental(Experimentals.PostQuantumCryptographyDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
public string ExportEncryptedPkcs8PrivateKeyPem(
ReadOnlySpan passwordBytes,
PbeParameters pbeParameters)
@@ -1151,6 +1176,7 @@ public string ExportEncryptedPkcs8PrivateKeyPem(
///
/// or is .
///
+ [Experimental(Experimentals.PostQuantumCryptographyDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
public string ExportEncryptedPkcs8PrivateKeyPem(
string password,
PbeParameters pbeParameters)
@@ -1344,6 +1370,7 @@ public static MLDsa GenerateKey(MLDsaAlgorithm algorithm)
/// The platform does not support ML-DSA. Callers can use the property
/// to determine if the platform supports ML-DSA.
///
+ [Experimental(Experimentals.PostQuantumCryptographyDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
public static MLDsa ImportSubjectPublicKeyInfo(ReadOnlySpan source)
{
Helpers.ThrowIfAsnInvalidLength(source);
@@ -1376,6 +1403,7 @@ public static MLDsa ImportSubjectPublicKeyInfo(ReadOnlySpan source)
///
/// is .
///
+ [Experimental(Experimentals.PostQuantumCryptographyDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
public static MLDsa ImportSubjectPublicKeyInfo(byte[] source)
{
ArgumentNullException.ThrowIfNull(source);
@@ -1413,6 +1441,7 @@ public static MLDsa ImportSubjectPublicKeyInfo(byte[] source)
/// The platform does not support ML-DSA. Callers can use the property
/// to determine if the platform supports ML-DSA.
///
+ [Experimental(Experimentals.PostQuantumCryptographyDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
public static MLDsa ImportPkcs8PrivateKey(ReadOnlySpan source)
{
Helpers.ThrowIfAsnInvalidLength(source);
@@ -1427,6 +1456,7 @@ public static MLDsa ImportPkcs8PrivateKey(ReadOnlySpan source)
///
/// is .
///
+ [Experimental(Experimentals.PostQuantumCryptographyDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
public static MLDsa ImportPkcs8PrivateKey(byte[] source)
{
ArgumentNullException.ThrowIfNull(source);
@@ -1476,6 +1506,7 @@ public static MLDsa ImportPkcs8PrivateKey(byte[] source)
/// The platform does not support ML-DSA. Callers can use the property
/// to determine if the platform supports ML-DSA.
///
+ [Experimental(Experimentals.PostQuantumCryptographyDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
public static MLDsa ImportEncryptedPkcs8PrivateKey(ReadOnlySpan passwordBytes, ReadOnlySpan source)
{
Helpers.ThrowIfAsnInvalidLength(source);
@@ -1525,6 +1556,7 @@ public static MLDsa ImportEncryptedPkcs8PrivateKey(ReadOnlySpan passwordBy
/// The platform does not support ML-DSA. Callers can use the property
/// to determine if the platform supports ML-DSA.
///
+ [Experimental(Experimentals.PostQuantumCryptographyDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
public static MLDsa ImportEncryptedPkcs8PrivateKey(ReadOnlySpan password, ReadOnlySpan source)
{
Helpers.ThrowIfAsnInvalidLength(source);
@@ -1541,6 +1573,7 @@ public static MLDsa ImportEncryptedPkcs8PrivateKey(ReadOnlySpan password,
///
/// or is .
///
+ [Experimental(Experimentals.PostQuantumCryptographyDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
public static MLDsa ImportEncryptedPkcs8PrivateKey(string password, byte[] source)
{
ArgumentNullException.ThrowIfNull(password);
@@ -1585,6 +1618,7 @@ public static MLDsa ImportEncryptedPkcs8PrivateKey(string password, byte[] sourc
///
///
///
+ [Experimental(Experimentals.PostQuantumCryptographyDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
public static MLDsa ImportFromPem(ReadOnlySpan source)
{
ThrowIfNotSupported();
@@ -1602,6 +1636,7 @@ public static MLDsa ImportFromPem(ReadOnlySpan source)
///
/// is .
///
+ [Experimental(Experimentals.PostQuantumCryptographyDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
public static MLDsa ImportFromPem(string source)
{
ArgumentNullException.ThrowIfNull(source);
@@ -1669,6 +1704,7 @@ public static MLDsa ImportFromPem(string source)
///
/// This method supports the ENCRYPTED PRIVATE KEY PEM label.
///
+ [Experimental(Experimentals.PostQuantumCryptographyDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
public static MLDsa ImportFromEncryptedPem(ReadOnlySpan source, ReadOnlySpan password)
{
ThrowIfNotSupported();
@@ -1733,6 +1769,7 @@ public static MLDsa ImportFromEncryptedPem(ReadOnlySpan source, ReadOnlySp
///
/// This method supports the ENCRYPTED PRIVATE KEY PEM label.
///
+ [Experimental(Experimentals.PostQuantumCryptographyDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
public static MLDsa ImportFromEncryptedPem(ReadOnlySpan source, ReadOnlySpan passwordBytes)
{
ThrowIfNotSupported();
@@ -1747,6 +1784,7 @@ public static MLDsa ImportFromEncryptedPem(ReadOnlySpan source, ReadOnlySp
///
/// or is .
///
+ [Experimental(Experimentals.PostQuantumCryptographyDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
public static MLDsa ImportFromEncryptedPem(string source, string password)
{
ArgumentNullException.ThrowIfNull(source);
@@ -1760,6 +1798,7 @@ public static MLDsa ImportFromEncryptedPem(string source, string password)
///
/// or is .
///
+ [Experimental(Experimentals.PostQuantumCryptographyDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
public static MLDsa ImportFromEncryptedPem(string source, byte[] passwordBytes)
{
ArgumentNullException.ThrowIfNull(source);
@@ -1988,6 +2027,7 @@ protected virtual void Dispose(bool disposing)
///
/// An error occurred while signing the hash.
///
+ [Experimental(Experimentals.PostQuantumCryptographyDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
protected abstract void SignPreHashCore(ReadOnlySpan hash, ReadOnlySpan context, string hashAlgorithmOid, Span destination);
///
@@ -2011,6 +2051,7 @@ protected virtual void Dispose(bool disposing)
///
/// An error occurred while verifying the hash.
///
+ [Experimental(Experimentals.PostQuantumCryptographyDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
protected abstract bool VerifyPreHashCore(ReadOnlySpan hash, ReadOnlySpan context, string hashAlgorithmOid, ReadOnlySpan signature);
///
diff --git a/src/libraries/Common/src/System/Security/Cryptography/MLDsaAlgorithm.cs b/src/libraries/Common/src/System/Security/Cryptography/MLDsaAlgorithm.cs
index 1b30552e4ceddc..61dfbe4069f62e 100644
--- a/src/libraries/Common/src/System/Security/Cryptography/MLDsaAlgorithm.cs
+++ b/src/libraries/Common/src/System/Security/Cryptography/MLDsaAlgorithm.cs
@@ -10,7 +10,6 @@ namespace System.Security.Cryptography
/// Represents a specific algorithm within the ML-DSA family.
///
[DebuggerDisplay("{Name,nq}")]
- [Experimental(Experimentals.PostQuantumCryptographyDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
public sealed class MLDsaAlgorithm : IEquatable
{
///
diff --git a/src/libraries/Common/src/System/Security/Cryptography/MLDsaCng.cs b/src/libraries/Common/src/System/Security/Cryptography/MLDsaCng.cs
index ba51f4aba7fdec..e8f881581c63c9 100644
--- a/src/libraries/Common/src/System/Security/Cryptography/MLDsaCng.cs
+++ b/src/libraries/Common/src/System/Security/Cryptography/MLDsaCng.cs
@@ -21,7 +21,6 @@ namespace System.Security.Cryptography
/// cryptographic libraries.
///
///
- [Experimental(Experimentals.PostQuantumCryptographyDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
public sealed partial class MLDsaCng : MLDsa
{
private CngKey _key;
diff --git a/src/libraries/Common/src/System/Security/Cryptography/Oids.cs b/src/libraries/Common/src/System/Security/Cryptography/Oids.cs
index 10785201fde8ab..92d055bc598f13 100644
--- a/src/libraries/Common/src/System/Security/Cryptography/Oids.cs
+++ b/src/libraries/Common/src/System/Security/Cryptography/Oids.cs
@@ -135,24 +135,24 @@ internal static partial class Oids
internal const string Mgf1 = "1.2.840.113549.1.1.8";
internal const string PSpecified = "1.2.840.113549.1.1.9";
- internal const string MLDsa44WithRSA2048PssPreHashSha256 = "2.16.840.1.114027.80.9.1.0";
- internal const string MLDsa44WithRSA2048Pkcs15PreHashSha256 = "2.16.840.1.114027.80.9.1.1";
- internal const string MLDsa44WithEd25519PreHashSha512 = "2.16.840.1.114027.80.9.1.2";
- internal const string MLDsa44WithECDsaP256PreHashSha256 = "2.16.840.1.114027.80.9.1.3";
- internal const string MLDsa65WithRSA3072PssPreHashSha512 = "2.16.840.1.114027.80.9.1.4";
- internal const string MLDsa65WithRSA3072Pkcs15PreHashSha512 = "2.16.840.1.114027.80.9.1.5";
- internal const string MLDsa65WithRSA4096PssPreHashSha512 = "2.16.840.1.114027.80.9.1.6";
- internal const string MLDsa65WithRSA4096Pkcs15PreHashSha512 = "2.16.840.1.114027.80.9.1.7";
- internal const string MLDsa65WithECDsaP256PreHashSha512 = "2.16.840.1.114027.80.9.1.8";
- internal const string MLDsa65WithECDsaP384PreHashSha512 = "2.16.840.1.114027.80.9.1.9";
- internal const string MLDsa65WithECDsaBrainpoolP256r1PreHashSha512 = "2.16.840.1.114027.80.9.1.10";
- internal const string MLDsa65WithEd25519PreHashSha512 = "2.16.840.1.114027.80.9.1.11";
- internal const string MLDsa87WithECDsaP384PreHashSha512 = "2.16.840.1.114027.80.9.1.12";
- internal const string MLDsa87WithECDsaBrainpoolP384r1PreHashSha512 = "2.16.840.1.114027.80.9.1.13";
- internal const string MLDsa87WithEd448PreHashShake256_512 = "2.16.840.1.114027.80.9.1.14";
- internal const string MLDsa87WithRSA3072PssPreHashSha512 = "2.16.840.1.114027.80.9.1.15";
- internal const string MLDsa87WithRSA4096PssPreHashSha512 = "2.16.840.1.114027.80.9.1.16";
- internal const string MLDsa87WithECDsaP521PreHashSha512 = "2.16.840.1.114027.80.9.1.17";
+ internal const string MLDsa44WithRSA2048PssPreHashSha256 = "2.16.840.1.114027.80.9.1.20";
+ internal const string MLDsa44WithRSA2048Pkcs15PreHashSha256 = "2.16.840.1.114027.80.9.1.21";
+ internal const string MLDsa44WithEd25519PreHashSha512 = "2.16.840.1.114027.80.9.1.22";
+ internal const string MLDsa44WithECDsaP256PreHashSha256 = "2.16.840.1.114027.80.9.1.23";
+ internal const string MLDsa65WithRSA3072PssPreHashSha512 = "2.16.840.1.114027.80.9.1.24";
+ internal const string MLDsa65WithRSA3072Pkcs15PreHashSha512 = "2.16.840.1.114027.80.9.1.25";
+ internal const string MLDsa65WithRSA4096PssPreHashSha512 = "2.16.840.1.114027.80.9.1.26";
+ internal const string MLDsa65WithRSA4096Pkcs15PreHashSha512 = "2.16.840.1.114027.80.9.1.27";
+ internal const string MLDsa65WithECDsaP256PreHashSha512 = "2.16.840.1.114027.80.9.1.28";
+ internal const string MLDsa65WithECDsaP384PreHashSha512 = "2.16.840.1.114027.80.9.1.29";
+ internal const string MLDsa65WithECDsaBrainpoolP256r1PreHashSha512 = "2.16.840.1.114027.80.9.1.30";
+ internal const string MLDsa65WithEd25519PreHashSha512 = "2.16.840.1.114027.80.9.1.31";
+ internal const string MLDsa87WithECDsaP384PreHashSha512 = "2.16.840.1.114027.80.9.1.32";
+ internal const string MLDsa87WithECDsaBrainpoolP384r1PreHashSha512 = "2.16.840.1.114027.80.9.1.33";
+ internal const string MLDsa87WithEd448PreHashShake256_512 = "2.16.840.1.114027.80.9.1.34";
+ internal const string MLDsa87WithRSA3072PssPreHashSha512 = "2.16.840.1.114027.80.9.1.35";
+ internal const string MLDsa87WithRSA4096PssPreHashSha512 = "2.16.840.1.114027.80.9.1.36";
+ internal const string MLDsa87WithECDsaP521PreHashSha512 = "2.16.840.1.114027.80.9.1.37";
// PKCS#7
internal const string NoSignature = "1.3.6.1.5.5.7.6.2";
diff --git a/src/libraries/Common/src/System/Security/Cryptography/X509Certificates/CertificateHelpers.Windows.cs b/src/libraries/Common/src/System/Security/Cryptography/X509Certificates/CertificateHelpers.Windows.cs
index 06b4f618a49d95..ae8aebf9380d76 100644
--- a/src/libraries/Common/src/System/Security/Cryptography/X509Certificates/CertificateHelpers.Windows.cs
+++ b/src/libraries/Common/src/System/Security/Cryptography/X509Certificates/CertificateHelpers.Windows.cs
@@ -25,6 +25,8 @@ internal static partial class CertificateHelpers
private static partial int GuessKeySpec(CngProvider provider, string keyName, bool machineKey, CngAlgorithmGroup? algorithmGroup);
+ private static partial SafeCertContextHandle DuplicateCertificateHandle(TCertificate certificate);
+
#if !SYSTEM_SECURITY_CRYPTOGRAPHY
[SupportedOSPlatform("windows")]
#endif
@@ -75,7 +77,7 @@ internal static TCertificate CopyWithPrivateKey(TCertificate certificate, MLDsa
internal static T? GetPrivateKey(TCertificate certificate, Func createCsp, Func createCng)
where T : class, IDisposable
{
- using (SafeCertContextHandle certContext = Interop.Crypt32.CertDuplicateCertificateContext(certificate.Handle))
+ using (SafeCertContextHandle certContext = DuplicateCertificateHandle(certificate))
{
SafeNCryptKeyHandle? ncryptKey = TryAcquireCngPrivateKey(certContext, out CngKeyHandleOpenOptions cngHandleOptions);
if (ncryptKey != null)
diff --git a/src/libraries/Common/src/System/Security/Cryptography/X509Certificates/X509CertificateLoader.Pkcs12.cs b/src/libraries/Common/src/System/Security/Cryptography/X509Certificates/X509CertificateLoader.Pkcs12.cs
index 1e6b5974c6e667..1175a3e07f4034 100644
--- a/src/libraries/Common/src/System/Security/Cryptography/X509Certificates/X509CertificateLoader.Pkcs12.cs
+++ b/src/libraries/Common/src/System/Security/Cryptography/X509Certificates/X509CertificateLoader.Pkcs12.cs
@@ -22,14 +22,15 @@ public static partial class X509CertificateLoader
private const int NTE_FAIL = unchecked((int)0x80090020);
#endif
-#pragma warning disable CA1805
- private static readonly AttributeAsn? s_syntheticKspAttribute =
+ private const X509KeyStorageFlags EphemeralKeySet =
#if NET
- null;
+ X509KeyStorageFlags.EphemeralKeySet;
#else
- BuildSyntheticKspAttribute();
+ (X509KeyStorageFlags)0x20;
#endif
-#pragma warning restore CA1805
+
+ private static readonly AttributeAsn s_syntheticKspAttribute = BuildSyntheticKspAttribute();
+ private static readonly AttributeAsn s_syntheticCapiCspAttribute = BuildSyntheticCapiAttribute();
static partial void LoadPkcs12NoLimits(
ReadOnlyMemory data,
@@ -71,6 +72,7 @@ private static Pkcs12Return LoadPkcs12(
}
BagState bagState = default;
+ bagState.SetStorageFlags(keyStorageFlags);
try
{
@@ -279,6 +281,7 @@ private static void ProcessSafeContents(
outer.ThrowIfNotEmpty();
HashSet duplicateAttributeCheck = new();
+ CngMachineKeyState machineKeyState = CngMachineKeyState.Unknown;
while (reader.HasData)
{
@@ -370,16 +373,59 @@ private static void ProcessSafeContents(
// so always preserve it.
Oids.MsPkcs12MachineKeySet => true,
Oids.Pkcs9FriendlyName => limits.PreserveKeyName,
- Oids.MsPkcs12KeyProviderName => limits.PreserveStorageProvider,
+ Oids.MsPkcs12KeyProviderName => ProviderNameIsRelevant,
_ => limits.PreserveUnknownAttributes,
});
}
- if (!loaderLimits.PreserveStorageProvider && s_syntheticKspAttribute.HasValue)
+ AttributeAsn? providerName = null;
+
+ if (ProviderNameIsRelevant)
{
- int newCount = (bag.BagAttributes?.Length).GetValueOrDefault(0) + 1;
- Array.Resize(ref bag.BagAttributes, newCount);
- bag.BagAttributes[newCount - 1] = s_syntheticKspAttribute.GetValueOrDefault();
+ // Ephemeral loads have to go into CNG, but also won't get access denied,
+
+ if ((bagState.StorageFlags & EphemeralKeySet) == 0 &&
+ !loaderLimits.PreserveStorageProvider)
+ {
+ providerName = DetermineStorageProvider(
+ bag.BagAttributes,
+ bagState.StorageFlags,
+ ref machineKeyState);
+ }
+
+ // If DetermineStorageProvider returns null, leave an existing provider alone,
+ // but if there's no provider, add the synthetic KSP attribute.
+
+ // Otherwise, replace any existing provider with what it returned,
+ // or add what it said if there are no provider attributes.
+
+ bool hasAttribute = false;
+
+ foreach (AttributeAsn attr in bag.BagAttributes ?? Array.Empty())
+ {
+ if (attr.AttrType == Oids.MsPkcs12KeyProviderName)
+ {
+ hasAttribute = true;
+
+ if (providerName.HasValue)
+ {
+ if (attr.AttrValues?.Length > 0)
+ {
+ for (int i = 0; i < attr.AttrValues.Length; i++)
+ {
+ attr.AttrValues[i] = providerName.GetValueOrDefault().AttrValues[0];
+ }
+ }
+ }
+ }
+ }
+
+ if (!hasAttribute)
+ {
+ int oldCount = (bag.BagAttributes?.Length).GetValueOrDefault(0);
+ Array.Resize(ref bag.BagAttributes, oldCount + 1);
+ bag.BagAttributes[oldCount] = s_syntheticKspAttribute;
+ }
}
bagState.AddKey(bag);
@@ -568,8 +614,18 @@ static int GetRawKdfCount(in AlgorithmIdentifierAsn algorithmIdentifier)
}
}
-#if !NET
- private static AttributeAsn? BuildSyntheticKspAttribute()
+ private static bool ProviderNameIsRelevant =>
+#if NET
+ OperatingSystem.IsWindows();
+#else
+ // The netstandard builds could use RuntimeInformation.IsOSPlatform,
+ // but we'd still need a #else for .NET Framework, so netstandard
+ // and netfx will both say provider name is relevant and process
+ // the attributes accordingly.
+ true;
+#endif
+
+ private static AttributeAsn BuildSyntheticKspAttribute()
{
AsnWriter writer = new AsnWriter(AsnEncodingRules.DER);
writer.WriteCharacterString(UniversalTagNumber.BMPString, "Microsoft Software Key Storage Provider");
@@ -580,14 +636,257 @@ static int GetRawKdfCount(in AlgorithmIdentifierAsn algorithmIdentifier)
AttrValues = new[] { new ReadOnlyMemory(writer.Encode()) }
};
}
+
+ private static AttributeAsn BuildSyntheticCapiAttribute()
+ {
+ AsnWriter writer = new AsnWriter(AsnEncodingRules.DER);
+ writer.WriteCharacterString(UniversalTagNumber.BMPString, "Microsoft Enhanced RSA and AES Cryptographic Provider");
+
+ return new AttributeAsn
+ {
+ AttrType = Oids.MsPkcs12KeyProviderName,
+ AttrValues = new[] { new ReadOnlyMemory(writer.Encode()) }
+ };
+ }
+
+ private static AttributeAsn? DetermineStorageProvider(
+ AttributeAsn[]? bagAttributes,
+ X509KeyStorageFlags storageFlags,
+ ref CngMachineKeyState machineKeyState)
+ {
+ // Windows CNG and Windows CAPI have different default permissions models for machine keys.
+ //
+ // CAPI allows anyone to create a machine key, CNG only allows administrators.
+ //
+ // But if a system has changed their permissions to allow non-admins to create CNG machine keys,
+ // then, by all means, we should use CNG.
+
+ // This all breaks down to:
+ //
+ // if (machine key && can't make machine keys && known CAPI provider)
+ // {
+ // if (RSA)
+ // {
+ // return CAPI PROV_RSA_AES;
+ // }
+ // else
+ // {
+ // pretend PreserveStorageProvider was set.
+ // }
+ // }
+ //
+ // return CNG KSP;
+
+ if (HasMachineKey(bagAttributes, storageFlags) && HasCapiCsp(bagAttributes, out bool isRsa))
+ {
+ if (machineKeyState == CngMachineKeyState.Unknown)
+ {
+ machineKeyState = CheckMachineKeyPermissions();
+ }
+
+ if (machineKeyState == CngMachineKeyState.Denied)
+ {
+ if (isRsa)
+ {
+ return s_syntheticCapiCspAttribute;
+ }
+
+ // A DSS or DH CAPI provider, preserve it.
+ return null;
+ }
+ }
+
+ // Not a machine key, or wasn't known to be a CAPI key, so use CNG.
+ return s_syntheticKspAttribute;
+
+ static bool HasMachineKey(AttributeAsn[]? bagAttributes, X509KeyStorageFlags storageKind)
+ {
+ // This needs to be kept in sync with the Windows MapStorageFlags behavior.
+ // We say that both UserKeySet & MachineKeySet maps to a user key.
+
+ if ((storageKind & X509KeyStorageFlags.UserKeySet) != 0)
+ {
+ return false;
+ }
+
+ if ((storageKind & X509KeyStorageFlags.MachineKeySet) != 0)
+ {
+ return true;
+ }
+
+ // The Machine Key Set attribute OID is a sentinel, the attribute has no interpreted value.
+ // So, any attribute that specifies it means it's a machine key.
+ if (bagAttributes is not null)
+ {
+ foreach (AttributeAsn attr in bagAttributes)
+ {
+ if (attr.AttrType == Oids.MsPkcs12MachineKeySet)
+ {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ static CngMachineKeyState CheckMachineKeyPermissions()
+ {
+#if NET || NETFRAMEWORK
+ CngKey? cngKey = null;
+
+ try
+ {
+#if NET
+ Debug.Assert(OperatingSystem.IsWindows());
#endif
+ cngKey = CngKey.Create(
+ CngAlgorithm.Rsa,
+ "netperm-" + Guid.NewGuid().ToString("B"),
+ new CngKeyCreationParameters
+ {
+ Provider = CngProvider.MicrosoftSoftwareKeyStorageProvider,
+ KeyCreationOptions = CngKeyCreationOptions.MachineKey,
+ });
+
+ return CngMachineKeyState.Permitted;
+ }
+ catch (CryptographicException)
+ {
+ return CngMachineKeyState.Denied;
+ }
+ finally
+ {
+ cngKey?.Delete();
+ }
+#else
+ // The netstandard builds shouldn't ever execute on a relevant configuration,
+ // so it's not worth adding a reference to the Cng package for this method
+ // to compile.
+ return CngMachineKeyState.Permitted;
+#endif
+ }
+
+ static bool HasCapiCsp(AttributeAsn[]? bagAttributes, out bool isRsa)
+ {
+ isRsa = false;
+
+ if (bagAttributes is not null)
+ {
+ foreach (AttributeAsn attr in bagAttributes)
+ {
+ if (attr.AttrType == Oids.MsPkcs12KeyProviderName && attr.AttrValues?.Length > 0)
+ {
+ return HasCapiValue(attr.AttrValues[0].Span, out isRsa);
+ }
+ }
+ }
+
+ // If there is no provider name at all, then PFXImportCertStore will use the CAPI
+ // MS_DEF_PROV provider, so it's a CAPI key.
+ return true;
+
+ static bool HasCapiValue(ReadOnlySpan encodedAttribute, out bool isRsa)
+ {
+ // All of the MS_*_PROV_W values from wincrypt.h, except MS_SCARD_PROV(_W).
+ const string MS_DEF_PROV = "Microsoft Base Cryptographic Provider v1.0";
+ const string MS_ENHANCED_PROV = "Microsoft Enhanced Cryptographic Provider v1.0";
+ const string MS_STRONG_PROV = "Microsoft Strong Cryptographic Provider";
+ const string MS_DEF_RSA_SIG_PROV = "Microsoft RSA Signature Cryptographic Provider";
+ const string MS_DEF_RSA_SCHANNEL_PROV = "Microsoft RSA SChannel Cryptographic Provider";
+ const string MS_DEF_DSS_PROV = "Microsoft Base DSS Cryptographic Provider";
+ const string MS_DEF_DSS_DH_PROV = "Microsoft Base DSS and Diffie-Hellman Cryptographic Provider";
+ const string MS_ENH_DSS_DH_PROV = "Microsoft Enhanced DSS and Diffie-Hellman Cryptographic Provider";
+ const string MS_DEF_DH_SCHANNEL_PROV = "Microsoft DH SChannel Cryptographic Provider";
+ const string MS_ENH_RSA_AES_PROV = "Microsoft Enhanced RSA and AES Cryptographic Provider";
+ const string MS_ENH_RSA_AES_PROV_XP = "Microsoft Enhanced RSA and AES Cryptographic Provider (Prototype)";
+
+ isRsa = false;
+
+ if (!Asn1Tag.TryDecode(encodedAttribute, out Asn1Tag tag, out _))
+ {
+ return false;
+ }
+
+ if (tag.TagClass != TagClass.Universal)
+ {
+ return false;
+ }
+
+ string? providerName;
+
+ try
+ {
+ UniversalTagNumber encodingType = (UniversalTagNumber)tag.TagValue;
+ int bytesRead = 0;
+
+ // Windows writes the provider using BMPString, but reads it from any type.
+ // Technically, Windows will read it as a NumericString, because they don't
+ // validate characters being outside the character set.
+ // Since we do validation, NumericString is omitted.
+ providerName = encodingType switch
+ {
+ UniversalTagNumber.BMPString or
+ UniversalTagNumber.UTF8String or
+ UniversalTagNumber.IA5String or
+ UniversalTagNumber.PrintableString or
+ UniversalTagNumber.VisibleString or
+ UniversalTagNumber.T61String => AsnDecoder.ReadCharacterString(
+ encodedAttribute,
+ AsnEncodingRules.BER,
+ encodingType,
+ out bytesRead),
+ _ => null,
+ };
+
+ if (bytesRead != encodedAttribute.Length)
+ {
+ return false;
+ }
+ }
+ catch (AsnContentException)
+ {
+ return false;
+ }
+
+ isRsa = providerName switch
+ {
+ MS_DEF_PROV or
+ MS_ENHANCED_PROV or
+ MS_STRONG_PROV or
+ MS_DEF_RSA_SIG_PROV or
+ MS_DEF_RSA_SCHANNEL_PROV or
+ MS_ENH_RSA_AES_PROV or
+ MS_ENH_RSA_AES_PROV_XP => true,
+ _ => false,
+ };
+
+ return isRsa || providerName switch
+ {
+ MS_DEF_DSS_PROV or
+ MS_DEF_DSS_DH_PROV or
+ MS_ENH_DSS_DH_PROV or
+ MS_DEF_DH_SCHANNEL_PROV => true,
+ _ => false,
+ };
+ }
+ }
+ }
+
private readonly partial struct Pkcs12Return
{
internal partial bool HasValue();
internal partial X509Certificate2 ToCertificate();
}
+ private enum CngMachineKeyState
+ {
+ Unknown,
+ Permitted,
+ Denied,
+ };
+
private partial struct BagState
{
private SafeBagAsn[]? _certBags;
@@ -599,6 +898,17 @@ private partial struct BagState
private int _decryptBufferOffset;
private int _keyDecryptBufferOffset;
private byte _passwordState;
+ private X509KeyStorageFlags _storageFlags;
+
+ internal void SetStorageFlags(X509KeyStorageFlags storageFlags)
+ {
+ const X509KeyStorageFlags RelevantFlags =
+ X509KeyStorageFlags.MachineKeySet |
+ X509KeyStorageFlags.UserKeySet |
+ EphemeralKeySet;
+
+ _storageFlags = storageFlags & RelevantFlags;
+ }
internal void Init(Pkcs12LoaderLimits loaderLimits)
{
@@ -634,6 +944,8 @@ public void Dispose()
this = default;
}
+ internal readonly X509KeyStorageFlags StorageFlags => _storageFlags;
+
public readonly int CertCount => _certCount;
public readonly int KeyCount => _keyCount;
diff --git a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.ServerCertificates.cs b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.ServerCertificates.cs
index b2d0179378eca8..0ed517ae168426 100644
--- a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.ServerCertificates.cs
+++ b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.ServerCertificates.cs
@@ -246,6 +246,7 @@ public async Task NoCallback_RevokedCertificate_NoRevocationChecking_Succeeds()
public async Task NoCallback_RevokedCertificate_RevocationChecking_Fails()
{
HttpClientHandler handler = CreateHttpClientHandler();
+ handler.CheckCertificateRevocationList = true;
using (HttpClient client = CreateHttpClient(handler))
{
await Assert.ThrowsAsync(() => client.GetAsync(Configuration.Http.RevokedCertRemoteServer));
diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/CompositeMLDsa/CompositeMLDsaContractTests.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/CompositeMLDsa/CompositeMLDsaContractTests.cs
index 5e1dd854f41660..6b523c4c51c6ab 100644
--- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/CompositeMLDsa/CompositeMLDsaContractTests.cs
+++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/CompositeMLDsa/CompositeMLDsaContractTests.cs
@@ -2,7 +2,9 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System.Collections.Generic;
+using System.Formats.Asn1;
using System.Linq;
+using System.Security.Cryptography.Asn1;
using Xunit;
using CompositeMLDsaTestVector = System.Security.Cryptography.Tests.CompositeMLDsaTestData.CompositeMLDsaTestVector;
@@ -32,6 +34,20 @@ public static void NullArgumentValidation(CompositeMLDsaAlgorithm algorithm, boo
AssertExtensions.Throws("data", () => dsa.VerifyData(null, null));
AssertExtensions.Throws("signature", () => dsa.VerifyData(Array.Empty(), null));
+
+ AssertExtensions.Throws("password", () => dsa.ExportEncryptedPkcs8PrivateKey((string)null, null));
+ AssertExtensions.Throws("password", () => dsa.ExportEncryptedPkcs8PrivateKeyPem((string)null, null));
+ AssertExtensions.Throws("password", () => dsa.TryExportEncryptedPkcs8PrivateKey((string)null, null, Span.Empty, out _));
+
+ AssertExtensions.Throws("pbeParameters", () => dsa.ExportEncryptedPkcs8PrivateKey(ReadOnlySpan.Empty, null));
+ AssertExtensions.Throws("pbeParameters", () => dsa.ExportEncryptedPkcs8PrivateKey(ReadOnlySpan.Empty, null));
+ AssertExtensions.Throws("pbeParameters", () => dsa.ExportEncryptedPkcs8PrivateKey(string.Empty, null));
+ AssertExtensions.Throws("pbeParameters", () => dsa.ExportEncryptedPkcs8PrivateKeyPem(ReadOnlySpan.Empty, null));
+ AssertExtensions.Throws("pbeParameters", () => dsa.ExportEncryptedPkcs8PrivateKeyPem(ReadOnlySpan.Empty, null));
+ AssertExtensions.Throws("pbeParameters", () => dsa.ExportEncryptedPkcs8PrivateKeyPem(string.Empty, null));
+ AssertExtensions.Throws("pbeParameters", () => dsa.TryExportEncryptedPkcs8PrivateKey(ReadOnlySpan.Empty, null, Span.Empty, out _));
+ AssertExtensions.Throws("pbeParameters", () => dsa.TryExportEncryptedPkcs8PrivateKey(ReadOnlySpan.Empty, null, Span.Empty, out _));
+ AssertExtensions.Throws("pbeParameters", () => dsa.TryExportEncryptedPkcs8PrivateKey(string.Empty, null, Span.Empty, out _));
}
[Fact]
@@ -62,6 +78,37 @@ public static void ArgumentValidation(CompositeMLDsaAlgorithm algorithm, bool sh
AssertExtensions.Throws("context", () => dsa.VerifyData(Array.Empty(), new byte[maxSignatureSize], new byte[256]));
}
+ [Theory]
+ [MemberData(nameof(ArgumentValidationData))]
+ public static void ArgumentValidation_PbeParameters(CompositeMLDsaAlgorithm algorithm, bool shouldDispose)
+ {
+ using CompositeMLDsa dsa = CompositeMLDsaMockImplementation.Create(algorithm);
+
+ if (shouldDispose)
+ {
+ // Test that argument validation exceptions take precedence over ObjectDisposedException
+ dsa.Dispose();
+ }
+
+ CompositeMLDsaTestHelpers.AssertEncryptedExportPkcs8PrivateKey(export =>
+ {
+ // Unknown algorithm
+ AssertExtensions.Throws(() =>
+ export(dsa, "PLACEHOLDER", new PbeParameters(PbeEncryptionAlgorithm.Unknown, HashAlgorithmName.SHA1, 42)));
+
+ // TripleDes3KeyPkcs12 only works with SHA1
+ AssertExtensions.Throws(() =>
+ export(dsa, "PLACEHOLDER", new PbeParameters(PbeEncryptionAlgorithm.TripleDes3KeyPkcs12, HashAlgorithmName.SHA512, 42)));
+ });
+
+ CompositeMLDsaTestHelpers.AssertEncryptedExportPkcs8PrivateKey(export =>
+ {
+ // Bytes not allowed in TripleDes3KeyPkcs12
+ AssertExtensions.Throws(() =>
+ export(dsa, "PLACEHOLDER", new PbeParameters(PbeEncryptionAlgorithm.TripleDes3KeyPkcs12, HashAlgorithmName.SHA1, 42)));
+ }, CompositeMLDsaTestHelpers.EncryptionPasswordType.Byte);
+ }
+
[Theory]
[MemberData(nameof(CompositeMLDsaTestData.AllAlgorithmsTestData), MemberType = typeof(CompositeMLDsaTestData))]
public static void TryExportCompositeMLDsaPublicKey_LowerBound(CompositeMLDsaAlgorithm algorithm)
@@ -478,7 +525,7 @@ public static void ExportCompositeMLDsaPrivateKey_Array_UpperBound(CompositeMLDs
public static void SignData_LowerBound(CompositeMLDsaAlgorithm algorithm)
{
using CompositeMLDsaMockImplementation dsa = CompositeMLDsaMockImplementation.Create(algorithm);
- int lowerBound = 32 + CompositeMLDsaTestHelpers.MLDsaAlgorithms[algorithm].SignatureSizeInBytes +
+ int lowerBound = CompositeMLDsaTestHelpers.MLDsaAlgorithms[algorithm].SignatureSizeInBytes +
CompositeMLDsaTestHelpers.ExecuteComponentFunc(
algorithm,
rsa => rsa.KeySizeInBits / 8,
@@ -545,7 +592,7 @@ public static void VerifyData_Threshold(CompositeMLDsaAlgorithm algorithm)
CompositeMLDsaTestHelpers.ExecuteComponentFunc(
algorithm,
rsa => algorithm.MaxSignatureSizeInBytes,
- ecdsa => 32 + CompositeMLDsaTestHelpers.MLDsaAlgorithms[algorithm].SignatureSizeInBytes + 8,
+ ecdsa => CompositeMLDsaTestHelpers.MLDsaAlgorithms[algorithm].SignatureSizeInBytes + 8,
eddsa => algorithm.MaxSignatureSizeInBytes);
AssertExtensions.FalseExpression(dsa.VerifyData(ReadOnlySpan.Empty, new byte[threshold - 1]));
@@ -926,6 +973,223 @@ public static void Dispose_CallsVirtual(CompositeMLDsaAlgorithm algorithm)
CompositeMLDsaTestHelpers.VerifyDisposed(dsa);
}
+ [Theory]
+ [MemberData(nameof(CompositeMLDsaTestData.AllAlgorithmsTestData), MemberType = typeof(CompositeMLDsaTestData))]
+ public static void ExportSubjectPublicKeyInfo_CallsExportPublicKey(CompositeMLDsaAlgorithm algorithm)
+ {
+ CompositeMLDsaTestHelpers.AssertExportSubjectPublicKeyInfo(export =>
+ {
+ using CompositeMLDsaMockImplementation dsa = CompositeMLDsaMockImplementation.Create(algorithm);
+
+ dsa.ExportCompositeMLDsaPublicKeyCoreHook = dest => dest.Length;
+ dsa.AddLengthAssertion();
+ dsa.AddFillDestination(1);
+
+ byte[] exported = export(dsa);
+ AssertExtensions.GreaterThan(dsa.ExportCompositeMLDsaPublicKeyCoreCallCount, 0);
+
+ SubjectPublicKeyInfoAsn exportedSpki = SubjectPublicKeyInfoAsn.Decode(exported, AsnEncodingRules.DER);
+ AssertExtensions.FilledWith(1, exportedSpki.SubjectPublicKey.Span);
+ Assert.Equal(CompositeMLDsaTestHelpers.AlgorithmToOid(algorithm), exportedSpki.Algorithm.Algorithm);
+ AssertExtensions.FalseExpression(exportedSpki.Algorithm.Parameters.HasValue);
+ });
+ }
+
+ [Theory]
+ [MemberData(nameof(CompositeMLDsaTestData.AllAlgorithmsTestData), MemberType = typeof(CompositeMLDsaTestData))]
+ public static void TryExportPkcs8PrivateKey_DestinationTooSmall(CompositeMLDsaAlgorithm algorithm)
+ {
+ using CompositeMLDsaMockImplementation dsa = CompositeMLDsaMockImplementation.Create(algorithm);
+
+ // Early heuristic based bailout so no core methods are called
+ AssertExtensions.FalseExpression(
+ dsa.TryExportPkcs8PrivateKey(new byte[CompositeMLDsaTestHelpers.ExpectedPrivateKeySizeLowerBound(algorithm) - 1], out int bytesWritten));
+ Assert.Equal(0, bytesWritten);
+ }
+
+ [Theory]
+ [MemberData(nameof(CompositeMLDsaTestData.AllAlgorithmsTestData), MemberType = typeof(CompositeMLDsaTestData))]
+ public static void ExportPkcs8PrivateKey_DestinationInitialSize(CompositeMLDsaAlgorithm algorithm)
+ {
+ using CompositeMLDsaMockImplementation dsa = CompositeMLDsaMockImplementation.Create(algorithm);
+
+ dsa.TryExportPkcs8PrivateKeyCoreHook = (Span destination, out int bytesWritten) =>
+ {
+ // The first call should at least be the size of the private key
+ destination.Fill(42);
+ AssertExtensions.GreaterThanOrEqualTo(destination.Length, CompositeMLDsaTestHelpers.ExpectedPrivateKeySizeLowerBound(algorithm));
+ bytesWritten = destination.Length;
+
+ // Before we return, update the next callback so subsequent calls fail the test
+ dsa.TryExportPkcs8PrivateKeyCoreHook = (Span destination, out int bytesWritten) =>
+ {
+ Assert.Fail();
+ bytesWritten = 0;
+ return true;
+ };
+
+ return true;
+ };
+
+ byte[] exported = dsa.ExportPkcs8PrivateKey();
+
+ Assert.Equal(1, dsa.TryExportPkcs8PrivateKeyCoreCallCount);
+ AssertExtensions.FilledWith(42, exported);
+ }
+
+ [Theory]
+ [MemberData(nameof(CompositeMLDsaTestData.AllAlgorithmsTestData), MemberType = typeof(CompositeMLDsaTestData))]
+ public static void ExportPkcs8PrivateKey_Resizes(CompositeMLDsaAlgorithm algorithm)
+ {
+ using CompositeMLDsaMockImplementation dsa = CompositeMLDsaMockImplementation.Create(algorithm);
+
+ int originalSize = -1;
+ dsa.TryExportPkcs8PrivateKeyCoreHook = (Span destination, out int bytesWritten) =>
+ {
+ // Return false to force a resize
+ bool ret = false;
+ originalSize = destination.Length;
+ bytesWritten = 0;
+
+ // Before we return false, update the callback so the next call will succeed
+ dsa.TryExportPkcs8PrivateKeyCoreHook = (Span destination, out int bytesWritten) =>
+ {
+ // New buffer must be larger than the original
+ bool ret = true;
+ AssertExtensions.GreaterThan(destination.Length, originalSize);
+ destination.Fill(42);
+ bytesWritten = destination.Length;
+
+ // Before we return, update the next callback so subsequent calls fail the test
+ dsa.TryExportPkcs8PrivateKeyCoreHook = (Span destination, out int bytesWritten) =>
+ {
+ Assert.Fail();
+ bytesWritten = 0;
+ return true;
+ };
+
+ return ret;
+ };
+
+ return ret;
+ };
+
+ byte[] exported = dsa.ExportPkcs8PrivateKey();
+
+ Assert.Equal(2, dsa.TryExportPkcs8PrivateKeyCoreCallCount);
+ AssertExtensions.FilledWith(42, exported);
+ }
+
+ [Theory]
+ [MemberData(nameof(CompositeMLDsaTestData.AllAlgorithmsTestData), MemberType = typeof(CompositeMLDsaTestData))]
+ public static void ExportPkcs8PrivateKey_IgnoreReturnValue(CompositeMLDsaAlgorithm algorithm)
+ {
+ using CompositeMLDsaMockImplementation dsa = CompositeMLDsaMockImplementation.Create(algorithm);
+
+ int[] valuesToWrite = [-1, 0, int.MaxValue];
+ int index = 0;
+
+ int finalDestinationSize = -1;
+ dsa.TryExportPkcs8PrivateKeyCoreHook = (Span destination, out int bytesWritten) =>
+ {
+ // Go through all the values we want to test, and once we reach the last one,
+ // return true with a valid value
+ if (index >= valuesToWrite.Length)
+ {
+ finalDestinationSize = bytesWritten = 1;
+ return true;
+ }
+
+ // This returned value should should be ignored. There's no way to check
+ // what happens with it, but at the very least we should expect no exceptions
+ // and the correct number of calls.
+ bytesWritten = valuesToWrite[index];
+ index++;
+ return false;
+ };
+
+ int actualSize = dsa.ExportPkcs8PrivateKey().Length;
+ Assert.Equal(finalDestinationSize, actualSize);
+ Assert.Equal(valuesToWrite.Length + 1, dsa.TryExportPkcs8PrivateKeyCoreCallCount);
+ }
+
+ [Theory]
+ [MemberData(nameof(CompositeMLDsaTestData.AllAlgorithmsTestData), MemberType = typeof(CompositeMLDsaTestData))]
+ public static void ExportPkcs8PrivateKey_HandleBadReturnValue(CompositeMLDsaAlgorithm algorithm)
+ {
+ using CompositeMLDsaMockImplementation dsa = CompositeMLDsaMockImplementation.Create(algorithm);
+
+ Func getBadReturnValue = (int destinationLength) => destinationLength + 1;
+ CompositeMLDsaMockImplementation.TryExportFunc hook = (Span destination, out int bytesWritten) =>
+ {
+ bool ret = true;
+
+ bytesWritten = getBadReturnValue(destination.Length);
+
+ // Before we return, update the next callback so subsequent calls fail the test
+ dsa.TryExportPkcs8PrivateKeyCoreHook = (Span destination, out int bytesWritten) =>
+ {
+ Assert.Fail();
+ bytesWritten = 0;
+ return true;
+ };
+
+ return ret;
+ };
+
+ dsa.TryExportPkcs8PrivateKeyCoreHook = hook;
+ Assert.Throws(dsa.ExportPkcs8PrivateKey);
+ Assert.Equal(1, dsa.TryExportPkcs8PrivateKeyCoreCallCount);
+
+ dsa.TryExportPkcs8PrivateKeyCoreHook = hook;
+ getBadReturnValue = (int destinationLength) => int.MaxValue;
+ Assert.Throws(dsa.ExportPkcs8PrivateKey);
+ Assert.Equal(2, dsa.TryExportPkcs8PrivateKeyCoreCallCount);
+
+ dsa.TryExportPkcs8PrivateKeyCoreHook = hook;
+ getBadReturnValue = (int destinationLength) => -1;
+ Assert.Throws(dsa.ExportPkcs8PrivateKey);
+ Assert.Equal(3, dsa.TryExportPkcs8PrivateKeyCoreCallCount);
+ }
+
+ [Theory]
+ [MemberData(nameof(CompositeMLDsaTestData.AllAlgorithmsTestData), MemberType = typeof(CompositeMLDsaTestData))]
+ public static void ExportPkcs8PrivateKey_HandleBadReturnBuffer(CompositeMLDsaAlgorithm algorithm)
+ {
+ CompositeMLDsaTestHelpers.AssertEncryptedExportPkcs8PrivateKey(exportEncrypted =>
+ {
+ using CompositeMLDsaMockImplementation dsa = CompositeMLDsaMockImplementation.Create(algorithm);
+
+ // Create a bad encoding
+ AsnWriter writer = new AsnWriter(AsnEncodingRules.DER);
+ writer.WriteBitString("some string"u8);
+ byte[] validEncoding = writer.Encode();
+ Memory badEncoding = validEncoding.AsMemory(0, validEncoding.Length - 1); // Chop off the last byte
+
+ CompositeMLDsaMockImplementation.TryExportFunc hook = (Span destination, out int bytesWritten) =>
+ {
+ bool ret = badEncoding.Span.TryCopyTo(destination);
+ bytesWritten = ret ? badEncoding.Length : 0;
+ return ret;
+ };
+
+ dsa.TryExportPkcs8PrivateKeyCoreHook = hook;
+
+ // Exporting the key should work without any issues because there's no validation
+ AssertExtensions.SequenceEqual(badEncoding.Span, dsa.ExportPkcs8PrivateKey().AsSpan());
+
+ int numberOfCalls = dsa.TryExportPkcs8PrivateKeyCoreCallCount;
+ dsa.TryExportPkcs8PrivateKeyCoreCallCount = 0;
+
+ // However, exporting the encrypted key should fail because it validates the PKCS#8 private key encoding first
+ AssertExtensions.Throws(() =>
+ exportEncrypted(dsa, "PLACEHOLDER", new PbeParameters(PbeEncryptionAlgorithm.Aes128Cbc, HashAlgorithmName.SHA1, 1)));
+
+ // Sanity check that the code to export the private key was called
+ Assert.Equal(numberOfCalls, dsa.TryExportPkcs8PrivateKeyCoreCallCount);
+ });
+ }
+
private static void AssertExpectedFill(ReadOnlySpan buffer, ReadOnlySpan content, int offset, byte paddingElement)
{
// Ensure that the data was filled correctly
diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/CompositeMLDsa/CompositeMLDsaFactoryTests.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/CompositeMLDsa/CompositeMLDsaFactoryTests.cs
index 24617d110df62c..0a7ebefa8f9d12 100644
--- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/CompositeMLDsa/CompositeMLDsaFactoryTests.cs
+++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/CompositeMLDsa/CompositeMLDsaFactoryTests.cs
@@ -2,8 +2,9 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System.Formats.Asn1;
-using System.Linq;
+using System.Security.Cryptography.Asn1;
using Microsoft.DotNet.RemoteExecutor;
+using Test.Cryptography;
using Xunit;
using Xunit.Sdk;
@@ -16,13 +17,24 @@ public static void NullArgumentValidation()
{
AssertExtensions.Throws("algorithm", static () => CompositeMLDsa.GenerateKey(null));
AssertExtensions.Throws("algorithm", static () => CompositeMLDsa.IsAlgorithmSupported(null));
- AssertExtensions.Throws("algorithm", static () => CompositeMLDsa.ImportCompositeMLDsaPrivateKey(null, Array.Empty()));
+ AssertExtensions.Throws("algorithm", static () => CompositeMLDsa.ImportCompositeMLDsaPrivateKey(null, null));
AssertExtensions.Throws("algorithm", static () => CompositeMLDsa.ImportCompositeMLDsaPrivateKey(null, ReadOnlySpan.Empty));
- AssertExtensions.Throws("algorithm", static () => CompositeMLDsa.ImportCompositeMLDsaPublicKey(null, Array.Empty()));
+ AssertExtensions.Throws("algorithm", static () => CompositeMLDsa.ImportCompositeMLDsaPublicKey(null, null));
AssertExtensions.Throws("algorithm", static () => CompositeMLDsa.ImportCompositeMLDsaPublicKey(null, ReadOnlySpan.Empty));
AssertExtensions.Throws("source", static () => CompositeMLDsa.ImportCompositeMLDsaPrivateKey(CompositeMLDsaAlgorithm.MLDsa44WithECDsaP256, null));
AssertExtensions.Throws("source", static () => CompositeMLDsa.ImportCompositeMLDsaPublicKey(CompositeMLDsaAlgorithm.MLDsa44WithECDsaP256, null));
+ AssertExtensions.Throws("source", static () => CompositeMLDsa.ImportPkcs8PrivateKey(null));
+ AssertExtensions.Throws("source", static () => CompositeMLDsa.ImportSubjectPublicKeyInfo(null));
+ AssertExtensions.Throws("source", static () => CompositeMLDsa.ImportFromPem(null));
+ AssertExtensions.Throws("source", static () => CompositeMLDsa.ImportEncryptedPkcs8PrivateKey("PLACEHOLDER", null));
+ AssertExtensions.Throws("source", static () => CompositeMLDsa.ImportFromEncryptedPem(null, (string)null));
+ AssertExtensions.Throws("source", static () => CompositeMLDsa.ImportFromEncryptedPem(null, (byte[])null));
+
+ AssertExtensions.Throws("password", static () => CompositeMLDsa.ImportEncryptedPkcs8PrivateKey((string)null, null));
+ AssertExtensions.Throws("password", static () => CompositeMLDsa.ImportFromEncryptedPem(string.Empty, (string)null));
+
+ AssertExtensions.Throws("passwordBytes", static () => CompositeMLDsa.ImportFromEncryptedPem(string.Empty, (byte[])null));
}
[Theory]
@@ -45,7 +57,7 @@ public static void ImportBadPrivateKey_ShortMLDsaSeed(CompositeMLDsaAlgorithm al
public static void ImportBadPrivateKey_OnlyMLDsaSeed(CompositeMLDsaAlgorithm algorithm)
{
MLDsaKeyInfo mldsaVector = CompositeMLDsaTestData.GetMLDsaIetfTestVector(algorithm);
- AssertImportBadPrivateKey(algorithm, mldsaVector.PrivateSeed.ToArray());
+ AssertImportBadPrivateKey(algorithm, mldsaVector.PrivateSeed);
}
[Theory]
@@ -74,14 +86,14 @@ public static void ImportBadPrivateKey_Rsa_WrongAlgorithm()
{
// Get vector for MLDsa65WithRSA3072Pss
CompositeMLDsaTestData.CompositeMLDsaTestVector differentTradKey =
- CompositeMLDsaTestData.AllIetfVectors.Single(vector => vector.Algorithm == CompositeMLDsaAlgorithm.MLDsa65WithRSA3072Pss);
+ CompositeMLDsaTestData.GetIetfTestVector(CompositeMLDsaAlgorithm.MLDsa65WithRSA3072Pss);
// But use MLDsa65WithRSA4096Pss
AssertImportBadPrivateKey(CompositeMLDsaAlgorithm.MLDsa65WithRSA4096Pss, differentTradKey.SecretKey);
// And flip
differentTradKey =
- CompositeMLDsaTestData.AllIetfVectors.Single(vector => vector.Algorithm == CompositeMLDsaAlgorithm.MLDsa65WithRSA4096Pss);
+ CompositeMLDsaTestData.GetIetfTestVector(CompositeMLDsaAlgorithm.MLDsa65WithRSA4096Pss);
AssertImportBadPrivateKey(CompositeMLDsaAlgorithm.MLDsa65WithRSA3072Pss, differentTradKey.SecretKey);
}
@@ -91,14 +103,14 @@ public static void ImportBadPrivateKey_ECDsa_WrongAlgorithm()
{
// Get vector for MLDsa65WithECDsaP256
CompositeMLDsaTestData.CompositeMLDsaTestVector differentTradKey =
- CompositeMLDsaTestData.AllIetfVectors.Single(vector => vector.Algorithm == CompositeMLDsaAlgorithm.MLDsa65WithECDsaP256);
+ CompositeMLDsaTestData.GetIetfTestVector(CompositeMLDsaAlgorithm.MLDsa65WithECDsaP256);
// But use MLDsa65WithECDsaP384
AssertImportBadPrivateKey(CompositeMLDsaAlgorithm.MLDsa65WithECDsaP384, differentTradKey.SecretKey);
// And flip
differentTradKey =
- CompositeMLDsaTestData.AllIetfVectors.Single(vector => vector.Algorithm == CompositeMLDsaAlgorithm.MLDsa65WithECDsaP384);
+ CompositeMLDsaTestData.GetIetfTestVector(CompositeMLDsaAlgorithm.MLDsa65WithECDsaP384);
AssertImportBadPrivateKey(CompositeMLDsaAlgorithm.MLDsa65WithECDsaP256, differentTradKey.SecretKey);
}
@@ -145,69 +157,57 @@ static byte[] CreateKeyWithVersion(int? version)
return ComposeKeys(
MLDsaTestsData.IetfMLDsa65.PrivateSeed,
- WriteECPrivateKey(version, ecdsaKey.D, ecdsaKey.Curve.Oid.Value, ecdsaKey.Q));
+ WriteECPrivateKey(version, ecdsaKey.D, oid: null, point: null));
}
}
[Fact]
public static void ImportBadPrivateKey_ECDsa_NoPrivateKey()
{
- ECParameters ecdsaKey = EccTestData.GetNistP256ReferenceKey();
-
- // no private key
byte[] compositeKey = ComposeKeys(
MLDsaTestsData.IetfMLDsa65.PrivateSeed,
- WriteECPrivateKey(version: 1, d: null, ecdsaKey.Curve.Oid.Value, point: ecdsaKey.Q));
+ WriteECPrivateKey(version: 1, d: null, oid: null, point: null));
AssertImportBadPrivateKey(CompositeMLDsaAlgorithm.MLDsa65WithECDsaP256, compositeKey);
}
[Fact]
- public static void ImportBadPrivateKey_ECDsa_WrongCurve()
+ public static void ImportBadPrivateKey_ECDsa_HasCurve()
{
- CompositeMLDsaAlgorithm algorithm = CompositeMLDsaAlgorithm.MLDsa65WithECDsaP256;
-
- // Wrong curve OID
- AssertImportBadPrivateKey(
- algorithm,
- CreateKeyWithCurveOid(ECCurve.NamedCurves.nistP521.Oid.Value));
+ ECParameters ecdsaKey = EccTestData.GetNistP256ReferenceKey();
+ // Domain parameters are not allowed
AssertImportBadPrivateKey(
- algorithm,
- CreateKeyWithCurveOid("1.3.36.3.3.2.8.1.1.7")); // brainpoolP256r1
-
- // Domain parameters are optional, don't throw (unless platform does not support Composite ML-DSA)
- CompositeMLDsaTestHelpers.AssertImportPrivateKey(
- import => AssertThrowIfNotSupported(() => import(), algorithm),
- algorithm,
- CreateKeyWithCurveOid(ECCurve.NamedCurves.nistP256.Oid.Value));
+ CompositeMLDsaAlgorithm.MLDsa65WithECDsaP256,
+ ComposeKeys(
+ MLDsaTestsData.IetfMLDsa65.PrivateSeed,
+ WriteECPrivateKey(version: 1, ecdsaKey.D, ecdsaKey.Curve.Oid.Value, point: null)));
+ }
- static byte[] CreateKeyWithCurveOid(string? oid)
- {
- ECParameters ecdsaKey = EccTestData.GetNistP256ReferenceKey();
+ [Fact]
+ public static void ImportPrivateKey_ECDsa_HasPublicKey()
+ {
+ ECParameters ecdsaKey = EccTestData.GetNistP256ReferenceKey();
- return ComposeKeys(
+ // Public key is not allowed
+ AssertImportBadPrivateKey(
+ CompositeMLDsaAlgorithm.MLDsa65WithECDsaP256,
+ ComposeKeys(
MLDsaTestsData.IetfMLDsa65.PrivateSeed,
- WriteECPrivateKey(version: 1, ecdsaKey.D, oid, ecdsaKey.Q));
- }
+ WriteECPrivateKey(version: 1, ecdsaKey.D, oid: null, ecdsaKey.Q)));
}
[Fact]
- public static void ImportPrivateKey_ECDsa_NoPublicKey()
+ public static void ImportPrivateKey_ECDsa_HasCurveAndPublicKey()
{
- CompositeMLDsaAlgorithm algorithm = CompositeMLDsaAlgorithm.MLDsa65WithECDsaP256;
ECParameters ecdsaKey = EccTestData.GetNistP256ReferenceKey();
- // no public key
- byte[] compositeKey = ComposeKeys(
- MLDsaTestsData.IetfMLDsa65.PrivateSeed,
- WriteECPrivateKey(version: 1, ecdsaKey.D, ecdsaKey.Curve.Oid.Value, point: null));
-
- // Public key is optional, don't throw (unless platform does not support Composite ML-DSA)
- CompositeMLDsaTestHelpers.AssertImportPrivateKey(
- import => AssertThrowIfNotSupported(() => import(), algorithm),
- algorithm,
- compositeKey);
+ // Domain parameters and public key are not allowed
+ AssertImportBadPrivateKey(
+ CompositeMLDsaAlgorithm.MLDsa65WithECDsaP256,
+ ComposeKeys(
+ MLDsaTestsData.IetfMLDsa65.PrivateSeed,
+ WriteECPrivateKey(version: 1, ecdsaKey.D, ecdsaKey.Curve.Oid.Value, ecdsaKey.Q)));
}
static byte[] ComposeKeys(byte[] mldsaKey, AsnWriter tradKey)
@@ -296,7 +296,7 @@ public static void ImportBadPublicKey_ShortMLDsaKey(CompositeMLDsaAlgorithm algo
public static void ImportBadPublicKey_OnlyMLDsaKey(CompositeMLDsaAlgorithm algorithm)
{
MLDsaKeyInfo mldsaVector = CompositeMLDsaTestData.GetMLDsaIetfTestVector(algorithm);
- AssertImportBadPublicKey(algorithm, mldsaVector.PublicKey.ToArray());
+ AssertImportBadPublicKey(algorithm, mldsaVector.PublicKey);
}
[Theory]
@@ -348,14 +348,14 @@ public static void ImportBadPublicKey_Rsa_WrongAlgorithm()
{
// Get vector for MLDsa65WithRSA3072Pss
CompositeMLDsaTestData.CompositeMLDsaTestVector differentTradKey =
- CompositeMLDsaTestData.AllIetfVectors.Single(vector => vector.Algorithm == CompositeMLDsaAlgorithm.MLDsa65WithRSA3072Pss);
+ CompositeMLDsaTestData.GetIetfTestVector(CompositeMLDsaAlgorithm.MLDsa65WithRSA3072Pss);
// But use MLDsa65WithRSA4096Pss
AssertImportBadPublicKey(CompositeMLDsaAlgorithm.MLDsa65WithRSA4096Pss, differentTradKey.PublicKey);
// And flip
differentTradKey =
- CompositeMLDsaTestData.AllIetfVectors.Single(vector => vector.Algorithm == CompositeMLDsaAlgorithm.MLDsa65WithRSA4096Pss);
+ CompositeMLDsaTestData.GetIetfTestVector(CompositeMLDsaAlgorithm.MLDsa65WithRSA4096Pss);
AssertImportBadPublicKey(CompositeMLDsaAlgorithm.MLDsa65WithRSA3072Pss, differentTradKey.PublicKey);
}
@@ -365,14 +365,14 @@ public static void ImportBadPublicKey_ECDsa_WrongAlgorithm()
{
// Get vector for MLDsa65WithECDsaP256
CompositeMLDsaTestData.CompositeMLDsaTestVector differentTradKey =
- CompositeMLDsaTestData.AllIetfVectors.Single(vector => vector.Algorithm == CompositeMLDsaAlgorithm.MLDsa65WithECDsaP256);
+ CompositeMLDsaTestData.GetIetfTestVector(CompositeMLDsaAlgorithm.MLDsa65WithECDsaP256);
// But use MLDsa65WithECDsaP384
AssertImportBadPublicKey(CompositeMLDsaAlgorithm.MLDsa65WithECDsaP384, differentTradKey.PublicKey);
// And flip
differentTradKey =
- CompositeMLDsaTestData.AllIetfVectors.Single(vector => vector.Algorithm == CompositeMLDsaAlgorithm.MLDsa65WithECDsaP384);
+ CompositeMLDsaTestData.GetIetfTestVector(CompositeMLDsaAlgorithm.MLDsa65WithECDsaP384);
AssertImportBadPublicKey(CompositeMLDsaAlgorithm.MLDsa65WithECDsaP256, differentTradKey.PublicKey);
}
@@ -405,6 +405,190 @@ private static void AssertImportBadPublicKey(CompositeMLDsaAlgorithm algorithm,
key);
}
+ [Fact]
+ public static void ArgumentValidation_MalformedAsnEncoding()
+ {
+ // Generate a valid ASN.1 encoding
+ byte[] encodedBytes = CreateAsn1EncodedBytes();
+ int actualEncodedLength = encodedBytes.Length;
+
+ // Add a trailing byte so the length indicated in the encoding will be smaller than the actual data.
+ Array.Resize(ref encodedBytes, actualEncodedLength + 1);
+ AssertThrows(encodedBytes);
+
+ // Remove the last byte so the length indicated in the encoding will be larger than the actual data.
+ Array.Resize(ref encodedBytes, actualEncodedLength - 1);
+ AssertThrows(encodedBytes);
+
+ static void AssertThrows(byte[] encodedBytes)
+ {
+ CompositeMLDsaTestHelpers.AssertImportSubjectPublicKeyInfo(
+ import => Assert.Throws(() => import(encodedBytes)),
+ import => AssertThrowIfNotSupported(() => Assert.Throws(() => import(encodedBytes))));
+
+ CompositeMLDsaTestHelpers.AssertImportPkcs8PrivateKey(
+ import => Assert.Throws(() => import(encodedBytes)),
+ import => AssertThrowIfNotSupported(() => Assert.Throws(() => import(encodedBytes))));
+
+ CompositeMLDsaTestHelpers.AssertImportEncryptedPkcs8PrivateKey(
+ import => Assert.Throws(() => import("PLACEHOLDER", encodedBytes)),
+ import => AssertThrowIfNotSupported(() => Assert.Throws(() => import("PLACEHOLDER", encodedBytes))));
+ }
+ }
+
+ [Fact]
+ public static void ImportSpki_BerEncoding()
+ {
+ byte[] spki = CompositeMLDsaTestData.GetIetfTestVector(CompositeMLDsaAlgorithm.MLDsa65WithECDsaP384).Spki;
+ byte[] berSpki = AsnUtils.ConvertDerToNonDerBer(spki);
+
+ CompositeMLDsaTestHelpers.AssertImportSubjectPublicKeyInfo(import =>
+ AssertThrowIfNotSupported(() =>
+ Assert.Throws(() => import(berSpki))));
+ }
+
+ [Fact]
+ public static void Import_WrongAsnType()
+ {
+ // Create an incorrect ASN.1 structure to pass into the import methods.
+ AsnWriter writer = new AsnWriter(AsnEncodingRules.DER);
+ AlgorithmIdentifierAsn algorithmIdentifier = new AlgorithmIdentifierAsn
+ {
+ Algorithm = CompositeMLDsaTestHelpers.AlgorithmToOid(CompositeMLDsaAlgorithm.MLDsa65WithECDsaP384),
+ };
+ algorithmIdentifier.Encode(writer);
+ byte[] wrongAsnType = writer.Encode();
+
+ CompositeMLDsaTestHelpers.AssertImportSubjectPublicKeyInfo(
+ import => AssertThrowIfNotSupported(() => Assert.Throws(() => import(wrongAsnType))));
+
+ CompositeMLDsaTestHelpers.AssertImportPkcs8PrivateKey(
+ import => AssertThrowIfNotSupported(() => Assert.Throws(() => import(wrongAsnType))));
+
+ CompositeMLDsaTestHelpers.AssertImportEncryptedPkcs8PrivateKey(
+ import => AssertThrowIfNotSupported(() => Assert.Throws(() => import("PLACEHOLDER", wrongAsnType))));
+ }
+
+ [Fact]
+ public static void ImportSubjectPublicKeyInfo_AlgorithmErrorsInAsn()
+ {
+#if !NETFRAMEWORK // Does not support exporting RSA SPKI
+ if (!OperatingSystem.IsBrowser())
+ {
+ // RSA key
+ using RSA rsa = RSA.Create();
+ byte[] rsaSpkiBytes = rsa.ExportSubjectPublicKeyInfo();
+ CompositeMLDsaTestHelpers.AssertImportSubjectPublicKeyInfo(
+ import => AssertThrowIfNotSupported(() => Assert.Throws(() => import(rsaSpkiBytes))));
+ }
+#endif
+
+ // Create an invalid Composite ML-DSA SPKI with parameters
+ SubjectPublicKeyInfoAsn spki = new SubjectPublicKeyInfoAsn
+ {
+ Algorithm = new AlgorithmIdentifierAsn
+ {
+ Algorithm = CompositeMLDsaTestHelpers.AlgorithmToOid(CompositeMLDsaAlgorithm.MLDsa65WithECDsaP384),
+ Parameters = CompositeMLDsaTestHelpers.s_derBitStringFoo, // <-- Invalid
+ },
+ SubjectPublicKey = CompositeMLDsaTestData.GetIetfTestVector(CompositeMLDsaAlgorithm.MLDsa65WithECDsaP384).PublicKey,
+ };
+
+ CompositeMLDsaTestHelpers.AssertImportSubjectPublicKeyInfo(
+ import => AssertThrowIfNotSupported(() => Assert.Throws(() => import(spki.Encode()))));
+
+ spki.Algorithm.Parameters = AsnUtils.DerNull;
+
+ CompositeMLDsaTestHelpers.AssertImportSubjectPublicKeyInfo(
+ import => AssertThrowIfNotSupported(() => Assert.Throws(() => import(spki.Encode()))));
+
+ // Sanity check
+ spki.Algorithm.Parameters = null;
+ CompositeMLDsaTestHelpers.AssertImportSubjectPublicKeyInfo(import => AssertThrowIfNotSupported(() => import(spki.Encode())));
+ }
+
+ [Fact]
+ public static void ImportPkcs8PrivateKey_AlgorithmErrorsInAsn()
+ {
+#if !NETFRAMEWORK // Does not support exporting RSA PKCS#8 private key
+ if (!OperatingSystem.IsBrowser())
+ {
+ // RSA key isn't valid for ML-DSA
+ using RSA rsa = RSA.Create();
+ byte[] rsaPkcs8Bytes = rsa.ExportPkcs8PrivateKey();
+ CompositeMLDsaTestHelpers.AssertImportPkcs8PrivateKey(
+ import => AssertThrowIfNotSupported(() => Assert.Throws(() => import(rsaPkcs8Bytes))));
+ }
+#endif
+
+ // Create an invalid Composite ML-DSA PKCS8 with parameters
+ PrivateKeyInfoAsn pkcs8 = new PrivateKeyInfoAsn
+ {
+ PrivateKeyAlgorithm = new AlgorithmIdentifierAsn
+ {
+ Algorithm = CompositeMLDsaTestHelpers.AlgorithmToOid(CompositeMLDsaAlgorithm.MLDsa65WithECDsaP384),
+ Parameters = CompositeMLDsaTestHelpers.s_derBitStringFoo, // <-- Invalid
+ },
+ PrivateKey = CompositeMLDsaTestData.GetIetfTestVector(CompositeMLDsaAlgorithm.MLDsa65WithECDsaP384).SecretKey,
+ };
+
+ CompositeMLDsaTestHelpers.AssertImportPkcs8PrivateKey(
+ import => AssertThrowIfNotSupported(() => Assert.Throws(() => import(pkcs8.Encode()))));
+
+ pkcs8.PrivateKeyAlgorithm.Parameters = AsnUtils.DerNull;
+
+ CompositeMLDsaTestHelpers.AssertImportPkcs8PrivateKey(
+ import => AssertThrowIfNotSupported(() => Assert.Throws(() => import(pkcs8.Encode()))));
+
+ // Sanity check
+ pkcs8.PrivateKeyAlgorithm.Parameters = null;
+ CompositeMLDsaTestHelpers.AssertImportPkcs8PrivateKey(import => AssertThrowIfNotSupported(() => import(pkcs8.Encode())));
+ }
+
+ [Fact]
+ public static void ImportFromPem_MalformedPem()
+ {
+ AssertThrows(WritePemRaw("UNKNOWN LABEL", []));
+ AssertThrows(string.Empty);
+ AssertThrows(WritePemRaw("ENCRYPTED PRIVATE KEY", []));
+ AssertThrows(WritePemRaw("PUBLIC KEY", []) + '\n' + WritePemRaw("PUBLIC KEY", []));
+ AssertThrows(WritePemRaw("PRIVATE KEY", []) + '\n' + WritePemRaw("PUBLIC KEY", []));
+ AssertThrows(WritePemRaw("PUBLIC KEY", []) + '\n' + WritePemRaw("PRIVATE KEY", []));
+ AssertThrows(WritePemRaw("PRIVATE KEY", []) + '\n' + WritePemRaw("PRIVATE KEY", []));
+ AssertThrows(WritePemRaw("PRIVATE KEY", "%"));
+ AssertThrows(WritePemRaw("PUBLIC KEY", "%"));
+
+ static void AssertThrows(string pem)
+ {
+ AssertThrowIfNotSupported(() =>
+ AssertExtensions.Throws("source", () => CompositeMLDsa.ImportFromPem(pem)));
+ AssertThrowIfNotSupported(() =>
+ AssertExtensions.Throws("source", () => CompositeMLDsa.ImportFromPem(pem.AsSpan())));
+ }
+ }
+
+ [Fact]
+ public static void ImportFromEncryptedPem_MalformedPem()
+ {
+ AssertThrows(WritePemRaw("UNKNOWN LABEL", []));
+ AssertThrows(WritePemRaw("CERTIFICATE", []));
+ AssertThrows(string.Empty);
+ AssertThrows(WritePemRaw("ENCRYPTED PRIVATE KEY", []) + '\n' + WritePemRaw("ENCRYPTED PRIVATE KEY", []));
+ AssertThrows(WritePemRaw("ENCRYPTED PRIVATE KEY", "%"));
+
+ static void AssertThrows(string encryptedPem)
+ {
+ AssertThrowIfNotSupported(() =>
+ AssertExtensions.Throws("source", () => CompositeMLDsa.ImportFromEncryptedPem(encryptedPem, "PLACEHOLDER")));
+ AssertThrowIfNotSupported(() =>
+ AssertExtensions.Throws("source", () => CompositeMLDsa.ImportFromEncryptedPem(encryptedPem, "PLACEHOLDER"u8)));
+ AssertThrowIfNotSupported(() =>
+ AssertExtensions.Throws("source", () => CompositeMLDsa.ImportFromEncryptedPem(encryptedPem.AsSpan(), "PLACEHOLDER")));
+ AssertThrowIfNotSupported(() =>
+ AssertExtensions.Throws("source", () => CompositeMLDsa.ImportFromEncryptedPem(encryptedPem, "PLACEHOLDER"u8.ToArray())));
+ }
+ }
+
[Theory]
[MemberData(nameof(CompositeMLDsaTestData.SupportedAlgorithmsTestData), MemberType = typeof(CompositeMLDsaTestData))]
public static void AlgorithmMatches_GenerateKey(CompositeMLDsaAlgorithm algorithm)
@@ -472,9 +656,11 @@ public static void IsSupported_InitializesCrypto()
// Asserts the test throws PlatformNotSupportedException if Composite ML-DSA is supported;
// otherwise runs the test normally.
- private static void AssertThrowIfNotSupported(Action test, CompositeMLDsaAlgorithm algorithm)
+ private static void AssertThrowIfNotSupported(Action test, CompositeMLDsaAlgorithm? algorithm = null)
{
- if (CompositeMLDsa.IsAlgorithmSupported(algorithm))
+ bool isSupported = algorithm is null ? CompositeMLDsa.IsSupported : CompositeMLDsa.IsAlgorithmSupported(algorithm);
+
+ if (isSupported)
{
test();
}
@@ -494,5 +680,16 @@ private static void AssertThrowIfNotSupported(Action test, CompositeMLDsaAlgorit
}
}
}
+
+ private static byte[] CreateAsn1EncodedBytes()
+ {
+ AsnWriter writer = new AsnWriter(AsnEncodingRules.BER);
+ writer.WriteOctetString("some data"u8);
+ byte[] encodedBytes = writer.Encode();
+ return encodedBytes;
+ }
+
+ private static string WritePemRaw(string label, ReadOnlySpan data) =>
+ $"-----BEGIN {label}-----\n{data.ToString()}\n-----END {label}-----";
}
}
diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/CompositeMLDsa/CompositeMLDsaImplementationTests.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/CompositeMLDsa/CompositeMLDsaImplementationTests.cs
index 03ac1315b541ff..2d7c9c7bba839e 100644
--- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/CompositeMLDsa/CompositeMLDsaImplementationTests.cs
+++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/CompositeMLDsa/CompositeMLDsaImplementationTests.cs
@@ -1,6 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using Test.Cryptography;
using Xunit;
namespace System.Security.Cryptography.Tests
@@ -39,6 +40,22 @@ private static void AssertCompositeMLDsaIsOnlyPublicAncestor(Func
+ CompositeMLDsaTestHelpers.AssertExportPrivateKey(export =>
+ CompositeMLDsaTestHelpers.WithDispose(import(nonMinimalEncoding), mldsa =>
+ AssertExtensions.SequenceEqual(vector.SecretKey, export(mldsa)))));
+ }
+
#region Roundtrip by exporting then importing
[Theory]
@@ -97,6 +114,141 @@ public void RoundTrip_Export_Import_PrivateKey(CompositeMLDsaAlgorithm algorithm
});
}
+ [Theory]
+ [MemberData(nameof(CompositeMLDsaTestData.SupportedAlgorithmsTestData), MemberType = typeof(CompositeMLDsaTestData))]
+ public void RoundTrip_Export_Import_Pkcs8PrivateKey(CompositeMLDsaAlgorithm algorithm)
+ {
+ // Generate new key
+ using CompositeMLDsa dsa = GenerateKey(algorithm);
+ byte[] privateKey = dsa.ExportCompositeMLDsaPrivateKey();
+ byte[] publicKey = dsa.ExportCompositeMLDsaPublicKey();
+
+ CompositeMLDsaTestHelpers.AssertExportPkcs8PrivateKey(export =>
+ CompositeMLDsaTestHelpers.AssertImportPkcs8PrivateKey(import =>
+ {
+ // Roundtrip it using PKCS#8
+ using CompositeMLDsa roundTrippedDsa = import(export(dsa));
+
+ // The keys should be the same
+ Assert.Equal(algorithm, roundTrippedDsa.Algorithm);
+ AssertExtensions.SequenceEqual(publicKey, roundTrippedDsa.ExportCompositeMLDsaPublicKey());
+ AssertExtensions.SequenceEqual(privateKey, roundTrippedDsa.ExportCompositeMLDsaPrivateKey());
+ }));
+ }
+
+ [Theory]
+ [MemberData(nameof(CompositeMLDsaTestData.SupportedAlgorithmsTestData), MemberType = typeof(CompositeMLDsaTestData))]
+ public void RoundTrip_Export_Import_SPKI(CompositeMLDsaAlgorithm algorithm)
+ {
+ // Generate new key
+ using CompositeMLDsa dsa = GenerateKey(algorithm);
+ byte[] publicKey = dsa.ExportCompositeMLDsaPublicKey();
+
+ CompositeMLDsaTestHelpers.AssertExportSubjectPublicKeyInfo(export =>
+ CompositeMLDsaTestHelpers.AssertImportSubjectPublicKeyInfo(import =>
+ {
+ // Roundtrip it using SPKI
+ using CompositeMLDsa roundTrippedDsa = import(export(dsa));
+
+ // The keys should be the same
+ Assert.Equal(algorithm, roundTrippedDsa.Algorithm);
+ AssertExtensions.SequenceEqual(publicKey, roundTrippedDsa.ExportCompositeMLDsaPublicKey());
+ Assert.Throws(() => roundTrippedDsa.ExportCompositeMLDsaPrivateKey());
+ }));
+ }
+
+ [Theory]
+ [MemberData(nameof(CompositeMLDsaTestData.SupportedAlgorithmsTestData), MemberType = typeof(CompositeMLDsaTestData))]
+ public void RoundTrip_Export_Import_EncryptedPkcs8PrivateKey(CompositeMLDsaAlgorithm algorithm)
+ {
+ // Generate new key
+ using CompositeMLDsa dsa = GenerateKey(algorithm);
+ byte[] privateKey = dsa.ExportCompositeMLDsaPrivateKey();
+ byte[] publicKey = dsa.ExportCompositeMLDsaPublicKey();
+
+ PbeParameters pbeParameters = new PbeParameters(PbeEncryptionAlgorithm.Aes128Cbc, HashAlgorithmName.SHA1, 1);
+
+ CompositeMLDsaTestHelpers.AssertEncryptedExportPkcs8PrivateKey(export =>
+ CompositeMLDsaTestHelpers.AssertImportEncryptedPkcs8PrivateKey(import =>
+ {
+ // Roundtrip it using encrypted PKCS#8
+ using CompositeMLDsa roundTrippedDsa = import("PLACEHOLDER", export(dsa, "PLACEHOLDER", pbeParameters));
+
+ // The keys should be the same
+ Assert.Equal(algorithm, roundTrippedDsa.Algorithm);
+ AssertExtensions.SequenceEqual(privateKey, roundTrippedDsa.ExportCompositeMLDsaPrivateKey());
+ AssertExtensions.SequenceEqual(publicKey, roundTrippedDsa.ExportCompositeMLDsaPublicKey());
+ }));
+ }
+
+ [Theory]
+ [MemberData(nameof(CompositeMLDsaTestData.SupportedAlgorithmsTestData), MemberType = typeof(CompositeMLDsaTestData))]
+ public void RoundTrip_Export_Import_Pkcs8PrivateKeyPem(CompositeMLDsaAlgorithm algorithm)
+ {
+ // Generate new key
+ using CompositeMLDsa dsa = GenerateKey(algorithm);
+ byte[] privateKey = dsa.ExportCompositeMLDsaPrivateKey();
+ byte[] publicKey = dsa.ExportCompositeMLDsaPublicKey();
+
+ CompositeMLDsaTestHelpers.AssertExportToPrivateKeyPem(export =>
+ CompositeMLDsaTestHelpers.AssertImportFromPem(import =>
+ {
+ // Roundtrip it using PEM
+ using CompositeMLDsa roundTrippedDsa = import(export(dsa));
+
+ // The keys should be the same
+ Assert.Equal(algorithm, roundTrippedDsa.Algorithm);
+ AssertExtensions.SequenceEqual(privateKey, roundTrippedDsa.ExportCompositeMLDsaPrivateKey());
+ AssertExtensions.SequenceEqual(publicKey, roundTrippedDsa.ExportCompositeMLDsaPublicKey());
+ }));
+ }
+
+ [Theory]
+ [MemberData(nameof(CompositeMLDsaTestData.SupportedAlgorithmsTestData), MemberType = typeof(CompositeMLDsaTestData))]
+ public void RoundTrip_Export_Import_SPKIPem(CompositeMLDsaAlgorithm algorithm)
+ {
+ // Generate new key
+ using CompositeMLDsa dsa = GenerateKey(algorithm);
+ byte[] privateKey = dsa.ExportCompositeMLDsaPrivateKey();
+ byte[] publicKey = dsa.ExportCompositeMLDsaPublicKey();
+
+ CompositeMLDsaTestHelpers.AssertExportToPublicKeyPem(export =>
+ CompositeMLDsaTestHelpers.AssertImportFromPem(import =>
+ {
+ // Roundtrip it using PEM
+ using CompositeMLDsa roundTrippedDsa = import(export(dsa));
+
+ // The keys should be the same
+ Assert.Equal(algorithm, roundTrippedDsa.Algorithm);
+ AssertExtensions.SequenceEqual(publicKey, roundTrippedDsa.ExportCompositeMLDsaPublicKey());
+ Assert.Throws(() => roundTrippedDsa.ExportCompositeMLDsaPrivateKey());
+ }));
+ }
+
+ [Theory]
+ [MemberData(nameof(CompositeMLDsaTestData.SupportedAlgorithmsTestData), MemberType = typeof(CompositeMLDsaTestData))]
+ public void RoundTrip_Export_Import_EncryptedPkcs8PrivateKeyPem(CompositeMLDsaAlgorithm algorithm)
+ {
+ // Generate new key
+ using CompositeMLDsa dsa = GenerateKey(algorithm);
+ byte[] privateKey = dsa.ExportCompositeMLDsaPrivateKey();
+ byte[] publicKey = dsa.ExportCompositeMLDsaPublicKey();
+
+ PbeParameters pbeParameters = new PbeParameters(PbeEncryptionAlgorithm.Aes128Cbc, HashAlgorithmName.SHA1, 1);
+
+ CompositeMLDsaTestHelpers.AssertExportToEncryptedPem(export =>
+ CompositeMLDsaTestHelpers.AssertImportFromEncryptedPem(import =>
+ {
+ // Roundtrip it using encrypted PKCS#8
+ using CompositeMLDsa roundTrippedDsa = import(export(dsa, "PLACEHOLDER", pbeParameters), "PLACEHOLDER");
+
+ // The keys should be the same
+ Assert.Equal(algorithm, roundTrippedDsa.Algorithm);
+ AssertExtensions.SequenceEqual(privateKey, roundTrippedDsa.ExportCompositeMLDsaPrivateKey());
+ AssertExtensions.SequenceEqual(publicKey, roundTrippedDsa.ExportCompositeMLDsaPublicKey());
+ }));
+ }
+
#endregion Roundtrip by exporting then importing
#region Roundtrip by importing then exporting
@@ -125,6 +277,26 @@ public void RoundTrip_Import_Export_PrivateKey(CompositeMLDsaTestData.CompositeM
info.SecretKey);
}
+ [Theory]
+ [MemberData(nameof(CompositeMLDsaTestData.SupportedAlgorithmIetfVectorsTestData), MemberType = typeof(CompositeMLDsaTestData))]
+ public void RoundTrip_Import_Export_SpkiPublicKey(CompositeMLDsaTestData.CompositeMLDsaTestVector info)
+ {
+ CompositeMLDsaTestHelpers.AssertImportSubjectPublicKeyInfo(import =>
+ CompositeMLDsaTestHelpers.AssertExportSubjectPublicKeyInfo(export =>
+ CompositeMLDsaTestHelpers.WithDispose(import(info.Spki), dsa =>
+ AssertExtensions.SequenceEqual(info.Spki, export(dsa)))));
+ }
+
+ [Theory]
+ [MemberData(nameof(CompositeMLDsaTestData.SupportedAlgorithmIetfVectorsTestData), MemberType = typeof(CompositeMLDsaTestData))]
+ public void RoundTrip_Import_Export_Pkcs8PrivateKey(CompositeMLDsaTestData.CompositeMLDsaTestVector info)
+ {
+ CompositeMLDsaTestHelpers.AssertImportPkcs8PrivateKey(import =>
+ CompositeMLDsaTestHelpers.AssertExportPrivateKey(export =>
+ CompositeMLDsaTestHelpers.WithDispose(import(info.Pkcs8), dsa =>
+ CompositeMLDsaTestHelpers.AssertPrivateKeyEquals(info.Algorithm, info.SecretKey, export(dsa)))));
+ }
+
#endregion Roundtrip by importing then exporting
protected override CompositeMLDsa GenerateKey(CompositeMLDsaAlgorithm algorithm) =>
diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/CompositeMLDsa/CompositeMLDsaMockImplementation.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/CompositeMLDsa/CompositeMLDsaMockImplementation.cs
index b78e08e5b3ca4b..2fe0d5da49fb34 100644
--- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/CompositeMLDsa/CompositeMLDsaMockImplementation.cs
+++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/CompositeMLDsa/CompositeMLDsaMockImplementation.cs
@@ -18,18 +18,21 @@ public CompositeMLDsaMockImplementation(CompositeMLDsaAlgorithm algorithm)
internal delegate int SignDataFunc(ReadOnlySpan data, ReadOnlySpan context, Span destination);
internal delegate bool VerifyDataFunc(ReadOnlySpan data, ReadOnlySpan context, ReadOnlySpan signature);
internal delegate int ExportFunc(Span destination);
+ internal delegate bool TryExportFunc(Span destination, out int written);
internal delegate void DisposeAction(bool disposing);
public int SignDataCoreCallCount = 0;
public int VerifyDataCoreCallCount = 0;
public int ExportCompositeMLDsaPublicKeyCoreCallCount = 0;
public int ExportCompositeMLDsaPrivateKeyCoreCallCount = 0;
+ public int TryExportPkcs8PrivateKeyCoreCallCount = 0;
public int DisposeCallCount = 0;
public SignDataFunc SignDataCoreHook { get; set; } = (_, _, _) => { Assert.Fail(); return 0; };
public VerifyDataFunc VerifyDataCoreHook { get; set; } = (_, _, _) => { Assert.Fail(); return false; };
public ExportFunc ExportCompositeMLDsaPublicKeyCoreHook { get; set; } = _ => { Assert.Fail(); return 0; };
public ExportFunc ExportCompositeMLDsaPrivateKeyCoreHook { get; set; } = _ => { Assert.Fail(); return 0; };
+ public TryExportFunc TryExportPkcs8PrivateKeyCoreHook { get; set; } = (destination, out bytesWritten) => { Assert.Fail(); bytesWritten = 0; return false; };
public DisposeAction DisposeHook { get; set; } = _ => { };
protected override int SignDataCore(ReadOnlySpan data, ReadOnlySpan context, Span destination)
@@ -64,7 +67,8 @@ protected override void Dispose(bool disposing)
protected override bool TryExportPkcs8PrivateKeyCore(Span destination, out int bytesWritten)
{
- throw new NotImplementedException();
+ TryExportPkcs8PrivateKeyCoreCallCount++;
+ return TryExportPkcs8PrivateKeyCoreHook(destination, out bytesWritten);
}
public void AddLengthAssertion()
@@ -74,7 +78,7 @@ public void AddLengthAssertion()
{
int ret = oldTrySignDataCoreHook(data, context, destination);
AssertExtensions.LessThanOrEqualTo(
- 32 + CompositeMLDsaTestHelpers.MLDsaAlgorithms[Algorithm].SignatureSizeInBytes, // randomizer + mldsaSig
+ CompositeMLDsaTestHelpers.MLDsaAlgorithms[Algorithm].SignatureSizeInBytes, // mldsaSig
destination.Length);
return ret;
};
@@ -84,7 +88,7 @@ public void AddLengthAssertion()
{
bool ret = oldVerifyDataCoreHook(data, context, signature);
AssertExtensions.LessThanOrEqualTo(
- 32 + CompositeMLDsaTestHelpers.MLDsaAlgorithms[Algorithm].SignatureSizeInBytes, // randomizer + mldsaSig
+ CompositeMLDsaTestHelpers.MLDsaAlgorithms[Algorithm].SignatureSizeInBytes, // mldsaSig
signature.Length);
return ret;
};
@@ -93,9 +97,9 @@ public void AddLengthAssertion()
ExportCompositeMLDsaPublicKeyCoreHook = (Span destination) =>
{
int ret = oldExportCompositeMLDsaPublicKeyCoreHook(destination);
- AssertExtensions.LessThanOrEqualTo(
- CompositeMLDsaTestHelpers.MLDsaAlgorithms[Algorithm].PublicKeySizeInBytes,
- destination.Length);
+ AssertExtensions.GreaterThanOrEqualTo(
+ destination.Length,
+ CompositeMLDsaTestHelpers.ExpectedPublicKeySizeLowerBound(Algorithm));
return ret;
};
@@ -103,9 +107,19 @@ public void AddLengthAssertion()
ExportCompositeMLDsaPrivateKeyCoreHook = (Span destination) =>
{
int ret = oldExportCompositeMLDsaPrivateKeyCoreHook(destination);
- AssertExtensions.LessThanOrEqualTo(
- CompositeMLDsaTestHelpers.MLDsaAlgorithms[Algorithm].PrivateSeedSizeInBytes,
- destination.Length);
+ AssertExtensions.GreaterThanOrEqualTo(
+ destination.Length,
+ CompositeMLDsaTestHelpers.ExpectedPrivateKeySizeLowerBound(Algorithm));
+ return ret;
+ };
+
+ TryExportFunc oldTryExportPkcs8PrivateKeyCoreHook = TryExportPkcs8PrivateKeyCoreHook;
+ TryExportPkcs8PrivateKeyCoreHook = (Span destination, out int bytesWritten) =>
+ {
+ bool ret = oldTryExportPkcs8PrivateKeyCoreHook(destination, out bytesWritten);
+ AssertExtensions.GreaterThanOrEqualTo(
+ destination.Length,
+ CompositeMLDsaTestHelpers.ExpectedPrivateKeySizeLowerBound(Algorithm));
return ret;
};
}
@@ -211,6 +225,14 @@ public void AddFillDestination(byte b)
destination.Fill(b);
return destination.Length;
};
+
+ TryExportFunc oldTryExportPkcs8PrivateKeyCoreHook = TryExportPkcs8PrivateKeyCoreHook;
+ TryExportPkcs8PrivateKeyCoreHook = (Span destination, out int bytesWritten) =>
+ {
+ bool ret = oldTryExportPkcs8PrivateKeyCoreHook(destination, out bytesWritten);
+ destination.Fill(b);
+ return ret;
+ };
}
public void AddFillDestination(byte[] fillContents)
@@ -253,6 +275,21 @@ public void AddFillDestination(byte[] fillContents)
return 0;
};
+
+ TryExportFunc oldTryExportPkcs8PrivateKeyCoreHook = TryExportPkcs8PrivateKeyCoreHook;
+ TryExportPkcs8PrivateKeyCoreHook = (Span destination, out int bytesWritten) =>
+ {
+ bool ret = oldTryExportPkcs8PrivateKeyCoreHook(destination, out int localBytesWritten);
+
+ if (fillContents.AsSpan().TryCopyTo(destination))
+ {
+ bytesWritten = fillContents.Length;
+ return true;
+ }
+
+ bytesWritten = 0;
+ return false;
+ };
}
}
}
diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/CompositeMLDsa/CompositeMLDsaTestData.Raw.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/CompositeMLDsa/CompositeMLDsaTestData.Raw.cs
index 7ca48b35a17eb4..3924873f1537ae 100644
--- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/CompositeMLDsa/CompositeMLDsaTestData.Raw.cs
+++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/CompositeMLDsa/CompositeMLDsaTestData.Raw.cs
@@ -10,148 +10,148 @@ public static partial class CompositeMLDsaTestData
[
new("id-MLDSA44-RSA2048-PSS-SHA256",
CompositeMLDsaAlgorithm.MLDsa44WithRSA2048Pss,
- "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",
+ "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",
- "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"),
+ "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"),
new("id-MLDSA44-RSA2048-PKCS15-SHA256",
CompositeMLDsaAlgorithm.MLDsa44WithRSA2048Pkcs15,
- "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",
+ "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",
- "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"),
+ "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"),
new("id-MLDSA44-Ed25519-SHA512",
CompositeMLDsaAlgorithm.MLDsa44WithEd25519,
- "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",
+ "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",
- "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"),
+ "yKtBUjv+qg1yBtBqVCGhTsX2THeMyVGQXghk57y0TTucSL4wx5MGXOpoNLZ5oK1bzhvwAp6iF4Aat2vyIjLr+dCVBruibCBaNaG9gRmGcN3y9BMUbpv+vU4KDt1kQ9aYD3zkbfdK5LOVrmiwxqPDKGWv+WvvF9fFWYXV1lvmPDeZlpKTetxH0rJNpSP+MvKcP53dkw+DPLPwCyFkSMmlO4O122vqeaVltdF/4995Q1yy2mghsgg2NDrPzPM1HdGljtvNdEs1RFU6kl0XTKt0EeoC5X/Hl8QKfB6Hce1TJGxm1NcSCKAdB/zG+WVMw1CPqiWA+y4G8qIqjkwBiDe60bQ7dYZHVXnZrZrp4yVmT46tq60O5WacbR81wslccgaVD445VQ2UBw6gWDchZvTWuy59mlf2JbYZLES87FsIlZ1Thx9G/kkz55ulHrOGCTyzbOGnbOO7jmsXer3HyeRJlwujaQIM4hni6pcD7dkxjKbhR3AkyY1PXPMLr9pOW9pfLAyKQdC0TZ3tY6+5S6owPqCgvfRqgcdxNZJTAiCUV5W8zNgbkVhYiMCeq9liq/4O3cBkZO0nGJWu17v7F/PE9KndeFINomZZ9WaGe1mL7GLgVoXgaVIT711b0aqjLtl0vESyCkEUjMjAwjesAngoChHHo4L7rVnZU5V0vHx7d+AMyueaOeIo76nS8h2m2geR0Ysprrqv1hVuWuoPJBFKZihugTEXaqS20BT5m/pkhRNCgDlqcPUW8pJRqPtI1SvMU86aDs/bIh859yRpsKccgKDZrDQtjfKZ8vm2rF+yFiG8rinMKWffebFwYk1rqQDvaccbBe0RnNwrw6+2+2F6GIi26yMRSG8mA//hgujNZ9XT6/hyMSLb/pKVVrUtujqVIujtVmKJugbQDrdxEzIsb0oXJpa0Zur4OKusp2KsvR0xapFZYa3K5zX7fu7KiRD0/wnPAiazk7MWX3Jm9+tRpRaT+7UMN6MXpePbPLtw1ODzmnRYTxWGy2sCFIhXnDh+pNEL667W4OOWi4dPc4i/0q/aX9qZw6MB+xmaJ87qxGiZ91pIGi7i9yVrouTwGTZssuIUKMtP3VWpklb0CG/gfJWzYIo+ttWQXXUtauFMIfNlHz4I+ic5x6tXISnArvCbfwfLzM4GE7MI4CCA6gyfJ7uMXwyys3MwTlA5V0r2VKCuw+Bjso4CS1Rl1UA9tOld5HVfISe/vrKOrHpk3qQIUz/1WGqnUX+3fxZnDy408IuQoD6PXNocooRSvjqsAQ/wF9Gj7IXcHjYd9xTfRnh89mzn09LppGjpgM7m1d/QBfA/oVixJhuDCFyCWGi8VPxFGmyDTxs6+gl4u0/VHLJd8ay+M8tiZSIGXyo20OW+x7ZvMutRPWNeh0mtyySCRYZURIsVmjMYAq0XOK2UOGcJxy9+3MyolbkNSUV3VgZ931DFEJ3FOjHR8hhoCfWOYgWbOJKARAL+vOgsyvpYw+CDvGi4dVv1CtEXAqTFIA+5lKBJ+6Q9yg7CCfx9wQkvd0NP+OsyNiBnuA2DnrYZ9wmw4H+bjY1Tv3ZJIP3FJ6TT4EFmtRlj/Lamito1/VyWeAyuWDOfdd01ON3Cg36b6fN2f3iu2zfE2eiKWeqbancTDQuxTS3Hsllyxwes+7qpXZD5o1suJabNX4FwxwlXLYvihDy9i3UvfQhq6YE9K8xeeTVqW8CjqU29OTzIfPlRr+aAdI/WBPJCmiN9ygLa+Ay1IAI8gfM75oYCQX1ducqLqBZNFXyIL11y55j/QsBBxbtcCCkMLurW2ECf/zQk5ZgkHl7uqwwlt/hCBvvIk81J9ObK4BeNDjUxHp73tX90WsjBRIXD2adbN7TDmy11jAH3a+G9wu5FveOfKr8OyhBZRtheGrkwXFiaqbEH0hzIm4WoSNXDrR4dFXHg1BWdW/OI4ii97MZSv1bk17BH2ZfFsOVazgInjto1CYw9aLVqSIbpzaKL/hfhfStOaLXwGiLfvPDA/9LNeDscFC8BCUHMCztMYIvqXO2ce59iFRnoqsSZOe9Apmmoo3ufgLSf/iUL8EjtHB/cyZe+OdKVFQBLaBwTB5Da0VEnFsMdSKicP9R1Zgdcc83arPVmRyTMecmPlLxZlL4EHTcbpL8cSr+qi4LM+WB1CcsYhx/MY3qyIiGxzRwYFQ6Lkz/DX88Z/qKhtkNT3khQq3veEuMnZbUAOaArDtJIwZTllUYVxaetxgJVuvKiMgh8VebqiGt3ywWyIh66BpWBFUD5jsbhPpDAkbjSmgjhSllz6LFBCvSrwsBPJHedBNhWCcMzHSd/tZFK5ZVv/Q7BtA1VqP3xC3IWOjCrIusG5m4Fo8Y5CHweYzi+I8s58eiC1juLheDKSxJbTJqChfFv9V9W5f7BsS+UcFl4l3KQtgUpc1aaCQHqosFrkrQ4EcEoNExnBOFNxu6Zb0GX6EjVc6px2zf3Z8kE8u6G250b+uNOwe0rcjp2Fc/mjVLLr7a5/mlGqQEwHTuhBdd1Bbbfq0CSDNivVxGwr8uVI4vDAL2wW44AdaYV/LRtXoyrZDTIAUed8xiorZki7jNWWSV0TxxmcetoLvTOrT96rnEuIzdLFBki95KubuFYRUGJGHMLXqWpFbRUkHmbuEqns2LDE/lwQvzBftHlKgST59KgNZoSswhYkd/VqgGP+va66yQXKTvZkeewTuQ0FFwvISayNyKFkpnAv4hNNEDPFpyfF6RgCohzRs6Gjw/0UkBBbVOOo6yBeS2wiYm5MwLHzcp1AU0XibQBJTem1KJp0qUwY0kArCxg0DSgXQzCBR4/8f2fEIdTd6WI0OeIiU39auO8L3lHQ3hAx/3kAdV2crtYvoU3oMZ2SROWT4So16lrxdrn5E8ZPbKLlcsnQrpNABOJg15pbBgR00H1r7Xny4cR9hkZkHXFQpbPgUpvSc71MxQwzaE8K6KPXb8T7JcEOQfs0TLsemT4aBb3z8Jmrh2yRgU/nxH0sQgMmEuYAlK//A+BpPqGnFtCeI8WkxdDY6qca4cpoqLCaHFOAgsGaTrmbcgP4R4y1sUaJutRgQpstthieZInM0EzmBRQr5JkjdvakE5D1oZxUU94HyAFDBcxNztUb5SutM3V3Or1CBUYPkFCX2VofoKOuPH29wsVJDpaa3uEhZ2lq62vs7jGyM3Z7gYIExsjLjVDTmJke4GMmbG90t/k/P3/AAAAABAgNUzyz95Yugdxg1aX8vO16O5TZm8DBvCm0vPSrMrd7l0CUmD2B4pPxPHrJbJHgA5UiBSBjspH2pWzaS5SeJMBKX8K"),
new("id-MLDSA44-ECDSA-P256-SHA256",
CompositeMLDsaAlgorithm.MLDsa44WithECDsaP256,
- "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",
+ "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",
- "+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"),
+ "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"),
new("id-MLDSA65-RSA3072-PSS-SHA512",
CompositeMLDsaAlgorithm.MLDsa65WithRSA3072Pss,
- "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",
+ "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",
- "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"),
+ "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"),
new("id-MLDSA65-RSA3072-PKCS15-SHA512",
CompositeMLDsaAlgorithm.MLDsa65WithRSA3072Pkcs15,
- "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",
+ "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",
- "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"),
+ "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"),
new("id-MLDSA65-RSA4096-PSS-SHA512",
CompositeMLDsaAlgorithm.MLDsa65WithRSA4096Pss,
- "NUOhxJG0QB+/5ubHa5zeI9+RBDbfHXWCreA7dySYXwKrUbjgpjpY6Yl70Q6MqortOYuDd3UuRryTo/BBCVcUIE1+z6maze0RiE0kLtJmdx6hLpTRSGS3Ju1j/svuvnSYGLiYD1hxDro5wkV7SFp2KtMzSQPl3ft6BYvwEhbnDPHi1hqMSTSmGtdHogirldUDwzCM1B+HYHC+uZApkM75+et1TD63cG53368GiJe12EUilNFSLKffX6BHNDP7aut8Pt1MCshY1V9B2sC+rnJF+3kzfGDJNV6KTLTddHjOFgE5XpdI6HH62EZvuEWWrVZmMXzWJgpbNmTjHhOVLpEvW6AJBwSrnCN6dYZogcqJtoZnt9OcmjSMb12Nc175RxlbFp6G0c6qXWZUlaAyG2tTd4jSwCF7LzFXgQEodD/5dZwFtDyHXOVee8C0NXAXWUjJ22ofGFtcvVlj2QPiLEiMuQbEuzude9atpel1dbLXqydYFMft8o/8NCpkxORLicfFvqdeB20H7bfIwOdiAlfSZ7h3hM3tdrdnpoDnGmqpDMLofoDI2DHSuU65XSHdsrSoLzrWq4Hwfgg5L4fCxHqiueevgQupI7Yu8oYrXk17jXazlHD0h+8Zamedyt8L8tZDxDmYqKiY1AMJuByc1vrEenA8iesViwD5Tlrjw1/EppLQAij9v8KxR1x40Juyaxj3ScH6To+C/VzUfBH6OrxNUY9AD+cmCxXA0NSgKDOkYAs48ILF3jF8zieZvFg+5eWxLdDFQ0BD3bB7X3cZh/DeqmB9hc4Gmd9DFEn2Lj4WF01n6JYtvmjh7bMhTL5ge3W+BnZdqz2YqGVfGGfWvDXYcvWmTbtBeLjX8Badx+E3qGrhXv/jxs3RrwjxTl2ZFxaETb13x35wTBelxofcQVvPBerklv/4ypOrWGUVjMBmJWnjiJeOAap9EEMMRsGBzr1B1CezoNWy2VJ4eavqdC26Rj614VJqrq+5LAkh1nCvhZIZ4BIgZHK20T7jiZsUzxg8lwhB6ESaI+SPHlwsLjKPqtXTBw5g2LynWiB/Iao+MjHJRFgDI8AfgVslR4GLvuRQCiH340Zk18E7rnFVF9I3JMBhzXEbaWDTt+KeZGSd6AfEPvPsy8x5qmUWkSdpsy2f3rqrxqEG0+x3sUiLqsrDOMBNjR5b57DoZ+OA+84iTz95H1uvDYTlcXHNjd6R5U4I7Mezeblm8jX2uw7VwrzlhRMBdsXfo2EJELebws5GpkUPB18jrYR/VzzXTc6KvjAwE18Vf4w9mqzxT1G1UK8COlDQY/dH2T2DlvJ9IYFK7si/vMbfkAknAo9E7sRjYwt9h4RiruXnkw0+NV1YeVqatNoypLZzWgYY5lXqNcNl9mRb7YfGmCbCN5GiSrELA8sGOUhuHV2hAnf26Z6dpeehQHVlH5csGYAPPrPyvmDbVSBk34NKBY3Pf4Q1/zN1mAD3SLQpArHDox6lqfsikJrqd4KRU+Ep8SXhTiLTCnBhUTFvPNkRorK2QOiWMkudds5iW7ko4+4VmEAYxq2NRxsw1jUTdN2AKdfxz5Au+y3J/P+taL4lD7AjZymMpzEKJDOzAeF2J3W7g8a/L6lBkQeNPBv3BtdkN7obKt0JnvzOuEBwWKgAQlEzeQdlSgMJ9vKDCUZpy8dPUELhdXpfv6dB0k0mPZ4ViIQs+PkXFTjQ6PCBwHmt1tG73+IpMZgCoO0DbGNBQAejIsKi+VxuQr5BJL/hVxY/vW7SI1rJf7IcJNSkBswxsTsXOWVWm2wtQV0tllR76dPWJx6HCNca+F1PXcrGOJej5EySSENRwTO5DPggcqZA+MeTTOJIflTTQIIYTiANHDwJDFDLDZe+KTAETvUk4q+zOyOTdW9zHVqa4UdeFe50jFULDemwNJGz26ylKQ6EwFl7/s2NuMVGevEQN195xtLAolg2DzztGA19gHMxRr6O6QX1d4jCuBXbAzI2CbFNE5N1KGm2M4dqbwolIds79XyABBqy+HhvKHTLrgsVIATL5OejmTEDl8nS47bRr10e7rgfY6lKm0wINUk3fCrjPeU6fEk4HZNXFugb+2egFo3+Va/MlE5Zl7cdjUveJS6P5JKPJUeAJQL9ritlm4+d9+7IydlYkMRaVUctQsyg/mtr2dpNfYwdQ/YB8g5iKyxW9R3aF9EBHKCQmQhcryjLjJ84Q/6po2ktIyCD1T4NLFRVBjFHEMkPdLp0go0/yBzgzUUr517zZKrUF3rckWHX/HYr9QbPsD9g6I6jDpZh/gZ3QIDcgxG4JDh0S7KbEmTp5utQ+sqM2rW4KFD5ojbOA1LSbc9D9xCjtfeNdDScTgzngw9q2ktAOsM3AOPnxTSg18dJxcST9nd7obnUGIC18q+kFXfSXQRR12w2zt40lyn0GC01XikfnI5Jut1FK1pK8BBecAWKLejUb0zrbZraL88dtzwinAdL9YiaNAVjk7+QmOMA2ZD5s/vt2vs/bYUVL4d0fjSCm10pdNFYC0e0zFmMpiubbh2/26rZp48lMCjTILI2uvdunLSv98oTvGU4nNw5Lg5nmpR+Bgq+1duci1bvAsjLiYMcYCv7QlswggIKAoICAQDqLmjLbdCgn+22n5GgF5/rkr/unSPxyqoa9iDZOJBu7rcx6QfvpltD2GqAwITm9N9ENcRyJYFXbjRZpZUOGgWmCF9d0RmMXe1j7hpv9ieFVyE0oDJh5d/T5fThNGXJUHek5TMbplE0pIRUrVai+RRPfPDWM+qWGLO7CDZ6/pCcMYZdUSUnMzIb7FpWFkvHj5ZM21ehe4ICUxQuc4Bd0VsIrDpUkKHSbxy175OLiar7IyG92kj533iGWYXV6gt5MIr86z24VNLA7W3OLufA3RS9H/Y+MDzsrxaeDaJyYfFNisguAh9EyUBc1sM5UxzQF2NBZ5JUxSb43JDZfW1/EEW5bey0fSRZpHvEAI92xBudwXX5wrT2ProLJM9F2TuIGwkRDmDA4E7g7sWGRKYve4WVYj3bFcnfH5nDckKns7y26uLtBwtjiX5FqY3xek8jrbTS2taGhddnH4y13Sg5XegIquDYEM6C1Y9hmMLNeZ97IZfIRUQziMci0Ejpg7WevheV0x32Ca2mZ5atnwZZb3mBXz0a4u6HYcLmdgMvb0bnFsPsRNT/QfZv1DuLH1EGL1a4QGQUr0MRjJDANFoZ0zL08tCpZnZzdUy5426e4np291pr3yZb1t60VW+jfQ58nx2ntS5doJm1HGLKaeX7YdPkHCfLibQuqAji11dhDIjNswIDAQAB",
- "MIIZ2zCCCragAwIBAgIUWy7HkwtG4fQHtJ+Q0CkCv9kfOhUwDQYLYIZIAYb6a1AJAQYwRzENMAsGA1UECgwESUVURjEOMAwGA1UECwwFTEFNUFMxJjAkBgNVBAMMHWlkLU1MRFNBNjUtUlNBNDA5Ni1QU1MtU0hBNTEyMB4XDTI1MDcyMTIzMzAwNVoXDTM1MDcyMjIzMzAwNVowRzENMAsGA1UECgwESUVURjEOMAwGA1UECwwFTEFNUFMxJjAkBgNVBAMMHWlkLU1MRFNBNjUtUlNBNDA5Ni1QU1MtU0hBNTEyMIIJwjANBgtghkgBhvprUAkBBgOCCa8ANUOhxJG0QB+/5ubHa5zeI9+RBDbfHXWCreA7dySYXwKrUbjgpjpY6Yl70Q6MqortOYuDd3UuRryTo/BBCVcUIE1+z6maze0RiE0kLtJmdx6hLpTRSGS3Ju1j/svuvnSYGLiYD1hxDro5wkV7SFp2KtMzSQPl3ft6BYvwEhbnDPHi1hqMSTSmGtdHogirldUDwzCM1B+HYHC+uZApkM75+et1TD63cG53368GiJe12EUilNFSLKffX6BHNDP7aut8Pt1MCshY1V9B2sC+rnJF+3kzfGDJNV6KTLTddHjOFgE5XpdI6HH62EZvuEWWrVZmMXzWJgpbNmTjHhOVLpEvW6AJBwSrnCN6dYZogcqJtoZnt9OcmjSMb12Nc175RxlbFp6G0c6qXWZUlaAyG2tTd4jSwCF7LzFXgQEodD/5dZwFtDyHXOVee8C0NXAXWUjJ22ofGFtcvVlj2QPiLEiMuQbEuzude9atpel1dbLXqydYFMft8o/8NCpkxORLicfFvqdeB20H7bfIwOdiAlfSZ7h3hM3tdrdnpoDnGmqpDMLofoDI2DHSuU65XSHdsrSoLzrWq4Hwfgg5L4fCxHqiueevgQupI7Yu8oYrXk17jXazlHD0h+8Zamedyt8L8tZDxDmYqKiY1AMJuByc1vrEenA8iesViwD5Tlrjw1/EppLQAij9v8KxR1x40Juyaxj3ScH6To+C/VzUfBH6OrxNUY9AD+cmCxXA0NSgKDOkYAs48ILF3jF8zieZvFg+5eWxLdDFQ0BD3bB7X3cZh/DeqmB9hc4Gmd9DFEn2Lj4WF01n6JYtvmjh7bMhTL5ge3W+BnZdqz2YqGVfGGfWvDXYcvWmTbtBeLjX8Badx+E3qGrhXv/jxs3RrwjxTl2ZFxaETb13x35wTBelxofcQVvPBerklv/4ypOrWGUVjMBmJWnjiJeOAap9EEMMRsGBzr1B1CezoNWy2VJ4eavqdC26Rj614VJqrq+5LAkh1nCvhZIZ4BIgZHK20T7jiZsUzxg8lwhB6ESaI+SPHlwsLjKPqtXTBw5g2LynWiB/Iao+MjHJRFgDI8AfgVslR4GLvuRQCiH340Zk18E7rnFVF9I3JMBhzXEbaWDTt+KeZGSd6AfEPvPsy8x5qmUWkSdpsy2f3rqrxqEG0+x3sUiLqsrDOMBNjR5b57DoZ+OA+84iTz95H1uvDYTlcXHNjd6R5U4I7Mezeblm8jX2uw7VwrzlhRMBdsXfo2EJELebws5GpkUPB18jrYR/VzzXTc6KvjAwE18Vf4w9mqzxT1G1UK8COlDQY/dH2T2DlvJ9IYFK7si/vMbfkAknAo9E7sRjYwt9h4RiruXnkw0+NV1YeVqatNoypLZzWgYY5lXqNcNl9mRb7YfGmCbCN5GiSrELA8sGOUhuHV2hAnf26Z6dpeehQHVlH5csGYAPPrPyvmDbVSBk34NKBY3Pf4Q1/zN1mAD3SLQpArHDox6lqfsikJrqd4KRU+Ep8SXhTiLTCnBhUTFvPNkRorK2QOiWMkudds5iW7ko4+4VmEAYxq2NRxsw1jUTdN2AKdfxz5Au+y3J/P+taL4lD7AjZymMpzEKJDOzAeF2J3W7g8a/L6lBkQeNPBv3BtdkN7obKt0JnvzOuEBwWKgAQlEzeQdlSgMJ9vKDCUZpy8dPUELhdXpfv6dB0k0mPZ4ViIQs+PkXFTjQ6PCBwHmt1tG73+IpMZgCoO0DbGNBQAejIsKi+VxuQr5BJL/hVxY/vW7SI1rJf7IcJNSkBswxsTsXOWVWm2wtQV0tllR76dPWJx6HCNca+F1PXcrGOJej5EySSENRwTO5DPggcqZA+MeTTOJIflTTQIIYTiANHDwJDFDLDZe+KTAETvUk4q+zOyOTdW9zHVqa4UdeFe50jFULDemwNJGz26ylKQ6EwFl7/s2NuMVGevEQN195xtLAolg2DzztGA19gHMxRr6O6QX1d4jCuBXbAzI2CbFNE5N1KGm2M4dqbwolIds79XyABBqy+HhvKHTLrgsVIATL5OejmTEDl8nS47bRr10e7rgfY6lKm0wINUk3fCrjPeU6fEk4HZNXFugb+2egFo3+Va/MlE5Zl7cdjUveJS6P5JKPJUeAJQL9ritlm4+d9+7IydlYkMRaVUctQsyg/mtr2dpNfYwdQ/YB8g5iKyxW9R3aF9EBHKCQmQhcryjLjJ84Q/6po2ktIyCD1T4NLFRVBjFHEMkPdLp0go0/yBzgzUUr517zZKrUF3rckWHX/HYr9QbPsD9g6I6jDpZh/gZ3QIDcgxG4JDh0S7KbEmTp5utQ+sqM2rW4KFD5ojbOA1LSbc9D9xCjtfeNdDScTgzngw9q2ktAOsM3AOPnxTSg18dJxcST9nd7obnUGIC18q+kFXfSXQRR12w2zt40lyn0GC01XikfnI5Jut1FK1pK8BBecAWKLejUb0zrbZraL88dtzwinAdL9YiaNAVjk7+QmOMA2ZD5s/vt2vs/bYUVL4d0fjSCm10pdNFYC0e0zFmMpiubbh2/26rZp48lMCjTILI2uvdunLSv98oTvGU4nNw5Lg5nmpR+Bgq+1duci1bvAsjLiYMcYCv7QlswggIKAoICAQDqLmjLbdCgn+22n5GgF5/rkr/unSPxyqoa9iDZOJBu7rcx6QfvpltD2GqAwITm9N9ENcRyJYFXbjRZpZUOGgWmCF9d0RmMXe1j7hpv9ieFVyE0oDJh5d/T5fThNGXJUHek5TMbplE0pIRUrVai+RRPfPDWM+qWGLO7CDZ6/pCcMYZdUSUnMzIb7FpWFkvHj5ZM21ehe4ICUxQuc4Bd0VsIrDpUkKHSbxy175OLiar7IyG92kj533iGWYXV6gt5MIr86z24VNLA7W3OLufA3RS9H/Y+MDzsrxaeDaJyYfFNisguAh9EyUBc1sM5UxzQF2NBZ5JUxSb43JDZfW1/EEW5bey0fSRZpHvEAI92xBudwXX5wrT2ProLJM9F2TuIGwkRDmDA4E7g7sWGRKYve4WVYj3bFcnfH5nDckKns7y26uLtBwtjiX5FqY3xek8jrbTS2taGhddnH4y13Sg5XegIquDYEM6C1Y9hmMLNeZ97IZfIRUQziMci0Ejpg7WevheV0x32Ca2mZ5atnwZZb3mBXz0a4u6HYcLmdgMvb0bnFsPsRNT/QfZv1DuLH1EGL1a4QGQUr0MRjJDANFoZ0zL08tCpZnZzdUy5426e4np291pr3yZb1t60VW+jfQ58nx2ntS5doJm1HGLKaeX7YdPkHCfLibQuqAji11dhDIjNswIDAQABoxIwEDAOBgNVHQ8BAf8EBAMCB4AwDQYLYIZIAYb6a1AJAQYDgg8OAJMwUIenRNabP18/UQG4QDrgfTE1LYx2PVX1d+5b4r6+itGoxSsqITmKE8kfyT3HCqjETAMXXf3q7AoBWCqgRZu7UITikC3beZQEbNDgwn0UBGmqMKycofANanU1FXcZm4WyrjGidtHV9aNsZaWQ4cNNVgyDualE8oMW/G4WLtIiaCTR0Jx7LcrHGeLvk7NB3ESMSK6jIeAyq6pQylYvvpAO2SbPpOgNIQyxkfsUVIHZ79sjx0YMdsCWZXV09sFksbWT6K/0L8pxmCkcP5344gSlzG+GX1NVRWpiK+Kv75C6GV6JERUpRumP7D+14Ap6PmwAa3rb4Y0VcNIRub6z0I0H2ersTscNzJCd/a7WhGWJGtE5wE6kkVzNJe/VzEBEL+HjzOBYxpUEhuSf6Tuk4I8rwL3KthYXSCo9kNTRwTt6ZXVJWXPHxozDPHlEdLMpx8XvFeEtpRPYrUBNd1RvfsrQmDrzD85C7Lnp3yD0dOS1muVSeEk2EfgfyrJw71PukxTGOC5k9ineFL4eihCuLfjLsgy7XN1jDNyb8AEGC9iFxaYm9r01vCq5PwO36Zp1TBSa0u8ddfMyAvGyFcHr6jezMbNW/N7nBpzr9SPIywAuUIW22dsdkv/1qpl1e4atmkyWtSOwoIp8AEHEgabOwKv/nN9ovqWjLC9JHKqzY89JU17Xrh8inAiKaNkz1RKUHnIns8zB4a37pq17EuGY8Z0W9uKTmAr9NY90eb7m2vEGl2i5gg9IySQxENAAYpa9HKlsWsVS86EHMplvUB6Q9Tsa1MPSXp9XUFg5f9XVnXzVTIh6TQdrb2sGMNT/w2udtQIz4kV3anAGY0j90VbwKd4ALnAzoEHF/eAAY/+FORLkeLNLmYl5xSNMdgE8lnXn14//ejQV6gzefQa99uE3vfdG5/v+u7aPLHsNjT/bj4i5TW6WbvwQNEkQlh/vni2LiW9IVUdvVR/ETocttukM5V47wXnecZio5vAtJC4ydS3Dstw1RzVpy2wYIlpNGzDaKk1NvXsxdKmPwdmZyisLNftwF9uTc8A/yE3M1O3mt4/vO0Uty2S/o98dnRPLRF+sZ5c6VEsImIi0st56G6W3b1WspQS2Ob7h3wHW3PLTASLJQRZNTlkmXGujapIfJUQxnx59T6y3tOYwLcc0wi3SZPJ2LhsMVezDJsoo5RsRmTXBc2TxitsXzfGuCdxi/s6RdmS7PNuCEtjxmH0Dxv1/xsYeUyx0zYgWevNQRszBfPNaRLyD2LxqLAMBky3eAmgpCLVRvKipECUM95CwYNN188xJueYEpfVduGI78znbY/IfUEFCjU5KwUbOyxMtfnl2eMLlEjDrZby+30zvMm8JHa53sPaL/2du4Cq1g21J12OoZebssK/2sPF2tVZqQqTTDtMrmvueVsZyCCiWMRyF8kVmbUwSqjRgtITll9+lQbwlYYnQc9/Yo+9XhMotsg/Ufm3oWQseSva8VFTGXpCiz3YZjBCJcUtO/jHIeKKrFMmlf6VG5KAy3cmeARl8r5oyhYrMCl8BqjMCGcmMmR2CMbo44lbkPmNXPjnov0jUQUC+AUrfjn55kBQCKpK2c/AyepNPqtcBeJ/jR4CcvqvYfKOmPMRHtFwNWpFkZEukUtRpZ7xoVwddhYW37aSs5KIbC5PE+QedyOBtb2H3rxJP+3xsmK3/+crN8MJTF941wcWHcO78Qy+jlMmnD3X06qF3F61/oHbkWPvNN1WX77fYoPB+XVEcj8WTCwZyK2aHl1ekSa3hPovqigZ/xeAFYOkVsf/X25Jk9AcUOh10/JRpNKjsRZTv1xpiWaU4BcmIt5RxxzYd0KfD5tQvs4Of8Q40RdgJ+IUMUYllbWaxKsHbE2HaR3fRY2uUdet++yiMvTFei8zpvxUHtP1OcZiVf/FjfqQMkBg7NqXjr63RXG3S+VxqEmb4rAqmde5jecqfKC3zGnY1VJ6y3ys/vAoQbgral5kfTpn2wNLeNMK3V0FJdSC/QBtrkPXe9t6/VbUG/Yppf+gBHDjWm6gn6p5SIBNvIoQqQxt1ZbWDdhKz+3RjCJ9W7082eEiL/RL94Ubvhzd8R389r3JjarAmQDq+tnltLhNqw/PB2wpkZM6ZRvxnOj1q7OMj3WnyhuCMNcXITGYPlpT5sKJ3tTpN9S43kpla5TbGt+HEzS/D3BpB4E3qn49Raja3FAVFqD4/JupjjMBVVDjhyV5P7IxW8E5vcfcBU4YDIlAOlEeo7Y1MG+iMa35ZZJzVRqUouqfVIs56WJIII6a8IbziArfIRtPL+xs+siez3gtFfu1OO78Y5witDCCymFsM+zzynVe0pVrfK66jm27DMYgS0FVc9FGs9n+5KUIa79TVVDF4/apHh9VjM8OSmKm95QTTwY86SKiSFtojtzGmF5pPWhu1I/TISD9GKqYx7aO+X2g1eGtCRBP/gg+UMVNJQ2D1FgQ15WyalNAg6aon2rpe4tj0w35skI/qfFqol3yDa9ozaXtqaNOwfuPwUvIhK9thtDY5T282QbUuITYHm+Bp8PSFUgE40TxyoJwADLgWKNuYNuXA7pZGwWZBpoPL9JZ96zN7zi+0zlslMuGoV7o5HYPZDIk+/+E453e1mTarFDofCdC/KB9rWNuWASg1LCmRMxXuonbd5X26yqQ5cwYn7c/xNgzq2Y6eyP17DLhO2Xcf+L2GIEgL93MamiNloZzUcx+kZ1DNWlZqFAZ39afXkQFx8v1LqGQGtUyMmIvV96TqQF230MZf9dDJGah3H6BSIkrAR0CyJnWydhlc4N9nQH5W0vGC6zgvbehFCnvIdLRMMMdY7JhHv5C27ZeCj3ZnZs4JTKHlf2qlBEGx0/MjwTd1sHp3PsUy06GhL3zRNi1bv+mj7B46fnZ3iYOBCYcsWhgfC19EzwIbeF9syuB796LpkMq3rnK2aZkU1EXIWJQ8meoAH9IACPR7DdYZNH4QPhdfDrRUupIOZ26Y7i2Q7SiDheFf18JZenZzBxGb/rxqwXdLv/gyMeP9W00GAZrq+w0HVU8iJhjmwK+gY44+/qChu4eDh5d5wwMBwceczlv1IBvo8Hic6mZAPVH4D5nSGv9yom0strIQ1iGuChy1bm7f+Ad+9eslfsPK8L3X+TGzGi51k3i2yto5uns+JzSMvw+LRECzDHXvMoCkQShoYz3bW5yWO01BM9ICAPpzKKK310RVt4vgUytOYQokn2qxopAgLUsqr5kZJtwR9zyLGHh3TvQbotOWqBwPwgmzaYCg8uJouRs23IrYzuYKmRvtfxwyuopvUIKgWgLCNUvbyx94DXo5qlKnR7lrYtB8ExaO5hcutSy8f0mfHn3SijdBLxUsHjiAx55Bsvbps9iTbhb2ZqooQ76AuvD5BfFXYubfvBdT9O5gSjpPUrF37InSapYh5PyuBSfDVG2chd47UgQWUe1PS5yX0C1LjPZPIdwCAYKuwVjslXUwvsTEEsoNyyKGEs45nu/+lkRwVgO0v3z6T2w1L4p5szwec3gQ910b4lz+dbqBWuMLKfM/gTo+eFMA00dwW26eMIZZV4oOcLm6dL00nBtvf99UVkfOYO/fAmHRlbev2oKn+Oh+rcfWKLrA5Qlpkul89tVJJVtPr0q6pq8K5gCXvXkqtmz5A40807GfOXCNDu3EFpmm863lPor/cdTuTwGsD5LhkdLQrNMgY4P4/jk4tbXgRAeYHxxVm6So5fmiS88Tf2xMfh9/zuCiqKf4gccJL3e0dBuMib8yXd+NKlmZJfL4kRPKO9yzJn5AHLSVlMkERFDJOAxmbg+NBs4l3xnb4JLffVcy5FMv6ftI/WWgYdvFLTWNCiF3HNcyBo59T/veK9uwOifa9GDwfvAQwUxMAbwKCPmTm7qfAyK1WAl3lq0R1OmHdF69jCo19abLqKCZL9Cu0CzWovA54w0qTv0yyuXJ/+Tw1L4jzCxm7qbQE+2cjN5ektTMRMWIpLS6R1c4x+p0315RFG391F6YCxypsF2VxOjLKjT8YEf7/6wbVq0ryHYF5nyYFeooIxf0eJ+STowi81YUL3hY6cAmsA8Rh5yPeCVzk66vmBOy6LnDm2U5joSwvxEhfVJL8oKMDlyy9bNd1eYj/HvBvnEqsmLiQ/5VvfdRgvUNgMt7keFyDzvPvCBUAwi8UI0sTQEgXxc66x2J14W17Q+YLjAiR+UXb+rqcTu8RkU+lLQdXfbRs/5yiAf9g2NqIHAMGaLMN4P2GC915d5ouy5fEmOiH8jFIvqQEz80oEtTYgNM7J5fKWva6nN31MYab0usD+9zrjuJ9gU26H6yYHpYRZduSTJwMNl8V8k9RYudisKlQs7N/JFfWckeLDtFNLOmIgsc0N0FJThLbICOXKGwzhxSYGYrRlnC4TREXYKeurzl50BVhYyxzc/jAAAAAAAAAAAAAAAAAAAAAAAABwsPFB0ll7Pb4HA44VtZPdIvAU06H6BZFpZSAnc8XnF8GFSQMEyVF75hTU8QCgU2h8PEq9bdQt5XmoHZH8LwA6ERPMGq/EoIvY8A5dLOj9BUsCBvVOs8GNTAtg4vVYhp6cIdzFIcYKUdwvh5TlzWdeglIEDEoE+6I4weJxMh8Qo4CV5XMYXYcDr0w1tAz7RRgrsw8e/nhZ5UaoK4Tmrwl0lRsox5MQ0S4IM+Kv1BNAqy7tKN5QpafOYTLOnqKZ3mSbI0oYe/xpcR8YqRSfj/m3wjT7gOehWG/Y4nCdWMNDjFQZjN9g3GM1c5+gcknaZAhhEklsNm03bg4mBCbg80AeD1MZDM1LsJOXvKcgcuOiL/0wjOiaxLMJa8mJ2Scc6ULy8LhDV0NoSVJuFlfdKm6M8yNZ+kUHp52VRlylONrtbbjIa63TaJBnQVTLL/z5RDtlF2hZc0z+sUr+IuvqtrhEtQBPSSDYTm4wUXeirIET9qcU388dTNCCuLINLMAuSHneEW635klrwxO2kIqa4vxhT7vEKdoNOr8s669CoeSc1nFDsmd6g+ij5A66n7lE6jwruaE4rQn3IUWga9P607KAvlL7W5NGIiZfOCXbFHJTejZpzkjRusuAny99Cg0NTTOCQXfXWav7BPww5ExN39kvCQ4eWp/cWJjWRERuWLuI3EQXdWvoQ=",
- "vGyKLAFHEVAG0FkL6u2y5w/NguzP1R8HNloWgFvf61QwggkoAgEAAoICAQDqLmjLbdCgn+22n5GgF5/rkr/unSPxyqoa9iDZOJBu7rcx6QfvpltD2GqAwITm9N9ENcRyJYFXbjRZpZUOGgWmCF9d0RmMXe1j7hpv9ieFVyE0oDJh5d/T5fThNGXJUHek5TMbplE0pIRUrVai+RRPfPDWM+qWGLO7CDZ6/pCcMYZdUSUnMzIb7FpWFkvHj5ZM21ehe4ICUxQuc4Bd0VsIrDpUkKHSbxy175OLiar7IyG92kj533iGWYXV6gt5MIr86z24VNLA7W3OLufA3RS9H/Y+MDzsrxaeDaJyYfFNisguAh9EyUBc1sM5UxzQF2NBZ5JUxSb43JDZfW1/EEW5bey0fSRZpHvEAI92xBudwXX5wrT2ProLJM9F2TuIGwkRDmDA4E7g7sWGRKYve4WVYj3bFcnfH5nDckKns7y26uLtBwtjiX5FqY3xek8jrbTS2taGhddnH4y13Sg5XegIquDYEM6C1Y9hmMLNeZ97IZfIRUQziMci0Ejpg7WevheV0x32Ca2mZ5atnwZZb3mBXz0a4u6HYcLmdgMvb0bnFsPsRNT/QfZv1DuLH1EGL1a4QGQUr0MRjJDANFoZ0zL08tCpZnZzdUy5426e4np291pr3yZb1t60VW+jfQ58nx2ntS5doJm1HGLKaeX7YdPkHCfLibQuqAji11dhDIjNswIDAQABAoICAF3NvD1sXgrRNQuXjGIXxH+81zPR7yF94DiPiaXpQfWlmm0cHokw1lLtX+/17eaDhOFSNj/Q5Sfr5X1ZVcUByGxy4xx10ymGQD5slFtvuvHu7kahury7MzayYK5K6lDC8kHza07yhomzMqymiFMcubWDYwcyYY/BElFjX0tSKAPg1KURiXPTzokf2imsoassyXQ80jPFgNTEiYt3yZ4K68+kCXNxQdjEmDgKYMwel4YkUvI0+1FX4fPS7Ui8CN+BAdOAuUbad1c/Y+IYqM144UNGh8DuWqEmG0WxSXZO5DT+1+OSBwtrH+RwRF/0elCiZag/v/5DwLIjy8PKua8RihOR9vavi+5x5cuWPJleb/+Cu5s0rR4Eq3Rs9V4ras8LyqQphVmBE8T5JtPpdQA5QGNtHOVf6OexIpt+LbVtUhRIcGjrJu5iTyTPOZY3OOz35XCa109MC2tMcX5ghcCLMxj3wIZNAAwH3q0BS/U7cKshRwKkQN58RUDe8S7yssxrmkIWRJlY/n37ie6OcyOlSqjgyFo9nGDJIJhgX9HTKlKVuki6rnzh4npskQ6/VlVPWvPLZVKGnsEXKjefF6p7sjqv/6zOG5HgEs6lnI9OuofslOY5o4jOebiba8Mxx67ZGBKo0O1ElvCVUnYrAh41b05XX0s7MEyp2NsmBeCg5ElZAoIBAQD+ezZHaSjrMSEwFoMWwM+u32ze2XMmDK/Ix+6dJ7PIvnrUv8TnMTD/7duGyjjgnG3UzN18RNYZgpzjEOknL6qZC24rgXoRjYyTQkh9zSCRJ9HAZ0xrF0LLEond10DRTDtD4nHwIsFKKdwkD90wQxLedOTQxEfH0MP90EW8T9EtK0WwddSsIpNvUCh3KpX9qxr3nwPmb2MIVENEwaFvOfracr5vJu0+4vOeBGx9Auu09KYzzZX/U2z0E9cPIb/MPZEm9xuJOKshTifw3Os7KnUvX6GAKs0FEGZYWDqCylTCEq6w5bXRv+RnaVDB7H29jtinEL4Fj3boC3DQHQBR8i/bAoIBAQDrlC8D5fPAjycHfY2+8YPZZvoHnABe0oKpAbezqg58N62w+Ldf5wNdj8zeyEDLZo5sqs8u0n40yLwmSEAhh46M3OFDOzgjljcU+aXZHzqsnYncLz5wyy15Qh2BhrjoyU1/tbaUde93d3nDgPrQjSzrBbY6eeqVCa/4VQlz2zQ7+SUDNw6LITViOtilp7KR18eVDc00Ud7CoZI6umH5ydKrtCaVpHqTwqn4xi0E2zI9zV0NSzJp9ss6cXbTnTMM7LJ8hSOwQKUVZ8pGXVNU/TyjH9Wuyf6pwn6Po2Q5Ie9xCsyyHnVi0+7n4OuTxpgKEt+xv/zNPignJkV/agTW9Q0JAoIBAH3fM9neif7LLj8641w9wnwcxxzzMaGAZPJK8huJp8ODc/4HXL19916fqBXjsH5o4WqAao0s/zlfAXrOwoQ/b4KDxNqAEIDeIsoz3udaruEdcQJaFdJijwcjBE5WShk8O5Q4TWMZzcGBMwIjVqSoiIzABO2+KEMNX+QLQHMEh9JvtOizX55E++fzHhDTX505JP2WCbfRIIreIue/XrpFU275kngoKPESEK34QjETYMMAv7Sf27GO8jVIGvfBGb1MNp+vWk9lWEABCIB6xV9egNgN1TQv93ipw/WurkJDEelslDurY2N8Jt1/mhJRh2BbZ447GcJmU8oy3noR3jaqNEECggEBAMXAwK6/C5zrDlJFXQWaa5nFzcExfUYb5D7HCFQzPrGbc5yJTDWfEL4rhkjFRU75KjmiMQUXAYaBsx9Xqy36QvmQOTBct8V3xYk//66BfpmELUO+DOZWSDfv/iDK3NHcmcfI3BlH3tskWfx5exIyUDCBvPTdfsPZO/R0PdkZe4GUpTNLtlOobs2kpFR6r3Wp8wn2afmveBVd2AigiLpMZyJnubQIPDVpRZFlmkjnUAd9Ks2MACffWb4XnS4KWd5Rm4rXoJvFyE5tr+jdUqSXZ51vjcqKGdKbR+5/tBQZnowACtDCrLtnOLdBob+NB/f82/a0ORx5Pu+OOuy4LJPdZTECggEAIfeJZ8qwtUV/TBFnhKLOeyxs9Z/MSm1WORs8Gx3L0Z2bEYE2y0MAO536s7vD0m/CLUO0L1xFESH86VoOmHCtapUNab6hsJJV2dJkvflJRBGZDxhdMIfSJ5D7ZkmRJhrkkSfLA60DcBoTuZEcGjl8A1+LH2K2PJnaUrpM6deu/HlPWUC7TZeLsCVKgBZV0d6z59780UiBOjrBLsa+t+qBrJ8Kmoo842beamZIdO60E8Si5HePPMIx7aGIm79I/Dv5YmPsIWmlUV1GzyPRZjwu9fmmnWkIC23HSGSSArDR++E1MrnOwW52qhxzLvrI8V4DSg5UwAqHZlZxcOT5d2QPUA==",
- "MIIJYgIBADANBgtghkgBhvprUAkBBgSCCUy8bIosAUcRUAbQWQvq7bLnD82C7M/VHwc2WhaAW9/rVDCCCSgCAQACggIBAOouaMtt0KCf7bafkaAXn+uSv+6dI/HKqhr2INk4kG7utzHpB++mW0PYaoDAhOb030Q1xHIlgVduNFmllQ4aBaYIX13RGYxd7WPuGm/2J4VXITSgMmHl39Pl9OE0ZclQd6TlMxumUTSkhFStVqL5FE988NYz6pYYs7sINnr+kJwxhl1RJSczMhvsWlYWS8ePlkzbV6F7ggJTFC5zgF3RWwisOlSQodJvHLXvk4uJqvsjIb3aSPnfeIZZhdXqC3kwivzrPbhU0sDtbc4u58DdFL0f9j4wPOyvFp4NonJh8U2KyC4CH0TJQFzWwzlTHNAXY0FnklTFJvjckNl9bX8QRblt7LR9JFmke8QAj3bEG53BdfnCtPY+ugskz0XZO4gbCREOYMDgTuDuxYZEpi97hZViPdsVyd8fmcNyQqezvLbq4u0HC2OJfkWpjfF6TyOttNLa1oaF12cfjLXdKDld6Aiq4NgQzoLVj2GYws15n3shl8hFRDOIxyLQSOmDtZ6+F5XTHfYJraZnlq2fBllveYFfPRri7odhwuZ2Ay9vRucWw+xE1P9B9m/UO4sfUQYvVrhAZBSvQxGMkMA0WhnTMvTy0KlmdnN1TLnjbp7ienb3WmvfJlvW3rRVb6N9DnyfHae1Ll2gmbUcYspp5fth0+QcJ8uJtC6oCOLXV2EMiM2zAgMBAAECggIAXc28PWxeCtE1C5eMYhfEf7zXM9HvIX3gOI+JpelB9aWabRweiTDWUu1f7/Xt5oOE4VI2P9DlJ+vlfVlVxQHIbHLjHHXTKYZAPmyUW2+68e7uRqG6vLszNrJgrkrqUMLyQfNrTvKGibMyrKaIUxy5tYNjBzJhj8ESUWNfS1IoA+DUpRGJc9POiR/aKayhqyzJdDzSM8WA1MSJi3fJngrrz6QJc3FB2MSYOApgzB6XhiRS8jT7UVfh89LtSLwI34EB04C5Rtp3Vz9j4hiozXjhQ0aHwO5aoSYbRbFJdk7kNP7X45IHC2sf5HBEX/R6UKJlqD+//kPAsiPLw8q5rxGKE5H29q+L7nHly5Y8mV5v/4K7mzStHgSrdGz1XitqzwvKpCmFWYETxPkm0+l1ADlAY20c5V/o57Eim34ttW1SFEhwaOsm7mJPJM85ljc47PflcJrXT0wLa0xxfmCFwIszGPfAhk0ADAferQFL9TtwqyFHAqRA3nxFQN7xLvKyzGuaQhZEmVj+ffuJ7o5zI6VKqODIWj2cYMkgmGBf0dMqUpW6SLqufOHiemyRDr9WVU9a88tlUoaewRcqN58XqnuyOq//rM4bkeASzqWcj066h+yU5jmjiM55uJtrwzHHrtkYEqjQ7USW8JVSdisCHjVvTldfSzswTKnY2yYF4KDkSVkCggEBAP57NkdpKOsxITAWgxbAz67fbN7ZcyYMr8jH7p0ns8i+etS/xOcxMP/t24bKOOCcbdTM3XxE1hmCnOMQ6ScvqpkLbiuBehGNjJNCSH3NIJEn0cBnTGsXQssSid3XQNFMO0PicfAiwUop3CQP3TBDEt505NDER8fQw/3QRbxP0S0rRbB11Kwik29QKHcqlf2rGvefA+ZvYwhUQ0TBoW85+tpyvm8m7T7i854EbH0C67T0pjPNlf9TbPQT1w8hv8w9kSb3G4k4qyFOJ/Dc6zsqdS9foYAqzQUQZlhYOoLKVMISrrDltdG/5GdpUMHsfb2O2KcQvgWPdugLcNAdAFHyL9sCggEBAOuULwPl88CPJwd9jb7xg9lm+gecAF7SgqkBt7OqDnw3rbD4t1/nA12PzN7IQMtmjmyqzy7SfjTIvCZIQCGHjozc4UM7OCOWNxT5pdkfOqydidwvPnDLLXlCHYGGuOjJTX+1tpR173d3ecOA+tCNLOsFtjp56pUJr/hVCXPbNDv5JQM3DoshNWI62KWnspHXx5UNzTRR3sKhkjq6YfnJ0qu0JpWkepPCqfjGLQTbMj3NXQ1LMmn2yzpxdtOdMwzssnyFI7BApRVnykZdU1T9PKMf1a7J/qnCfo+jZDkh73EKzLIedWLT7ufg65PGmAoS37G//M0+KCcmRX9qBNb1DQkCggEAfd8z2d6J/ssuPzrjXD3CfBzHHPMxoYBk8kryG4mnw4Nz/gdcvX33Xp+oFeOwfmjhaoBqjSz/OV8Bes7ChD9vgoPE2oAQgN4iyjPe51qu4R1xAloV0mKPByMETlZKGTw7lDhNYxnNwYEzAiNWpKiIjMAE7b4oQw1f5AtAcwSH0m+06LNfnkT75/MeENNfnTkk/ZYJt9Egit4i579eukVTbvmSeCgo8RIQrfhCMRNgwwC/tJ/bsY7yNUga98EZvUw2n69aT2VYQAEIgHrFX16A2A3VNC/3eKnD9a6uQkMR6WyUO6tjY3wm3X+aElGHYFtnjjsZwmZTyjLeehHeNqo0QQKCAQEAxcDArr8LnOsOUkVdBZprmcXNwTF9RhvkPscIVDM+sZtznIlMNZ8QviuGSMVFTvkqOaIxBRcBhoGzH1erLfpC+ZA5MFy3xXfFiT//roF+mYQtQ74M5lZIN+/+IMrc0dyZx8jcGUfe2yRZ/Hl7EjJQMIG89N1+w9k79HQ92Rl7gZSlM0u2U6huzaSkVHqvdanzCfZp+a94FV3YCKCIukxnIme5tAg8NWlFkWWaSOdQB30qzYwAJ99ZvhedLgpZ3lGbitegm8XITm2v6N1SpJdnnW+NyooZ0ptH7n+0FBmejAAK0MKsu2c4t0Ghv40H9/zb9rQ5HHk+74467Lgsk91lMQKCAQAh94lnyrC1RX9MEWeEos57LGz1n8xKbVY5GzwbHcvRnZsRgTbLQwA7nfqzu8PSb8ItQ7QvXEURIfzpWg6YcK1qlQ1pvqGwklXZ0mS9+UlEEZkPGF0wh9InkPtmSZEmGuSRJ8sDrQNwGhO5kRwaOXwDX4sfYrY8mdpSukzp1678eU9ZQLtNl4uwJUqAFlXR3rPn3vzRSIE6OsEuxr636oGsnwqaijzjZt5qZkh07rQTxKLkd488wjHtoYibv0j8O/liY+whaaVRXUbPI9FmPC71+aadaQgLbcdIZJICsNH74TUyuc7BbnaqHHMu+sjxXgNKDlTACodmVnFw5Pl3ZA9Q",
+ "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",
- "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"),
+ "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"),
new("id-MLDSA65-RSA4096-PKCS15-SHA512",
CompositeMLDsaAlgorithm.MLDsa65WithRSA4096Pkcs15,
- "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",
+ "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",
- "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"),
+ "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"),
new("id-MLDSA65-ECDSA-P256-SHA512",
CompositeMLDsaAlgorithm.MLDsa65WithECDsaP256,
- "Q13kc+0JAWW48IN4kLGkJOELbj2c0t19iTqJDmFK9grtsah6WwK2pjuvOTx7THjroS+FFTbDjXxifp38hBobpvBUgBz9UFWoSWLtyLG19MxiIcdNsbjSJnveC0n2sb80EUn4ajo76ZzKqzw/53641kcqJ9kh3idISWzNrAS6xvXV7wl0nPbPLRwj0dMQ6kMcSCI4uSEUV0BIZq/wVJJmkS3zaq05HjxiA4faetjxFY8nNbAUW2tIvNX2iQcmcNMU7lE9BcIFs/e63I3ucOoqSr5P6pnGBJ6le8YyyGLTDY5yAxZuTVYN6Bxn7F7B/XVAsJv52NhykBLeuJqYGZEtawgR/zZeDTgso3OLY+O5ZFWVpNGYpLjqb+tvJHkd9ZVPo3cQi5kj6c68aJ7cz050YDsOb20YcSFASbVb+2pXfVjjvBOmbwpK5wuf0F3Ztq5mYtyR0vKvX+rrtcmVuJLxepqTTi3NOZ4Jh0SJ2dVpqpC3FswVpRATRbW1uLCT14Hv25Y0NMd6Eb1eUZehg9rPQdHq6nVtzQy390Pr2b/+JSEPgJPCgYA8epGjSbriNzuQZoa4JteMRNNe0kcZUEoEATyOmk5RBHK3FZSk1DTr6hvnivc7+CWKyOgQ8XqWjFUIuPxve6LmNtCMX/IQyMGOJ9cEG9p8v2C65N0wngvaytJqXgPZvfCA8eT2CMbp1cZhrHVcJ3+vwMzA+TwHNOG1n+hDvPamrTwFyunMo7+VOEALEqG9jt8XOHAr/2WwlnlHxOJLShs0eFzl06jvc5VuaxRBTJCbU78sdNYMOTFo0MnII6mcMxOu5Uq4DKYXJmQHykmtZLzmUy8ov2z+zUgJqmwGsOP3MzCMKC/wvsLhjQdxfIHct25fQ81NOG7u1BDyhVyK3/U9Tb7SsnskS+SJEcd+ZfCS2LzDxeZQRFUrdam6wjBZ38oPpi84ehT0Fr6yihxODNOMs5DS4eS93ikaYa3WSSde9R+MFaXHGBCL7o+yqpOT6NWQ7An5sqxdzMyV5SKwzfJVNcw+55i0sqL4EM4PMTRUVF4KqSDm4ZluU4lYazWBAo+c9beGY0hIcTVRFPE4pFEdCw3i2To7Xvoy5ykruT6SLguhuIkAPhPcSlSbP2y2oE5+XPKRv0i7ejvSwPoSQLnGX4q+eng/+6ql0CqQFITz8GWXBMnJrh7vt9jbyqDixiNhJc/3Sjellq6R9vo5vKvgCrYC5UpSRt7+Ub0iTKHvXcqKds0ZYktRPEnRd55+HX5StXeeaSvpMqpO5GpYme1KRUHZKb30v68TehW9cV1R+07eXKLobTUmKiF49hAlpcTbTMmJ2vDvz5NnBbR/JbaZO1APGCbawTwCbhWApucosw+BPY/cbBKNPtlO7sk5v+Q8FmxrFKJw/6tk1lyWfttlCR8UzfTOZajyxDPLdqUiRaH1Eh2mBZ1gqC9ebFiCtMoSlbQaNrvFlIb0ELcUZ9DtswZe1BtS5JQGjv1RtbsaM2xq9Oiq1hXSdHIyl1WbMRcaT/7HbW2odJfyF0u/wEy3lVh2vb+2mFegDid6vV1kYX3qd8sknm3Pkz6ZC5ITZ/iD4iwGAATPUB/knepDohTz4WutM/6halDR9oW5PPvG5QA+1nEDU2CCCYEjcS3TNLtr3XcykFhCs61XIaZ+6xq5MifQtWpiUH5GT1RSm4YriVs2yvRNhoNaW0ggoKSG/za332/P+JGwNhz1J7Vt4BGirhWySBasfDwm1HPdb53a2lUTFIXyBAOm4s7Mm5XfRFGmKISb8UyHYK6BkNJ7sETqQqKogajAHnzLUVeNaVcHkDkr2EWk/esb82hKZozmPagOm0giu8md5qab3aE9I/HJM1V/YicAvzVH8DjG6vktd1witPRGGQ1AttPmqPoWG2H3Zi1VgCBY/HGAZhbMD84eiegtgsaGsFfcpefp4sMY2PpEqhFMUS0bJ3Y7d/UGtrn43CW6Ty87E3GKtjw4bef89LIwM/wwc5vDmSR8azo07P6RZ2M8V6SmEXEpFYQd6Zy+OdyCezgul+z7FtVztDeMalb+sC0c2npWJYoF6xZ6JU6qPjc0bZEKdQE4Ks5UmZbygfNzzlycU+NOjYU7coZvlUQtqUsOkEyEOM26zRNh2kg33leVD9vUR8vBWZv/18EyLETA1EjYanGkIabEs89JDm2y8dCG/zUMLT0kRHrPrkG4extyhyyGiNwZ1PsT4GAzatIDvIsZV1nbLKs3xnbqSOrsmEI0VuiEdzY8KDpJ+3306sahRj+gViV+tevGsGUN1NmlAgq3oiL5+N2eaPgdrFbkwYurwiOyP0fLrVbp5oE06eGQoAec1aj6JBTZWcII5XCKsArSnaqb3WlVxyst0L/1Y1qFX24kRPHme6HnfcnFytH0A+u4zpv4S8+DucV/5xWDyB+jdPcx9pieEK41NPgc9R6v+rlj/uc8K2oUBdgwkuEYPj7+FSArLlJQx247ab/cc081G1uJJteUPK47ADrZyJBUMJ/Aj+4LjMDzArdGdjqEZP4V3NrNJPksBoXK7/kx8gBr/4Efn9iuCs8w6nxDMD9G63ewx4fX4pmQP+gcHj37iEIHGJEEwqYBQomB1ZeTdc8fomXtPG8iJ7XykETqQFGOM+zy0C8zccyQOL67LChvbVmhgj4XbvlzoHaVHjNaXDWjXoM18g==",
- "MIIWVDCCCOegAwIBAgIUSnoyhZkfRkcpLVASUAUX8UNeHUswDQYLYIZIAYb6a1AJAQgwRjENMAsGA1UECgwESUVURjEOMAwGA1UECwwFTEFNUFMxJTAjBgNVBAMMHGlkLU1MRFNBNjUtRUNEU0EtUDI1Ni1TSEE1MTIwHhcNMjUwNzIxMjMzMDA2WhcNMzUwNzIyMjMzMDA2WjBGMQ0wCwYDVQQKDARJRVRGMQ4wDAYDVQQLDAVMQU1QUzElMCMGA1UEAwwcaWQtTUxEU0E2NS1FQ0RTQS1QMjU2LVNIQTUxMjCCB/UwDQYLYIZIAYb6a1AJAQgDggfiAENd5HPtCQFluPCDeJCxpCThC249nNLdfYk6iQ5hSvYK7bGoelsCtqY7rzk8e0x466EvhRU2w418Yn6d/IQaG6bwVIAc/VBVqEli7cixtfTMYiHHTbG40iZ73gtJ9rG/NBFJ+Go6O+mcyqs8P+d+uNZHKifZId4nSElszawEusb11e8JdJz2zy0cI9HTEOpDHEgiOLkhFFdASGav8FSSZpEt82qtOR48YgOH2nrY8RWPJzWwFFtrSLzV9okHJnDTFO5RPQXCBbP3utyN7nDqKkq+T+qZxgSepXvGMshi0w2OcgMWbk1WDegcZ+xewf11QLCb+djYcpAS3riamBmRLWsIEf82Xg04LKNzi2PjuWRVlaTRmKS46m/rbyR5HfWVT6N3EIuZI+nOvGie3M9OdGA7Dm9tGHEhQEm1W/tqV31Y47wTpm8KSucLn9Bd2bauZmLckdLyr1/q67XJlbiS8Xqak04tzTmeCYdEidnVaaqQtxbMFaUQE0W1tbiwk9eB79uWNDTHehG9XlGXoYPaz0HR6up1bc0Mt/dD69m//iUhD4CTwoGAPHqRo0m64jc7kGaGuCbXjETTXtJHGVBKBAE8jppOUQRytxWUpNQ06+ob54r3O/glisjoEPF6loxVCLj8b3ui5jbQjF/yEMjBjifXBBvafL9guuTdMJ4L2srSal4D2b3wgPHk9gjG6dXGYax1XCd/r8DMwPk8BzThtZ/oQ7z2pq08BcrpzKO/lThACxKhvY7fFzhwK/9lsJZ5R8TiS0obNHhc5dOo73OVbmsUQUyQm1O/LHTWDDkxaNDJyCOpnDMTruVKuAymFyZkB8pJrWS85lMvKL9s/s1ICapsBrDj9zMwjCgv8L7C4Y0HcXyB3LduX0PNTThu7tQQ8oVcit/1PU2+0rJ7JEvkiRHHfmXwkti8w8XmUERVK3WpusIwWd/KD6YvOHoU9Ba+soocTgzTjLOQ0uHkvd4pGmGt1kknXvUfjBWlxxgQi+6PsqqTk+jVkOwJ+bKsXczMleUisM3yVTXMPueYtLKi+BDODzE0VFReCqkg5uGZblOJWGs1gQKPnPW3hmNISHE1URTxOKRRHQsN4tk6O176MucpK7k+ki4LobiJAD4T3EpUmz9stqBOflzykb9Iu3o70sD6EkC5xl+Kvnp4P/uqpdAqkBSE8/BllwTJya4e77fY28qg4sYjYSXP90o3pZaukfb6Obyr4Aq2AuVKUkbe/lG9Ikyh713KinbNGWJLUTxJ0Xeefh1+UrV3nmkr6TKqTuRqWJntSkVB2Sm99L+vE3oVvXFdUftO3lyi6G01JiohePYQJaXE20zJidrw78+TZwW0fyW2mTtQDxgm2sE8Am4VgKbnKLMPgT2P3GwSjT7ZTu7JOb/kPBZsaxSicP+rZNZcln7bZQkfFM30zmWo8sQzy3alIkWh9RIdpgWdYKgvXmxYgrTKEpW0Gja7xZSG9BC3FGfQ7bMGXtQbUuSUBo79UbW7GjNsavToqtYV0nRyMpdVmzEXGk/+x21tqHSX8hdLv8BMt5VYdr2/tphXoA4ner1dZGF96nfLJJ5tz5M+mQuSE2f4g+IsBgAEz1Af5J3qQ6IU8+FrrTP+oWpQ0faFuTz7xuUAPtZxA1NgggmBI3Et0zS7a913MpBYQrOtVyGmfusauTIn0LVqYlB+Rk9UUpuGK4lbNsr0TYaDWltIIKCkhv82t99vz/iRsDYc9Se1beARoq4VskgWrHw8JtRz3W+d2tpVExSF8gQDpuLOzJuV30RRpiiEm/FMh2CugZDSe7BE6kKiqIGowB58y1FXjWlXB5A5K9hFpP3rG/NoSmaM5j2oDptIIrvJneamm92hPSPxyTNVf2InAL81R/A4xur5LXdcIrT0RhkNQLbT5qj6Fhth92YtVYAgWPxxgGYWzA/OHonoLYLGhrBX3KXn6eLDGNj6RKoRTFEtGyd2O3f1Bra5+Nwluk8vOxNxirY8OG3n/PSyMDP8MHObw5kkfGs6NOz+kWdjPFekphFxKRWEHemcvjncgns4Lpfs+xbVc7Q3jGpW/rAtHNp6ViWKBesWeiVOqj43NG2RCnUBOCrOVJmW8oHzc85cnFPjTo2FO3KGb5VELalLDpBMhDjNus0TYdpIN95XlQ/b1EfLwVmb/9fBMixEwNRI2GpxpCGmxLPPSQ5tsvHQhv81DC09JER6z65BuHsbcocshojcGdT7E+BgM2rSA7yLGVdZ2yyrN8Z26kjq7JhCNFbohHc2PCg6Sft99OrGoUY/oFYlfrXrxrBlDdTZpQIKt6Ii+fjdnmj4HaxW5MGLq8Ijsj9Hy61W6eaBNOnhkKAHnNWo+iQU2VnCCOVwirAK0p2qm91pVccrLdC/9WNahV9uJETx5nuh533JxcrR9APruM6b+EvPg7nFf+cVg8gfo3T3MfaYnhCuNTT4HPUer/q5Y/7nPCtqFAXYMJLhGD4+/hUgKy5SUMduO2m/3HNPNRtbiSbXlDyuOwA62ciQVDCfwI/uC4zA8wK3RnY6hGT+FdzazST5LAaFyu/5MfIAa/+BH5/YrgrPMOp8QzA/Rut3sMeH1+KZkD/oHB49+4hCBxiRBMKmAUKJgdWXk3XPH6Jl7TxvIie18pBE6kBRjjPs8tAvM3HMkDi+uywob21ZoYI+F275c6B2lR4zWlw1o16DNfKjEjAQMA4GA1UdDwEB/wQEAwIHgDANBgtghkgBhvprUAkBCAOCDVYAkFUQgtxAwNABW4DGALmrlSY1X0WFTZHpo+tYCpH7/J0Rd+vE6rjJ3lFiaRh9tarxAVN2bToM3QV1cETMjS4rpkkVUMSjvcHreBixdeYGZAR4Us/cG/UjrOV3uB1R4DXbZH15rYB9DoeJJXc/Xbe4yJ5kuq4+cDDqTf+yLwVbIbH1moR/woAFmIxeI4xRF3vRsP31vsBJEjG5etA/Bs2JP/E7TuI4qNugGsr4+vW8F6Kzom5g+AvMoTyUR9ekSXMGRQ/45lzBUxwMMLfUrauWUjj22s57+WMMuErddV54RMZ0Ikmg1FSGfOz0lwIC2IFME/gTwhBMfrMnHKCF8E7fgOs0Nq9aBVQ2/UnHD6TisE0FHUy6XvJjnOJUPZ/dlCGuEpI95YyigfJHyRVDJhduwPvN8J0YAJ0I7SmG8eLp5UWs4P+WmxrSW/GnSkdKQ4iJgUEB5tvKHqcMLrazYu0hox+LBvPfd1mpSaBlFb9JeidzpctFnPnxtIPrsPHaV3q1Dt09NyctqnMaetW5H+naSL0OWr4NnR2NbPBPkcbdjnt2lbtaVSRtrKgXYB5rCHFqpoAsn31YllFE8i+b6UZQK1Q9GggCbryhHmeYPAV/dKjKGGl6dZdNrpGl7OWi9FrGAgoZ3v9Sc4+hzNHzTf2L8dcTFuyih1P/k0n5MQNsxGNjnt5K0JSM2pGLAQS4r+Nb7fBsgfrqFAWzh1GM2qiiEvcSn9j1KnA3VUY8k9+vrnXJZOjDCA0pbpLX4Qngop7sKHiRgWW1gaErUX33D4igDsGNV5sqNg8D1DDGA+EEvId+JTVcp5SBRWTpshWC5jXPfMrkM0JY1FBnT85gMAMpg1bTcuGSSLPGvq016n78EnyGsOeLUABGY1SWEcjyv/BaEJTPMGbwjMvieZw3LhWjusSKr8THOBSedJgapxcL39vky3ZrsvDoJO4sMzONZqyWO31lqk+VNpfvUCugjew38OWMTeh/GKggGZWfw/LaexsWfFVk2xQxAwa7/3QYsafyKmfVeLNx1Kn4w7ywn//M/mMT9pWbB++VFUxeur+sWn4kmM2I5dmIkMI2TK2XwaA3SrugSuSvohkDf3OD3gJx5l/f4PeVqU4o2ZHzFXYufvtRuVeGNY3f9e9NrhufqmIZAeWGyV8zWxREnWF6nNc9kR4VuvW1KUlQ2H9LJ9dEqYkkY/x903jZCGRjV/NH51I05tw5yDeNaNjq42ixPpjXzvhLgEizC4mbp80asQofezJ2a9kot/45epKCgmDSY96RfpRF+pEEr5yZjyOGNy1qoWuIhgG59vgnyAFt53iquOBvS/grLd4riwtngJrG5GE6F/OGhlI6/Qv0u7iovOeSESanxApzdv825YpQ8rB6ZvY760KaxSolLKXNMH50a1cz6fwV7kkq562mUmOdcKhGu56A4kQNT9KasURcQPiia/HuTKZP2hu9tSYK/6YIbCCtlb2Uc8ui1io36xcRJt2ik7kAl7c6LjqzPlr4yKev/Ve/e89T9V99E7sl1sL9IUytkl+dRWpNVzFEvWZEdheMzDdY+Dzr1WjYKBtYDTksW5EsMBZsp2qh45MDastSwr0yCe0iqj5IOjw8DjOzmGtK5eH+b3F6CshxQifYT5hNT1z0XmeXfBoo6S+74QE2tZJmvQ95akUojUNPe8zQk1xtoqRRHMwLdv1jgED4AqeSHI+T7yJIeUZ+0RN8dlXKWrYNwA6R99Wv5EUG5JagFbo4W8Nx92sL/DeLlduzxuazXSkAJ+9J/oymAC1MEZ+sxxZJff9E9zbImWup0N3Nsam8+svIAiGvMcPR0ZVmWDj/ixY790NbQWT6ZxmBESm0/hh/YrvJ/1xJUFTiX7WV8o9ewUsvqX+Y1RasDehwoR1efn+21OI5QMrLoltIfHIuM97ssUSKEEG4Fx6QGOUb/+57LvCcCT+Equ5Al7Dqaa93bjFrWMgPRWoNgaxVzJEHrhUTYrkfYPEc5SLdn1Zab6P42mqWSHSL6OK2VceW1INa8sfP12Y8g05rlf7cqu6uEcBPPCIyjuxIBg4bUwHa4CmqRVAdkOd2b5cApXVxIYWqdnMf2rLPx0OhnEnApck3nVzAW+gAJMtnDZHnXj1m34fnKISDM7Fq8Wb+WVfuaekq8DIeuRHmXopCtb8HukmZBz6aIJRWuV2B5pqBNwtREKT544wURXbFIL4GlCPQ7xzdeN0vTWgIrT8n0VIOtxq8XwERqhpBkKVdxUE3R5/v3srvPrby/dOl0YLvZQQjoptqnrcPpfXa5ahC35lSMxlWGdD7QalJ3wlTyLrIx5UN0z0nrO8rdw2M3n1+absdjEiJbfHZx6MDIw0vsWPXmpHhw2iWYmwQ7imELJzGBmVq2gKYYhyyE84gC3KXccv55ChUDsGs77kMycHcC6n3NgWtmRdshRFjk2JKdF+CLcCb03carPKNtgSvRi7Bc8MQL5IO5vMWn8mgm89ykjtZ9i/bkYIB0VDpU7hzVTnpw4ePuUUT+/RAGrJM5+7D8nmJlgqMxpK30VFENctlL5suviZRMpmvwf/Ii/5HmiAhJIwBCnjZ7YuMw/iF7Xwdc+G93kQ4h1+VTAvgz4MddurXd6XneNZY4lZDr7d7k5ZnaxngwmWYUI0g+kNqctv4alelDQYNiWIb8zFsoAOBZHzJnyuZApuHgTvZFhxep2DkJJL6n3hKD9UF+Gg5Rd/OeNx16jcP+Abzh47PCyrcojfveLDNhFSE8MXF0NiCy6amW9brf90/OCzKPtsbhIRzKUFLMQx3xl2jJsmik2kq2nvKcWuXDmC8TN3Vd2rq5WtVfOuycP4+cgVz50SvIIC+W9S8PzTZccV9MLTxBFRnXCLNOvTLaj9k/lDe4/IuWeNodI07Fndrro+AfFIzo2S8Eo+RbPTchYT/xmqdtYS7E6caSv0fpZAXldu9xZiPUP8nwHSGl149xM19366yvydNOXPIdmTiKVIgb3ZSm7k2Gqi8cbpCj1OF0DgDXKCvC22ji7uqLhc12jo2R9mfamOVR831B0v/44bjoE70xtZik/N2j9e4/M0Wh1K+DXxMkPg77CJPqYW7lpkQLm6RiOkboWLXAe38aU8K70Uco8ZtUaejneROO10nOiv6apceXsiae6Hmo6XjLaX2x83o0pga8ybyOpS8mM6tVyhgGr1xBXXcgUOx/6aux0rT/p5ZoabWbtFWAZUn+hnFVMIuHApiLVU/WUszL/ZbPYhdUGgTfUi5OYh4D7b6rSP4J4zsBYMAGkfXljWrbu/QA+hAprrZBDcPMmfSci58WNOdBYeVuejG+J8u2aICRjwTNkX2VRgPlRFLo7nNcG7A7HVk7/phqKx8S6bSthotRrTHoAiCFVfPne1pb4Kdu2ho12BfjnjOJZnPhpOgi1nN2jpdSUp7NyVepQW+YJDxrRYdWsdVBYZi7R36ZSC+4wm0UTrf+RYwSRECVySO7Wpk9674u/uySsVIlSJo6neCNJk2zXhOyq1e1jF8q3HdNE5RNFxaZKB/jLaSiZs+my+LgAwpCVRk0fLmr3KomjvNMLsLZrxIqeAU3SL339pTsEtWlSJ3ZT5BfGQuvwVSNwwskQDjaUitMLSjBNjLwg/wBtyy+OT3OddJc3goyZTVbYXZt5HFB8SqxUUOskaLv9g3GMt6nPnsGTlc2vxGkWTO8Hl4geWs2nVsPIoLnZY+agJhO3FeH+/bt013lmhRhk9TC0vPP316NbZrx18u7Z4CmgGfF6XA73hkcHwH8/aAhNGRd2FLvBYXsuigAtqBoSD8fg9wtFrW0C2XeXUQnT8Gq/R0hRdLJKv6MYYfgAJWbr+Bhw7iX44TrWuRS0pO443710JK3mzAbruFb7j/NoVLcD3C6fWMZEaTo6KjDO7933lKMnq6wz3ztD/OtPyJBE3hm/qgKXGCdLU3nHjYa9W6izSaYtRjGBal5IqrvOHO6DXdOofCtnTGLwLDqdeiJFinyxJyMmxkqHOumEF4ZxiEYclmc4ua1dtus3huJxE/E8lgAycE58HeQLG7T46oBSRLa9fpGs6gFDs36x85L+GtNhQyyF/Rbgpu56fc9NqcAE0KjZzPOeC9ZXe6dzo3QI95LVKPXdKpNtqiSV+hVN5OU76hBkvm0NsELbnZsts0926brwXDXrLEQc9/u+L59ce+565W7VdS4u2uqjTJXytSbuT3YME9CO01MzfGnrsP73zhB5qqbcAmhWJqP6rfIMcdvlUG/m/D5cd0P3M5K67TkMQ2NHi2hwKoz8Y91aC6S0MWe+4uBR4a+DqMaT6p/kdbF8nyJWrbD5mNmB4SFTAFHc8udweD3fE4o6qeniQ+euLZzoIUYECd/LyDQmlbgAN5e8zjEhZbiIq31dtinab9IlV1kJyj6V6MIXuRz9HzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFDREYGiAwRgIhAL+D4vDzcB3ZM/xvB3yxe9W4tnLOTEADX1C5ZNTSkcHRAiEAn6IRC5L8fjO/qRDVeI5zEFBUFi5Mnl3B0uou9NUzUoo=",
- "NCfLco/gqZ46P6/5N4Ahw10pB0VjEju8zg0hgMtAzikwdwIBAQQgDoZCamJZUq/PovJ2AUb4AsvXIU3/DKqbnKFg/AIUIZmgCgYIKoZIzj0DAQehRANCAATCpgFCiYHVl5N1zx+iZe08byIntfKQROpAUY4z7PLQLzNxzJA4vrssKG9tWaGCPhdu+XOgdpUeM1pcNaNegzXy",
- "MIGuAgEAMA0GC2CGSAGG+mtQCQEIBIGZNCfLco/gqZ46P6/5N4Ahw10pB0VjEju8zg0hgMtAzikwdwIBAQQgDoZCamJZUq/PovJ2AUb4AsvXIU3/DKqbnKFg/AIUIZmgCgYIKoZIzj0DAQehRANCAATCpgFCiYHVl5N1zx+iZe08byIntfKQROpAUY4z7PLQLzNxzJA4vrssKG9tWaGCPhdu+XOgdpUeM1pcNaNegzXy",
+ "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",
- "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"),
+ "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"),
new("id-MLDSA65-ECDSA-P384-SHA512",
CompositeMLDsaAlgorithm.MLDsa65WithECDsaP384,
- "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",
+ "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",
- "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"),
+ "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"),
new("id-MLDSA65-ECDSA-brainpoolP256r1-SHA512",
CompositeMLDsaAlgorithm.MLDsa65WithECDsaBrainpoolP256r1,
- "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",
+ "uS3yQiYHUwJmfD3TrFkFNz6VHeyqvlNZeUAREz6DwrimABMuMFaeGzoZLpc8H8W1zEc4FXrGFTCUtb4VjAuCtWqh4SyFJkwcKdy1JtooFh8Rb3TGfHaC3VqpGEOna0NS5eyXG4erl9lwQUjNNxvM5eVXJqJKO4niSsFQgC2SDigh/alT/1E7SjTuM5HGiBh2Iz9J2Z+NjwSnrnNAwf4pDTLxgpeCEoxvMT8hmyYv/M3OOiqIOD7075RllXtfuSYJbOwEH0Q/yPfgXmNLE37ULYkuL90yUhBy8GMDqjj1xlTJYXZvYmFXFxZGtwEzVsCrQaX+kd2jVHI779oa0d3fxnxkBeGKzSU7yts8+aNTZ69qm0vQL59Prc4FMt3mQ4aFt4g9pIHcLT1xGqFky3HihOKIPwnIzjqzqGctTRcu30qhC8Qbdl6QWmw6EC2SCaeGfb8Bib1Ox5gFuXGS/A7BXI/LVw5oaGeAhb/jyZ32R1gYPWz1ghSL9+gepg1UIeqLP69kHvNStPOKs3wNPf4mYtLpPixXZ4rOyidXt3PcbKdKq5hJ/ECU7k9nT4HBKIVjV9eLMWDrO+eMN5y5HvIQnDH7LfBx0ubcX4TBHQOSpHqhieYO4GNBMYY8bigs0KGxC0r7Yp/fGlc937ZV8KNyoiyNV2VrfVmiD7f9+aeZMuVWQ6mo0kBrndwwS9MrKnIO3ew3VDoJy6mE94i3ZFrFVYlnR2PtN1Crwcbz3aM4bpOWBv3pjQvW8Co/BdrJZ0Gy+H0frx/CAznznpcmtRDx6uPjvQPAaqHgDBsFyNqzfIhPcoS60cGqOCQP2dfBMToJ1uPGKjZrmEbAMoWFMBIwj6s4rTivXw3fdiT18A0MYT1/jHMli8qH8M89Rr2KKMKHL5T0cyf6b4ukxyiXp8AD8lvMty/UX9KesOVVr+for6U7ra1n0c8SPH4GyaRr7DV4SyZfe013Is7h3vv3Innvb4zMaKsBJza6AJEQn4mvFkz9INtBzw2asp3juhTLSRHcWlFjDIOIrTwEoLWV3HfksGj9NVsBrKH5Y4XuTU1ciCKY+mW+9yBzORD7YcYAs7D1eFOzqE/3CPQRvUg4qOm/GuGwkM74QUkuTyAE8Xm4awos5Qu2QWzQeWpQSQkAjiHPO4mpa3SCMh2dcjzctW7g6UUBDI5J1B26MFAApjolLIMl0pjgdt6L5c7TFEa1iuUxj27fFHqMRLik2WvqkX7X4G50ecNwY7rsue4+7DxD5SJTufRTY4EkNaThV6uuMH8NfBElG4qMl0UerG9Ax64iNAadu31rS76wMaaiwWhkmfM6T7oStWxGJPQCCQo60ycLZREKpQi+usGZwL1r8qpgxMrhwFB9ctiVP0MocrWWW1+Bo13kI0fh0ummpUlvwNW03LriRL7hGPjiDlpQGk3OfwDjHhnNPwkO8eUH1xhkHJsaxd2OkNb+PzC8UhvG8eN+FmovwkFQdsS9qqRSaOjPX6tQsOnzVtAyM5/uV1OEMWQ1Wfka4LdgF9uUL1OBC2VlMHil3J0KaRcpBWqcalgHHuuYe9uf5vMPHiMwgTob+mtU0QR+Knl78oSXrgs5bQ0u+v1JblmusknsJ3mcWdfzUdowB4u4eC523l/fhAsA4EZlCi+76HfNZ4i2NXYafUoNcdfl5qo3M2g1NA8HcsFO6S5bsaIgYMzPeXEErqJqXG2KWyZ6sek85nup0xFnVw/tnBmR9CTqxgxqEjLScZyPTUmQj4+5hOBCVU79R51ZlZcbKJ+W1M9v7yy9lGwnyyGM1LNleSRSL+hsZOuItNSh9pBn2AHrXpGjwS0jl1uoevFsUy5el4/BBkUB5i2FVf+gXkByqPci/3/OTqEt1qP2cSHy0Moc5EtqUHxgg8NG1XH/Q1+AlESJ9oJ+VcwWusys+rhi1VIICs7u6PzRrYH/MkcnAn/PpzkUJI5EjCDESDYcbdosmHh/YOONMf1KVOWUpMe3doxyqwd8gpDbc3Fd23UqkcFtHwd8fEPNxmAkNNqmug+d1V5yJ8TLk58ph+3UeyjeWP34Qe93jW+Bk1iTwlGKeMOazLMOK8A/v+gI4jXMnkhaszxD3xlofPgoQ0tQyVYPOyD1gC68j/t0rqoY3d5zadMbCJyPNeNkVbQD6vcUODljH9MxtHXvOXUyEYKF79hI+zhvVWUknAYnw3WNuV7bUu7xNwYuHX9Kh/epgHxA36PUWE2iZBeABSblTRWrjgUL5EVKlH7ziH0V98UHRSxAq1S6Zih4IxVUsoXa3rzgMKcLAGzC92P8qAMzQ32w27ZlsVC5DlBtlgeWK2qNTfAKgQG/gIqC6CsTv28JcsBMGzTqUxKbytUdItYMBBnvWO3GwANfVVJ6sGegbYkV+KFcGstIR318PFq72tUmPNEKulWMPMsWumSqbF8e2HVRd+mALQqAAU8OSpf+LX+GXpujR3lKYukDOjjSk07Xz0CocJ2MwESd3WouBBg6F8q1DB6TM03rGyyWX8hN+N2tpCbJFS27wRGVrQEFIbuq29Vq0MlfsPGETxxDF0FrLaOVP2YNjQP0fmTyfhbadMKwCzBkx3h84Min8aq4TiZrq44Ekx7mKgU5v9Ge9cRAYG5dZ3cZ7dmBf4CgtYeJYxAHdT1yjyTrGZskibk5/nzxj8oW72qc/QejEuXCXn6j6Sm/cw==",
+ "MIIWSTCCCP2gAwIBAgIUEQNK3B/tFbvBo/ySSmGL6z4KVucwDQYLYIZIAYb6a1AJAR4wUTENMAsGA1UECgwESUVURjEOMAwGA1UECwwFTEFNUFMxMDAuBgNVBAMMJ2lkLU1MRFNBNjUtRUNEU0EtYnJhaW5wb29sUDI1NnIxLVNIQTUxMjAeFw0yNTA5MTgyMDU4MjlaFw0zNTA5MTkyMDU4MjlaMFExDTALBgNVBAoMBElFVEYxDjAMBgNVBAsMBUxBTVBTMTAwLgYDVQQDDCdpZC1NTERTQTY1LUVDRFNBLWJyYWlucG9vbFAyNTZyMS1TSEE1MTIwggf1MA0GC2CGSAGG+mtQCQEeA4IH4gC5LfJCJgdTAmZ8PdOsWQU3PpUd7Kq+U1l5QBETPoPCuKYAEy4wVp4bOhkulzwfxbXMRzgVesYVMJS1vhWMC4K1aqHhLIUmTBwp3LUm2igWHxFvdMZ8doLdWqkYQ6drQ1Ll7Jcbh6uX2XBBSM03G8zl5Vcmoko7ieJKwVCALZIOKCH9qVP/UTtKNO4zkcaIGHYjP0nZn42PBKeuc0DB/ikNMvGCl4ISjG8xPyGbJi/8zc46Kog4PvTvlGWVe1+5Jgls7AQfRD/I9+BeY0sTftQtiS4v3TJSEHLwYwOqOPXGVMlhdm9iYVcXFka3ATNWwKtBpf6R3aNUcjvv2hrR3d/GfGQF4YrNJTvK2zz5o1Nnr2qbS9Avn0+tzgUy3eZDhoW3iD2kgdwtPXEaoWTLceKE4og/CcjOOrOoZy1NFy7fSqELxBt2XpBabDoQLZIJp4Z9vwGJvU7HmAW5cZL8DsFcj8tXDmhoZ4CFv+PJnfZHWBg9bPWCFIv36B6mDVQh6os/r2Qe81K084qzfA09/iZi0uk+LFdnis7KJ1e3c9xsp0qrmEn8QJTuT2dPgcEohWNX14sxYOs754w3nLke8hCcMfst8HHS5txfhMEdA5KkeqGJ5g7gY0ExhjxuKCzQobELSvtin98aVz3ftlXwo3KiLI1XZWt9WaIPt/35p5ky5VZDqajSQGud3DBL0ysqcg7d7DdUOgnLqYT3iLdkWsVViWdHY+03UKvBxvPdozhuk5YG/emNC9bwKj8F2slnQbL4fR+vH8IDOfOelya1EPHq4+O9A8BqoeAMGwXI2rN8iE9yhLrRwao4JA/Z18ExOgnW48YqNmuYRsAyhYUwEjCPqzitOK9fDd92JPXwDQxhPX+McyWLyofwzz1GvYoowocvlPRzJ/pvi6THKJenwAPyW8y3L9Rf0p6w5VWv5+ivpTutrWfRzxI8fgbJpGvsNXhLJl97TXcizuHe+/ciee9vjMxoqwEnNroAkRCfia8WTP0g20HPDZqyneO6FMtJEdxaUWMMg4itPASgtZXcd+SwaP01WwGsofljhe5NTVyIIpj6Zb73IHM5EPthxgCzsPV4U7OoT/cI9BG9SDio6b8a4bCQzvhBSS5PIATxebhrCizlC7ZBbNB5alBJCQCOIc87ialrdIIyHZ1yPNy1buDpRQEMjknUHbowUACmOiUsgyXSmOB23ovlztMURrWK5TGPbt8UeoxEuKTZa+qRftfgbnR5w3Bjuuy57j7sPEPlIlO59FNjgSQ1pOFXq64wfw18ESUbioyXRR6sb0DHriI0Bp27fWtLvrAxpqLBaGSZ8zpPuhK1bEYk9AIJCjrTJwtlEQqlCL66wZnAvWvyqmDEyuHAUH1y2JU/QyhytZZbX4GjXeQjR+HS6aalSW/A1bTcuuJEvuEY+OIOWlAaTc5/AOMeGc0/CQ7x5QfXGGQcmxrF3Y6Q1v4/MLxSG8bx434Wai/CQVB2xL2qpFJo6M9fq1Cw6fNW0DIzn+5XU4QxZDVZ+Rrgt2AX25QvU4ELZWUweKXcnQppFykFapxqWAce65h725/m8w8eIzCBOhv6a1TRBH4qeXvyhJeuCzltDS76/UluWa6ySewneZxZ1/NR2jAHi7h4LnbeX9+ECwDgRmUKL7vod81niLY1dhp9Sg1x1+XmqjczaDU0DwdywU7pLluxoiBgzM95cQSuompcbYpbJnqx6Tzme6nTEWdXD+2cGZH0JOrGDGoSMtJxnI9NSZCPj7mE4EJVTv1HnVmVlxson5bUz2/vLL2UbCfLIYzUs2V5JFIv6Gxk64i01KH2kGfYAetekaPBLSOXW6h68WxTLl6Xj8EGRQHmLYVV/6BeQHKo9yL/f85OoS3Wo/ZxIfLQyhzkS2pQfGCDw0bVcf9DX4CURIn2gn5VzBa6zKz6uGLVUggKzu7o/NGtgf8yRycCf8+nORQkjkSMIMRINhxt2iyYeH9g440x/UpU5ZSkx7d2jHKrB3yCkNtzcV3bdSqRwW0fB3x8Q83GYCQ02qa6D53VXnInxMuTnymH7dR7KN5Y/fhB73eNb4GTWJPCUYp4w5rMsw4rwD+/6AjiNcyeSFqzPEPfGWh8+ChDS1DJVg87IPWALryP+3Suqhjd3nNp0xsInI8142RVtAPq9xQ4OWMf0zG0de85dTIRgoXv2Ej7OG9VZSScBifDdY25XttS7vE3Bi4df0qH96mAfEDfo9RYTaJkF4AFJuVNFauOBQvkRUqUfvOIfRX3xQdFLECrVLpmKHgjFVSyhdrevOAwpwsAbML3Y/yoAzNDfbDbtmWxULkOUG2WB5Yrao1N8AqBAb+AioLoKxO/bwlywEwbNOpTEpvK1R0i1gwEGe9Y7cbAA19VUnqwZ6BtiRX4oVway0hHfXw8Wrva1SY80Qq6VYw8yxa6ZKpsXx7YdVF36YAtCoABTw5Kl/4tf4Zem6NHeUpi6QM6ONKTTtfPQKhwnYzARJ3dai4EGDoXyrUMHpMzTesbLJZfyE343a2kJskVLbvBEZWtAQUhu6rb1WrQyV+w8YRPHEMXQWsto5U/Zg2NA/R+ZPJ+Ftp0wrALMGTHeHzgyKfxqrhOJmurjgSTHuYqBTm/0Z71xEBgbl1ndxnt2YF/gKC1h4ljEAd1PXKPJOsZmySJuTn+fPGPyhbvapz9B6MS5cJefqPpKb9zoxIwEDAOBgNVHQ8BAf8EBAMCB4AwDQYLYIZIAYb6a1AJAR4Dgg01AAyCjuWjAppQM2UeNL8mCqISHC3PqWRCzjy3bE0ZGBdjyN1v3E0dcBx1l79WscdTKCDFFOh+xgVEtjRxIwv/Sxi+8BP0iSbMPr/wbL/sZaMB2n1pgCYwPd33azmHMBNyJKffrJ/12AiY0C3qcJwTNuhTZNw6lC4s+faJodxt31HJS7WXy+DBSsHt3BxPpLXd9EkkOK3bYym7uK6fKBxtU3h6HPSZeCK02k5pkV9+x5gTdz+m4ljBXgMvOEptoBAs0BQyAbX0ZECilZ5VWuJlm/ljAlP4ja4+ZeVueofr8AIlwq3emEyCxhcNJBTEWlpabhPL2uL/S0qgZtDSjzcPLAd8U6ct4ogXybp2u7bW2aBsd0igWShe3EHmjOvQdomK/hiZCAIySh0cZxP7XGHjCR8/SG+gj1xUIAXQGIsBqmqWHeiiXzZFmWV4Uqkh1HFSy4LGIeh9qdaIJDvowxMvCBFSzcDrvRiyhjzbHxv7e9CJ+1LkH5Ogjs+vjSP2ga9K1Kxpn4JjXYV5BC/VNpNQpUHMM2t35wytI2VGp6WnA9GYZvYFsmp46ozAudCAca203teqBKjBSMwQXkKPPN0dfEsFLbF5KG7zT1egAy+SPl9knIrDg8O43MXTt0sxO7t1GGFqLHMd6x3oJdxS+Zehw+EIrjVzt1M8o5drgtUYfXIce6EH8YgO9skpnS4/Ng68iri8h5cMxJanx6kT8KEQmEhjY1Zgfe7Lp+SIQd/vnxUEr+tR6q7fguTrCWTqX1ObhfXoEApp4Hb860ElC6NIr9+gC167YeVYdYaYTDngY4nTftkWdTDRIoUweJ1sB5EKq+kpNcm/Ufl5aquy+LiggFBG73dxLkZCErRLfLolRGSe+nZ2t7RpE3Z0rfvCv31DChC9U1pi7aER5aUkWZUR86gQRjNIXIeqoqdFbnSvXZ7YE5S7LnL52XEk02836y0r3g4ADd7ALmWenAndbSNn9gS8InWZXtHyq8bhCcKI6L6+hfpEqdNEIxSdBFI+heDdoXLxZNteBQwUR3cMFp5DUDtd93W2mGGiqUfMvpCYsum4SOo9rKBNzHvGinbO4QcBpgyCJHK+c/JORM5tWcGQShQLFvKUCx+L0zZyKQFW8JfAlJ7O/dHb8RwtwDMj2racNBD6Ueki+fAyU8jgtQEIZaLM19IIEI2+cM43IDPhKjjJLhFYLuvXnHp1unUDl29/4heDGk0Z+uqc+x1oA4jbAWIhxhhbuWnp5msGktxjw8LbtrfgBpZ3SMhb2J/BpRuzfcwApPMir+1WZqnYrguyF7w3hBnTr7jg3Ub5aHbYgyVXdMZN98+1NCMwlqNjor0ivArUHSz3B1olWuFibzWNojQZ7y1qvhzNjk2Yx5KtIddt+ZYfoCuhIfT8IhnFYZJCg53EZXbtaJ/pYWEjoRy5CcfNTGE5cyFwEr3GZVttVqKuEdQzEMZjQ8ojv5NuY0FERM78xA2DXQ8YJYVp1IKAXX5FcbSIw6ftA/h0urZ7nsdiuN9zrrvwu4qeaooAs97+hNyy7PU363ek1y51qokCtyt2hTh84F77Gj26nfOlCuhS1C+/Qdr9efQqLqPAqhsKJ2AAqrxh9Mz9+kb0D9OGLeLvI4tne6WDgug6r0fsANH5O1GQafWw79LbqhuAxKY46gb9Ug/C+jEgwzSnzMf0vjAZj/OvS01vnuaLsBYZTvqRUdxt++fbcoYnMfDh0CT7yT4bkS16bcfrI22luEozEih23Jj2IX0ADg5MoO4tty7dt7+LxV/IkNWh7oy6Tvi03J1Pdth8e4vHD1cM1kZg6EMJGHncU85nhO6CL8aduLMMW3HayRwO9CAtEpe5+w1laO3lwesOkBCXyur+JG5L+1eNg1gogk7S4sOqikj4f8xdn6UBKk3TuDKT+3/JqHP7Bri+w3V8SiqLChV76ljFhI7slqGpfJVOAgELtmSMXPXd/Zn1oghvYSMVpC+s2J12c04zeLMrZG4Kch0UptLt1FxalkVcsOB3V2J9h/1dokGBGRtGlkuUgwKlVQkzXcfbiKVfL5Pdr1wzBSBtZDaRYVRA5UTikd3JDTve92YMJupQpTD+N2TZf3HnjnAIWh8h54gcshSRnUkC5IXCj3eofhCfQrXpQOuTHlMa7f6JtKB3+M0Khccvv2bWicNYlIxfLEuvOvzAkybIQOvbx4puMzV2N211SmU4OCi4waM/HFgabir48dwaFUfLaeSlqHBkPXOA4EPd5sU0arThOFKh5rxzNAxCNb0MuHDpNmn2q4LwhkSCR57r/eEh+exrJaBZW+ytCtREsFNHIOw9QMj9R3ETamH+++7K/jGSzw5NGor4k1jNmTSK1AxqHq/wBFmbFYXktGV40wHdTKaRAD5gEfQSnM7UNVN1Azo6wBpOBFRWL/zyxAz7fk2g+xqZvgP+xT/xIUkiXKcf+YZr4tbKhxud+z1WQg2B1hKcaOzyq80Sh+NxTS9sJASOR6zAdgcOYBHxaKkLG1FJX2QT/7QKFw5+X7KZPQlWGBuolo+2ARjrSkzShzwUbauduQQrhz5uE3aAKhwzWmZDFmvGjYTJtQsq3IkWz4GTeVn4UiLjzormgAr6QU47pQCf3ODC4Zeffxjq045MTjsDDfs+KBw1NfFz60NH7iCdCgJ5HcwBSO3mOnqQ4h68BaRi7ckz7mr9L2diiqL/++KL6SjQ3io8PY0L1XyQv+LQW/EVGuY9nIFstldgWxle0+CKk5bSseJyNw3ZOjiys4xhj6VjTk6Xl7On/ZooLP7fwNFpMExpEPZ16ythWheW2/hoTCTZxom7v0gySmGPPDTDn6z4C+PZ5SxE48nn/3u0eDURETTboJv2ShJTPiLNBgxijDWKMfWoz9NGA7Do/ZZuxrOZcUYP8TAHrRzkvDUwLejf1tBB+Z1BL0waWUsMtr+EVj4LYOlxCsBDG+Ex/0wR15hb9YbngxU0QW2sFHFiZS8xXJBKtW8DpIIPX8Zd/2yicC5zxGwhiXuD1qjjSXUBMZkzxwlMTMqsZFKhabbtz2Sv3vnZa/0f+C6elED3q+1BSQzU/LScID3+P/xYV54GwWDRMi1GktFPFhg/MqiDUtqgM+y2nb9wsyELWT5o04s7xsdC1lW0CmEQrN1pOKuQ70B0WmpYEHZmWOHPrSal3s69uJTxEuFVR75xdxeIldt6ddru02wtCQRL3afAqSExpFsMsvh4nWHwc9Rtr08rAfMFHQAWRiND6qjD3rxim+XAmGEsKcEO1L3efRtMVtQhYwF9ZDOepxS+H46SDVQ/ujtDB/LIzYA4ZwmogHMNblqQfnmIKXQo8r0q5I0nFj03P5Bnsfg/RJNhQbL3ZhyeJytAE58t/++ImiUXZ1UKBx8WHaU0QKyCYLKQO7LsnBw/GEdc7cSnFd5PZBEbfXylUdmJ1aPCwjHfzc4+uy3Mr1C6hv6z4di1iA1jtC9mzL8TjlnRrpvkwia2JHCug+vqCEKY8ALJ2OMq69wj7CATqghhPAiUtbnbzi4Uw+1Jzvq+slX/aa62gvd6gGfyOYuQ/ygT1q4V13wkBUdr5sl5+Eu0lLv9Zuvi6mx11EPJSm24yRhFP9sG4rYfQIV3D+XU6RSP+hwQZz8dhw6WNJncjBymJ7vJ0g33VFzH9bhr5bqimiIQu/zieRR07frUw4gB8hqk0TSut8aTPp7pzo67UVGqFSJUvJ8lRiY4ngH7Xjee8YwQG/1TUctqdQ2Fy6q+r8f+3R05OZR9nLwzJq3cMUyxiemSE3XZQUnblRBGIcN7gBA4l3Ih9HAarvjBeNZFDm4QT0LyuQ58aVt5rrOZvZnRsCiPQ6YkUyZTuR/8N29jvyRzMxUtHa7ekm26BRo7+O487hasRhKt4XMckSCRmB8zxVZgMJnx2ZuDI5NXzHz1JXa2xxAfqrA2Cd7Yr+IC4SgZIxFBelqMk6TomC0V2WTADUrbZj43+qyCszTWLd5Ieyq9y1Wn6yZlYZygjuz9wUaKNnU4KZV0f3h7/WuY3/FqtuN8x0KKVYRTmK/8gAbdNpQDBa44HxPIlXCTabODLrPGDnLUMBslWT2yOG/nI0sUcFpL6L1f67PGpllJXPJ+ewrtE7GHl1V9B2+Bw36JDBQ/yn90T1ha5BT86wAJ49C8QYZk0Q+nh4wJOhi8nJPkcpB+rQv34kQ3gB3fmoJgq2xZcrKsX3a+IeA3C9wkoES1fbW1scLfzz9rdTeLus2MVMlypSbtjrqypgxJU2n7DJPb9LmTJLQmUev/TeliL0W/RN3EpbS2HnTGp1HlUduDsb1o2hjlxC5qotPHy5tKy3XEK/kq4BnRNVlapLK1uAEJNlSfytMuN0Nkdn3OF0qhvcz1+kKBhZ3D3u8xXPgAAAAAAAAAAAAAAAAAAAAAAAcOFRwjJjBFAiBkpFLRFWOu14vj22ySlPyhqbWmeOXVyVNK8g2z40YEKAIhAJx+X+RQZG62yS0OdJBbW8/MVaS8qQbYjMnBf25O3OgU",
+ "7fiFEk6AEFdqfL4IkjrcxBPjJMHrywKRITfTFiYsCvkwJQIBAQQgZxuxzh9rmPqLJY8JblineAXnfkDFLSFp1NAp8fAT8KM=",
+ "MFsCAQAwDQYLYIZIAYb6a1AJAR4ER+34hRJOgBBXany+CJI63MQT4yTB68sCkSE30xYmLAr5MCUCAQEEIGcbsc4fa5j6iyWPCW5Yp3gF535AxS0hadTQKfHwE/Cj",
"VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZy4=",
- "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"),
+ "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"),
new("id-MLDSA65-Ed25519-SHA512",
CompositeMLDsaAlgorithm.MLDsa65WithEd25519,
- "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",
+ "+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",
- "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"),
+ "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"),
new("id-MLDSA87-ECDSA-P384-SHA512",
CompositeMLDsaAlgorithm.MLDsa87WithECDsaP384,
- "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",
+ "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",
- "FFLDJfvIWWcTvNL790AcyaMUObAEpNXlFztIPlLwJBfB/t42omzsge+q8mj41Qu1JDP6/U0qERmqHIHrsDi1IlJhjZCSuV0u7iV8dAelDPCuDG04+Otc7omuaX4hNdGu5kfneFFZE+mNqQslSNpCfzTUGmA0qengF6YCLEbiVxgT8lw2hW9Ett568BTdLEADeGPyjxaJPkt5E00TgdGW8SerU24ebF9ucsh/zfzzB37h5NIv6Zj1903YclfeZdVqhmqqoCIhtNAq1TvhqNUM7RdibaOzxW8Ffetq4NynjAd6N4/ZyXrfw0tJIGZjrZKSltiFre6PC/PAvaq9DRyLO6tKcHk1zJ4TXuXhl2g0gsi55b9wH0k/mdGMZkx/D9hRYqOMJkwRxUHxqVO59PIa6CrYnrNTjK3bZOA7oLTFZrwmzzKUoXQfJeXeGQ5FO968ovlNQkBeYTH5ZTCXGHaAxLsU6hOHjLg8g7rsV8m5Y3CEUpid5B9OjWJ3PnNg+VXXGbNF3ejgUOvhcl+0eAUovJj/gGyRZvbai/vc8r+XZN+iXYzHHoIkv3lesZkngKjaDX0YFAMkZwoM37pNxpRtT6l7eHpWMR9Q++XERe/D8YC5elWneCLdqha4McQewCZAR9s4K+w/+ZDmvAMlCe/XPcv3Ytf5zf4OOS9fSeI622RS6WnWtrzQHn7uKmkvm7+dwXCV+R4SxxYnVUEPCl9a+nvkOd4gVEtR0ouXsKauvkwvP7sFhFgK340nus8Ocrn4rUg2egxz5UZxlJs58qyPCy164wq6uuSSEbqIaOyC6FYP972sPNGWvOUpBQP8pC74BZAyjqjT1QSw+WT9udBSVQwTbKBwl9HWZkPAGUzEoaJH1IGkV0Z0/K1eFt1q3hSqeTU0CWbD9GTpJ354VHh9MhskBzjbotjNGcEvvNhd0PICgLk5r/fXZB3G3pOs+1xOW6VRqJ+4tdVKmNa8mlZbImL7GZAk+v7rkoeZz5uDPzMmu5EqJ74JgHL1YYPsSFn7nVlDl2XxKup0uH1y8jgpVrwPumQ/wICjerhUdCruzp+HIERuVuQqqcLBBPLUhOxlznkjKWoRvkndUYTqhvNr1w/cVpNJGmZWEQblItaPim8XT+4h67pyBDSpCr2qGosVv6IMjxD0BFq29Jx2IiBYZ5A9eN4+f8liUKJHL78Ltwx21/j/QvWzXUecjeRbXiwYgCRUDwfvac+AJ/WKG1DOpWEmp/AXDxXHShXT0r4odpl+w3wepMu79XGZBUtH0Ur674S1NdXQmzracP1koE8Tg8Jajcs7yLbjm24LBCPu0Kw4Ma5upuuNyHR5c+LPIPoofpNXL66bz3/mfqXPzL9jK4OgnUYeYSJezcF91X04DqDOB0d1/1N0prwhhNmvJMukQKSz3pU56J3ZfAxuGGsabmBJ+X2LI/90jljlXvPbGH+PDr1QYU0yxqItMUfkU+0QpfWC+mPKV37XD6TnFlyeJ61V68atJUpbnPgGVu9gmhhmV5UICx+CDRryAG+bo4AtF65U+N1uTLURsWgnnbqTybpdcQ3u6qljInqbTuGPtHA6We9J/k01uXWupykDyUtYSvFqoansE6V6hPVIlAlP3oMpSXg0840ZDY1DMtZc1dafC2l0kUKkNh3CfBnaS/VcV/ZaIASXJsqLpcrBZx1dygc5qU83uWJZ59nnhF22Le9GLXno+a0/btdXMbV4gsayjoEOTwErUwwL8SsGXtzFZfNuYQcH2T/1etbfYZgwNHlQRS/3bPOezD6XkyvdazWhkJZ1T/mJShKN7rXMrI0XSqrUP6E27hOyiwcWX7CnXpjXN3Uv1jWyQ7wvdv36jMfRR6wXLt6Z9LOhqBmPaW4nf4JtmXtGWl5FfgK631Es0GwJAJVvBGKiVnjONJNXYi1YUOaBZQjGtKhFBlW3s2gse5P5Bj9wTFmNodtvGOOu5X/64qo8jKD4WionSWqlCh0i3BjUAqWZZOUjP215z4dOMpYXuqsH53CZPrBp4IECM787AGjkT5L/OzNWe3o1qdPwF2sbvXfgMYu0MSTxKXOmhv1af/b9fYIqgBdsT3oZvXwRFlhO/p7Nx+FeesZ2yoOa7ITcAlf1VoHOQDBhplAAN9YDJtN8BeieJE7gMKQIym2DOZtFAYdA5At/vo2CEdQjVG/WAgZ9rMgJ4qS1qt6qaub3WO13wImFzjC59pMfeeALSXWWsToCMsAThVppL5+RLbUEdpKZx+Gm3ewZjNs3jbnIy7pdUmQEDJNA54dp65AhFhTFXZkZ/Meaj1O0g//EQa8Oh4dthDzk750g7gWNjg1sIHXF5K7isM0H2XtYOQ5oxq0+mX6RXmjk9QFA2IddGZ3s3NbgVFpzXTTjNYGzKjN5my0V0tOtbFSd6lgpbUyOR/NdBEZYhWHC1iCc28zVX6bX72ODO+YLnyckfUHtvJ0ogncDwJrXEckPhgZMXrZ4ex7MQY9u+OzqJBew6QJ5Lda12atMJ7Ojy2d6B1Vsqy5W38IdQbqGob97uLULjrMfaFHyI3rmfq2AIZX7oCZcZ+S7bdngj7WPiVfN32ORi3hMSzlQ/Kv2mHjrVxu8ec/lChRtCiM89PDRFvthAyoBkWRxurkPYEwh3OoapUCvo0TjK/745EmtMzVIVJbVkcOmfwjri7pLCZovmotCS1tJAslppmF1TVxJz1zqiJ1eWTyg+AFhzvrfItkofx+y9PobLbcUP/GRiyuQlDPrXX1Vg2EWnB7FoHco6F2LD7n7B2TpcSAYJlLHT2KktwffclVNlBSKeXncp8M8iWkyYgdlqVC1cLj7YN0MXOZ3HkOF7Gja2xngqPGYUjdjTzkVFM2TBU/2ADhjfLjNyS4NdnUilb1t/ef+PIo68lomhYewBqslp2EvdzLo+de5rUIS2wGnXMIgxePZ5UIhEyPmus4LBhLqFUKpPX0HFSz9fKVnkgaVonxN8jaXRRitGTsmXeyKUuKwMMH6EoBHiRYV7OHUqObv2w+KwbR97EjgSr8GHlOD4aVvZiRWpPt6dZMNaaUfHAI+iXXvrdXJk2iHcqIjNNDCJdCAb49yOsSk/DZMvwsk9PAMZvikr5WbuNx+B0G7kAgIwQWkvqtLaipMnmcYkAD9/gEKl+2kkz5xuIfle0ym2vPUieYRb4y8EJ9km0DKxQ+kTNSLjMcLWtJzxymIGcZsc7vnHNgOe2ys6yXgSSXLuRxh1Qh6rFoN3n05WnctgTHTZTa1KVP8DUy5mbiq2/oWBkq4vRIdT/QuQXaRf9ZHHyDWVqK1EJ23yxaXx+VpURyC8lXKvkGqfvQkNtqAAvG4Ts0LwagxNx8Ai7Zw+ncqOIT7e5UaylPiX4ye65yxoUnHNvqcGcfW5k2hK9Yr0xOe0MtBW+v4kZ3SuY1P5P5RFkI7kAPP32SJOTQbByJStz3C4HptMTwlcsw6PKp0p2diley7xDoD90l6asTV6q95Aa/bNxQy1YYzD+twdVgH7EcciMDmvQFGGhahLgyXDcLdOnoWue8Nplca4fa6iNADBhEsoNQipCNqU5zaYWgDvMixx1F1k5FGtKn4bs+alYhdtJ80BU/LFuLXiOGhRIYuNoqPyctTca/Klauu8nwth15nXzk4CZXLA28MFLZx1WGAOmj3KoTCcGnYMeEdxY5OkM5XaEWmf25VCs0lL+xDDwDIV10Zjs6HACzGOMLeOvaMoYBydiA3Peh3/XVXYx9gfMGOm33MNbhjd2ukZLJcdaLYA/4b/M4NCYGHyKPCKHFV0jPO3zZRQicjloe9qOZ6kxVxzOYCOKg04ChjwFdLhZ60ZLsvyJZHqMWV21oAe/zI8cIyA06N0PTEMcFsOmLONaxLVpxCRUx36Ku9PBKAgXoim8+KiN+YKtfAklQy1AKKJM9R8pweI6xAvtndCkIBW0JNyLzE8pj8irPqJr7Mpza+0BH+Qlkfwv0NUwiPFvUvlo79gXLM8L8jgnav8u+oPC0iTs+kzC0fy6vZftSvOYdWKuKhFvG22ApuQiHIECWueNu9NqfjMq2F4dZcf4YOYALbPMoGYj6qexVct1afRnL3QjAHUjx9mQaWTmJ9a8J0MU2fCQbMvdPFCBrAXmlmUH8sL7h58/0Z62VsHNUD5SxSbtTf7V3biWRrAn0qYHq2xB4GHVzh3YaJO5Vd1ZpNXchkryJRKG4duNUDN7kPx+jYRd1SnLOJ8tGVFrZI4zEDJaEw++IaGDVPTNKYZffbYBgrJ6LQWs6nzU6PEOVxDgQxJq1OqcyvoSP0oZcX5ObdbqnlyDa9Ari349SGpbeEmnKfGqXc+gkmWuz2RNlf2fB0bi8REay8So+4Y7WOxuT2IDnPi0D9ghSCjrEeU0+LGf8bqniTpDiIA7q81CUNNR7+wLEB+58zd1rCXUeQ2FYgn4HguTkHvvvFlNH0T+uDMKybyRfqxi7hbydAk36774v3wX6Ox4ghdGPJAX1weniY0zvPdBT5ll2bDWySHGdcU3vybaDmmnxya5h7e9MtwtDAaiA9X+9nj1kdjv094D6H1TlV0PmI0FjZVC//l+wj6s2a4kvylrbdIGfGkPLPI/CvIee8IgjiYOn/HnYyWGDd5sfu1EI3VyoEBaY9YciyODlGhGlySlc+qhFJ2LCAEwzRw8hwD8KQjHoWEBDjGNDdPn7cM2BPEUCzhQrS8NnEZXkqC0b4QCFiSdu/bTH+WgJ7Gns9RV/Hi4C0bjY2SR7D1hhN02ZziwgmciqvqUf6uNVL6Gt2BDrbYUsjom/OD559SLhMFmQ8uNQ68iX4LOG7KuzXF+3e6NprDup8iUG5IXNF/QWG/Rc7XhlQeCGVloHhVAnkJir1Piei+8yjnKKQ9PKl6SPIA9gf7aIFq8cKfnumlr+mSKoHiNO39+8DOC2XhmzHzE/zjgb+kwwF5eVvye+svOjbXdK1DXpzpYxHNMGff+qpoaTMKhNSS0IeCvC6DX63nLhjvh+DLgFXFn7dG+TQH9I/Ed6BeiY/J/8X3PZ+kIYp87RMIYNS/u0KFHQWqRZGPVrvlXU/Ck6sOJCJmmXSKvKn8ep5DW3LJOypM9pIx9DQIVzSg8CNE6QMEwMRAismpDRgizbQ5lqaCIHImn51X+MRBs4gK7vO2MF3bmKPGsMWUPb7SxGbDRWF85zMyeKofsC2A4MEbk2eHX1rowAyfjkaK1UhXUN6cJu5r6UI4fCROXDA2qL+0BpMo+iNofxBTu8xbz9vwEKHquM3rtdIcwLiryD9szBG8XGdjvVHzMiezPsA/vDhakrxYW24iy21E+maf/NlE3aASLMd8RaYBxbn5NvRDXA+YKna6txxyMp4s1x4hAJ0WsypcC6Gzsjnm37FNokViwQlb82hjH8/Rp3G9TAZPtTMcD0A5BJdM2QJ47fHyt+ZMv0YMXUpOKA1ta6N7FD6iRrkltIWPKwIbkwKObgJilHMtl1Fe0BvBYMwkCkW78fdw+lhUhCx/Jl3kB7WIIJeYynEH3wk7vxhALyFdiysrF/ivlBPVctsWDJSeXXdlWtbm0/wL5A+ShfbU/0rEXPL93Uqs9yP7c+laKYEt9Lc2qCHXP7teFbBBhAJgI4a39m9KZczrcTvHJK5ecDBNplplI2pDfyZO2thpUmvShpnWGD63TAb0SLBrDyGbe8oq/z1bbiOgmb4tf5jZVWT+vkArCqvN48fwpGNY5bPJQmFXb+DycgvKmUF0eW54v/BaYCjMUA7ceaQ0nzRZmFvBhWsudT8mFlRPoNxquPXWj488rEEU4uJ5zlfsrFJvBzIQowz7fj0q0hjsAcptjJEWNQdmv+kSUMwwznDo9IZn8ufqrG5rjndahjuiWpScLAYH9SNi8qPz4LhS2TsYOG/jjEeFBPZ7CbtgGn0zKj8ZWalLNPvIA6EYxB7GDavtDzTi7BEhyWqUxJQxO0ANEEIFuxLBEYPvNeD0cj21Lb0T8s4OSYZQxz7fvqYbuS/XOmtzYpRyc133KT2500mKSRZyO3XsHuCkenaKFw9DVHZvZP3iGmoVT+1UnRcY2R83Eq9uyDA7tQRUXX9McpurF1gulXc/Mji2mhIqlNpENJN4C/EOq1LQyIkMzTd6Rtje/5TkZmb1UFFdZzE9ANMyNf7FSAjfowvR4qVssLrKj5MT1l2qOXm6wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYKDxUaHyYwMGQCMHQgmSvds/aGGSa2tUtf8AifzEkZUGAcMX/+1gygyei4i2mzBy0yHBY0NKKEFpukqgIwTAZmZy57qev0wh1Kl5OTN3ij9dSOLLTSEZlZOyGWDck0sJ+aX6OzRyza6waqCuBc"),
+ "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"),
new("id-MLDSA87-ECDSA-brainpoolP384r1-SHA512",
CompositeMLDsaAlgorithm.MLDsa87WithECDsaBrainpoolP384r1,
- "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",
+ "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",
- "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"),
+ "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"),
new("id-MLDSA87-Ed448-SHAKE256",
CompositeMLDsaAlgorithm.MLDsa87WithEd448,
- "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",
+ "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",
- "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"),
+ "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"),
new("id-MLDSA87-RSA3072-PSS-SHA512",
CompositeMLDsaAlgorithm.MLDsa87WithRSA3072Pss,
- "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",
+ "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",
- "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"),
+ "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"),
new("id-MLDSA87-RSA4096-PSS-SHA512",
CompositeMLDsaAlgorithm.MLDsa87WithRSA4096Pss,
- "sCJhE+NzunR3WvgdR7CbqFKQrkiBnbjaYhZ3GIHATVR7eaQ0p1JxhnLvDjCoIoqVHc1LwdBjOZfN1LOsKBk9/nk4Ji891P6+46TB/pI4jq6Da6Bo7qLTu1o4MsQ+RqA+mpE9EpvHdRQv2OaMnYdLz/NsRcdNrnTBuxa2iE3+65gKpwESaYX7r0uEkCJRkn7B6Njxa+3jKbJGHjIiVjgpZQLhRMb3xaawccO6GxTTq5fc3mdNum66y5fWjn2zunGr0en8DZ5SApeQ2SKLko7Zx31iFCVpfxA1bm3iT7B2AvIUr9pbRViBVRm77/NA/1oG3q2nXA+juUNmoB9lZLwkyI6TVhkpCJOn0Lj6A6zQ9I6HD2XuNBBS+Ukdhum6om8jPJwO3d9TNlHq5cgmj4aYptpjUnGzss+4cDIw7qh3/g8khoFi/e7Rq+WwxeLd3wzXqIW/6mCtsDCFSh+jpsEr/a7SyiLBGlUV2y8e4rywCsojuQErDOBYKC29p4h+aE+SCSnZHvqbD+oDeQDfibDaA6PntWflqxa44Xw1j5PwndVEoIu5mJX6xhv7myBwsmNJX+psLJ8/00LCVLiXvnM1PNxDc2VzyqY/mKfqRud5Q8tZTZKsA8+JmZnDREFKcATsd5lK9CQR4FVXLVUuMF6CriohQUaiVPN5yJrUoggvSniLPbEJvEb/3MDSlAoso5khW5X/JmpieCJAEvOc9sxiUNo7TtOlYa+67fDDg3NDrqS/GkQU3dbmolqD8q0GvGN7MAn8CrOeg23n9dcPjJGOfEjFBFazCuu/Jl8mboxmVMlwaRCM2WGuOVHIXebGoe5mm9umwu1cKLaOi1guezR9h+ntWL893hQi9X9bu8ppFBlh2+3OIrDObgJzeEHtla/pHgINrUOtH3hJbIv4z6nu2Qf2NqJLNIpHo6sxMh7IqEO/mbe7YSZVDBUVZj0P+ykLpZe5p5nKLtmqZfhqdBT2aAVwFdK4fxYife5HHrQd4uzW0uwe4um8h5blThJy7UffexrGCNj8kYJgLOwiSK/307ZmBKKP5/T1ysbvsYtYp3zo1dnvs2ida0hKsa1/t6Imw85Z8CaPTxVdK0czIKurUyAONemyb3xYphEcl55dqca0xKI7VlbrPPu5zJjMA4h+9fO5hla51WngfZTT6Oh9UY4T0j20P1K+tvnxBrp/pL00fHlLbpcQREopqI2tdM0qVWSFQ6e0ARvuRa/bKw96eUmNd5CugOhhyagbdahiSGcfi8ntUAlVJYQzEu9Q5MvNSOWq4GTiCBNKrEi0iRmHmPA0V/NbBxhXop7Ox7EDr6mpf2ee00tMaT8RkxtncxBGy00KC0anESGsbtIcdhYJhaOarVIkfeokRvYGqxs1TSQgyuiTwUMON3j3KKmmsNTFl1a8hLsJ7qweV4B55Lpf6Pwwa7XF2AmqH4bRsOopH5BumWfY4+jn+kkLqj79L4jk9k/IZRAfORiTtPabk/9IpIAe8jYucXA0lOwIhyRmtRaor8kFYAQf2DKPKuwpr4ImNhGlcD0qDhsKKbdAHNzVF/0p2goVmC3jATtkT/8RUiMb0sgSGppOkTOD4X+lfspVaYjHB/xiLODo6WC3DO1Kym4MrjCehAcnwFAamTRBKiJ98YTPFKuTmkOKFBX0mVhQqctHI+rSnm+slNEH7tscpfYeOtGrnG8La9Tpd7iNi80LoU3ihfyPFVjoS0GFLMOp6I31KKe0YRQIHdblGWt7dzgiG95t29WqrwxOpNXAfkNGZATa7pF83h/STawLkQot4Wd565VdIsXKaO6Fq7saWR08f0jscM84xDMcWA2OkKAqTsDusJl9n7Z10Wnq4pXFDKvGTwGQuP6+NZc2o2GW5FpgkaONyH8AVCyPv714iPPmGMOTJ0YRMUh7HGMBh7DuhD/hQ2jJVU1aglsQo1DCZJ1C/E6aiZspOAW8RIn56c4kBnot0RIZ7Q0TL75RYGh00VnT3P3qbPvbiVAT8NGTeKl76dudWlDy0DXEFI/L5Q4W0+q5odM/UA7UTAIT+FvVu/XIkVzbFlxemMfa/1XDQEk1Br5q9bNLJfMViciwvI697aSHx+3QwxauQAyJqo3R4Rk64RrAWnLGw114CQEeFoLqZbihd9Y9vYB7LvOxaixai0SHJcAYLK4Tefjzx4mlFPfB/0aE1dSwjAnFm3UzwSg9jp5EmlOaHWA2uOnPoL6vmhlbvkIFdDEpgErCokXMXOtpjIasZMuJgS78ocHe8Ozs8jFb2zD+qHC8rqOPHl5ripP7FK3FICbWbrZ34M47durfXRTumev5zPXxf/DhCVyfQKoD+rqYZjTCTmitjuJpi7CKng8K7onGAsKtzLBtzv2j6uUbUUTQCz8w0RKE6+jGVXQ/fhiU8Y3IiiPwSK0Zocux5Q39MfD6hsML5+PD54tZmwk4UjsLWxvoo50OFbBSLA7Q4RfuFZUdPcvSEAMPcnxmyk4MZ1eFGu8reQeUAQ+Ezt/wvMZ1t2cbbBnjfe0PLk7iKYS4FwZbVIAOLGY3nZam4qtnk9qgVSR2FjSabQ4bClQE1kk0Scd+hYJd00s1PD3cIjwzocq3zMqD3C2V0Y51r2eB4GQ2P2U5g8aUWSfLJjKi5TLdL0bxgdsUSXPTO6ukuwMi9GDx70/tmsZ7jlI8l2Plc0GYmQszj/qFEfxbc4EJyI5DBrFu323OHSl9KEPbairu+siPFzks1PUBQ3cK6s1ubiym6NbCVFF1he6P1TequNHv86ffzlALnbmL7jZaobf88Ubjwe4RAxcze6o2mBrKqWUDNoYMqk2KLYaQx4pT9lq8ZxKuSRvViwqkYd1G2qm2HddnAfWvhXRERBoYY4/OkYBrsf/awwDpZoeLShADvDkqiXrcKXAMg9jTeURW/KVxRwZ1X28QGUftQ1yi8x9KMUQ/MeLIfdWHAtYkQKCbjUxpqsOlNvSIdZ/8TVTeTca68zRsnCdrK1vvb/lNJ6XIbVXybluRSEPOyIwHGM6M6IZmTtpPcuGdyx1YvpdEws9c4G6fttr9Hh4G/+TlX9DuSc1ypeDwXpywOJWS7UGE5VZUhW3eXzBKmH4VxWAlMa4xr6edKVt/qyq317OHQW3aD48AlQ/HMBFXtzipyNp8nK4FddUugV8pYs5yRPNriKiw0uiAg5CLJ8ONfts5kztkKXbRIYMT+z2Z1C8roP4IvZqtDLw6JwGc4VqoJAmJDJnbcJaaMBMrT7zzIPX/brYAuiCXvQ4HnTAcOObCHnutgM8z+rHX0K3oOWFjRwCyk2RWRutUZ979EpM5HPpzF24UwBGAjQWpErTUza2HlFX6yjg5JLWsxXoQ0L5OJLlgwvU8pTYfoUpuf8N7JeugFWN16myJSK+woMcvIfBDsZ9ns6gm8nYMSGO6cjGAF2kayKoqw6LH6WaUZw7YP/UWVYWyx7Q6VlQH4n5IMIICCgKCAgEAyftH5eqBTTQUcRdQyO9bpayQ1JpSKC6sQgMGzuIBesYuSshIsY5dUsfiUZafu/UTCXAbMiYJa/tprINB4VkOfMmW2fW9BGdU5jLktLuYsdHk6CJjGq3CkMVLQzbVOsK/YrcbI/SpAy1RIRFx+05g/pfP2TUIuyNvtuNDmVrZj7oN1maBGKqgT8Bc0gvhrWcQFop1bQ470CGA1j58getQ4CUOcfifM1w84KIV6RcPsNjNhr/KAzp7i1Uh0eKmQNm0HdYYR55YPa0tB7hejQmBSM5CBvwCVF/L2XEKXTI+yy86NygDSN2smy7njUozkvZ0TMr8hQlV81EyNlR7xu3V/xhVLwsxOSOnMIKF4OKgGZqX/rgRvTgLOgLxpUVW5H9/CIiA+/58wywgxweUjP92e3n9V+TTABxYWpGeyQUO4/3Pk0UKttORbrfiQoXHcwY157RwVxlnw8c/qi3gImOJZg4IuYcrj/l5WI+hHXVwFKHbz4n4bzrIEE6LkrKGcmH4nigGOt+F09fq/6lv9ZFErA4Gc5I5G+Y0D68DKd1IySnHf+t0DSpGLPl+QqR2ShA7oUngxa7PHfPe707eD0TzJSQFHnpXcIgR/DEvi3insPbOlyFaH4qxHB4OYha/aaaRR/+BJNVa5fEJhSv/PjU4qbz9IMcXPic7o9D1F47y0PECAwEAAQ==",
- "MIIhgTCCDTagAwIBAgIUGsOJgZ/eV3g3vuIqiOubtFNHIpgwDQYLYIZIAYb6a1AJARAwRzENMAsGA1UECgwESUVURjEOMAwGA1UECwwFTEFNUFMxJjAkBgNVBAMMHWlkLU1MRFNBODctUlNBNDA5Ni1QU1MtU0hBNTEyMB4XDTI1MDcyMTIzMzAwN1oXDTM1MDcyMjIzMzAwN1owRzENMAsGA1UECgwESUVURjEOMAwGA1UECwwFTEFNUFMxJjAkBgNVBAMMHWlkLU1MRFNBODctUlNBNDA5Ni1QU1MtU0hBNTEyMIIMQjANBgtghkgBhvprUAkBEAOCDC8AsCJhE+NzunR3WvgdR7CbqFKQrkiBnbjaYhZ3GIHATVR7eaQ0p1JxhnLvDjCoIoqVHc1LwdBjOZfN1LOsKBk9/nk4Ji891P6+46TB/pI4jq6Da6Bo7qLTu1o4MsQ+RqA+mpE9EpvHdRQv2OaMnYdLz/NsRcdNrnTBuxa2iE3+65gKpwESaYX7r0uEkCJRkn7B6Njxa+3jKbJGHjIiVjgpZQLhRMb3xaawccO6GxTTq5fc3mdNum66y5fWjn2zunGr0en8DZ5SApeQ2SKLko7Zx31iFCVpfxA1bm3iT7B2AvIUr9pbRViBVRm77/NA/1oG3q2nXA+juUNmoB9lZLwkyI6TVhkpCJOn0Lj6A6zQ9I6HD2XuNBBS+Ukdhum6om8jPJwO3d9TNlHq5cgmj4aYptpjUnGzss+4cDIw7qh3/g8khoFi/e7Rq+WwxeLd3wzXqIW/6mCtsDCFSh+jpsEr/a7SyiLBGlUV2y8e4rywCsojuQErDOBYKC29p4h+aE+SCSnZHvqbD+oDeQDfibDaA6PntWflqxa44Xw1j5PwndVEoIu5mJX6xhv7myBwsmNJX+psLJ8/00LCVLiXvnM1PNxDc2VzyqY/mKfqRud5Q8tZTZKsA8+JmZnDREFKcATsd5lK9CQR4FVXLVUuMF6CriohQUaiVPN5yJrUoggvSniLPbEJvEb/3MDSlAoso5khW5X/JmpieCJAEvOc9sxiUNo7TtOlYa+67fDDg3NDrqS/GkQU3dbmolqD8q0GvGN7MAn8CrOeg23n9dcPjJGOfEjFBFazCuu/Jl8mboxmVMlwaRCM2WGuOVHIXebGoe5mm9umwu1cKLaOi1guezR9h+ntWL893hQi9X9bu8ppFBlh2+3OIrDObgJzeEHtla/pHgINrUOtH3hJbIv4z6nu2Qf2NqJLNIpHo6sxMh7IqEO/mbe7YSZVDBUVZj0P+ykLpZe5p5nKLtmqZfhqdBT2aAVwFdK4fxYife5HHrQd4uzW0uwe4um8h5blThJy7UffexrGCNj8kYJgLOwiSK/307ZmBKKP5/T1ysbvsYtYp3zo1dnvs2ida0hKsa1/t6Imw85Z8CaPTxVdK0czIKurUyAONemyb3xYphEcl55dqca0xKI7VlbrPPu5zJjMA4h+9fO5hla51WngfZTT6Oh9UY4T0j20P1K+tvnxBrp/pL00fHlLbpcQREopqI2tdM0qVWSFQ6e0ARvuRa/bKw96eUmNd5CugOhhyagbdahiSGcfi8ntUAlVJYQzEu9Q5MvNSOWq4GTiCBNKrEi0iRmHmPA0V/NbBxhXop7Ox7EDr6mpf2ee00tMaT8RkxtncxBGy00KC0anESGsbtIcdhYJhaOarVIkfeokRvYGqxs1TSQgyuiTwUMON3j3KKmmsNTFl1a8hLsJ7qweV4B55Lpf6Pwwa7XF2AmqH4bRsOopH5BumWfY4+jn+kkLqj79L4jk9k/IZRAfORiTtPabk/9IpIAe8jYucXA0lOwIhyRmtRaor8kFYAQf2DKPKuwpr4ImNhGlcD0qDhsKKbdAHNzVF/0p2goVmC3jATtkT/8RUiMb0sgSGppOkTOD4X+lfspVaYjHB/xiLODo6WC3DO1Kym4MrjCehAcnwFAamTRBKiJ98YTPFKuTmkOKFBX0mVhQqctHI+rSnm+slNEH7tscpfYeOtGrnG8La9Tpd7iNi80LoU3ihfyPFVjoS0GFLMOp6I31KKe0YRQIHdblGWt7dzgiG95t29WqrwxOpNXAfkNGZATa7pF83h/STawLkQot4Wd565VdIsXKaO6Fq7saWR08f0jscM84xDMcWA2OkKAqTsDusJl9n7Z10Wnq4pXFDKvGTwGQuP6+NZc2o2GW5FpgkaONyH8AVCyPv714iPPmGMOTJ0YRMUh7HGMBh7DuhD/hQ2jJVU1aglsQo1DCZJ1C/E6aiZspOAW8RIn56c4kBnot0RIZ7Q0TL75RYGh00VnT3P3qbPvbiVAT8NGTeKl76dudWlDy0DXEFI/L5Q4W0+q5odM/UA7UTAIT+FvVu/XIkVzbFlxemMfa/1XDQEk1Br5q9bNLJfMViciwvI697aSHx+3QwxauQAyJqo3R4Rk64RrAWnLGw114CQEeFoLqZbihd9Y9vYB7LvOxaixai0SHJcAYLK4Tefjzx4mlFPfB/0aE1dSwjAnFm3UzwSg9jp5EmlOaHWA2uOnPoL6vmhlbvkIFdDEpgErCokXMXOtpjIasZMuJgS78ocHe8Ozs8jFb2zD+qHC8rqOPHl5ripP7FK3FICbWbrZ34M47durfXRTumev5zPXxf/DhCVyfQKoD+rqYZjTCTmitjuJpi7CKng8K7onGAsKtzLBtzv2j6uUbUUTQCz8w0RKE6+jGVXQ/fhiU8Y3IiiPwSK0Zocux5Q39MfD6hsML5+PD54tZmwk4UjsLWxvoo50OFbBSLA7Q4RfuFZUdPcvSEAMPcnxmyk4MZ1eFGu8reQeUAQ+Ezt/wvMZ1t2cbbBnjfe0PLk7iKYS4FwZbVIAOLGY3nZam4qtnk9qgVSR2FjSabQ4bClQE1kk0Scd+hYJd00s1PD3cIjwzocq3zMqD3C2V0Y51r2eB4GQ2P2U5g8aUWSfLJjKi5TLdL0bxgdsUSXPTO6ukuwMi9GDx70/tmsZ7jlI8l2Plc0GYmQszj/qFEfxbc4EJyI5DBrFu323OHSl9KEPbairu+siPFzks1PUBQ3cK6s1ubiym6NbCVFF1he6P1TequNHv86ffzlALnbmL7jZaobf88Ubjwe4RAxcze6o2mBrKqWUDNoYMqk2KLYaQx4pT9lq8ZxKuSRvViwqkYd1G2qm2HddnAfWvhXRERBoYY4/OkYBrsf/awwDpZoeLShADvDkqiXrcKXAMg9jTeURW/KVxRwZ1X28QGUftQ1yi8x9KMUQ/MeLIfdWHAtYkQKCbjUxpqsOlNvSIdZ/8TVTeTca68zRsnCdrK1vvb/lNJ6XIbVXybluRSEPOyIwHGM6M6IZmTtpPcuGdyx1YvpdEws9c4G6fttr9Hh4G/+TlX9DuSc1ypeDwXpywOJWS7UGE5VZUhW3eXzBKmH4VxWAlMa4xr6edKVt/qyq317OHQW3aD48AlQ/HMBFXtzipyNp8nK4FddUugV8pYs5yRPNriKiw0uiAg5CLJ8ONfts5kztkKXbRIYMT+z2Z1C8roP4IvZqtDLw6JwGc4VqoJAmJDJnbcJaaMBMrT7zzIPX/brYAuiCXvQ4HnTAcOObCHnutgM8z+rHX0K3oOWFjRwCyk2RWRutUZ979EpM5HPpzF24UwBGAjQWpErTUza2HlFX6yjg5JLWsxXoQ0L5OJLlgwvU8pTYfoUpuf8N7JeugFWN16myJSK+woMcvIfBDsZ9ns6gm8nYMSGO6cjGAF2kayKoqw6LH6WaUZw7YP/UWVYWyx7Q6VlQH4n5IMIICCgKCAgEAyftH5eqBTTQUcRdQyO9bpayQ1JpSKC6sQgMGzuIBesYuSshIsY5dUsfiUZafu/UTCXAbMiYJa/tprINB4VkOfMmW2fW9BGdU5jLktLuYsdHk6CJjGq3CkMVLQzbVOsK/YrcbI/SpAy1RIRFx+05g/pfP2TUIuyNvtuNDmVrZj7oN1maBGKqgT8Bc0gvhrWcQFop1bQ470CGA1j58getQ4CUOcfifM1w84KIV6RcPsNjNhr/KAzp7i1Uh0eKmQNm0HdYYR55YPa0tB7hejQmBSM5CBvwCVF/L2XEKXTI+yy86NygDSN2smy7njUozkvZ0TMr8hQlV81EyNlR7xu3V/xhVLwsxOSOnMIKF4OKgGZqX/rgRvTgLOgLxpUVW5H9/CIiA+/58wywgxweUjP92e3n9V+TTABxYWpGeyQUO4/3Pk0UKttORbrfiQoXHcwY157RwVxlnw8c/qi3gImOJZg4IuYcrj/l5WI+hHXVwFKHbz4n4bzrIEE6LkrKGcmH4nigGOt+F09fq/6lv9ZFErA4Gc5I5G+Y0D68DKd1IySnHf+t0DSpGLPl+QqR2ShA7oUngxa7PHfPe707eD0TzJSQFHnpXcIgR/DEvi3insPbOlyFaH4qxHB4OYha/aaaRR/+BJNVa5fEJhSv/PjU4qbz9IMcXPic7o9D1F47y0PECAwEAAaMSMBAwDgYDVR0PAQH/BAQDAgeAMA0GC2CGSAGG+mtQCQEQA4IUNABLCL+e6yGTUhz6nEk63l31iTWACl9ERGijDOo1A41jNcKtfT3t4UZajJAv4VdHTfEB25yCPQZ2S7nBTTOB+tUn0EQGUA3uuRDfLCOFimLANKpRdMYm66Y6wqhorJeQ4pwrYG5Zv7I3q1ttrlzV2A5NSi4Gn2iPQI/3VrnS5gJ3Vin2nY42sT6BSVB+uXQFmCq38SdrdTK6DLx4PQ2JMaPn2HW53XAkTsIGgh1j5GRepGFR0d62eOqPVdMhVDECUDcoPKK73qIbZXeCnfSpylY/URomgU6UcJ9/F/rVinAzLseSKBQnX/js9pwY4yuwMhjNDMFbaTJa9tUL4qvIlGAPw/9E5dOIW6eBcKsPPqV7lqip1XBzLY+Aau/fYsFGBWSTWklFz6+l0UpaqDi9LYH2pxj0ltL04DLVuAto3PXFynm2RqnZFkeq1qm9+5zGSq+bZi7OR+7gQ9MfmIuFNKctuFF0D/EXEtMKu1uGXEf81MvMCxTRN0G6CabPDM2boa/2fodSJlXtBqYtkRy7naS+a5cqsRr2ACLPcr6tuiM56BACnYdHbrCJ7smAeFui6exVC1UOwQiZcyrh4KlWw5yJOFATMkX9nwzG3DjvupatBvd55WMQDqucqBQ7cpmI2lfJC7GBgE69gjgWukeRNGkySlgqu9ZenivTsSgKEN+PFLb6Q5bfZ4vFEQ6I9IhW4YUgnnVQKWr4VLERsnG9oq5ryue7kiCbfBDDyP2KPUcxNGjwmlfDhpcsclzseKSrNMcWQpMJ4Dk+wavslmhsUIHwS6rtU45OIzPpJGzvUQkCDXIX3jMHiwbn9ck4v+F5GRuFQn2NTnxnS6ndykVMF5NIA9vwn2CrBuY0ZPH3phwNvgFIS4l6ltKBZNXFoFfi+vRRgnn/BOUmcItbfQzlkGVNEb9SILuqx8CNRVUXV4SxT+CZGWGF6mc/TRc90NBGHViskLZZZrG2ucFyswq8Sl2k09BymCHK/GQf5S8U368hbeysxRneVMh48jUznBMdsrqK0Hpz8rFAVfr3ewuFQEA1hvMJfJom/i4+jXMn9FSvbiLAXEn70/mGNpmOHC7L8EjFRzsA19/xLYrfc+rvcTLQyldNfkMXWiOn4ufKAC9B7kV0EZ+I2cAftlcltpEnDIBYdfHVuykrgY6KPpkHStUywxWv1zeeP6N6UBLEQR5IvB3ZIbyY4Vaj3aP+YqB3cM6kYeOuxBYJqSi9EXZQO2E7dAlJSIE7ZKjAIH1mWXM6eg0GGv8aXidJczQpxi+dDK/2KN4Y3nPyAqjdWOqAr3VJY3chOZ97kJ54ZQPiLvLsOYcD/7Hio4TDoHSGiTEKJ+s3oTLQhq2qMdzFqgrOSVXa5e7d2ztdLvwsrSQMEqssOt758x/PYP317bZ+K7TTqkVm4I8JM2j7sRNRvfxnso/uMTbA1oG/br8NyjMsSdqHSxjizkJpTsMhXHcziVuWQQzwgXrWUv8pwGRivV9mwS2AFqxYJQt1I/gyQOU4zC1suuoWGPPLhIxpM7mUgGtux15f9SkkFxNCBjiILTXU4uIG9aJ/Vg6DCkZIoXJ1xIuDicfUtlnndX1YCioK2KmMvt7msCDU5810hNHyKC8WQ+WwiWWfPsl3cPGyzK0cBV8rIJqcVTPgKVy8ubxHunTh7buRV6F0Q1kVdliJ1nqxCPpjXSjVrBHprqsBgigLUrmU5ETOJVWauggz4F3prVX3U8izUnZaDO7XSVF6lGZYu7tTIcO6mJRzo6zUkErVUstUYCdVrDGb6Pm2BcpVWmqy2Lea0+mDsP52oNbduxq4XRPczvrFsDMOJd8OZTG+XFW9fmfOtZcI//M1gvmDn+HieC6HVQGR5VOO8m6a+ulBjjnBxtBDEeK4T6f3TTdjNYO1taehDfdOLya5924SkYU4/WFPJ4VnyvZpuSetaGgFCjpCy5KvKrysv+ccmG3QhTvB0LgDv5W9uruXRLIkPjm5bYQR/ETTHh7oBCgeuYw+sWUGcSZuOTisnq284hAl7Ma6DxJgNc4Cxo83gsjcCpE4nXIZLq8/kh5GaflZ5JQyYdK8aIoRu1iqlLrQY2RWOO8i2NKaj3y1UCVAv/P3iBTtzbnERw8Qm3WYnu7ilYcmZem0J/H1l4NO3TXp63SPULxUCpnP7UdllpbCWsrE+4cy5RcpgfDuLlRyZOGCOTRsPanrkNTxoFIIlva83u+PQFUQXewI6Ca6A1RTD/aMDKg4bcE7FG1KoZ08uSXtfOG1xfcoEPzChHia2roHblLEa9NJiMRkGDYOjp7dAbbGbx0Sj3QzB+LDqLv+PV2MXlJob13Z7b5Fz4omCe4wGk23W78/4g/zojkuLVy8XWLs1f5ptsryGyMnwgTOC/npebdX4NLNGESYo5CUvRyVlgnz6qi7AQ2HMmZxvQoIXXYtpW1iLqK9yAYJBR0Bv4jEeZK0h/49B6FgTj5weaagmLq9lFiIJ9ciJ8h/9i5vrYqcXQk3MXfue0DLap5klXQzpmNCphr6Yu+YD154xBxOGACnofcJcML5nQVkntTpNbIZiI+sxxRwnmm3jto0LM0nVWCTuXqkk0DI6gNjxvxId1nSTUe2qxaka1acR+PdSjU0kptzOlxi2k4uluTJCQ2Pfj7xeC7ZRy+4oSWhPC8lMDx3aTsLK1hd1YWIr/PirBf5VLdK5sVVsQbHTmIXFyjlEcqOEcUzaTDBoe3TbdvSGaCS975txTIGOUl/nrNgQ8nHYMGIZE+/5Ne3/ShvlXUbwAr800cfYgvH8ymhBM4KO7o/XFmR1wiNBB6MGQcHIlqzec99AY5pJKJVNHAEya+R5KTMnSI4V2D9/pho0XTfyKMYCDPe7tqxm1kVtJn/UUEzJO10Vr1rEdy2hGcEAyky881tnQ19EbbT3w1DLaT4dJtwGmVdlftRDMW9uEXpA0TjRadDilsElboX1065IKiplpkrUK/3wFAlRyLcgt+xQ0tHAI0uz1jrbzooT9sVSA5cHrOxnmEXtKZDjd6sdeu8XPM9/2gycFRb9meksZtW4qu0TUucIPhVYgu/HZ1msrWyMyGPF+Cg3UnyZvZml/hmxJXfyKsoWlpLNpThvX0PU+zVSDzqML2QmmQqHYd8cTx+k9zJA+4rIvAyvrgU20moMiaL5OPkVk9L4NoiEsEMYTNpxkcundIz7O/8gFu40uU/ocm1WoJavNt8DLMHOtx2e8+DrAW45+g+V1EGZ7vcliZqlFOsHbw1DGtRd2x2eULrm38BPcAVfpF5dLFPOxuqOJSNiNKlxVz3Tks1sObXhygDsvKvEWcGmYCpkY32Deds+P3Mid7K+MzvDdMn8Wlz5fkbBFyNepSLocoXs/F+TL1WCL3GkEEiy8Y3HFVYrhmBF0BbA1iK5a4jLhaTGRBrJ8rWtHnH3BjAy9uX2HkLdpnn2SR4vKsJV1tebMKxfCZYzL3LJxw61mOfY9WFO8IrnAlgm+x+Qay2XwB7U/GHLrovxQwpRK/2T93ynC1y3ZPrEj2icYCMrFX93Q/Vw52VGg320i+ZWQi908uCoVMMpv0bYoVQzvO/51xDCsXukeWmqflNRrzPzqo8Z5FPnuA2HCJef38fb9vFkPWX2PSBEyiIFZzhoAC8lIuZ29mU05C/BxvG3dKJTvj2nlvSiUs+vG1B3qhW2g1AsMW7oJcGDYgZ2vohEz0v1DV4nvBs1KoJnTz/MA3s7Wo8GpkkfyvvlXvjiaPHjVP9X4LPuYIE7WFrMczwe+vgtSyA+RMdBYEuF92wjXbYrfrCena3Et7o1uP3Wg3mYzPJGst1rhZTgNAss2g3wivjX7BSbz3uZ5GzTJDx0G/W8agFicoGLPXfiHuZctX1rIglshxMfG/rGI3BgCxrWG5SHBjXObsqnXw/4zmzLq+9cnI9Cf3UDmGaREWz1VfYBwjatpCMuZhEA9l1zyoMnjjxdmDPc5/o5z2j6OsbCgJsxQmf+xxIN+iaZwTWZzVNpDIi09WSZt9QaZdng1kmSZmgJVDP3PGvPtLeAC1nzBiHQTYsOzdKgDD0bWD//a58Jo5RiUIQdRGnkG8NubBtNPe/JcfyXO5PeE7dChuihggT9aSA2T28VeC+Sal5KprqesN0MiswYxA3ln74b6LQZtnIRoZc3Aoaj82urToiBbk443sIDTFXlbzhIunfe6DNFzm0ZABQzhb/DdWiiBwKV+QWdju+4iC6KbLIcx9rrL1fDvqrW5eFJ3fBJRgG2fH59r/mPbD3CqnehunDubTZjovKixELzzbRT3KOIxeBT/tNdovuAl7A/kmywnmf0rilqAhMC4KfRkpEJvY3ogE81opsTgqhTeuGIw4AsOo6SD+SoScwWaTXYrgmuJngMXzeacPJkaaR2l5TKmeX786vHWaMm6qwBshVsFr47gW1JjyllAvYRXwXsYf4Noh39bcvHQLcVzVA3NPnKXkZC3as42hrzMlGWGmxMQejqGeBcB2hxYwL8R4xcn2Jxi2xFLWAc8PSZJPnNM5fokB6Dv1AT3J7uGJ8hrKFdbo1B1G92GpT+5j6YD9f836eud3FkMS+jnf1GTqv27RZ7rNjth301pS10wvhW8SKGS7Xo8/e433M6lNNdDv+iwN6HDrTfKdMph8By06f3vEDB3SIMRdVMRaiocOhwxbM3vtIhQ3KAfbViubT2vYYbCXQruY7CLc8Lq9zgwpso545INH3pIikvHVH5w2N+ncsMBBct41LnOGQF3F6D/L8jr+KonjDh7o5QOKUItyMc1VqMjz83desDy5RUqxT2G4JFmN+IgAiO1247tjMGUs4C5fgYUtYw3+pQP5NSXDWPfZbTd0s1t1U2oQjKvrQRHoPUtran4nr9YXxBpInxY2f0+9qttwY86mrLjYNHJfDuCh5CwEtlSDCOxA+CxGCPzjz1Fh/gqHhKZ5Y1MjyBM6KbPlKq8Cp8oM5N18KuW6f/3e0Eaa816CJ/nk+ZBclvt2gmcmStOCpr4Om9e3SssLL3b70jMKCvcguz5ruBC4AWVLm/JE9jWFbcYnjcIDp2p9CB4eacerXUpzs3b2G+6XcJ11S801lmuv0Vdq3DU6dINwtyUEd6BVHuKrqQopKM+Bnn2QowyDE7fZkJQMpzq5GxJ8/x2fI6umaCfrp2Sak4mZbGsbM96lcg5SPmLHB7wkaB2UQNImk0KEq6Z4APmPEeZ8ULnkzpxEuMq43+WmtHDd1Aj5qvMWQifxWg5QrE757ofOl92JKV8u8zsR588dcTKpXUtny1od+M4VaTQaAgiJbzBrO9Y8zZod7LbDfLd7E9PcY1E9BW9H9eEtfakW0RrL5BPeFnHCWWFTa1Z72KzW8Om08xsTS1Ivn/OBdPIJVDpWfeodQ8X5B+N8qNe1uVebG/FDVoIBwpYVtpijc3W6fNmc5+XXHceLy7hiC86hTkeDSrm9CTah2JHj2KziTxqNbQj4Qwoo2UR6wMZ3Pi3ekj7DwjNpfT8ruBQeenaA3hOD0ren/bzwL8JbwukLnd8IlhZU7nCKQZfWt7fj6EtFKHjSsFKoY2w9/GP7zQP9GHaibHkMUWylP2pLnlTJDhKeCvCzML6OnRnjZuY3OojJaaRgoOreeY7l0veGNh9mLaspdrERJ8G+tsQm8FjxZz+RI2rfoLR4EUkp0AjqnFm8TFmHYB69C5kEX3Obz7gJRng+y5axZ1O7nnsYr2A2rJFBC0E+LLr1f5uxgi0e0r+20o4K7Xm+BPWT3pFtqlagYIHzJ0V6sUDFdUT8tCe+IwoLjjdC6RxBSSxRsCVrX0HOGwa+ZlxG2I8dYuAuh9Lyje5uvhyuaGIc7yaOdqgFA2DaXALE/zRQh+kgKBY7Zr84sObyIfsgEfq1yCehumX1c6RDJ8Uf5gl4qam4xtpqaGPy8sbBo3N4pFwGRQ6QUgErlGVLW2Twh3y8EdvRBe1WizzWDjSSbi1u7BSyXtys62AFB2lCosh2iNUM4wMgNt5v3EVUiHlIb9Gzj/QGisFAMdbMA26ygNAEezmHHTaJn9mcBauL7y5m3mx0P4L6LckJEm0hmA++vksnYZSaHZVfSA9vssTSx4XUGI/3kjVmYi24RYfV6Igj/EyBZZJCay/8LE1FkaGtxjKyzwuVUYQwTLC2J3iBS5e4NDis5WX+W8v0BKm/M1g4SbIGSmZ4AAAAAAAAAAAAAAAAAAAAAAAAAAAAACBQWHCApLjUO30vBXl9/sgsOm/rMPS7J/zCwg4HFp6hNZ+vfVt4xgnrLs+DvFGv9J4wZIP+BcVcTxB32T7wdM6lgO1SwTz/Bgi0cu31a3GQHC4XXqhSB6ENa1zSgzTnOVPmX9QXLfpKbvoimfzk7o7/gOo3uYRmfu5qvzxBUbkHaortWp6ZtGUla1TgkC+CAE0V8wRYng0OjKGrNbG3i8BNvOxsapeYEnrpNjUQ7qHkbhfwSh+JzUrJ+LwYZB4aZ6dbrEBB6sJDCfqsCnNB/qxzkTt0Fqn0elmpXi9YjzXpyUlktDGCM8kbvH9aghM9xVV/WOslEWMa9Rg8KCQnJsf7GqpsL5shhBD9SWV3coo2uwxqqBLFl0Ar0+ZiMWYnf6ycdvJMJXLOh35Fin0pN3/bRNRgY+jGzCBVZfOrZEOPUdafnYHTqJfiiWBt0T1WArNmT3iI5oJnYpbDNdPkj1B86NBrxf2CGGuK/3XjY1cUbmO4tRCcXMClcO+gj2XDE1qovPI6ZF3agOARhOy+0iLmXRNksMiMTz9KZ1Ry8ms2emGenTNDiDSfRG4F9j4lAL+zO0C0xf1+3SmCoxpwgyBzdLiF+/zKxSjFfkOCqwc54TTQgDqnd7NL6Om3/Fg+EjqJR93NlEif2LzdIjzxyTAWAhMitcsJ5HYJviyvqLEUpGW9uSmxxkQ==",
- "q9A3XnQrxNd3GsHrlJMuDZmkC0Jy3IRz0VUbJDjjpMMwggkoAgEAAoICAQDJ+0fl6oFNNBRxF1DI71ulrJDUmlIoLqxCAwbO4gF6xi5KyEixjl1Sx+JRlp+79RMJcBsyJglr+2msg0HhWQ58yZbZ9b0EZ1TmMuS0u5ix0eToImMarcKQxUtDNtU6wr9itxsj9KkDLVEhEXH7TmD+l8/ZNQi7I2+240OZWtmPug3WZoEYqqBPwFzSC+GtZxAWinVtDjvQIYDWPnyB61DgJQ5x+J8zXDzgohXpFw+w2M2Gv8oDOnuLVSHR4qZA2bQd1hhHnlg9rS0HuF6NCYFIzkIG/AJUX8vZcQpdMj7LLzo3KANI3aybLueNSjOS9nRMyvyFCVXzUTI2VHvG7dX/GFUvCzE5I6cwgoXg4qAZmpf+uBG9OAs6AvGlRVbkf38IiID7/nzDLCDHB5SM/3Z7ef1X5NMAHFhakZ7JBQ7j/c+TRQq205Fut+JChcdzBjXntHBXGWfDxz+qLeAiY4lmDgi5hyuP+XlYj6EddXAUodvPifhvOsgQTouSsoZyYfieKAY634XT1+r/qW/1kUSsDgZzkjkb5jQPrwMp3UjJKcd/63QNKkYs+X5CpHZKEDuhSeDFrs8d897vTt4PRPMlJAUeeldwiBH8MS+LeKew9s6XIVofirEcHg5iFr9pppFH/4Ek1Vrl8QmFK/8+NTipvP0gxxc+Jzuj0PUXjvLQ8QIDAQABAoICAE/gvlhg223q0MLA08QDVR06F7Tcqu0VOC6K/+BFZQxm39vXRVhi0ulv/0MA7H7qtvKekULN5B/+N5Zv+lfiXmZfWvcrxeq96sd3DReksQhx17MuFj9wxGd4fwE/6Cfq6MFjZKpdkZGeFF2dhpQ6NQW6iAqAfMl1hDKxwgQd97htfhdyRk+4+tlPW+X9qOxou+YOL85HOMRg25De+WJv63YZcZMFHgCz06eKsluSMTRhKTbHFl8ce8toiY11swYmkqLSDpwUNRV/LTXGZi4kuipO17HnbAxuLjH6EH0257p3HPC/ND1W3XIppI0t8SOHsArGpAMA5Crry43M736GhIA+6rBmeuvwRx8RP+ycRVatZcTAs3KeQrS2ecpIEUzkQKwlnjCT0xtrLDn3tdIN+XxVgGMyCusV9Ac5A2xumtRPju6hdG0KWS7LH0lvE5s5NooTo0Z/5WnW4Nx8O20TaZvPJw36zXQiOFNGChxmYng4lWBhEtcDbyV01hqlkrIqx/jUemDTBj8+e1+3y1/Ko+XFNx/LEv16VB9xTkFTcJo+D9OTXEzBmpQrOP+FNJaytbdLhSnmDwW+BM5NpG4+7xIX4AlM9IfiUB7Q5/NpKApJ2TAFy9WaXzUCl0wXZRBgRpJ/ApM4mFGjLMVFxEBXUNF0ph53n0up5o/L5J32F3W5AoIBAQD+DHQLeICoMOib8dAD6Yh2tIy7ysQEn0PNXSxZqd81BvZ1IhMk18P4e90uSyYLMKTACvoRKXuuSQz2LyLMerFfgxKbjGcDl1sLVQ0g0L6IARD9fhFh6iYd2xuYK3b+d24I3BdZhY1Z7GouJPSmJkGllk+IiSJ5QJWSXu6ic21BCQBSG8U6DzJhh+GnrM+rLwAEMMqXm1x5dBRbXPIUhSyb20whrseZ9LaPnVDcIvrGIKfc7+R5MEPfo6eRhGIsu3vZEhEZEFAJt2WB29cQvkiPi6G1Aze3xWQ6UhNCTJPxfIJY4/UHoas+gvvscZKfffdzYkNDt73yNMbDC897KFonAoIBAQDLiHIh4kzJvTTVdgpPPGUjr7726/h+Gc/+AVovEB69P2QD0g6pDSGDQj9oGEtmBj7h9mO6q+V+1xb0pD3WXcPFes43AUeqde1OvHTDeq7BjV28U3ayVell4mZuwCJPLOHeJoSlhmnTFfRDmjOrfAO/yW56k+d9utUm7sE5SfXN4uDwBP80HuDJ3TLgP2icJW6hTdte+0zVxPZQkg/c+Um3fFXkhQJCv5jE0UCArKQaWrjvLbW8u6Lk5OPgK6EXDwQTW9GxB2PoYHbeq9Ovr4hExnJXddPUiFvVySlUK6Q1dP05hLpuDnfXx1i5wpd/q/OuOCkEkg9WVLMcXheNkGMnAoIBAHiOeFMpMASgkQHP0qLIo9WRAGftZO+8lHRUDsPN9Po4/6O+M898BKdaQC/DwZ31y3jGvLyALw0Z5Wi+HYljf+CPVrkx+4Ccxrut9Ljp1kC8IM/qj10jvErWu1WO6rz+99yEdSAqXFWb9xdGukJOTUDC/6MPUKixmUkIe73jgKkoGFreis1ugL3/uXnUbAgUGbHjZYBkXZHVIAPrK4XJXM3pV0t0oYvRsQCd6s1MXCzBOmeB/63y1YK/KrnHVL9diPwNssduEk1KFoV1Sa3MXqqf3HEFwd8XcOSsJi+EH4CtUT3Vj2W7toPHrL0beDTvlgnPS5RLEXxqxxev9xm+oGkCggEAf7TIcCxPJBH88acUBu2NRFwEhWhATdciY20zye3ia7o3phIKMtZTXcmWgVklDgoDMMLphnpPEEwjUjMvva6tpN5OP8Mk1XcTBGFJHlJ/DmEGHKF+C53OSahJv1n87RLrUfl3J2j0Q4c18ajynLm+nHrmQDFHgeNV1Qzf3nNisOGXY+KuwmRRhTeusXf3ymnORZXVfH5Pkp34M0vCelNMhr2UI0O1zG3tjCkDwPkSKpscCK70pkxRhC9+L+0QMaixVPg61UoezPKiA0trEoQgC488tVXwKR26CaUjsnWDniserBV06JNZbOHe8QeBCZG532nLituelfulOrprKt8a5wKCAQEAjW1WZdB94pJ8fzs2IWMKwgM2KDBIXiOD9PCzZ3CqNPYzUaXsw23hkztSoF6M2fxI68AD6Bc6vXP/wtoRuf8jrC3Y3Q+ctULoO7BFewWz7qzqRC8FsVKcZNhHVEEWAPAiVt4XniEUNQcPeA1I6pKipG12DsYfIqBlkjfY2QN2aiONEjKZzEtE45IuuDJ86sWlwiXopFOeOIJGMA7S8IzE8SLHLI+2+6CwYiC9Z33hSHqva3uNcSN/qvS3WlcQ2NNlCKIdUJO3/4gARawor7eL/OsLVdXzWK5XoBsolfg0RSw/wZOuuZwyqYC2yKkt3qtLvcb2wfrhdwMwkD4EzzscFQ==",
- "MIIJYgIBADANBgtghkgBhvprUAkBEASCCUyr0DdedCvE13caweuUky4NmaQLQnLchHPRVRskOOOkwzCCCSgCAQACggIBAMn7R+XqgU00FHEXUMjvW6WskNSaUigurEIDBs7iAXrGLkrISLGOXVLH4lGWn7v1EwlwGzImCWv7aayDQeFZDnzJltn1vQRnVOYy5LS7mLHR5OgiYxqtwpDFS0M21TrCv2K3GyP0qQMtUSERcftOYP6Xz9k1CLsjb7bjQ5la2Y+6DdZmgRiqoE/AXNIL4a1nEBaKdW0OO9AhgNY+fIHrUOAlDnH4nzNcPOCiFekXD7DYzYa/ygM6e4tVIdHipkDZtB3WGEeeWD2tLQe4Xo0JgUjOQgb8AlRfy9lxCl0yPssvOjcoA0jdrJsu541KM5L2dEzK/IUJVfNRMjZUe8bt1f8YVS8LMTkjpzCCheDioBmal/64Eb04CzoC8aVFVuR/fwiIgPv+fMMsIMcHlIz/dnt5/Vfk0wAcWFqRnskFDuP9z5NFCrbTkW634kKFx3MGNee0cFcZZ8PHP6ot4CJjiWYOCLmHK4/5eViPoR11cBSh28+J+G86yBBOi5KyhnJh+J4oBjrfhdPX6v+pb/WRRKwOBnOSORvmNA+vAyndSMkpx3/rdA0qRiz5fkKkdkoQO6FJ4MWuzx3z3u9O3g9E8yUkBR56V3CIEfwxL4t4p7D2zpchWh+KsRweDmIWv2mmkUf/gSTVWuXxCYUr/z41OKm8/SDHFz4nO6PQ9ReO8tDxAgMBAAECggIAT+C+WGDbberQwsDTxANVHToXtNyq7RU4Lor/4EVlDGbf29dFWGLS6W//QwDsfuq28p6RQs3kH/43lm/6V+JeZl9a9yvF6r3qx3cNF6SxCHHXsy4WP3DEZ3h/AT/oJ+rowWNkql2RkZ4UXZ2GlDo1BbqICoB8yXWEMrHCBB33uG1+F3JGT7j62U9b5f2o7Gi75g4vzkc4xGDbkN75Ym/rdhlxkwUeALPTp4qyW5IxNGEpNscWXxx7y2iJjXWzBiaSotIOnBQ1FX8tNcZmLiS6Kk7XsedsDG4uMfoQfTbnuncc8L80PVbdcimkjS3xI4ewCsakAwDkKuvLjczvfoaEgD7qsGZ66/BHHxE/7JxFVq1lxMCzcp5CtLZ5ykgRTORArCWeMJPTG2ssOfe10g35fFWAYzIK6xX0BzkDbG6a1E+O7qF0bQpZLssfSW8Tmzk2ihOjRn/ladbg3Hw7bRNpm88nDfrNdCI4U0YKHGZieDiVYGES1wNvJXTWGqWSsirH+NR6YNMGPz57X7fLX8qj5cU3H8sS/XpUH3FOQVNwmj4P05NcTMGalCs4/4U0lrK1t0uFKeYPBb4Ezk2kbj7vEhfgCUz0h+JQHtDn82koCknZMAXL1ZpfNQKXTBdlEGBGkn8CkziYUaMsxUXEQFdQ0XSmHnefS6nmj8vknfYXdbkCggEBAP4MdAt4gKgw6Jvx0APpiHa0jLvKxASfQ81dLFmp3zUG9nUiEyTXw/h73S5LJgswpMAK+hEpe65JDPYvIsx6sV+DEpuMZwOXWwtVDSDQvogBEP1+EWHqJh3bG5grdv53bgjcF1mFjVnsai4k9KYmQaWWT4iJInlAlZJe7qJzbUEJAFIbxToPMmGH4aesz6svAAQwypebXHl0FFtc8hSFLJvbTCGux5n0to+dUNwi+sYgp9zv5HkwQ9+jp5GEYiy7e9kSERkQUAm3ZYHb1xC+SI+LobUDN7fFZDpSE0JMk/F8gljj9Qehqz6C++xxkp9993NiQ0O3vfI0xsMLz3soWicCggEBAMuIciHiTMm9NNV2Ck88ZSOvvvbr+H4Zz/4BWi8QHr0/ZAPSDqkNIYNCP2gYS2YGPuH2Y7qr5X7XFvSkPdZdw8V6zjcBR6p17U68dMN6rsGNXbxTdrJV6WXiZm7AIk8s4d4mhKWGadMV9EOaM6t8A7/JbnqT53261SbuwTlJ9c3i4PAE/zQe4MndMuA/aJwlbqFN2177TNXE9lCSD9z5Sbd8VeSFAkK/mMTRQICspBpauO8ttby7ouTk4+AroRcPBBNb0bEHY+hgdt6r06+viETGcld109SIW9XJKVQrpDV0/TmEum4Od9fHWLnCl3+r8644KQSSD1ZUsxxeF42QYycCggEAeI54UykwBKCRAc/Sosij1ZEAZ+1k77yUdFQOw830+jj/o74zz3wEp1pAL8PBnfXLeMa8vIAvDRnlaL4diWN/4I9WuTH7gJzGu630uOnWQLwgz+qPXSO8Sta7VY7qvP733IR1ICpcVZv3F0a6Qk5NQML/ow9QqLGZSQh7veOAqSgYWt6KzW6Avf+5edRsCBQZseNlgGRdkdUgA+srhclczelXS3Shi9GxAJ3qzUxcLME6Z4H/rfLVgr8qucdUv12I/A2yx24STUoWhXVJrcxeqp/ccQXB3xdw5KwmL4QfgK1RPdWPZbu2g8esvRt4NO+WCc9LlEsRfGrHF6/3Gb6gaQKCAQB/tMhwLE8kEfzxpxQG7Y1EXASFaEBN1yJjbTPJ7eJrujemEgoy1lNdyZaBWSUOCgMwwumGek8QTCNSMy+9rq2k3k4/wyTVdxMEYUkeUn8OYQYcoX4Lnc5JqEm/WfztEutR+XcnaPRDhzXxqPKcub6ceuZAMUeB41XVDN/ec2Kw4Zdj4q7CZFGFN66xd/fKac5FldV8fk+SnfgzS8J6U0yGvZQjQ7XMbe2MKQPA+RIqmxwIrvSmTFGEL34v7RAxqLFU+DrVSh7M8qIDS2sShCALjzy1VfApHboJpSOydYOeKx6sFXTok1ls4d7xB4EJkbnfacuK256V+6U6umsq3xrnAoIBAQCNbVZl0H3iknx/OzYhYwrCAzYoMEheI4P08LNncKo09jNRpezDbeGTO1KgXozZ/EjrwAPoFzq9c//C2hG5/yOsLdjdD5y1Qug7sEV7BbPurOpELwWxUpxk2EdUQRYA8CJW3heeIRQ1Bw94DUjqkqKkbXYOxh8ioGWSN9jZA3ZqI40SMpnMS0Tjki64MnzqxaXCJeikU544gkYwDtLwjMTxIscsj7b7oLBiIL1nfeFIeq9re41xI3+q9LdaVxDY02UIoh1Qk7f/iABFrCivt4v86wtV1fNYrlegGyiV+DRFLD/Bk665nDKpgLbIqS3eq0u9xvbB+uF3AzCQPgTPOxwV",
+ "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",
- "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"),
+ "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"),
new("id-MLDSA87-ECDSA-P521-SHA512",
CompositeMLDsaAlgorithm.MLDsa87WithECDsaP521,
- "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",
+ "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",
- "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"),
+ "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"),
];
}
}
diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/CompositeMLDsa/CompositeMLDsaTestData.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/CompositeMLDsa/CompositeMLDsaTestData.cs
index 65bb8c366609a9..d2ba00adbb7ea9 100644
--- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/CompositeMLDsa/CompositeMLDsaTestData.cs
+++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/CompositeMLDsa/CompositeMLDsaTestData.cs
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System.Collections.Generic;
+using System.Formats.Asn1;
using System.Linq;
using Xunit.Sdk;
@@ -20,6 +21,8 @@ public class CompositeMLDsaTestVector
internal byte[] Pkcs8 { get; }
internal byte[] Signature { get; }
+ internal byte[] Spki { get; }
+
internal CompositeMLDsaTestVector(string tcId, CompositeMLDsaAlgorithm algo, string pk, string x5c, string sk, string sk_pkcs8, string m, string s)
{
Id = tcId;
@@ -30,6 +33,19 @@ internal CompositeMLDsaTestVector(string tcId, CompositeMLDsaAlgorithm algo, str
Pkcs8 = Convert.FromBase64String(sk_pkcs8);
Message = Convert.FromBase64String(m);
Signature = Convert.FromBase64String(s);
+
+ AsnReader reader = new AsnReader(Certificate, AsnEncodingRules.DER);
+ AsnReader certificate = reader.ReadSequence();
+ AsnReader tbsCertificate = certificate.ReadSequence();
+
+ tbsCertificate.ReadEncodedValue(); // Version
+ tbsCertificate.ReadEncodedValue(); // SerialNumber
+ tbsCertificate.ReadEncodedValue(); // Signature
+ tbsCertificate.ReadEncodedValue(); // Issuer
+ tbsCertificate.ReadEncodedValue(); // Validity
+ tbsCertificate.ReadEncodedValue(); // Subject
+
+ Spki = tbsCertificate.ReadEncodedValue().ToArray();
}
public override string ToString() => Id;
@@ -43,7 +59,7 @@ internal CompositeMLDsaTestVector(string tcId, CompositeMLDsaAlgorithm algo, str
internal static CompositeMLDsaTestVector[] SupportedAlgorithmIetfVectors =>
field ??= AllIetfVectors.Where(v => CompositeMLDsa.IsAlgorithmSupported(v.Algorithm)).ToArray();
- public static IEnumerable