diff --git a/documentation/design-docs/ipc-protocol.md b/documentation/design-docs/ipc-protocol.md index a02c3582e7..f4334e396d 100644 --- a/documentation/design-docs/ipc-protocol.md +++ b/documentation/design-docs/ipc-protocol.md @@ -324,7 +324,7 @@ enum class ProcessCommandId : uint8_t ProcessInfo2 = 0x04, EnablePerfMap = 0x05, DisablePerfMap = 0x06, - ApplyStartupHook = 0x07 + ApplyStartupHook = 0x07, ProcessInfo3 = 0x08, // future } @@ -1327,6 +1327,50 @@ struct Payload > Available since .NET 6.0 +### `SetEnvironmentVariable` + +Command Code: `0x0403` + +The `SetEnvironmentVariable` command sets an environment variable in the runtime process. + +In the event of an [error](#Errors), the runtime will attempt to send an error message and subsequently close the connection. + +#### Inputs: + +Header: `{ Magic; Size; 0x0403; 0x0000 }` + +Payload: +* `string name`: The environment variable name to set. +* `string value`: The value to assign. + +#### Returns (as an IPC Message Payload): + +Header: `{ Magic; size; 0xFF00; 0x0000; }` + +`SetEnvironmentVariable` returns: +* `int32 hresult`: The result of setting the environment variable (`0` indicates success) + +##### Details: + +Input: +```c +Payload +{ + string name + string value +} +``` + +Returns: +```c +Payload +{ + int32 hresult +} +``` + +> Available since .NET 6.0 + ### `ProcessInfo2` Command Code: `0x0404` diff --git a/eng/Version.Details.props b/eng/Version.Details.props index e98bd685db..90f23f6297 100644 --- a/eng/Version.Details.props +++ b/eng/Version.Details.props @@ -6,12 +6,16 @@ This file should be imported by eng/Versions.props - 4.0.0-beta.25610.1 - 4.0.0-beta.25610.1 + 4.0.0-beta.26072.1 + 4.0.0-beta.26072.1 2.0.0-beta5.25210.1 1.0.105-preview.225 + + 10.0.0-beta.26066.3 + 10.0.0-beta.26066.3 + 7.0.0-beta.22316.2 10.0.2 10.0.2-servicing.25603.103 @@ -19,8 +23,6 @@ This file should be imported by eng/Versions.props 5.0.0-2.25603.103 5.0.0-2.25603.103 10.0.102 - 10.0.0-beta.25603.103 - 10.0.0-beta.25603.103 10.0.102-servicing.25603.103 10.0.2 10.0.2-servicing.25603.103 @@ -30,8 +32,6 @@ This file should be imported by eng/Versions.props 10.0.2-servicing.25603.103 10.0.2-servicing.25603.103 10.0.2-servicing.25603.103 - - 7.0.0-beta.22316.2 @@ -42,6 +42,10 @@ This file should be imported by eng/Versions.props $(SystemCommandLinePackageVersion) $(XamarinAndroidToolsAndroidSdkPackageVersion) + + $(MicrosoftDotNetArcadeSdkPackageVersion) + $(MicrosoftDotNetCodeAnalysisPackageVersion) + $(MicrosoftDotNetRemoteExecutorPackageVersion) $(MicrosoftAspNetCoreAppRefPackageVersion) $(MicrosoftAspNetCoreAppRefInternalPackageVersion) @@ -49,8 +53,6 @@ This file should be imported by eng/Versions.props $(MicrosoftCodeAnalysisAnalyzersPackageVersion) $(MicrosoftCodeAnalysisCSharpPackageVersion) $(MicrosoftCodeAnalysisNetAnalyzersPackageVersion) - $(MicrosoftDotNetArcadeSdkPackageVersion) - $(MicrosoftDotNetCodeAnalysisPackageVersion) $(MicrosoftNETSdkPackageVersion) $(MicrosoftNETCoreAppRefPackageVersion) $(MicrosoftNETCorePlatformsPackageVersion) @@ -60,7 +62,5 @@ This file should be imported by eng/Versions.props $(runtimeosxx64MicrosoftDotNetCdacTransportPackageVersion) $(runtimewinarm64MicrosoftDotNetCdacTransportPackageVersion) $(runtimewinx64MicrosoftDotNetCdacTransportPackageVersion) - - $(MicrosoftDotNetRemoteExecutorPackageVersion) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 5a7068e214..5f57c52542 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,13 +1,13 @@ - + https://github.com/microsoft/clrmd - 41c1e91786141d37b26cfdfb8059fc522e81fb8d + 6c44f5535222dbe59de9b7c5384d5303d56bdf5c - + https://github.com/microsoft/clrmd - 41c1e91786141d37b26cfdfb8059fc522e81fb8d + 6c44f5535222dbe59de9b7c5384d5303d56bdf5c https://github.com/dotnet/command-line-api @@ -19,13 +19,13 @@ - - https://github.com/dotnet/dotnet - 5ddd0ddc0ebadca21645a05c419ed5a034454605 + + https://github.com/dotnet/arcade + af17297350d5e5357d2ab3d69369d2a58b8bc4ab - - https://github.com/dotnet/dotnet - 5ddd0ddc0ebadca21645a05c419ed5a034454605 + + https://github.com/dotnet/arcade + af17297350d5e5357d2ab3d69369d2a58b8bc4ab https://github.com/dotnet/arcade diff --git a/eng/Versions.props b/eng/Versions.props index e40a722c1e..52988e350d 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -3,7 +3,7 @@ https://github.com/dotnet/diagnostics preview - 9.0.0 + 10.0.0 true true - 9.0.10 - 8.0.21 + 9.0.12 + 8.0.23 default diff --git a/eng/common/core-templates/job/publish-build-assets.yml b/eng/common/core-templates/job/publish-build-assets.yml index e7daa6d2fa..b955fac6e1 100644 --- a/eng/common/core-templates/job/publish-build-assets.yml +++ b/eng/common/core-templates/job/publish-build-assets.yml @@ -80,7 +80,7 @@ jobs: # If it's not devdiv, it's dnceng ${{ if ne(variables['System.TeamProject'], 'DevDiv') }}: name: NetCore1ESPool-Publishing-Internal - image: windows.vs2019.amd64 + image: windows.vs2022.amd64 os: windows steps: - ${{ if eq(parameters.is1ESPipeline, '') }}: @@ -120,6 +120,14 @@ jobs: - task: NuGetAuthenticate@1 + # Populate internal runtime variables. + - template: /eng/common/templates/steps/enable-internal-sources.yml + ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: + parameters: + legacyCredential: $(dn-bot-dnceng-artifact-feeds-rw) + + - template: /eng/common/templates/steps/enable-internal-runtimes.yml + - task: AzureCLI@2 displayName: Publish Build Assets inputs: @@ -132,6 +140,9 @@ jobs: /p:IsAssetlessBuild=${{ parameters.isAssetlessBuild }} /p:MaestroApiEndpoint=https://maestro.dot.net /p:OfficialBuildId=$(OfficialBuildId) + -runtimeSourceFeed https://ci.dot.net/internal + -runtimeSourceFeedKey '$(dotnetbuilds-internal-container-read-token-base64)' + condition: ${{ parameters.condition }} continueOnError: ${{ parameters.continueOnError }} @@ -200,6 +211,8 @@ jobs: -ArtifactsPublishingAdditionalParameters '${{ parameters.artifactsPublishingAdditionalParameters }}' -SymbolPublishingAdditionalParameters '${{ parameters.symbolPublishingAdditionalParameters }}' -SkipAssetsPublishing '${{ parameters.isAssetlessBuild }}' + -runtimeSourceFeed https://ci.dot.net/internal + -runtimeSourceFeedKey '$(dotnetbuilds-internal-container-read-token-base64)' - ${{ if eq(parameters.enablePublishBuildArtifacts, 'true') }}: - template: /eng/common/core-templates/steps/publish-logs.yml diff --git a/eng/common/core-templates/job/source-build.yml b/eng/common/core-templates/job/source-build.yml index d805d5faeb..c08b3ad8ad 100644 --- a/eng/common/core-templates/job/source-build.yml +++ b/eng/common/core-templates/job/source-build.yml @@ -63,7 +63,7 @@ jobs: demands: ImageOverride -equals build.ubuntu.2004.amd64 ${{ if eq(variables['System.TeamProject'], 'internal') }}: name: $[replace(replace(eq(contains(coalesce(variables['System.PullRequest.TargetBranch'], variables['Build.SourceBranch'], 'refs/heads/main'), 'release'), 'true'), True, 'NetCore1ESPool-Svc-Internal'), False, 'NetCore1ESPool-Internal')] - image: 1es-mariner-2 + image: Azure-Linux-3-Amd64 os: linux ${{ else }}: pool: diff --git a/eng/common/core-templates/job/source-index-stage1.yml b/eng/common/core-templates/job/source-index-stage1.yml index 30530359a5..76baf5c272 100644 --- a/eng/common/core-templates/job/source-index-stage1.yml +++ b/eng/common/core-templates/job/source-index-stage1.yml @@ -3,7 +3,7 @@ parameters: sourceIndexBuildCommand: powershell -NoLogo -NoProfile -ExecutionPolicy Bypass -Command "eng/common/build.ps1 -restore -build -binarylog -ci" preSteps: [] binlogPath: artifacts/log/Debug/Build.binlog - condition: '' + condition: eq(variables['Build.SourceBranch'], 'refs/heads/main') dependsOn: '' pool: '' is1ESPipeline: '' @@ -25,10 +25,10 @@ jobs: pool: ${{ if eq(variables['System.TeamProject'], 'public') }}: name: $(DncEngPublicBuildPool) - image: windows.vs2022.amd64.open + image: windows.vs2026preview.scout.amd64.open ${{ if eq(variables['System.TeamProject'], 'internal') }}: name: $(DncEngInternalBuildPool) - image: windows.vs2022.amd64 + image: windows.vs2026preview.scout.amd64 steps: - ${{ if eq(parameters.is1ESPipeline, '') }}: @@ -41,4 +41,4 @@ jobs: - template: /eng/common/core-templates/steps/source-index-stage1-publish.yml parameters: - binLogPath: ${{ parameters.binLogPath }} \ No newline at end of file + binLogPath: ${{ parameters.binLogPath }} diff --git a/eng/common/core-templates/post-build/post-build.yml b/eng/common/core-templates/post-build/post-build.yml index 55361908c2..b942a79ef0 100644 --- a/eng/common/core-templates/post-build/post-build.yml +++ b/eng/common/core-templates/post-build/post-build.yml @@ -127,11 +127,11 @@ stages: ${{ else }}: ${{ if eq(parameters.is1ESPipeline, true) }}: name: $(DncEngInternalBuildPool) - image: windows.vs2022.amd64 + image: windows.vs2026preview.scout.amd64 os: windows ${{ else }}: name: $(DncEngInternalBuildPool) - demands: ImageOverride -equals windows.vs2022.amd64 + demands: ImageOverride -equals windows.vs2026preview.scout.amd64 steps: - template: /eng/common/core-templates/post-build/setup-maestro-vars.yml @@ -175,7 +175,7 @@ stages: os: windows ${{ else }}: name: $(DncEngInternalBuildPool) - demands: ImageOverride -equals windows.vs2022.amd64 + demands: ImageOverride -equals windows.vs2026preview.scout.amd64 steps: - template: /eng/common/core-templates/post-build/setup-maestro-vars.yml parameters: @@ -236,7 +236,7 @@ stages: os: windows ${{ else }}: name: $(DncEngInternalBuildPool) - demands: ImageOverride -equals windows.vs2022.amd64 + demands: ImageOverride -equals windows.vs2026preview.scout.amd64 steps: - template: /eng/common/core-templates/post-build/setup-maestro-vars.yml parameters: @@ -293,11 +293,11 @@ stages: ${{ else }}: ${{ if eq(parameters.is1ESPipeline, true) }}: name: NetCore1ESPool-Publishing-Internal - image: windows.vs2019.amd64 + image: windows.vs2022.amd64 os: windows ${{ else }}: name: NetCore1ESPool-Publishing-Internal - demands: ImageOverride -equals windows.vs2019.amd64 + demands: ImageOverride -equals windows.vs2022.amd64 steps: - template: /eng/common/core-templates/post-build/setup-maestro-vars.yml parameters: @@ -307,6 +307,13 @@ stages: - task: NuGetAuthenticate@1 + # Populate internal runtime variables. + - template: /eng/common/templates/steps/enable-internal-sources.yml + parameters: + legacyCredential: $(dn-bot-dnceng-artifact-feeds-rw) + + - template: /eng/common/templates/steps/enable-internal-runtimes.yml + # Darc is targeting 8.0, so make sure it's installed - task: UseDotNet@2 inputs: @@ -328,3 +335,5 @@ stages: -ArtifactsPublishingAdditionalParameters '${{ parameters.artifactsPublishingAdditionalParameters }}' -SymbolPublishingAdditionalParameters '${{ parameters.symbolPublishingAdditionalParameters }}' -SkipAssetsPublishing '${{ parameters.isAssetlessBuild }}' + -runtimeSourceFeed https://ci.dot.net/internal + -runtimeSourceFeedKey '$(dotnetbuilds-internal-container-read-token-base64)' diff --git a/eng/common/core-templates/steps/install-microbuild.yml b/eng/common/core-templates/steps/install-microbuild.yml index f2248ebfd7..553fce66b9 100644 --- a/eng/common/core-templates/steps/install-microbuild.yml +++ b/eng/common/core-templates/steps/install-microbuild.yml @@ -11,22 +11,41 @@ parameters: # Unfortunately, _SignType can't be used to exclude the use of the service connection in non-real sign scenarios. The # variable is not available in template expression. _SignType has a very large proliferation across .NET, so replacing it is tough. microbuildUseESRP: true + # Microbuild installation directory + microBuildOutputFolder: $(Agent.TempDirectory)/MicroBuild continueOnError: false steps: - ${{ if eq(parameters.enableMicrobuild, 'true') }}: - ${{ if eq(parameters.enableMicrobuildForMacAndLinux, 'true') }}: - # Installing .NET 8 is required to use the MicroBuild signing plugin on non-Windows platforms + # Needed to download the MicroBuild plugin nupkgs on Mac and Linux when nuget.exe is unavailable - task: UseDotNet@2 displayName: Install .NET 8.0 SDK for MicroBuild Plugin inputs: packageType: sdk version: 8.0.x - # Installing the SDK in a '.dotnet-microbuild' directory is required for signing. - # See target FindDotNetPathForMicroBuild in arcade/src/Microsoft.DotNet.Arcade.Sdk/tools/Sign.proj - # Do not remove '.dotnet-microbuild' from the path without changing the corresponding logic. - installationPath: $(Agent.TempDirectory)/.dotnet-microbuild + installationPath: ${{ parameters.microBuildOutputFolder }}/.dotnet-microbuild + condition: and(succeeded(), ne(variables['Agent.Os'], 'Windows_NT')) + + - script: | + set -euo pipefail + + # UseDotNet@2 prepends the dotnet executable path to the PATH variable, so we can call dotnet directly + version=$(dotnet --version) + cat << 'EOF' > ${{ parameters.microBuildOutputFolder }}/global.json + { + "sdk": { + "version": "$version", + "paths": [ + "${{ parameters.microBuildOutputFolder }}/.dotnet-microbuild" + ], + "errorMessage": "The .NET SDK version $version is required to install the MicroBuild signing plugin." + } + } + EOF + displayName: 'Add global.json to MicroBuild Installation path' + workingDirectory: ${{ parameters.microBuildOutputFolder }} condition: and(succeeded(), ne(variables['Agent.Os'], 'Windows_NT')) - script: | @@ -64,7 +83,7 @@ steps: ConnectedPMEServiceName: 248d384a-b39b-46e3-8ad5-c2c210d5e7ca env: TeamName: $(_TeamName) - MicroBuildOutputFolderOverride: $(Agent.TempDirectory)/MicroBuild + MicroBuildOutputFolderOverride: ${{ parameters.microBuildOutputFolder }} SYSTEM_ACCESSTOKEN: $(System.AccessToken) continueOnError: ${{ parameters.continueOnError }} condition: and(succeeded(), eq(variables['Agent.Os'], 'Windows_NT'), in(variables['_SignType'], 'real', 'test')) @@ -76,6 +95,7 @@ steps: signType: $(_SignType) zipSources: false feedSource: https://dnceng.pkgs.visualstudio.com/_packaging/MicroBuildToolset/nuget/v3/index.json + workingDirectory: ${{ parameters.microBuildOutputFolder }} ${{ if eq(parameters.microbuildUseESRP, true) }}: ConnectedServiceName: 'MicroBuild Signing Task (DevDiv)' ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: @@ -84,7 +104,7 @@ steps: ConnectedPMEServiceName: c24de2a5-cc7a-493d-95e4-8e5ff5cad2bc env: TeamName: $(_TeamName) - MicroBuildOutputFolderOverride: $(Agent.TempDirectory)/MicroBuild + 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 10f825e270..5a927b4c7b 100644 --- a/eng/common/core-templates/steps/publish-logs.yml +++ b/eng/common/core-templates/steps/publish-logs.yml @@ -26,8 +26,10 @@ steps: # 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 '$(System.DefaultWorkingDirectory)/PostBuildLogs' - -BinlogToolVersion ${{parameters.BinlogToolVersion}} + -BinlogToolVersion '${{parameters.BinlogToolVersion}}' -TokensFilePath '$(System.DefaultWorkingDirectory)/eng/BinlogSecretsRedactionFile.txt' + -runtimeSourceFeed https://ci.dot.net/internal + -runtimeSourceFeedKey '$(dotnetbuilds-internal-container-read-token-base64)' '$(publishing-dnceng-devdiv-code-r-build-re)' '$(MaestroAccessToken)' '$(dn-bot-all-orgs-artifact-feeds-rw)' diff --git a/eng/common/core-templates/steps/source-build.yml b/eng/common/core-templates/steps/source-build.yml index acf16ed349..b9c86c18ae 100644 --- a/eng/common/core-templates/steps/source-build.yml +++ b/eng/common/core-templates/steps/source-build.yml @@ -24,7 +24,7 @@ steps: # in the default public locations. internalRuntimeDownloadArgs= if [ '$(dotnetbuilds-internal-container-read-token-base64)' != '$''(dotnetbuilds-internal-container-read-token-base64)' ]; then - internalRuntimeDownloadArgs='/p:DotNetRuntimeSourceFeed=https://ci.dot.net/internal /p:DotNetRuntimeSourceFeedKey=$(dotnetbuilds-internal-container-read-token-base64) --runtimesourcefeed https://ci.dot.net/internal --runtimesourcefeedkey $(dotnetbuilds-internal-container-read-token-base64)' + internalRuntimeDownloadArgs='/p:DotNetRuntimeSourceFeed=https://ci.dot.net/internal /p:DotNetRuntimeSourceFeedKey=$(dotnetbuilds-internal-container-read-token-base64) --runtimesourcefeed https://ci.dot.net/internal --runtimesourcefeedkey '$(dotnetbuilds-internal-container-read-token-base64)'' fi buildConfig=Release diff --git a/eng/common/internal-feed-operations.ps1 b/eng/common/internal-feed-operations.ps1 index 92b77347d9..c282d3ae40 100644 --- a/eng/common/internal-feed-operations.ps1 +++ b/eng/common/internal-feed-operations.ps1 @@ -26,7 +26,7 @@ function SetupCredProvider { $url = 'https://raw.githubusercontent.com/microsoft/artifacts-credprovider/master/helpers/installcredprovider.ps1' Write-Host "Writing the contents of 'installcredprovider.ps1' locally..." - Invoke-WebRequest $url -OutFile installcredprovider.ps1 + Invoke-WebRequest $url -UseBasicParsing -OutFile installcredprovider.ps1 Write-Host 'Installing plugin...' .\installcredprovider.ps1 -Force diff --git a/eng/common/post-build/nuget-verification.ps1 b/eng/common/post-build/nuget-verification.ps1 index ac5c69ffca..eea88e653c 100644 --- a/eng/common/post-build/nuget-verification.ps1 +++ b/eng/common/post-build/nuget-verification.ps1 @@ -65,7 +65,7 @@ if ($NuGetExePath) { Write-Host "Downloading nuget.exe from $nugetExeUrl..." $ProgressPreference = 'SilentlyContinue' try { - Invoke-WebRequest $nugetExeUrl -OutFile $downloadedNuGetExe + Invoke-WebRequest $nugetExeUrl -UseBasicParsing -OutFile $downloadedNuGetExe $ProgressPreference = 'Continue' } catch { $ProgressPreference = 'Continue' diff --git a/eng/common/post-build/publish-using-darc.ps1 b/eng/common/post-build/publish-using-darc.ps1 index 1eda208a3b..48e55598bd 100644 --- a/eng/common/post-build/publish-using-darc.ps1 +++ b/eng/common/post-build/publish-using-darc.ps1 @@ -7,7 +7,9 @@ param( [Parameter(Mandatory=$false)][string] $ArtifactsPublishingAdditionalParameters, [Parameter(Mandatory=$false)][string] $SymbolPublishingAdditionalParameters, [Parameter(Mandatory=$false)][string] $RequireDefaultChannels, - [Parameter(Mandatory=$false)][string] $SkipAssetsPublishing + [Parameter(Mandatory=$false)][string] $SkipAssetsPublishing, + [Parameter(Mandatory=$false)][string] $runtimeSourceFeed, + [Parameter(Mandatory=$false)][string] $runtimeSourceFeedKey ) try { diff --git a/eng/common/post-build/redact-logs.ps1 b/eng/common/post-build/redact-logs.ps1 index b7fc195915..472d5bb562 100644 --- a/eng/common/post-build/redact-logs.ps1 +++ b/eng/common/post-build/redact-logs.ps1 @@ -7,8 +7,9 @@ param( # File with strings to redact - separated by newlines. # For comments start the line with '# ' - such lines are ignored [Parameter(Mandatory=$false)][string] $TokensFilePath, - [Parameter(ValueFromRemainingArguments=$true)][String[]]$TokensToRedact -) + [Parameter(ValueFromRemainingArguments=$true)][String[]]$TokensToRedact, + [Parameter(Mandatory=$false)][string] $runtimeSourceFeed, + [Parameter(Mandatory=$false)][string] $runtimeSourceFeedKey) try { $ErrorActionPreference = 'Stop' diff --git a/eng/common/sdk-task.ps1 b/eng/common/sdk-task.ps1 index b62e132d32..b64b66a627 100644 --- a/eng/common/sdk-task.ps1 +++ b/eng/common/sdk-task.ps1 @@ -9,6 +9,8 @@ Param( [switch][Alias('nobl')]$excludeCIBinaryLog, [switch]$noWarnAsError, [switch] $help, + [string] $runtimeSourceFeed = '', + [string] $runtimeSourceFeedKey = '', [Parameter(ValueFromRemainingArguments=$true)][String[]]$properties ) @@ -68,7 +70,7 @@ try { $GlobalJson.tools | Add-Member -Name "vs" -Value (ConvertFrom-Json "{ `"version`": `"16.5`" }") -MemberType NoteProperty } if( -not ($GlobalJson.tools.PSObject.Properties.Name -match "xcopy-msbuild" )) { - $GlobalJson.tools | Add-Member -Name "xcopy-msbuild" -Value "17.13.0" -MemberType NoteProperty + $GlobalJson.tools | Add-Member -Name "xcopy-msbuild" -Value "18.0.0" -MemberType NoteProperty } if ($GlobalJson.tools."xcopy-msbuild".Trim() -ine "none") { $xcopyMSBuildToolsFolder = InitializeXCopyMSBuild $GlobalJson.tools."xcopy-msbuild" -install $true diff --git a/eng/common/templates/variables/pool-providers.yml b/eng/common/templates/variables/pool-providers.yml index e0b19c14a0..18693ea120 100644 --- a/eng/common/templates/variables/pool-providers.yml +++ b/eng/common/templates/variables/pool-providers.yml @@ -23,7 +23,7 @@ # # pool: # name: $(DncEngInternalBuildPool) -# demands: ImageOverride -equals windows.vs2019.amd64 +# demands: ImageOverride -equals windows.vs2022.amd64 variables: - ${{ if eq(variables['System.TeamProject'], 'internal') }}: - template: /eng/common/templates-official/variables/pool-providers.yml diff --git a/eng/common/tools.ps1 b/eng/common/tools.ps1 index 06b44de787..049fe6db99 100644 --- a/eng/common/tools.ps1 +++ b/eng/common/tools.ps1 @@ -277,7 +277,7 @@ function GetDotNetInstallScript([string] $dotnetRoot) { Retry({ Write-Host "GET $uri" - Invoke-WebRequest $uri -OutFile $installScript + Invoke-WebRequest $uri -UseBasicParsing -OutFile $installScript }) } @@ -394,8 +394,8 @@ function InitializeVisualStudioMSBuild([bool]$install, [object]$vsRequirements = # If the version of msbuild is going to be xcopied, # use this version. Version matches a package here: - # https://dev.azure.com/dnceng/public/_artifacts/feed/dotnet-eng/NuGet/Microsoft.DotNet.Arcade.MSBuild.Xcopy/versions/17.13.0 - $defaultXCopyMSBuildVersion = '17.13.0' + # https://dev.azure.com/dnceng/public/_artifacts/feed/dotnet-eng/NuGet/Microsoft.DotNet.Arcade.MSBuild.Xcopy/versions/18.0.0 + $defaultXCopyMSBuildVersion = '18.0.0' if (!$vsRequirements) { if (Get-Member -InputObject $GlobalJson.tools -Name 'vs') { @@ -510,7 +510,7 @@ function InitializeXCopyMSBuild([string]$packageVersion, [bool]$install) { Write-Host "Downloading $packageName $packageVersion" $ProgressPreference = 'SilentlyContinue' # Don't display the console progress UI - it's a huge perf hit Retry({ - Invoke-WebRequest "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/flat2/$packageName/$packageVersion/$packageName.$packageVersion.nupkg" -OutFile $packagePath + Invoke-WebRequest "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/flat2/$packageName/$packageVersion/$packageName.$packageVersion.nupkg" -UseBasicParsing -OutFile $packagePath }) if (!(Test-Path $packagePath)) { @@ -556,23 +556,30 @@ function LocateVisualStudio([object]$vsRequirements = $null){ 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 + Invoke-WebRequest "https://netcorenativeassets.blob.core.windows.net/resource-packages/external/windows/vswhere/$vswhereVersion/vswhere.exe" -UseBasicParsing -OutFile $vswhereExe }) } - if (!$vsRequirements) { $vsRequirements = $GlobalJson.tools.vs } + if (!$vsRequirements) { + if (Get-Member -InputObject $GlobalJson.tools -Name 'vs' -ErrorAction SilentlyContinue) { + $vsRequirements = $GlobalJson.tools.vs + } else { + $vsRequirements = $null + } + } + $args = @('-latest', '-format', 'json', '-requires', 'Microsoft.Component.MSBuild', '-products', '*') if (!$excludePrereleaseVS) { $args += '-prerelease' } - if (Get-Member -InputObject $vsRequirements -Name 'version') { + if ($vsRequirements -and (Get-Member -InputObject $vsRequirements -Name 'version' -ErrorAction SilentlyContinue)) { $args += '-version' $args += $vsRequirements.version } - if (Get-Member -InputObject $vsRequirements -Name 'components') { + if ($vsRequirements -and (Get-Member -InputObject $vsRequirements -Name 'components' -ErrorAction SilentlyContinue)) { foreach ($component in $vsRequirements.components) { $args += '-requires' $args += $component diff --git a/eng/pipelines/templateInternal.yml b/eng/pipelines/templateInternal.yml index 2f2c05b298..1cb31f4a97 100644 --- a/eng/pipelines/templateInternal.yml +++ b/eng/pipelines/templateInternal.yml @@ -30,8 +30,7 @@ extends: tsa: enabled: true settings: - # Do not add CFSClean2 yet - microbuild needs some endpoints behind it. - networkIsolationPolicy: Permissive,CFSClean + networkIsolationPolicy: Permissive,CFSClean,CFSClean2 featureFlags: autoBaseline: true diff --git a/global.json b/global.json index 9f6c495ef7..c22c2ccbb2 100644 --- a/global.json +++ b/global.json @@ -1,11 +1,11 @@ { "sdk": { - "version": "10.0.101", + "version": "10.0.102", "allowPrerelease": true, "rollForward": "major" }, "tools": { - "dotnet": "10.0.101", + "dotnet": "10.0.102", "runtimes": { "dotnet": [ "$(MicrosoftNETCoreApp80Version)" @@ -18,6 +18,6 @@ "msbuild-sdks": { "Microsoft.Build.NoTargets": "3.5.0", "Microsoft.Build.Traversal": "3.4.0", - "Microsoft.DotNet.Arcade.Sdk": "10.0.0-beta.25603.103" + "Microsoft.DotNet.Arcade.Sdk": "10.0.0-beta.26066.3" } } diff --git a/src/SOS/Strike/sos.cpp b/src/SOS/Strike/sos.cpp index f74b1c2c6b..65bda1e299 100644 --- a/src/SOS/Strike/sos.cpp +++ b/src/SOS/Strike/sos.cpp @@ -103,10 +103,10 @@ namespace sos { TADDR temp; if (FAILED(MOVE(temp, mAddress))) - sos::Throw("Object %s has an invalid method table.", DMLListNearObj(mAddress)); + sos::Throw("Failed to read memory at Object %s.", DMLListNearObj(mAddress)); if (temp == (TADDR)0) - sos::Throw("Object %s has an invalid method table.", DMLListNearObj(mAddress)); + sos::Throw("Object %s has a corrupt method table.", DMLListNearObj(mAddress)); mMT = temp & ~METHODTABLE_PTR_LOW_BITMASK; } diff --git a/src/SOS/Strike/strike.cpp b/src/SOS/Strike/strike.cpp index 4e3f74e9e5..5ea9d956d2 100644 --- a/src/SOS/Strike/strike.cpp +++ b/src/SOS/Strike/strike.cpp @@ -4513,9 +4513,9 @@ HRESULT PrintThreadsFromThreadStore(BOOL bMiniDump, BOOL bPrintLiveThreadsOnly) if (SafeReadMemory(taLTOH, &taMT, sizeof(taMT), NULL)) { if (NameForMT_s(taMT, g_mdName, mdNameLen)) - lastCol += WString(g_mdName) + W(" ") + ExceptionPtr(taLTOH); + lastCol += WString(g_mdName) + W(" ") + WString(ExceptionPtr(taLTOH)); else - lastCol += WString(W(" (")) + Pointer(taLTOH) + W(")"); + lastCol += WString(W(" (")) + WString(Pointer(taLTOH)) + W(")"); // Print something if there are nested exceptions on the thread if (Thread.firstNestedException) @@ -10942,7 +10942,10 @@ class ClrStackImpl out.WriteColumn(1, bFull ? String("") : NativePtr(ip)); // This is a clr!Frame. - out.WriteColumn(2, GetFrameFromAddress(TO_TADDR(FrameData.frameAddr), pStackWalk, bFull)); + WString frameName = GetFrameFromAddress(TO_TADDR(FrameData.frameAddr), pStackWalk, bFull); + if (IsDMLEnabled()) + frameName = DmlEscape(frameName); + out.WriteColumn(2, frameName); // Print out gc references for the Frame. for (unsigned int i = 0; i < refCount; ++i) @@ -10976,7 +10979,10 @@ class ClrStackImpl // The unmodified IP is displayed which points after the exception in most cases. This means that the // printed IP and the printed line number often will not map to one another and this is intentional. out.WriteColumn(1, InstructionPtr(ip)); - out.WriteColumn(2, MethodNameFromIP(ip, bSuppressLines, bFull, bFull, bAdjustIPForLineNumber)); + WString methodName = MethodNameFromIP(ip, bSuppressLines, bFull, bFull, bAdjustIPForLineNumber); + if (IsDMLEnabled()) + methodName = DmlEscape(methodName); + out.WriteColumn(2, methodName); // Print out gc references. refCount will be zero if bGC is false (or if we // failed to fetch gc reference information). @@ -11045,12 +11051,12 @@ class ClrStackImpl foundPlatform = true; String outputFormat3 = " %3s=%016llx %3s=%016llx %3s=%016llx\n"; String outputFormat2 = " %3s=%016llx %3s=%016llx\n"; - ExtOut(outputFormat3, "rsp", context.Amd64Context.Rsp, "rbp", context.Amd64Context.Rbp, "rip", context.Amd64Context.Rip); - ExtOut(outputFormat3, "rax", context.Amd64Context.Rax, "rbx", context.Amd64Context.Rbx, "rcx", context.Amd64Context.Rcx); - ExtOut(outputFormat3, "rdx", context.Amd64Context.Rdx, "rsi", context.Amd64Context.Rsi, "rdi", context.Amd64Context.Rdi); - ExtOut(outputFormat3, "r8", context.Amd64Context.R8, "r9", context.Amd64Context.R9, "r10", context.Amd64Context.R10); - ExtOut(outputFormat3, "r11", context.Amd64Context.R11, "r12", context.Amd64Context.R12, "r13", context.Amd64Context.R13); - ExtOut(outputFormat2, "r14", context.Amd64Context.R14, "r15", context.Amd64Context.R15); + ExtOut(outputFormat3.c_str(), "rsp", context.Amd64Context.Rsp, "rbp", context.Amd64Context.Rbp, "rip", context.Amd64Context.Rip); + ExtOut(outputFormat3.c_str(), "rax", context.Amd64Context.Rax, "rbx", context.Amd64Context.Rbx, "rcx", context.Amd64Context.Rcx); + ExtOut(outputFormat3.c_str(), "rdx", context.Amd64Context.Rdx, "rsi", context.Amd64Context.Rsi, "rdi", context.Amd64Context.Rdi); + ExtOut(outputFormat3.c_str(), "r8", context.Amd64Context.R8, "r9", context.Amd64Context.R9, "r10", context.Amd64Context.R10); + ExtOut(outputFormat3.c_str(), "r11", context.Amd64Context.R11, "r12", context.Amd64Context.R12, "r13", context.Amd64Context.R13); + ExtOut(outputFormat2.c_str(), "r14", context.Amd64Context.R14, "r15", context.Amd64Context.R15); } #endif #if defined(SOS_TARGET_X86) @@ -11059,9 +11065,9 @@ class ClrStackImpl foundPlatform = true; String outputFormat3 = " %3s=%08x %3s=%08x %3s=%08x\n"; String outputFormat2 = " %3s=%08x %3s=%08x\n"; - ExtOut(outputFormat3, "esp", context.X86Context.Esp, "ebp", context.X86Context.Ebp, "eip", context.X86Context.Eip); - ExtOut(outputFormat3, "eax", context.X86Context.Eax, "ebx", context.X86Context.Ebx, "ecx", context.X86Context.Ecx); - ExtOut(outputFormat3, "edx", context.X86Context.Edx, "esi", context.X86Context.Esi, "edi", context.X86Context.Edi); + ExtOut(outputFormat3.c_str(), "esp", context.X86Context.Esp, "ebp", context.X86Context.Ebp, "eip", context.X86Context.Eip); + ExtOut(outputFormat3.c_str(), "eax", context.X86Context.Eax, "ebx", context.X86Context.Ebx, "ecx", context.X86Context.Ecx); + ExtOut(outputFormat3.c_str(), "edx", context.X86Context.Edx, "esi", context.X86Context.Esi, "edi", context.X86Context.Edi); } #endif #if defined(SOS_TARGET_ARM) @@ -11071,13 +11077,13 @@ class ClrStackImpl String outputFormat3 = " %3s=%08x %3s=%08x %3s=%08x\n"; String outputFormat2 = " %s=%08x %s=%08x\n"; String outputFormat1 = " %s=%08x\n"; - ExtOut(outputFormat3, "r0", context.ArmContext.R0, "r1", context.ArmContext.R1, "r2", context.ArmContext.R2); - ExtOut(outputFormat3, "r3", context.ArmContext.R3, "r4", context.ArmContext.R4, "r5", context.ArmContext.R5); - ExtOut(outputFormat3, "r6", context.ArmContext.R6, "r7", context.ArmContext.R7, "r8", context.ArmContext.R8); - ExtOut(outputFormat3, "r9", context.ArmContext.R9, "r10", context.ArmContext.R10, "r11", context.ArmContext.R11); - ExtOut(outputFormat1, "r12", context.ArmContext.R12); - ExtOut(outputFormat3, "sp", context.ArmContext.Sp, "lr", context.ArmContext.Lr, "pc", context.ArmContext.Pc); - ExtOut(outputFormat2, "cpsr", context.ArmContext.Cpsr, "fpscr", context.ArmContext.Fpscr); + ExtOut(outputFormat3.c_str(), "r0", context.ArmContext.R0, "r1", context.ArmContext.R1, "r2", context.ArmContext.R2); + ExtOut(outputFormat3.c_str(), "r3", context.ArmContext.R3, "r4", context.ArmContext.R4, "r5", context.ArmContext.R5); + ExtOut(outputFormat3.c_str(), "r6", context.ArmContext.R6, "r7", context.ArmContext.R7, "r8", context.ArmContext.R8); + ExtOut(outputFormat3.c_str(), "r9", context.ArmContext.R9, "r10", context.ArmContext.R10, "r11", context.ArmContext.R11); + ExtOut(outputFormat1.c_str(), "r12", context.ArmContext.R12); + ExtOut(outputFormat3.c_str(), "sp", context.ArmContext.Sp, "lr", context.ArmContext.Lr, "pc", context.ArmContext.Pc); + ExtOut(outputFormat2.c_str(), "cpsr", context.ArmContext.Cpsr, "fpscr", context.ArmContext.Fpscr); } #endif #if defined(SOS_TARGET_ARM64) @@ -11103,17 +11109,17 @@ class ClrStackImpl { foundPlatform = true; String outputFormat3 = " %3s=%016llx %3s=%016llx %3s=%016llx\n"; - ExtOut(outputFormat3, "r0", context.RiscV64Context.R0, "ra", context.RiscV64Context.Ra, "sp", context.RiscV64Context.Sp); - ExtOut(outputFormat3, "gp", context.RiscV64Context.Gp, "tp", context.RiscV64Context.Tp, "t0", context.RiscV64Context.T0); - ExtOut(outputFormat3, "t1", context.RiscV64Context.T1, "t2", context.RiscV64Context.T2, "fp", context.RiscV64Context.Fp); - ExtOut(outputFormat3, "s1", context.RiscV64Context.S1, "a0", context.RiscV64Context.A0, "a1", context.RiscV64Context.A1); - ExtOut(outputFormat3, "a2", context.RiscV64Context.A2, "a3", context.RiscV64Context.A3, "a4", context.RiscV64Context.A4); - ExtOut(outputFormat3, "a5", context.RiscV64Context.A5, "a6", context.RiscV64Context.A6, "a7", context.RiscV64Context.A7); - ExtOut(outputFormat3, "s2", context.RiscV64Context.S2, "s3", context.RiscV64Context.S3, "s4", context.RiscV64Context.S4); - ExtOut(outputFormat3, "s5", context.RiscV64Context.S5, "s6", context.RiscV64Context.S6, "s7", context.RiscV64Context.S7); - ExtOut(outputFormat3, "s8", context.RiscV64Context.S8, "s9", context.RiscV64Context.S9, "s10", context.RiscV64Context.S10); - ExtOut(outputFormat3, "s11", context.RiscV64Context.S11, "t3", context.RiscV64Context.T3, "t4", context.RiscV64Context.T4); - ExtOut(outputFormat3, "t5", context.RiscV64Context.T5, "t6", context.RiscV64Context.T6, "pc", context.RiscV64Context.Pc); + ExtOut(outputFormat3.c_str(), "r0", context.RiscV64Context.R0, "ra", context.RiscV64Context.Ra, "sp", context.RiscV64Context.Sp); + ExtOut(outputFormat3.c_str(), "gp", context.RiscV64Context.Gp, "tp", context.RiscV64Context.Tp, "t0", context.RiscV64Context.T0); + ExtOut(outputFormat3.c_str(), "t1", context.RiscV64Context.T1, "t2", context.RiscV64Context.T2, "fp", context.RiscV64Context.Fp); + ExtOut(outputFormat3.c_str(), "s1", context.RiscV64Context.S1, "a0", context.RiscV64Context.A0, "a1", context.RiscV64Context.A1); + ExtOut(outputFormat3.c_str(), "a2", context.RiscV64Context.A2, "a3", context.RiscV64Context.A3, "a4", context.RiscV64Context.A4); + ExtOut(outputFormat3.c_str(), "a5", context.RiscV64Context.A5, "a6", context.RiscV64Context.A6, "a7", context.RiscV64Context.A7); + ExtOut(outputFormat3.c_str(), "s2", context.RiscV64Context.S2, "s3", context.RiscV64Context.S3, "s4", context.RiscV64Context.S4); + ExtOut(outputFormat3.c_str(), "s5", context.RiscV64Context.S5, "s6", context.RiscV64Context.S6, "s7", context.RiscV64Context.S7); + ExtOut(outputFormat3.c_str(), "s8", context.RiscV64Context.S8, "s9", context.RiscV64Context.S9, "s10", context.RiscV64Context.S10); + ExtOut(outputFormat3.c_str(), "s11", context.RiscV64Context.S11, "t3", context.RiscV64Context.T3, "t4", context.RiscV64Context.T4); + ExtOut(outputFormat3.c_str(), "t5", context.RiscV64Context.T5, "t6", context.RiscV64Context.T6, "pc", context.RiscV64Context.Pc); } #endif #if defined(SOS_TARGET_LOONGARCH64) @@ -11121,17 +11127,17 @@ class ClrStackImpl { foundPlatform = true; String outputFormat3 = " %3s=%016llx %3s=%016llx %3s=%016llx\n"; - ExtOut(outputFormat3, "r0", context.LoongArch64Context.R0, "ra", context.LoongArch64Context.Ra, "tp", context.LoongArch64Context.Tp); - ExtOut(outputFormat3, "sp", context.LoongArch64Context.Sp, "a0", context.LoongArch64Context.A0, "a1", context.LoongArch64Context.A1); - ExtOut(outputFormat3, "a2", context.LoongArch64Context.A2, "a3", context.LoongArch64Context.A3, "a4", context.LoongArch64Context.A4); - ExtOut(outputFormat3, "a5", context.LoongArch64Context.A5, "a6", context.LoongArch64Context.A6, "a7", context.LoongArch64Context.A7); - ExtOut(outputFormat3, "t0", context.LoongArch64Context.T0, "t1", context.LoongArch64Context.T1, "t2", context.LoongArch64Context.T2); - ExtOut(outputFormat3, "t3", context.LoongArch64Context.T3, "t4", context.LoongArch64Context.T4, "t5", context.LoongArch64Context.T5); - ExtOut(outputFormat3, "t6", context.LoongArch64Context.T6, "t7", context.LoongArch64Context.T7, "t8", context.LoongArch64Context.T8); - ExtOut(outputFormat3, "x0", context.LoongArch64Context.X0, "fp", context.LoongArch64Context.Fp, "s0", context.LoongArch64Context.S0); - ExtOut(outputFormat3, "s1", context.LoongArch64Context.S1, "s2", context.LoongArch64Context.S2, "s3", context.LoongArch64Context.S3); - ExtOut(outputFormat3, "s4", context.LoongArch64Context.S4, "s5", context.LoongArch64Context.S5, "s6", context.LoongArch64Context.S6); - ExtOut(outputFormat3, "s7", context.LoongArch64Context.S7, "s8", context.LoongArch64Context.S8, "pc", context.LoongArch64Context.Pc); + ExtOut(outputFormat3.c_str(), "r0", context.LoongArch64Context.R0, "ra", context.LoongArch64Context.Ra, "tp", context.LoongArch64Context.Tp); + ExtOut(outputFormat3.c_str(), "sp", context.LoongArch64Context.Sp, "a0", context.LoongArch64Context.A0, "a1", context.LoongArch64Context.A1); + ExtOut(outputFormat3.c_str(), "a2", context.LoongArch64Context.A2, "a3", context.LoongArch64Context.A3, "a4", context.LoongArch64Context.A4); + ExtOut(outputFormat3.c_str(), "a5", context.LoongArch64Context.A5, "a6", context.LoongArch64Context.A6, "a7", context.LoongArch64Context.A7); + ExtOut(outputFormat3.c_str(), "t0", context.LoongArch64Context.T0, "t1", context.LoongArch64Context.T1, "t2", context.LoongArch64Context.T2); + ExtOut(outputFormat3.c_str(), "t3", context.LoongArch64Context.T3, "t4", context.LoongArch64Context.T4, "t5", context.LoongArch64Context.T5); + ExtOut(outputFormat3.c_str(), "t6", context.LoongArch64Context.T6, "t7", context.LoongArch64Context.T7, "t8", context.LoongArch64Context.T8); + ExtOut(outputFormat3.c_str(), "x0", context.LoongArch64Context.X0, "fp", context.LoongArch64Context.Fp, "s0", context.LoongArch64Context.S0); + ExtOut(outputFormat3.c_str(), "s1", context.LoongArch64Context.S1, "s2", context.LoongArch64Context.S2, "s3", context.LoongArch64Context.S3); + ExtOut(outputFormat3.c_str(), "s4", context.LoongArch64Context.S4, "s5", context.LoongArch64Context.S5, "s6", context.LoongArch64Context.S6); + ExtOut(outputFormat3.c_str(), "s7", context.LoongArch64Context.S7, "s8", context.LoongArch64Context.S8, "pc", context.LoongArch64Context.Pc); } #endif diff --git a/src/SOS/Strike/util.cpp b/src/SOS/Strike/util.cpp index a4731d5cba..69a238a291 100644 --- a/src/SOS/Strike/util.cpp +++ b/src/SOS/Strike/util.cpp @@ -5394,7 +5394,7 @@ WString GetFrameFromAddress(TADDR frameAddr, IXCLRDataStackWalk *pStackWalk, BOO else frameOutput += W("Frame"); - frameOutput += WString(W(": ")) + Pointer(frameAddr) + W("] "); + frameOutput += WString(W(": ")) + WString(Pointer(frameAddr)) + W("] "); // Print the frame's associated function info, if it has any. CLRDATA_ADDRESS mdesc = 0; @@ -5511,13 +5511,47 @@ WString MethodNameFromIP(CLRDATA_ADDRESS ip, BOOL bSuppressLines, BOOL bAssembly if (!bSuppressLines && SUCCEEDED(GetLineByOffset(TO_CDADDR(ip), &linenum, wszFileName, MAX_LONGPATH, bAdjustIPForLineNumber))) { - methodOutput += WString(W(" [")) + wszFileName + W(" @ ") + Decimal(linenum) + W("]"); + const WCHAR* fileNamePtr = wszFileName; + methodOutput += WString(W(" [")) + fileNamePtr + W(" @ ") + WString(Decimal(linenum)) + W("]"); } } return methodOutput; } +WString DmlEscape(const WString &input) +{ + const WCHAR *str = input.c_str(); + size_t len = input.length(); + WString result; + + for (size_t i = 0; i < len; i++) + { + // Ampersand must be escaped FIRST to avoid double-escaping + // For example, if input contains "<", we want to preserve it as "&lt;" not double-escape it + if (str[i] == L'&') + { + result += W("&"); + } + else if (str[i] == L'<') + { + result += W("<"); + } + else if (str[i] == L'>') + { + result += W(">"); + } + else + { + // Append single character + WCHAR temp[2] = { str[i], L'\0' }; + result += temp; + } + } + + return result; +} + HRESULT GetGCRefs(ULONG osID, SOSStackRefData **ppRefs, unsigned int *pRefCnt, SOSStackRefError **ppErrors, unsigned int *pErrCount) { if (ppRefs == NULL || pRefCnt == NULL) diff --git a/src/SOS/Strike/util.h b/src/SOS/Strike/util.h index 3598ee7879..f778ca3446 100644 --- a/src/SOS/Strike/util.h +++ b/src/SOS/Strike/util.h @@ -453,159 +453,8 @@ void ConvertToLower(__out_ecount(len) char *buffer, size_t len); extern const char * const DMLFormats[]; int GetHex(CLRDATA_ADDRESS addr, __out_ecount(len) char *out, size_t len, bool fill); -// A simple string class for mutable strings. We cannot use STL, so this is a stand in replacement -// for std::string (though it doesn't use the same interface). -template -class BaseString -{ -public: - BaseString() - : mStr(0), mSize(0), mLength(0) - { - const size_t size = 64; - - mStr = new T[size]; - mSize = size; - mStr[0] = 0; - } - - BaseString(const T *str) - : mStr(0), mSize(0), mLength(0) - { - CopyFrom(str, LEN(str)); - } - - BaseString(const BaseString &rhs) - : mStr(0), mSize(0), mLength(0) - { - *this = rhs; - } - - ~BaseString() - { - Clear(); - } - - const BaseString &operator=(const BaseString &rhs) - { - Clear(); - CopyFrom(rhs.mStr, rhs.mLength); - return *this; - } - - const BaseString &operator=(const T *str) - { - Clear(); - CopyFrom(str, LEN(str)); - return *this; - } - - const BaseString &operator +=(const T *str) - { - size_t len = LEN(str); - CopyFrom(str, len); - return *this; - } - - const BaseString &operator +=(const BaseString &str) - { - CopyFrom(str.mStr, str.mLength); - return *this; - } - - BaseString operator+(const T *str) const - { - return BaseString(mStr, mLength, str, LEN(str)); - } - - BaseString operator+(const BaseString &str) const - { - return BaseString(mStr, mLength, str.mStr, str.mLength); - } - - operator const T *() const - { - return mStr; - } - - const T *c_str() const - { - return mStr; - } - - size_t GetLength() const - { - return mLength; - } - -private: - BaseString(const T * str1, size_t len1, const T * str2, size_t len2) - : mStr(0), mSize(0), mLength(0) - { - const size_t size = len1 + len2 + 1 + ((len1 + len2) >> 1); - mStr = new T[size]; - mSize = size; - - CopyFrom(str1, len1); - CopyFrom(str2, len2); - } - - void Clear() - { - mLength = 0; - mSize = 0; - if (mStr) - { - delete [] mStr; - mStr = 0; - } - } - - void CopyFrom(const T *str, size_t len) - { - if (mLength + len + 1 >= mSize) - Resize(mLength + len + 1); - - COPY(mStr+mLength, mSize-mLength, str); - mLength += len; - } - - void Resize(size_t size) - { - /* We always resize at least one half bigger than we need. When CopyFrom requests a resize - * it asks for the exact size that's needed to concatenate strings. However in practice - * it's common to add multiple strings together in a row, e.g.: - * String foo = "One " + "Two " + "Three " + "Four " + "\n"; - * Ensuring the size of the string is bigger than we need, and that the minimum size is 64, - * we will cut down on a lot of needless resizes at the cost of a few bytes wasted in some - * cases. - */ - size += size >> 1; - if (size < 64) - size = 64; - - T *newStr = new T[size]; - - if (mStr) - { - COPY(newStr, size, mStr); - delete [] mStr; - } - else - { - newStr[0] = 0; - } - - mStr = newStr; - mSize = size; - } -private: - T *mStr; - size_t mSize, mLength; -}; - -typedef BaseString String; -typedef BaseString WString; +typedef std::string String; +typedef std::basic_string WString; template void Flatten(__out_ecount(len) T *data, unsigned int len) @@ -772,13 +621,14 @@ namespace Output } /* Converts this object into a Wide char string. This allows you to write the following code: - * WString foo = L"bar " + ObjectPtr(obj); + * WString foo = L"bar " + WString(ObjectPtr(obj)); * Where ObjectPtr is a subclass/typedef of this Format class. + * Note: With std::basic_string, explicit WString() wrapping is required for concatenation. */ operator WString() const { String str = *this; - const char *cstr = (const char *)str; + const char *cstr = str.c_str(); int len = MultiByteToWideChar(CP_ACP, 0, cstr, -1, NULL, 0); WCHAR *buffer = (WCHAR *)alloca(len*sizeof(WCHAR)); @@ -789,8 +639,9 @@ namespace Output } /* Converts this object into a String object. This allows you to write the following code: - * String foo = "bar " + ObjectPtr(obj); + * String foo = "bar " + String(ObjectPtr(obj)); * Where ObjectPtr is a subclass/typedef of this Format class. + * Note: With std::string, explicit String() wrapping is required for concatenation. */ operator String() const { @@ -1281,12 +1132,12 @@ class TableOutput void WriteColumn(int col, const String &str) { - WriteColumn(col, Output::Format(str)); + WriteColumn(col, Output::Format(str.c_str())); } void WriteColumn(int col, const WString &str) { - WriteColumn(col, Output::Format(str)); + WriteColumn(col, Output::Format(str.c_str())); } void WriteColumn(int col, __in_z WCHAR *str) @@ -2131,6 +1982,7 @@ WString BuildRegisterOutput(const SOSStackRefData &ref, bool printObj = true); WString MethodNameFromIP(CLRDATA_ADDRESS methodDesc, BOOL bSuppressLines = FALSE, BOOL bAssemblyName = FALSE, BOOL bDisplacement = FALSE, BOOL bAdjustIPForLineNumber = FALSE); HRESULT GetGCRefs(ULONG osID, SOSStackRefData **ppRefs, unsigned int *pRefCnt, SOSStackRefError **ppErrors, unsigned int *pErrCount); WString GetFrameFromAddress(TADDR frameAddr, IXCLRDataStackWalk *pStackwalk = NULL, BOOL bAssemblyName = FALSE); +WString DmlEscape(const WString &input); HRESULT PreferCanonMTOverEEClass(CLRDATA_ADDRESS eeClassPtr, BOOL *preferCanonMT, CLRDATA_ADDRESS *outCanonMT = NULL); diff --git a/src/Tools/dotnet-counters/CounterMonitor.cs b/src/Tools/dotnet-counters/CounterMonitor.cs index 87cfd4da79..2d40d47659 100644 --- a/src/Tools/dotnet-counters/CounterMonitor.cs +++ b/src/Tools/dotnet-counters/CounterMonitor.cs @@ -195,7 +195,7 @@ public async Task Monitor( using (DiagnosticsClientHolder holder = await builder.Build(ct, _processId, diagnosticPort, showChildIO: false, printLaunchCommand: false).ConfigureAwait(false)) using (VirtualTerminalMode vTerm = VirtualTerminalMode.TryEnable()) { - bool useAnsi = vTerm.IsEnabled; + bool useAnsi = vTerm?.IsEnabled ?? false; if (holder == null) { return ReturnCode.Ok; diff --git a/src/shared/gcinfo/gcinfodumper.cpp b/src/shared/gcinfo/gcinfodumper.cpp index cc7205ff14..ec53f6f440 100644 --- a/src/shared/gcinfo/gcinfodumper.cpp +++ b/src/shared/gcinfo/gcinfodumper.cpp @@ -194,7 +194,6 @@ BOOL GcInfoDumper::ReportPointerRecord ( #define vREG(reg, field) { offsetof(LoongArch64VolatileContextPointer, field) } vREG(zero, R0), REG(ra, Ra), - REG(tp, Tp), { offsetof(T_CONTEXT, Sp) }, vREG(a0, A0), vREG(a1, A1), @@ -360,7 +359,11 @@ PORTABILITY_ASSERT("GcInfoDumper::ReportPointerRecord is not implemented on this break; } #elif defined(TARGET_LOONGARCH64) - bool isVolatile = (iReg == 0 || (iReg >= 4 && iReg <= 21)); + if (iEncodedReg > 1) + { + iEncodedReg++; // We have to compensate for not tracking tp + } + bool isVolatile = (iReg == 0 || (iReg >= 3 && iReg <= 20)); if (ctx == 0) { if (!isVolatile) @@ -727,11 +730,9 @@ GcInfoDumper::EnumerateStateChangesResults GcInfoDumper::EnumerateStateChanges ( *(ppCallerReg + iReg) = ®disp.pCallerContext->S0 + iReg; } - // Set Ra, Tp, Fp + // Set Ra, Fp regdisp.pCurrentContextPointers->Ra = ®disp.pCurrentContext->Ra; regdisp.pCallerContextPointers->Ra = ®disp.pCallerContext->Ra; - regdisp.pCurrentContextPointers->Tp = ®disp.pCurrentContext->Tp; - regdisp.pCallerContextPointers->Tp = ®disp.pCallerContext->Tp; regdisp.pCurrentContextPointers->Fp = ®disp.pCurrentContext->Fp; regdisp.pCallerContextPointers->Fp = ®disp.pCallerContext->Fp; @@ -862,7 +863,10 @@ PORTABILITY_ASSERT("GcInfoDumper::EnumerateStateChanges is not implemented on th #ifdef PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED UINT32 safePointOffset = offset; #if defined(TARGET_AMD64) || defined(TARGET_ARM) || defined(TARGET_ARM64) || defined(TARGET_RISCV64) || defined(TARGET_LOONGARCH64) - safePointOffset++; + if (safePointDecoder.Version() < 4) + { + safePointOffset++; + } #endif if(safePointDecoder.IsSafePoint(safePointOffset)) { diff --git a/src/shared/inc/gcdecoder.cpp b/src/shared/inc/gcdecoder.cpp index 26001f5889..541011b5f7 100644 --- a/src/shared/inc/gcdecoder.cpp +++ b/src/shared/inc/gcdecoder.cpp @@ -197,7 +197,7 @@ PTR_CBYTE FASTCALL decodeHeader(PTR_CBYTE table, UINT32 version, InfoHdr* header header->syncStartOffset ^= HAS_SYNC_OFFSET; break; case FLIP_REV_PINVOKE_FRAME: - header->revPInvokeOffset = INVALID_REV_PINVOKE_OFFSET ? HAS_REV_PINVOKE_FRAME_OFFSET : INVALID_REV_PINVOKE_OFFSET; + header->revPInvokeOffset ^= (INVALID_REV_PINVOKE_OFFSET ^ HAS_REV_PINVOKE_FRAME_OFFSET); break; case NEXT_OPCODE: diff --git a/src/shared/inc/gcinfodecoder.h b/src/shared/inc/gcinfodecoder.h index 450e1fbf2f..a207310361 100644 --- a/src/shared/inc/gcinfodecoder.h +++ b/src/shared/inc/gcinfodecoder.h @@ -218,7 +218,7 @@ enum GcInfoDecoderFlags DECODE_INTERRUPTIBILITY = 0x08, DECODE_GC_LIFETIMES = 0x10, DECODE_NO_VALIDATION = 0x20, - DECODE_PSP_SYM = 0x40, + DECODE_PSP_SYM = 0x40, // Unused starting with v4 format DECODE_GENERICS_INST_CONTEXT = 0x80, // stack location of instantiation context for generics // (this may be either the 'this' ptr or the instantiation secret param) DECODE_GS_COOKIE = 0x100, // stack location of the GS cookie @@ -237,7 +237,7 @@ enum GcInfoHeaderFlags GC_INFO_IS_VARARG = 0x1, // unused = 0x2, // was GC_INFO_HAS_SECURITY_OBJECT GC_INFO_HAS_GS_COOKIE = 0x4, - GC_INFO_HAS_PSP_SYM = 0x8, + GC_INFO_HAS_PSP_SYM = 0x8, // Unused starting with v4 format GC_INFO_HAS_GENERICS_INST_CONTEXT_MASK = 0x30, GC_INFO_HAS_GENERICS_INST_CONTEXT_NONE = 0x00, GC_INFO_HAS_GENERICS_INST_CONTEXT_MT = 0x10, @@ -248,6 +248,8 @@ enum GcInfoHeaderFlags GC_INFO_WANTS_REPORT_ONLY_LEAF = 0x80, #elif defined(TARGET_ARM) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) GC_INFO_HAS_TAILCALLS = 0x80, +#else + // unused = 0x80, #endif // TARGET_AMD64 GC_INFO_HAS_EDIT_AND_CONTINUE_INFO = 0x100, GC_INFO_REVERSE_PINVOKE_FRAME = 0x200, @@ -300,7 +302,7 @@ class BitStreamReader } // NOTE: This routine is perf-critical - __forceinline size_t Read( int numBits ) + FORCEINLINE size_t Read( int numBits ) { SUPPORTS_DAC; @@ -325,7 +327,7 @@ class BitStreamReader // This version reads one bit // NOTE: This routine is perf-critical - __forceinline size_t ReadOneFast() + FORCEINLINE size_t ReadOneFast() { SUPPORTS_DAC; @@ -346,13 +348,13 @@ class BitStreamReader } - __forceinline size_t GetCurrentPos() + FORCEINLINE size_t GetCurrentPos() { SUPPORTS_DAC; return (size_t) ((m_pCurrent - m_pBuffer) * BITS_PER_SIZE_T + m_RelPos - m_InitialRelPos); } - __forceinline void SetCurrentPos( size_t pos ) + FORCEINLINE void SetCurrentPos( size_t pos ) { size_t adjPos = pos + m_InitialRelPos; m_pCurrent = m_pBuffer + adjPos / BITS_PER_SIZE_T; @@ -364,7 +366,7 @@ class BitStreamReader _ASSERTE(GetCurrentPos() == pos); } - __forceinline void Skip( SSIZE_T numBitsToSkip ) + FORCEINLINE void Skip( SSIZE_T numBitsToSkip ) { SUPPORTS_DAC; @@ -416,7 +418,7 @@ class BitStreamReader } } - __forceinline size_t DecodeVarLengthUnsigned(int base) + FORCEINLINE size_t DecodeVarLengthUnsigned(int base) { _ASSERTE((base > 0) && (base < (int)BITS_PER_SIZE_T)); @@ -583,6 +585,7 @@ class TGcInfoDecoder INT32 GetReversePInvokeFrameStackSlot(); bool HasMethodDescGenericsInstContext(); bool HasMethodTableGenericsInstContext(); + bool HasStackBaseRegister(); bool GetIsVarArg(); bool WantsReportOnlyLeaf(); #if defined(TARGET_ARM) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) @@ -780,6 +783,9 @@ class TGcInfoDecoder }; typedef TGcInfoDecoder GcInfoDecoder; +#ifdef FEATURE_INTERPRETER +typedef TGcInfoDecoder InterpreterGcInfoDecoder; +#endif // FEATURE_INTERPRETER #endif // USE_GC_INFO_DECODER diff --git a/src/shared/inc/gcinfotypes.h b/src/shared/inc/gcinfotypes.h index 10d22d6709..5736efb3f1 100644 --- a/src/shared/inc/gcinfotypes.h +++ b/src/shared/inc/gcinfotypes.h @@ -211,15 +211,6 @@ inline bool IsPointerFieldReturnKind(ReturnKind returnKind) return (returnKind == RT_Object || returnKind == RT_ByRef); } -inline bool IsValidReturnRegister(size_t regNo) -{ - return (regNo == 0) -#ifdef FEATURE_MULTIREG_RETURN - || (regNo == 1) -#endif // FEATURE_MULTIREG_RETURN - ; -} - inline bool IsStructReturnKind(ReturnKind returnKind) { // Two bits encode integer/ref/float return-kinds. @@ -260,7 +251,6 @@ inline ReturnKind GetStructReturnKind(ReturnKind reg0, ReturnKind reg1) inline ReturnKind ExtractRegReturnKind(ReturnKind returnKind, size_t returnRegOrdinal, bool& moreRegs) { _ASSERTE(IsValidReturnKind(returnKind)); - _ASSERTE(IsValidReturnRegister(returnRegOrdinal)); // Return kind of each return register is encoded in two bits at returnRegOrdinal*2 position from LSB ReturnKind regReturnKind = (ReturnKind)((returnKind >> (returnRegOrdinal * 2)) & 3); @@ -818,18 +808,18 @@ struct RISCV64GcInfoEncoding { // GC Pointers are 8-bytes aligned static inline constexpr int32_t NORMALIZE_STACK_SLOT (int32_t x) { return ((x)>>3); } static inline constexpr int32_t DENORMALIZE_STACK_SLOT (int32_t x) { return ((x)<<3); } - // All Instructions are 4 bytes long - static inline constexpr uint32_t NORMALIZE_CODE_LENGTH (uint32_t x) { return ((x)>>2); } - static inline constexpr uint32_t DENORMALIZE_CODE_LENGTH (uint32_t x) { return ((x)<<2); } + // All Instructions are 2/4 bytes long + static inline constexpr uint32_t NORMALIZE_CODE_LENGTH (uint32_t x) { return ((x)>>1); } + static inline constexpr uint32_t DENORMALIZE_CODE_LENGTH (uint32_t x) { return ((x)<<1); } // Encode Frame pointer X8 as zero, sp/x2 as 1 static inline constexpr uint32_t NORMALIZE_STACK_BASE_REGISTER (uint32_t x) { return ((x) == 8 ? 0u : 1u); } static inline constexpr uint32_t DENORMALIZE_STACK_BASE_REGISTER (uint32_t x) { return ((x) == 0 ? 8u : 2u); } static inline constexpr uint32_t NORMALIZE_SIZE_OF_STACK_AREA (uint32_t x) { return ((x)>>3); } static inline constexpr uint32_t DENORMALIZE_SIZE_OF_STACK_AREA (uint32_t x) { return ((x)<<3); } static const bool CODE_OFFSETS_NEED_NORMALIZATION = true; - // Instructions are 4 bytes long - static inline constexpr uint32_t NORMALIZE_CODE_OFFSET (uint32_t x) { return ((x)>>2); } - static inline constexpr uint32_t DENORMALIZE_CODE_OFFSET (uint32_t x) { return ((x)<<2); } + // Instructions are 2/4 bytes long + static inline constexpr uint32_t NORMALIZE_CODE_OFFSET (uint32_t x) { return ((x)>>1); } + static inline constexpr uint32_t DENORMALIZE_CODE_OFFSET (uint32_t x) { return ((x)<<1); } static const int PSP_SYM_STACK_SLOT_ENCBASE = 6; static const int GENERICS_INST_CONTEXT_STACK_SLOT_ENCBASE = 6; @@ -864,13 +854,7 @@ struct RISCV64GcInfoEncoding { static const int LIVESTATE_RLE_SKIP_ENCBASE = 4; }; -#else // defined(TARGET_xxx) - -#ifndef TARGET_X86 -#ifdef PORTABILITY_WARNING -PORTABILITY_WARNING("Please specialize these definitions for your platform!") -#endif -#endif +#elif defined(TARGET_X86) #ifndef TARGET_POINTER_SIZE #define TARGET_POINTER_SIZE 4 // equal to sizeof(void*) and the managed pointer size in bytes for this target @@ -924,6 +908,20 @@ struct X86GcInfoEncoding { static const int LIVESTATE_RLE_SKIP_ENCBASE = 4; }; +#elif defined(TARGET_WASM) + +#ifndef TARGET_POINTER_SIZE +#define TARGET_POINTER_SIZE 4 // equal to sizeof(void*) and the managed pointer size in bytes for this target +#endif + +#define TargetGcInfoEncoding InterpreterGcInfoEncoding + +#else // No target defined + +#ifdef PORTABILITY_WARNING +PORTABILITY_WARNING("Please specialize these definitions for your platform!") +#endif // PORTABILITY_WARNING + #endif // defined(TARGET_xxx) #ifdef FEATURE_INTERPRETER diff --git a/src/shared/vm/gcinfodecoder.cpp b/src/shared/vm/gcinfodecoder.cpp index 7dff38b946..5672d5d39e 100644 --- a/src/shared/vm/gcinfodecoder.cpp +++ b/src/shared/vm/gcinfodecoder.cpp @@ -19,7 +19,11 @@ #ifndef GET_CALLER_SP -#define GET_CALLER_SP(pREGDISPLAY) EECodeManager::GetCallerSp(pREGDISPLAY) +inline size_t GET_CALLER_SP(PREGDISPLAY pREGDISPLAY) +{ + _ASSERTE(false); + return 0; +} #endif // !GET_CALLER_SP #ifndef VALIDATE_OBJECTREF @@ -165,13 +169,15 @@ template bool TGcInfoDecoder::Predecod return true; } +#ifdef DECODE_OLD_FORMATS // Decode the offset to the PSPSym. // The PSPSym is relative to the caller SP on IA64 and the initial stack pointer before any stack allocation on X64 (InitialSP). - if (m_headerFlags & GC_INFO_HAS_PSP_SYM) + if (Version() < 4 && (m_headerFlags & GC_INFO_HAS_PSP_SYM)) { m_PSPSymStackSlot = GcInfoEncoding::DENORMALIZE_STACK_SLOT((INT32)m_Reader.DecodeVarLengthSigned(GcInfoEncoding::PSP_SYM_STACK_SLOT_ENCBASE)); } else +#endif { m_PSPSymStackSlot = NO_PSP_SYM; } @@ -377,18 +383,17 @@ TGcInfoDecoder::TGcInfoDecoder( { if(m_NumSafePoints) { + UINT32 offset = m_InstructionOffset; #ifdef DECODE_OLD_FORMATS - if (Version() < 4) + if (Version() < 4 && (flags & DECODE_INTERRUPTIBILITY)) { // Safepoints are encoded with a -1 adjustment // DECODE_GC_LIFETIMES adjusts the offset accordingly, but DECODE_INTERRUPTIBILITY does not // adjust here - UINT32 offset = flags & DECODE_INTERRUPTIBILITY ? m_InstructionOffset - 1 : m_InstructionOffset; - m_SafePointIndex = FindSafePoint(offset); + offset--; } -#else - m_SafePointIndex = FindSafePoint(m_InstructionOffset); #endif + m_SafePointIndex = FindSafePoint(offset); } } else if(flags & DECODE_FOR_RANGES_CALLBACK) @@ -454,6 +459,11 @@ template bool TGcInfoDecoder::HasMetho return (m_headerFlags & GC_INFO_HAS_GENERICS_INST_CONTEXT_MASK) == GC_INFO_HAS_GENERICS_INST_CONTEXT_MT; } +template bool TGcInfoDecoder::HasStackBaseRegister() +{ + return (m_headerFlags & GC_INFO_HAS_STACK_BASE_REGISTER) == GC_INFO_HAS_STACK_BASE_REGISTER; +} + #ifdef PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED // This is used for gcinfodumper: is the given offset @@ -661,7 +671,7 @@ template bool TGcInfoDecoder::HasTailC template bool TGcInfoDecoder::WantsReportOnlyLeaf() { // Only AMD64 with JIT64 can return false here. -#ifdef TARGET_AMD64 +#if defined(TARGET_AMD64) && defined(DECODE_OLD_FORMATS) return ((m_headerFlags & GC_INFO_WANTS_REPORT_ONLY_LEAF) != 0); #else return true; @@ -759,8 +769,6 @@ template bool TGcInfoDecoder::Enumerat #ifdef PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED - bool noTrackedRefs = false; - if(m_SafePointIndex < m_NumSafePoints && !executionAborted) { // Skip interruptibility information @@ -779,42 +787,29 @@ template bool TGcInfoDecoder::Enumerat // or execution will not resume at the current method // and nothing should be reported // - if(!executionAborted) + int countIntersections = 0; + UINT32 lastNormStop = 0; + for(UINT32 i=0; i= normStart && normBreakOffset < normStop) { - // No ranges and no explicit safepoint - must be MinOpts with untracked refs. - noTrackedRefs = true; + _ASSERTE(pseudoBreakOffset == 0); + countIntersections++; + pseudoBreakOffset = numInterruptibleLength + normBreakOffset - normStart; } + numInterruptibleLength += normStopDelta; + lastNormStop = normStop; } - - if(m_NumInterruptibleRanges != 0) + _ASSERTE(countIntersections <= 1); + if(countIntersections == 0 && executionAborted) { - int countIntersections = 0; - UINT32 lastNormStop = 0; - for(UINT32 i=0; i= normStart && normBreakOffset < normStop) - { - _ASSERTE(pseudoBreakOffset == 0); - countIntersections++; - pseudoBreakOffset = numInterruptibleLength + normBreakOffset - normStart; - } - numInterruptibleLength += normStopDelta; - lastNormStop = normStop; - } - _ASSERTE(countIntersections <= 1); - if(countIntersections == 0) - { - _ASSERTE(executionAborted); - LOG((LF_GCROOTS, LL_INFO100000, "Not reporting this frame because it is aborted and not fully interruptible.\n")); - goto ExitSuccess; - } + LOG((LF_GCROOTS, LL_INFO100000, "Not reporting this frame because it is aborted and not fully interruptible.\n")); + goto ExitSuccess; } } #else // !PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED @@ -1462,6 +1457,19 @@ template const GcSlotDesc* GcSlotDecoder bool TGcInfoDecoder::IsScratchStackSlot(INT32 spOffset, GcStackSlotBase spBase, PREGDISPLAY pRD) +{ +#ifdef FIXED_STACK_PARAMETER_SCRATCH_AREA + _ASSERTE( m_Flags & DECODE_GC_LIFETIMES ); + + TADDR pSlot = (TADDR) GetStackSlot(spOffset, spBase, pRD); + _ASSERTE(pSlot >= pRD->SP); + + return (pSlot < pRD->SP + m_SizeOfStackOutgoingAndScratchArea); +#else + return false; +#endif +} //----------------------------------------------------------------------------- // Platform-specific methods @@ -1530,21 +1538,6 @@ template bool TGcInfoDecoder::IsScratc } -template bool TGcInfoDecoder::IsScratchStackSlot(INT32 spOffset, GcStackSlotBase spBase, PREGDISPLAY pRD) -{ -#ifdef FIXED_STACK_PARAMETER_SCRATCH_AREA - _ASSERTE( m_Flags & DECODE_GC_LIFETIMES ); - - TADDR pSlot = (TADDR) GetStackSlot(spOffset, spBase, pRD); - _ASSERTE(pSlot >= pRD->SP); - - return (pSlot < pRD->SP + m_SizeOfStackOutgoingAndScratchArea); -#else - return FALSE; -#endif -} - - template void TGcInfoDecoder::ReportRegisterToGC( // AMD64 int regNum, unsigned gcFlags, @@ -1674,21 +1667,6 @@ template bool TGcInfoDecoder::IsScratc } -template bool TGcInfoDecoder::IsScratchStackSlot(INT32 spOffset, GcStackSlotBase spBase, PREGDISPLAY pRD) -{ -#ifdef FIXED_STACK_PARAMETER_SCRATCH_AREA - _ASSERTE( m_Flags & DECODE_GC_LIFETIMES ); - - TADDR pSlot = (TADDR) GetStackSlot(spOffset, spBase, pRD); - _ASSERTE(pSlot >= pRD->SP); - - return (pSlot < pRD->SP + m_SizeOfStackOutgoingAndScratchArea); -#else - return FALSE; -#endif -} - - template void TGcInfoDecoder::ReportRegisterToGC( // ARM int regNum, unsigned gcFlags, @@ -1771,21 +1749,6 @@ template bool TGcInfoDecoder::IsScratc return regNum <= 17 || regNum >= 29; // R12 and R14/LR are both scratch registers } -template bool TGcInfoDecoder::IsScratchStackSlot(INT32 spOffset, GcStackSlotBase spBase, PREGDISPLAY pRD) -{ -#ifdef FIXED_STACK_PARAMETER_SCRATCH_AREA - _ASSERTE( m_Flags & DECODE_GC_LIFETIMES ); - - TADDR pSlot = (TADDR) GetStackSlot(spOffset, spBase, pRD); - _ASSERTE(pSlot >= pRD->SP); - - return (pSlot < pRD->SP + m_SizeOfStackOutgoingAndScratchArea); -#else - return FALSE; -#endif - -} - template void TGcInfoDecoder::ReportRegisterToGC( // ARM64 int regNum, unsigned gcFlags, @@ -1926,20 +1889,6 @@ template bool TGcInfoDecoder::IsScratc return (regNum <= 21 && ((regNum >= 4) || (regNum == 1))); } -template bool TGcInfoDecoder::IsScratchStackSlot(INT32 spOffset, GcStackSlotBase spBase, PREGDISPLAY pRD) -{ -#ifdef FIXED_STACK_PARAMETER_SCRATCH_AREA - _ASSERTE( m_Flags & DECODE_GC_LIFETIMES ); - - TADDR pSlot = (TADDR) GetStackSlot(spOffset, spBase, pRD); - _ASSERTE(pSlot >= pRD->SP); - - return (pSlot < pRD->SP + m_SizeOfStackOutgoingAndScratchArea); -#else - return FALSE; -#endif -} - template void TGcInfoDecoder::ReportRegisterToGC( int regNum, unsigned gcFlags, @@ -2064,20 +2013,6 @@ template bool TGcInfoDecoder::IsScratc return (regNum >= 5 && regNum <= 7) || (regNum >= 10 and regNum <= 17) || regNum >= 28 || regNum == 1; } -template bool TGcInfoDecoder::IsScratchStackSlot(INT32 spOffset, GcStackSlotBase spBase, PREGDISPLAY pRD) -{ -#ifdef FIXED_STACK_PARAMETER_SCRATCH_AREA - _ASSERTE( m_Flags & DECODE_GC_LIFETIMES ); - - TADDR pSlot = (TADDR) GetStackSlot(spOffset, spBase, pRD); - _ASSERTE(pSlot >= pRD->SP); - - return (pSlot < pRD->SP + m_SizeOfStackOutgoingAndScratchArea); -#else - return FALSE; -#endif -} - template void TGcInfoDecoder::ReportRegisterToGC( int regNum, unsigned gcFlags, @@ -2153,12 +2088,6 @@ template bool TGcInfoDecoder::IsScratc return false; } -template bool TGcInfoDecoder::IsScratchStackSlot(INT32 spOffset, GcStackSlotBase spBase, PREGDISPLAY pRD) -{ - _ASSERTE( !"NYI" ); - return false; -} - template void TGcInfoDecoder::ReportRegisterToGC( int regNum, unsigned gcFlags, @@ -2170,8 +2099,48 @@ template void TGcInfoDecoder::ReportRe _ASSERTE( !"NYI" ); } +template OBJECTREF* TGcInfoDecoder::GetCapturedRegister( + int regNum, + PREGDISPLAY pRD + ) +{ + _ASSERTE( !"NYI" ); + return nullptr; +} + #endif // Unknown platform +#ifdef FEATURE_INTERPRETER +template <> OBJECTREF* TGcInfoDecoder::GetStackSlot( + INT32 spOffset, + GcStackSlotBase spBase, + PREGDISPLAY pRD + ) +{ + OBJECTREF* pObjRef = NULL; + + if( GC_SP_REL == spBase ) + { + _ASSERTE(!"GC_SP_REL is invalid for interpreter frames"); + } + else if( GC_CALLER_SP_REL == spBase ) + { + _ASSERTE(!"GC_CALLER_SP_REL is invalid for interpreter frames"); + } + else + { + // Interpreter-TODO: Enhance GcInfoEncoder/Decoder to allow omitting the stack slot base register for interpreted + // methods, since only one base (fp) is ever used for interpreter locals. See Interpreter-TODO in DecodeSlotTable. + _ASSERTE( GC_FRAMEREG_REL == spBase ); + uint8_t* fp = (uint8_t *)GetFP(pRD->pCurrentContext); + _ASSERTE(fp); + pObjRef = (OBJECTREF*)(fp + spOffset); + } + + return pObjRef; +} +#endif + template OBJECTREF* TGcInfoDecoder::GetStackSlot( INT32 spOffset, @@ -2271,7 +2240,13 @@ template void TGcInfoDecoder::ReportSt pCallBack(hCallBack, pObjRef, gcFlags DAC_ARG(DacSlotLocation(GetStackReg(spBase), spOffset, true))); } +#ifndef TARGET_WASM // Instantiate the decoder so other files can use it template class TGcInfoDecoder; +#endif // !TARGET_WASM + +#ifdef FEATURE_INTERPRETER +template class TGcInfoDecoder; +#endif // FEATURE_INTERPRETER #endif // USE_GC_INFO_DECODER diff --git a/src/tests/SOS.UnitTests/Debuggees/AsyncMain/AsyncMain.cs b/src/tests/SOS.UnitTests/Debuggees/AsyncMain/AsyncMain.cs new file mode 100644 index 0000000000..993cdc9c2a --- /dev/null +++ b/src/tests/SOS.UnitTests/Debuggees/AsyncMain/AsyncMain.cs @@ -0,0 +1,32 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Threading.Tasks; + +public class AsyncMainTest +{ + public static async Task Main(string[] args) + { + DivideData data = new() + { + Numerator = 16, + Denominator = 0, + }; + + Console.WriteLine($"{data.Numerator}/{data.Denominator} = {await DivideAsync(data)}"); + return 0; + } + + static async Task DivideAsync(DivideData data) + { + await Task.Delay(10); + return data.Numerator / data.Denominator; + } +} + +public class DivideData +{ + public int Numerator { get; set; } + public int Denominator { get; set; } +} diff --git a/src/tests/SOS.UnitTests/Debuggees/AsyncMain/AsyncMain.csproj b/src/tests/SOS.UnitTests/Debuggees/AsyncMain/AsyncMain.csproj new file mode 100644 index 0000000000..644ea7fa32 --- /dev/null +++ b/src/tests/SOS.UnitTests/Debuggees/AsyncMain/AsyncMain.csproj @@ -0,0 +1,7 @@ + + + Exe + $(BuildProjectFramework) + $(SupportedSubProcessTargetFrameworks) + + diff --git a/src/tests/SOS.UnitTests/SOS.cs b/src/tests/SOS.UnitTests/SOS.cs index 7099fc8d2b..9f8de78473 100644 --- a/src/tests/SOS.UnitTests/SOS.cs +++ b/src/tests/SOS.UnitTests/SOS.cs @@ -459,6 +459,12 @@ public async Task SimpleThrow(TestConfiguration config) await SOSTestHelpers.RunTest(config, debuggeeName: "SimpleThrow", scriptName: "SimpleThrow.script", Output, testTriage: true); } + [SkippableTheory, MemberData(nameof(Configurations))] + public async Task AsyncMain(TestConfiguration config) + { + await SOSTestHelpers.RunTest(config, debuggeeName: "AsyncMain", scriptName: "AsyncMain.script", Output, testTriage: true); + } + [SkippableTheory, MemberData(nameof(Configurations))] public async Task LineNums(TestConfiguration config) { diff --git a/src/tests/SOS.UnitTests/Scripts/AsyncMain.script b/src/tests/SOS.UnitTests/Scripts/AsyncMain.script new file mode 100644 index 0000000000..d0d6f7d637 --- /dev/null +++ b/src/tests/SOS.UnitTests/Scripts/AsyncMain.script @@ -0,0 +1,15 @@ +# +# Tests that ClrStack properly displays async Main method names with angle brackets when DML is enabled +# + +CONTINUE + +LOADSOS + +# Verify that ClrStack with /d (DML enabled) properly displays async method name with angle brackets +# The DML escape sequences are processed by the debugger and rendered back to literal angle brackets +SOSCOMMAND:ClrStack /d +VERIFY:.*OS Thread Id:\s+0x\s+.* +VERIFY:\s+Child\s+SP\s+IP\s+Call Site\s+ +# Verify that the method name contains
and is not trimmed to Main> +VERIFY:.*AsyncMainTest\.
\(.*\).*