From 603fa9cf0815af2279421af47b18c7108b5a631d Mon Sep 17 00:00:00 2001 From: Andrew Wang Date: Tue, 7 Mar 2023 18:12:26 -0800 Subject: [PATCH 1/9] Add SDL Tasks (#1390) * Add SDL Tasks --- eng/pipelines/MIDebugEngine-CI.yml | 12 +++++++++++ eng/pipelines/resources/TSAConfig.json | 9 ++++++++ .../resources/falsepositives.gdnsuppress | 1 + eng/pipelines/steps/APIScan.yml | 18 +++++++++++++--- eng/pipelines/steps/PostAnalysis.yml | 19 +++++++++++++++++ eng/pipelines/tasks/AntiMalware.yml | 21 +++++++++++++++++++ eng/pipelines/tasks/CredScan.yml | 3 ++- eng/pipelines/tasks/PSScriptAnalyzer.yml | 7 +++++++ eng/pipelines/tasks/TSAUpload.yml | 10 +++++++++ .../templates/CodeAnalysis.template.yml | 19 +++++++++++++++++ 10 files changed, 115 insertions(+), 4 deletions(-) create mode 100644 eng/pipelines/resources/TSAConfig.json create mode 100644 eng/pipelines/resources/falsepositives.gdnsuppress create mode 100644 eng/pipelines/steps/PostAnalysis.yml create mode 100644 eng/pipelines/tasks/AntiMalware.yml create mode 100644 eng/pipelines/tasks/PSScriptAnalyzer.yml create mode 100644 eng/pipelines/tasks/TSAUpload.yml diff --git a/eng/pipelines/MIDebugEngine-CI.yml b/eng/pipelines/MIDebugEngine-CI.yml index c41558db5..3f3bc40f4 100644 --- a/eng/pipelines/MIDebugEngine-CI.yml +++ b/eng/pipelines/MIDebugEngine-CI.yml @@ -1,5 +1,15 @@ --- name: $(Date:yyyMMdd).$(Rev:r) + +schedules: +# Run on the 1st and 15th of every month +- cron: 30 1 1,15 * * + displayName: Biweekly Build + branches: + include: + - main + always: true # Run even if there are no code changes + stages: - stage: CI dependsOn: [] @@ -8,6 +18,8 @@ stages: value: test - name: TeamName value: MDDDebugger + - name: Codeql.Enabled + value: true jobs: - template: ./jobs/VSEngSS-MicroBuild2022-1ES.job.yml parameters: diff --git a/eng/pipelines/resources/TSAConfig.json b/eng/pipelines/resources/TSAConfig.json new file mode 100644 index 000000000..bc6b0b5ca --- /dev/null +++ b/eng/pipelines/resources/TSAConfig.json @@ -0,0 +1,9 @@ +{ + "codebaseName": "MIEngine", + "notificationAliases": ["vsdbgnft@microsoft.com"], + "instanceUrl": "https://devdiv.visualstudio.com", + "projectName": "DevDiv", + "areaPath": "DevDiv\\VS Diagnostics\\Debugger - XPlat\\Cpp", + "iterationPath": "DevDiv", + "allTools": true +} \ No newline at end of file diff --git a/eng/pipelines/resources/falsepositives.gdnsuppress b/eng/pipelines/resources/falsepositives.gdnsuppress new file mode 100644 index 000000000..9e26dfeeb --- /dev/null +++ b/eng/pipelines/resources/falsepositives.gdnsuppress @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/eng/pipelines/steps/APIScan.yml b/eng/pipelines/steps/APIScan.yml index 7633c3b58..4aa947f75 100644 --- a/eng/pipelines/steps/APIScan.yml +++ b/eng/pipelines/steps/APIScan.yml @@ -1,21 +1,33 @@ parameters: - FolderToScan: '$(Pipeline.Workspace)\Lab.Release' + SourceFolder: '$(Pipeline.Workspace)\Lab.Release' steps: - task: CopyFiles@2 displayName: 'Copy Files to: $(Pipeline.Workspace)\ApiScanFiles' inputs: - SourceFolder: ${{ parameters.FolderToScan }} + SourceFolder: ${{ parameters.SourceFolder }} Contents: | **\*Microsoft@(*.dll|*.pdb|*.exe) - **\*Newtonsoft@(*.dll|*.pdb|*.exe) **\*OpenDebugAD7@(*.dll|*.pdb|*.exe) **\*WindowsDebugLauncher@(*.dll|*.pdb|*.exe) + **\Microsoft.VisualStudio.Debugger.Interop.UnixPortSupplier.DesignTime.dll !**\*.resources.dll + !**\Microsoft.VisualStudio.Debugger.Interop* + !**\vscode\Microsoft.VisualStudio.Interop.dll + !**\vscode\Microsoft.VisualStudio.Shared.VSCodeDebugProtocol.dll TargetFolder: '$(Pipeline.Workspace)\ApiScanFiles' CleanTargetFolder: true OverWrite: true +# This gets excluded by !**\Microsoft.VisualStudio.Debugger.Interop* but we create Microsoft.VisualStudio.Debugger.Interop.UnixPortSupplier.DesignTime.dll. +- task: CopyFiles@2 + displayName: 'Copy UnixPortSupplier to: $(Pipeline.Workspace)\ApiScanFiles' + inputs: + SourceFolder: ${{ parameters.SourceFolder }} + Contents: | + **\Microsoft.VisualStudio.Debugger.Interop.UnixPortSupplier.DesignTime.dll + TargetFolder: '$(Pipeline.Workspace)\ApiScanFiles' + - task: securedevelopmentteam.vss-secure-development-tools.build-task-apiscan.APIScan@2 displayName: 'Run APIScan' inputs: diff --git a/eng/pipelines/steps/PostAnalysis.yml b/eng/pipelines/steps/PostAnalysis.yml new file mode 100644 index 000000000..904e38b58 --- /dev/null +++ b/eng/pipelines/steps/PostAnalysis.yml @@ -0,0 +1,19 @@ +parameters: + GdnSuppressionFiles: $(Build.SourcesDirectory)\eng\pipelines\resources\falsepositives.gdnsuppress + +steps: +- task: securedevelopmentteam.vss-secure-development-tools.build-task-postanalysis.PostAnalysis@2 + displayName: 🏋️‍♀️ Break on compliance issues + inputs: + GdnBreakAllTools: true + GdnBreakSuppressionFiles: ${{ parameters.GdnSuppressionFiles }} + GdnBreakSuppressionSets: falsepositives + +- task: securedevelopmentteam.vss-secure-development-tools.build-task-postanalysis.PostAnalysis@2 + displayName: 📝 Generate Guardian Suppressions File + inputs: + GdnBreakAllTools: true + GdnBreakOutputSuppressionFile: $(Build.ArtifactStagingDirectory)\GuardianSuppressions + GdnBreakOutputSuppressionSet: falsepositives + continueOnError: true + condition: failed() \ No newline at end of file diff --git a/eng/pipelines/tasks/AntiMalware.yml b/eng/pipelines/tasks/AntiMalware.yml new file mode 100644 index 000000000..f6a85b339 --- /dev/null +++ b/eng/pipelines/tasks/AntiMalware.yml @@ -0,0 +1,21 @@ +parameters: + SourcePath: $(Build.SourcesDirectory) + ArtifactPath: $(Pipeline.Workspace) + +steps: +- task: AntiMalware@4 + displayName: 🔎 Run AntiMalware on source + inputs: + InputType: Basic + ScanType: CustomScan + FileDirPath: ${{ parameters.SourcePath }} + continueOnError: true + +- task: AntiMalware@4 + displayName: 🔎 Run AntiMalware on artifacts + inputs: + InputType: Basic + ScanType: CustomScan + FileDirPath: ${{ parameters.ArtifactPath }} + DisableRemediation: false + continueOnError: true \ No newline at end of file diff --git a/eng/pipelines/tasks/CredScan.yml b/eng/pipelines/tasks/CredScan.yml index 27deee744..7cac0e555 100644 --- a/eng/pipelines/tasks/CredScan.yml +++ b/eng/pipelines/tasks/CredScan.yml @@ -3,4 +3,5 @@ steps: displayName: 'Run CredScan' inputs: outputFormat: pre - debugMode: false \ No newline at end of file + debugMode: false + continueOnError: true \ No newline at end of file diff --git a/eng/pipelines/tasks/PSScriptAnalyzer.yml b/eng/pipelines/tasks/PSScriptAnalyzer.yml new file mode 100644 index 000000000..c1e50459b --- /dev/null +++ b/eng/pipelines/tasks/PSScriptAnalyzer.yml @@ -0,0 +1,7 @@ +steps: +- task: PSScriptAnalyzer@1 + displayName: 🔎 Run PSScriptAnalyzer + inputs: + Path: '$(Build.SourcesDirectory)' + Settings: required + Recurse: true \ No newline at end of file diff --git a/eng/pipelines/tasks/TSAUpload.yml b/eng/pipelines/tasks/TSAUpload.yml new file mode 100644 index 000000000..a71baa2d4 --- /dev/null +++ b/eng/pipelines/tasks/TSAUpload.yml @@ -0,0 +1,10 @@ +parameters: + TSAConfigFilePath: $(Build.SourcesDirectory)\eng\pipelines\resources\TSAconfig.json + +steps: +- task: securedevelopmentteam.vss-secure-development-tools.build-task-uploadtotsa.TSAUpload@2 + displayName: 📢 Create bugs for compliance tools results + inputs: + GdnPublishTsaOnboard: true + GdnPublishTsaConfigFile: ${{ parameters.TSAConfigFilePath }} # All relevant settings are in this file. + condition: succeededOrFailed() \ No newline at end of file diff --git a/eng/pipelines/templates/CodeAnalysis.template.yml b/eng/pipelines/templates/CodeAnalysis.template.yml index 20388caaf..84adf530a 100644 --- a/eng/pipelines/templates/CodeAnalysis.template.yml +++ b/eng/pipelines/templates/CodeAnalysis.template.yml @@ -14,13 +14,32 @@ steps: parameters: FolderToScan: $(Pipeline.Workspace)\Lab.Release +- template: ../tasks/AntiMalware.yml + parameters: + SourcePath: $(Build.SourcesDirectory)\src + - template: ../tasks/BinSkim.yml - template: ../tasks/PoliCheck.yml +- template: ../tasks/PSScriptAnalyzer.yml + - template: ../tasks/SdtReport.yml - template: ../tasks/PublishSecurityAnalysisLogs.yml parameters: ArtifactName: 'CodeAnalysis' + +## Create any bugs associated with the results. +- template: ../tasks/TSAUpload.yml + +## Finally, break the build if anything was found. This is so we can bring the issue to our attention. +- template: ../steps/PostAnalysis.yml + +- template: ../tasks/PublishPipelineArtifact.yml + parameters: + DisplayName: 🎁 Publish Artifact for Guardian Suppressions + artifactName: Guardian Suppressions + path: $(Build.ArtifactStagingDirectory)\GuardianSuppressions + condition: failed() ... \ No newline at end of file From 17d125203d02eb6bca8bfffec2156f0fe4fa37c5 Mon Sep 17 00:00:00 2001 From: Andrew Wang Date: Wed, 5 Apr 2023 16:30:14 -0700 Subject: [PATCH 2/9] Update Actions and Fix Build Warnings (#1394) Update Actions and Build Warnings This PR update the GitHub action tasks that are warning due to node-12 being outdated and cleaing up some C# warnings. The tasks are: - checkout v3 - setup-dotnet v3 - setup-msbuild v1.1 - Setup-VSTest v1.2 - upload-artifact v3 Also addrssed hardcoded strings that were the same name as the variable name that appeared as warnings. --- .github/workflows/Build-And-Test.yml | 32 +++++++++---------- src/MICore/JsonLaunchOptions.cs | 2 +- .../Docker/DockerContainerInstance.cs | 8 ++--- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/.github/workflows/Build-And-Test.yml b/.github/workflows/Build-And-Test.yml index 731711a59..73cfff4f4 100644 --- a/.github/workflows/Build-And-Test.yml +++ b/.github/workflows/Build-And-Test.yml @@ -22,20 +22,20 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: fetch-depth: 0 - name: Install .NET Core - uses: actions/setup-dotnet@v1 + uses: actions/setup-dotnet@v3 with: dotnet-version: 6.0.x - name: Setup MSBuild.exe - uses: microsoft/setup-msbuild@v1.0.2 + uses: microsoft/setup-msbuild@v1.1 - name: Setup NuGet.exe for use with actions - uses: NuGet/setup-nuget@v1.0.5 + uses: NuGet/setup-nuget@v1 - name: Build MIDebugEngine run: | @@ -44,7 +44,7 @@ jobs: Configuration: ${{ matrix.configuration }} - name: Setup VSTest.console.exe - uses: darenm/Setup-VSTest@v1 + uses: darenm/Setup-VSTest@v1.2 - name: Run VS Extension tests run: vstest.console.exe ${{ github.workspace }}\bin\${{ matrix.configuration }}\MICoreUnitTests.dll ${{ github.workspace }}\bin\${{ matrix.configuration }}\JDbgUnitTests.dll ${{ github.workspace }}\bin\${{ matrix.configuration }}\SSHDebugTests.dll ${{ github.workspace }}\bin\${{ matrix.configuration }}\MIDebugEngineUnitTests.dll @@ -54,20 +54,20 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: fetch-depth: 0 - name: Install .NET Core - uses: actions/setup-dotnet@v1 + uses: actions/setup-dotnet@v3 with: dotnet-version: 6.0.x - name: Setup MSBuild.exe - uses: microsoft/setup-msbuild@v1.0.2 + uses: microsoft/setup-msbuild@v1.1 - name: Setup NuGet.exe for use with actions - uses: NuGet/setup-nuget@v1.0.5 + uses: NuGet/setup-nuget@v1 - name: Build MIDebugEngine run: | @@ -102,7 +102,7 @@ jobs: dotnet test $CppTestsPath --logger "trx;LogFileName=$ResultsPath" - name: 'Upload Test Results' - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 if: ${{ always() }} with: name: win_msys2_x64_results @@ -112,12 +112,12 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: fetch-depth: 0 - name: Install .NET Core - uses: actions/setup-dotnet@v1 + uses: actions/setup-dotnet@v3 with: dotnet-version: 6.0.x @@ -143,7 +143,7 @@ jobs: ${{ github.workspace }}/eng/Scripts/CI-Test.sh - name: 'Upload Test Results' - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 if: ${{ always() }} with: name: linux_x64_results @@ -153,12 +153,12 @@ jobs: runs-on: macos-latest steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: fetch-depth: 0 - name: Install .NET Core - uses: actions/setup-dotnet@v1 + uses: actions/setup-dotnet@v3 with: dotnet-version: 6.0.x @@ -172,7 +172,7 @@ jobs: ${{ github.workspace }}/eng/Scripts/CI-Test.sh - name: 'Upload Test Results' - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 if: ${{ always() }} with: name: osx_x64_results diff --git a/src/MICore/JsonLaunchOptions.cs b/src/MICore/JsonLaunchOptions.cs index 5193234a8..6277a5633 100644 --- a/src/MICore/JsonLaunchOptions.cs +++ b/src/MICore/JsonLaunchOptions.cs @@ -54,7 +54,7 @@ public abstract partial class BaseOptions /// /// Indicates the console debugger that the MIDebugEngine will connect to. Allowed values are "gdb" "lldb". /// - [JsonProperty("MIMode", DefaultValueHandling = DefaultValueHandling.Ignore)] + [JsonProperty(nameof(MIMode), DefaultValueHandling = DefaultValueHandling.Ignore)] public string MIMode { get; set; } /// diff --git a/src/SSHDebugPS/Docker/DockerContainerInstance.cs b/src/SSHDebugPS/Docker/DockerContainerInstance.cs index f54362d3c..61b95713f 100644 --- a/src/SSHDebugPS/Docker/DockerContainerInstance.cs +++ b/src/SSHDebugPS/Docker/DockerContainerInstance.cs @@ -47,16 +47,16 @@ private DockerContainerInstance() { } [JsonProperty("Names")] public override string Name { get; set; } - [JsonProperty("Image")] + [JsonProperty(nameof(Image))] public string Image { get; private set; } - [JsonProperty("Ports")] + [JsonProperty(nameof(Ports))] public string Ports { get; set; } - [JsonProperty("Command")] + [JsonProperty(nameof(Command))] public string Command { get; private set; } - [JsonProperty("Status")] + [JsonProperty(nameof(Status))] public string Status { get; private set; } [JsonProperty("CreatedAt")] From c4ad01a588195f2949ad8f5c59e96c26494b5666 Mon Sep 17 00:00:00 2001 From: Sergey Bobko Date: Mon, 17 Apr 2023 21:47:10 +0200 Subject: [PATCH 3/9] Add "sendInvalidate" request (#1367) * parent 603fa9cf0815af2279421af47b18c7108b5a631d author Sergey 1667223527 -0700 committer Sergey Bobko 1680535841 +0000 Add "sendInvalidate" request This PR adds support for OpenDebugAD7 to handle `sendInvalidate` requests which will respond if it successfully fired an InvalidatedEvent to the UI. Here is the schema: ```json "SendInvalidateRequest": { "allOf": [ { "$ref": "#/definitions/Request" }, { "type": "object", "properties": { "areas": { "type": "array", "description": "Set of logical areas that got invalidated. This property has a hint characteristic: a client can only be expected to make a 'best effort' in honoring the areas but there are no guarantees. If this property is missing, empty, or if values are not understood, the client should assume a single value `all`.", "items": { "$ref": "#/definitions/InvalidatedAreas" } }, "threadId": { "type": "int", }, "stackFrameId": { "type": "int", }, }, "required": [ "areas" ] } ] }, ``` Co-authored-by: Andrew Wang --- src/OpenDebugAD7/AD7DebugSession.cs | 44 +++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/src/OpenDebugAD7/AD7DebugSession.cs b/src/OpenDebugAD7/AD7DebugSession.cs index c49b7b0b6..3c61e9ea0 100644 --- a/src/OpenDebugAD7/AD7DebugSession.cs +++ b/src/OpenDebugAD7/AD7DebugSession.cs @@ -128,8 +128,35 @@ public AD7DebugSession(Stream debugAdapterStdIn, Stream debugAdapterStdOut, List m_dataBreakpoints = new Dictionary(); m_exceptionBreakpoints = new List(); m_variableManager = new VariableManager(); + + //Register sendInvalidate request + Protocol.RegisterRequestType(r => this.HandleSendInvalidateRequestAsync(r)); + } + private void HandleSendInvalidateRequestAsync(IRequestResponder responder) + { + InvalidatedEvent invalidated = new InvalidatedEvent(); + + // Setting the area and adding it to the result + invalidated.Areas.Add(responder.Arguments.Areas); + + // Setting the StackFrameId if passed (and the 'threadId' is ignored). + if (null != responder.Arguments.StackFrameId) + { + invalidated.StackFrameId = responder.Arguments.StackFrameId; + } + + // Setting the ThreadId if passed + else if (null != responder.Arguments.ThreadId) + { + invalidated.ThreadId = responder.Arguments.ThreadId; + } + + + Protocol.SendEvent(invalidated); + + } #endregion #region Utility @@ -3874,4 +3901,21 @@ int IDebugSettingsCallback110.ShouldSuppressImplicitToStringCalls(out int pfSupp } } } + + internal class SendInvalidateRequest : DebugRequest + { + + public SendInvalidateRequest(): base("sendInvalidate") + { + } + } + + internal class SendInvalidateArguments : DebugRequestArguments + { + + public InvalidatedAreas Areas { get; set; } + public int? ThreadId { get; set; } + public int? StackFrameId { get; set; } + + } } From f530168188f23c4cf2c5799ce309ade66f854b4e Mon Sep 17 00:00:00 2001 From: Andrew Wang Date: Mon, 8 May 2023 17:00:33 -0700 Subject: [PATCH 4/9] Fix Remote AsyncBreak (#1399) https://github.com/microsoft/MIEngine/commit/5f6213cf60fdd271cd7bf6b03b4225a914a10da5 accidently broke async-break for gdb remote scenarios as we send "-exec-interrupt" for async-break instead of sending a 'kill SIGTRAP'. This PR modifies the `IsAsyncBreakSignal` to return a newly created enum `AsyncBreakSignal`, and renames it to `GetAsyncBreakSignal`. `GetAsyncBreakSignal` will now return if it saw a `SIGINT`, `SIGTRAP`, or `None` if its an unknown signal related to async break or no signal was retrieved at all. This will be used along with a new flag called `IsUsingExecInterrupt`, which will be set before `-exec-interrupt` is sent to the debugger. `IsUsingExecInterrupt` will be reset when the engine resolves the `async-break` from the user (see DebuggedProcess.cs changes) or when we are resolving an internal async break (See Debugger.cs DoInternalBreakActions). Resolves: #1382 --- .../CommandFactories/MICommandFactory.cs | 26 ++++++++++++++----- src/MICore/Debugger.cs | 15 ++++++++--- .../Engine.Impl/DebuggedProcess.cs | 6 ++++- 3 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/MICore/CommandFactories/MICommandFactory.cs b/src/MICore/CommandFactories/MICommandFactory.cs index 3529d37d3..eb2e22773 100644 --- a/src/MICore/CommandFactories/MICommandFactory.cs +++ b/src/MICore/CommandFactories/MICommandFactory.cs @@ -35,6 +35,17 @@ public enum ExceptionBreakpointStates BreakThrown = 0x2 } + /// + /// The signals that are using for async-break. + /// None will be used for no signal or signals that are not listed in the enum + /// + public enum AsyncBreakSignal + { + None = 0, + SIGTRAP = 2, + SIGINT = 5 + } + public abstract class MICommandFactory { protected Debugger _debugger; @@ -652,19 +663,22 @@ public virtual bool SupportsFrameFormatting get { return false; } } - public virtual bool IsAsyncBreakSignal(Results results) + public virtual AsyncBreakSignal GetAsyncBreakSignal(Results results) { - bool isAsyncBreak = false; - if (results.TryFindString("reason") == "signal-received") { - if (results.TryFindString("signal-name") == "SIGTRAP") + string signalName = results.TryFindString("signal-name"); + if (signalName == "SIGTRAP") + { + return MICore.AsyncBreakSignal.SIGTRAP; + } + else if (signalName == "SIGINT") { - isAsyncBreak = true; + return MICore.AsyncBreakSignal.SIGINT; } } - return isAsyncBreak; + return MICore.AsyncBreakSignal.None; } public Results IsModuleLoad(string cmd) diff --git a/src/MICore/Debugger.cs b/src/MICore/Debugger.cs index 295b919ca..00acc2d0d 100755 --- a/src/MICore/Debugger.cs +++ b/src/MICore/Debugger.cs @@ -283,8 +283,9 @@ private async void OnStopped(Results results) results = results.Add("frame", frameResult.Find("frame")); } - bool fIsAsyncBreak = MICommandFactory.IsAsyncBreakSignal(results); - if (await DoInternalBreakActions(fIsAsyncBreak)) + AsyncBreakSignal signal = MICommandFactory.GetAsyncBreakSignal(results); + bool isAsyncBreak = signal == AsyncBreakSignal.SIGTRAP || (IsUsingExecInterrupt && signal == AsyncBreakSignal.SIGINT); + if (await DoInternalBreakActions(isAsyncBreak)) { return; } @@ -409,6 +410,8 @@ private async Task DoInternalBreakActions(bool fIsAsyncBreak) { CmdContinueAsync(); processContinued = true; + // Reset since this -exec-interrupt was for an internal breakpoint. + IsUsingExecInterrupt = false; } if (firstException != null) @@ -591,7 +594,7 @@ internal bool IsLocalGdbTarget() _launchOptions is LocalLaunchOptions && !IsLocalLaunchUsingServer()); } - private bool IsRemoteGdbTarget() + internal bool IsRemoteGdbTarget() { return MICommandFactory.Mode == MIMode.Gdb && (_launchOptions is PipeLaunchOptions || _launchOptions is UnixShellPortLaunchOptions || @@ -606,6 +609,11 @@ protected bool IsCoreDump } } + /// + /// Flag to indicate that '-exec-interrupt' was used for async-break scenarios. + /// + public bool IsUsingExecInterrupt { get; protected set; } = false; + public async Task CmdTerminate() { if (!_terminating) @@ -749,6 +757,7 @@ public Task CmdBreakInternal() } } + IsUsingExecInterrupt = true; var res = CmdAsync("-exec-interrupt", ResultClass.done); return res.ContinueWith((t) => { diff --git a/src/MIDebugEngine/Engine.Impl/DebuggedProcess.cs b/src/MIDebugEngine/Engine.Impl/DebuggedProcess.cs index f7b68e0fd..538bef49a 100755 --- a/src/MIDebugEngine/Engine.Impl/DebuggedProcess.cs +++ b/src/MIDebugEngine/Engine.Impl/DebuggedProcess.cs @@ -1332,14 +1332,18 @@ private async Task HandleBreakModeEvent(ResultEventArgs results, BreakRequest br else if (reason == "signal-received") { string name = results.Results.TryFindString("signal-name"); + AsyncBreakSignal signal = MICommandFactory.GetAsyncBreakSignal(results.Results); + bool isAsyncBreak = signal == AsyncBreakSignal.SIGTRAP || (IsUsingExecInterrupt && signal == AsyncBreakSignal.SIGINT); if ((name == "SIG32") || (name == "SIG33")) { // we are going to ignore these (Sigma) signals for now CmdContinueAsyncConditional(breakRequest); } - else if (MICommandFactory.IsAsyncBreakSignal(results.Results)) + else if (isAsyncBreak) { _callback.OnAsyncBreakComplete(thread); + // Reset flag for real async break + IsUsingExecInterrupt = false; } else { From 73d569db5fc32003b8a9acf622d58ff22935f2cf Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Wed, 31 May 2023 00:10:18 +0100 Subject: [PATCH 5/9] [#1349] Always use `--simple-values` in newer versions of GDB. (#1400) * [#1349] Always use `--simple-values` in newer versions of GDB. In newer versions of GDB, the `--simple-values` option to the `-stack-list-arguments`, `-stack-list-locals` and `-stack-list-variables` commands no longer prints the value for references to compound types. This improves the performance of these commands when the stack has references to large data structures. When these versions of GDB are available, take advantage by using `--simple-values` in `DebuggedProcess.GetParameterInfoOnly` to fetch names and types in a single `-stack-list-arguments` command. This is faster than the old approach of using `--no-values` followed with `-var-create` and `-var-delete` for each parameter to get the type. The new method `MICommandFactory.SupportsSimpleValuesExcludesRefTypes` determines if the debugger supports the improved behaviour of the `--simple-values` option, by executing the `-list-features` command and checking for the `"simple-values-ref-types"` feature in the output. We cache the result on the `DebuggedProcess` object as the set of supported features does not change during the lifetime of the debug session. * fixup! [#1349] Always use `--simple-values` in newer versions of GDB. --- .../CommandFactories/MICommandFactory.cs | 18 +++++++++++++++ src/MICore/CommandFactories/gdb.cs | 12 ++++++++++ .../Engine.Impl/DebuggedProcess.cs | 23 +++++++++++++++++-- 3 files changed, 51 insertions(+), 2 deletions(-) diff --git a/src/MICore/CommandFactories/MICommandFactory.cs b/src/MICore/CommandFactories/MICommandFactory.cs index eb2e22773..700ddd46f 100644 --- a/src/MICore/CommandFactories/MICommandFactory.cs +++ b/src/MICore/CommandFactories/MICommandFactory.cs @@ -711,6 +711,24 @@ public virtual bool SupportsBreakpointChecksums() { return false; } + + /// + /// Get the set of features supported by the underlying debugger. + /// + public virtual Task> GetFeatures() + { + return Task.FromResult(new HashSet()); + } + + /// + /// True if the underlying debugger excludes the printing of references to + /// compound types when PrintValue.SimpleValues is used as an argument to + /// StackListLocals(), StackListArguments() and StackListVariables(). + /// + public virtual Task SupportsSimpleValuesExcludesRefTypes() + { + return Task.FromResult(false); + } #endregion } } diff --git a/src/MICore/CommandFactories/gdb.cs b/src/MICore/CommandFactories/gdb.cs index 65246bbfd..636a8a275 100644 --- a/src/MICore/CommandFactories/gdb.cs +++ b/src/MICore/CommandFactories/gdb.cs @@ -198,6 +198,18 @@ public override async Task EnableTargetAsyncOption() } } + public override async Task> GetFeatures() + { + Results results = await _debugger.CmdAsync("-list-features", ResultClass.done); + return new HashSet(results.Find("features").AsStrings); + } + + public override async Task SupportsSimpleValuesExcludesRefTypes() + { + HashSet features = await GetFeatures(); + return features.Contains("simple-values-ref-types"); + } + public override async Task Terminate() { // Although the mi documentation states that the correct command to terminate is -exec-abort diff --git a/src/MIDebugEngine/Engine.Impl/DebuggedProcess.cs b/src/MIDebugEngine/Engine.Impl/DebuggedProcess.cs index 538bef49a..6b9632386 100755 --- a/src/MIDebugEngine/Engine.Impl/DebuggedProcess.cs +++ b/src/MIDebugEngine/Engine.Impl/DebuggedProcess.cs @@ -52,6 +52,7 @@ internal class DebuggedProcess : MICore.Debugger private IProcessSequence _childProcessHandler; private bool _deleteEntryPointBreakpoint; private string _entryPointBreakpoint = string.Empty; + private bool? _simpleValuesExcludesRefTypes = null; public DebuggedProcess(bool bLaunched, LaunchOptions launchOptions, ISampleEngineCallback callback, WorkerThread worker, BreakpointManager bpman, AD7Engine engine, HostConfigurationStore configStore, HostWaitLoop waitLoop = null) : base(launchOptions, engine.Logger) { @@ -1985,8 +1986,26 @@ public async Task> GetParameterInfoOnly(AD7Threa //NOTE: eval is not called public async Task> GetParameterInfoOnly(AD7Thread thread, bool values, bool types, uint low, uint high) { - // If values are requested, request simple values, otherwise we'll use -var-create to get the type of argument it is. - var frames = await MICommandFactory.StackListArguments(values ? PrintValue.SimpleValues : PrintValue.NoValues, thread.Id, low, high); + PrintValue printValue = values ? PrintValue.SimpleValues : PrintValue.NoValues; + if (types && !values) + { + // We want types but not values. There is no PrintValue option for this, but if + // SimpleValues excludes printing values for references to compound types, then + // the fastest approach is to use SimpleValues (and ignore the values). + // Otherwise, the potential performance penalty of fetching values for + // references to compound types is too high, so use NoValues and follow up with + // -var-create to get the types. + if (!_simpleValuesExcludesRefTypes.HasValue) + { + _simpleValuesExcludesRefTypes = await this.MICommandFactory.SupportsSimpleValuesExcludesRefTypes(); + } + if (_simpleValuesExcludesRefTypes.Value) + { + printValue = PrintValue.SimpleValues; + } + } + + var frames = await MICommandFactory.StackListArguments(printValue, thread.Id, low, high); List parameters = new List(); foreach (var f in frames) From 1b18d41bfae867340be817a1bff9ff1086cd78a7 Mon Sep 17 00:00:00 2001 From: "microsoft-github-policy-service[bot]" <77245923+microsoft-github-policy-service[bot]@users.noreply.github.com> Date: Wed, 14 Jun 2023 10:25:36 -0700 Subject: [PATCH 6/9] Adding Microsoft SECURITY.MD (#1405) Microsoft mandatory file Co-authored-by: microsoft-github-policy-service[bot] <77245923+microsoft-github-policy-service[bot]@users.noreply.github.com> --- SECURITY.md | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 SECURITY.md diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 000000000..e138ec5d6 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,41 @@ + + +## Security + +Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). + +If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below. + +## Reporting Security Issues + +**Please do not report security vulnerabilities through public GitHub issues.** + +Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report). + +If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey). + +You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc). + +Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: + + * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) + * Full paths of source file(s) related to the manifestation of the issue + * The location of the affected source code (tag/branch/commit or direct URL) + * Any special configuration required to reproduce the issue + * Step-by-step instructions to reproduce the issue + * Proof-of-concept or exploit code (if possible) + * Impact of the issue, including how an attacker might exploit the issue + +This information will help us triage your report more quickly. + +If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs. + +## Preferred Languages + +We prefer all communications to be in English. + +## Policy + +Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd). + + From c8c71f394db710b931c833b962289b324fd1b915 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki?= Date: Wed, 28 Jun 2023 17:49:17 +0100 Subject: [PATCH 7/9] Align use of sendInvalidate request arguments (#1402) * Align use of sendInvalidate request arguments - sendInvalidate request arguments now behave like invalidate event. - Areas is an array of strings. - Areas can be empty, in this case client should assume 'all'. * Update src/OpenDebugAD7/AD7DebugSession.cs Allow sending an empty array of Areas. Co-authored-by: Andrew Wang * Update src/OpenDebugAD7/AD7DebugSession.cs Use Collection instead of List Co-authored-by: Andrew Wang * Update use of List --------- Co-authored-by: Andrew Wang --- src/OpenDebugAD7/AD7DebugSession.cs | 31 ++++++++++++++++------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/src/OpenDebugAD7/AD7DebugSession.cs b/src/OpenDebugAD7/AD7DebugSession.cs index 3c61e9ea0..bd22d1d05 100644 --- a/src/OpenDebugAD7/AD7DebugSession.cs +++ b/src/OpenDebugAD7/AD7DebugSession.cs @@ -137,23 +137,26 @@ public AD7DebugSession(Stream debugAdapterStdIn, Stream debugAdapterStdOut, List private void HandleSendInvalidateRequestAsync(IRequestResponder responder) { InvalidatedEvent invalidated = new InvalidatedEvent(); - - // Setting the area and adding it to the result - invalidated.Areas.Add(responder.Arguments.Areas); + // Set the Arguments only if passed + if (null != responder.Arguments) { + // Setting the Areas if passed + if (null != responder.Arguments.Areas) { + invalidated.Areas = responder.Arguments.Areas; + } - // Setting the StackFrameId if passed (and the 'threadId' is ignored). - if (null != responder.Arguments.StackFrameId) - { - invalidated.StackFrameId = responder.Arguments.StackFrameId; - } + // Setting the StackFrameId if passed (and the 'threadId' is ignored). + if (null != responder.Arguments.StackFrameId) + { + invalidated.StackFrameId = responder.Arguments.StackFrameId; + } - // Setting the ThreadId if passed - else if (null != responder.Arguments.ThreadId) - { - invalidated.ThreadId = responder.Arguments.ThreadId; + // Setting the ThreadId if passed + else if (null != responder.Arguments.ThreadId) + { + invalidated.ThreadId = responder.Arguments.ThreadId; + } } - Protocol.SendEvent(invalidated); } @@ -3913,7 +3916,7 @@ public SendInvalidateRequest(): base("sendInvalidate") internal class SendInvalidateArguments : DebugRequestArguments { - public InvalidatedAreas Areas { get; set; } + public List Areas { get; set; } public int? ThreadId { get; set; } public int? StackFrameId { get; set; } From 9233ae10ea093e5e7c7bb7b4f19692e6acab4267 Mon Sep 17 00:00:00 2001 From: Rakesh Ganesh Date: Fri, 7 Jul 2023 00:18:49 +0000 Subject: [PATCH 8/9] MIEngine: Introduce --thread and --frame options (#1401) Remove -thread-select and -stack-select-frame and introduce --thread and --frame options instead. It is general recommendation to not use -thread-select and -stack-select-frame and use --thread and --frame instead. More info can be found here: https://sourceware.org/gdb/onlinedocs/gdb/Context-management.html And here are the deprecation notes: -thread-select -thread-select: https://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Thread-Commands.html#GDB_002fMI-Thread-Commands -stack-select-frame -stack-select-frame: https://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Stack-Manipulation.html#GDB_002fMI-Stack-Manipulation Signed-off-by: intel-rganesh rakesh.ganesh@intel.com Signed-off-by: intel-rganesh rakesh.ganesh@intel.com Co-authored-by: Andrew Wang --- .../CommandFactories/MICommandFactory.cs | 62 ++++++++++++------- src/MICore/CommandFactories/gdb.cs | 44 ++++++++++--- src/MICore/CommandFactories/lldb.cs | 13 ++-- src/MICore/Debugger.cs | 7 +++ 4 files changed, 86 insertions(+), 40 deletions(-) diff --git a/src/MICore/CommandFactories/MICommandFactory.cs b/src/MICore/CommandFactories/MICommandFactory.cs index 700ddd46f..7b8454857 100644 --- a/src/MICore/CommandFactories/MICommandFactory.cs +++ b/src/MICore/CommandFactories/MICommandFactory.cs @@ -54,6 +54,8 @@ public abstract class MICommandFactory public abstract string Name { get; } + internal int MajorVersion { get; set; } + public static MICommandFactory GetInstance(MIMode mode, Debugger debugger) { MICommandFactory commandFactory; @@ -119,16 +121,18 @@ public virtual async Task ThreadInfo(uint? threadid = null) public async Task StackInfoDepth(int threadId, int maxDepth = 1000, ResultClass resultClass = ResultClass.done) { - string command = string.Format(CultureInfo.InvariantCulture, @"-stack-info-depth {0}", maxDepth); - Results results = await ThreadCmdAsync(command, resultClass, threadId); + string command = "-stack-info-depth"; + string args = string.Format(CultureInfo.InvariantCulture, $@"{maxDepth}"); + Results results = await ThreadCmdAsync(command, args, resultClass, threadId); return results; } public async Task StackListFrames(int threadId, uint lowFrameLevel, uint highFrameLevel = 1000) { - string command = string.Format(CultureInfo.InvariantCulture, @"-stack-list-frames {0} {1}", lowFrameLevel, highFrameLevel); - Results results = await ThreadCmdAsync(command, ResultClass.done, threadId); + string command = "-stack-list-frames"; + string args = string.Format(CultureInfo.InvariantCulture, $@"{lowFrameLevel} {highFrameLevel}"); + Results results = await ThreadCmdAsync(command, args, ResultClass.done, threadId); ListValue list = results.Find("stack"); if (list is ResultListValue) @@ -164,9 +168,10 @@ public async Task StackInfoFrame() /// public async Task StackListLocals(PrintValue printValues, int threadId, uint frameLevel) { - string cmd = string.Format(CultureInfo.InvariantCulture, @"-stack-list-locals {0}", (int)printValues); + string cmd = "-stack-list-locals"; + string args = string.Format(CultureInfo.InvariantCulture, $@"{(int)printValues}"); - Results localsResults = await ThreadFrameCmdAsync(cmd, ResultClass.done, threadId, frameLevel); + Results localsResults = await ThreadFrameCmdAsync(cmd, args, ResultClass.done, threadId, frameLevel); return localsResults.Find("locals"); } @@ -180,8 +185,9 @@ public async Task StackListLocals(PrintValue printValues, int threa /// This returns an array of results of frames, which contains a level and an args array. public virtual async Task StackListArguments(PrintValue printValues, int threadId, uint lowFrameLevel, uint hiFrameLevel) { - string cmd = string.Format(CultureInfo.InvariantCulture, @"-stack-list-arguments {0} {1} {2}", (int)printValues, lowFrameLevel, hiFrameLevel); - Results argumentsResults = await ThreadCmdAsync(cmd, ResultClass.done, threadId); + string command = "-stack-list-arguments"; + string args = string.Format(CultureInfo.InvariantCulture, $@"{(int)printValues} {lowFrameLevel} {hiFrameLevel}"); + Results argumentsResults = await ThreadCmdAsync(command, args, ResultClass.done, threadId); return argumentsResults.Find("stack-args").IsEmpty() ? new TupleValue[0] @@ -213,9 +219,9 @@ public async Task StackListArguments(PrintValue printValues, int thre /// Returns an array of results for variables public async Task StackListVariables(PrintValue printValues, int threadId, uint frameLevel) { - string cmd = string.Format(CultureInfo.InvariantCulture, @"-stack-list-variables {0}", (int)printValues); - - Results variablesResults = await ThreadFrameCmdAsync(cmd, ResultClass.done, threadId, frameLevel); + string cmd = "-stack-list-variables"; + string args = string.Format(CultureInfo.InvariantCulture, $@"{(int)printValues}"); + Results variablesResults = await ThreadFrameCmdAsync(cmd, args, ResultClass.done, threadId, frameLevel); return variablesResults.Find("variables"); } @@ -226,31 +232,36 @@ public async Task StackListVariables(PrintValue printValues, int public async Task ExecStep(int threadId, ResultClass resultClass = ResultClass.running) { string command = "-exec-step"; - await ThreadFrameCmdAsync(command, resultClass, threadId, 0); + string args = string.Empty; + await ThreadFrameCmdAsync(command, args, resultClass, threadId, 0); } public async Task ExecNext(int threadId, ResultClass resultClass = ResultClass.running) { string command = "-exec-next"; - await ThreadFrameCmdAsync(command, resultClass, threadId, 0); + string args = string.Empty; + await ThreadFrameCmdAsync(command, args, resultClass, threadId, 0); } public async Task ExecFinish(int threadId, ResultClass resultClass = ResultClass.running) { string command = "-exec-finish"; - await ThreadFrameCmdAsync(command, resultClass, threadId, 0); + string args = string.Empty; + await ThreadFrameCmdAsync(command, args, resultClass, threadId, 0); } public async Task ExecStepInstruction(int threadId, ResultClass resultClass = ResultClass.running) { string command = "-exec-step-instruction"; - await ThreadFrameCmdAsync(command, resultClass, threadId, 0); + string args = string.Empty; + await ThreadFrameCmdAsync(command, args, resultClass, threadId, 0); } public async Task ExecNextInstruction(int threadId, ResultClass resultClass = ResultClass.running) { string command = "-exec-next-instruction"; - await ThreadFrameCmdAsync(command, resultClass, threadId, 0); + string args = string.Empty; + await ThreadFrameCmdAsync(command, args, resultClass, threadId, 0); } /// @@ -296,15 +307,17 @@ public async Task DataListRegisterNames() public async Task DataListRegisterValues(int threadId) { - string command = "-data-list-register-values x"; - Results results = await ThreadCmdAsync(command, ResultClass.done, threadId); + string command = "-data-list-register-values"; + string args = "x"; + Results results = await ThreadCmdAsync(command, args, ResultClass.done, threadId); return results.Find("register-values").AsArray(); } public async Task DataEvaluateExpression(string expr, int threadId, uint frame) { - string command = "-data-evaluate-expression \"" + expr + "\""; - Results results = await ThreadFrameCmdAsync(command, ResultClass.None, threadId, frame); + string command = "-data-evaluate-expression"; + string args = $"\"{expr}\""; + Results results = await ThreadFrameCmdAsync(command, args, ResultClass.None, threadId, frame); return results.FindString("value"); } @@ -344,8 +357,9 @@ public virtual Task SetStepFiltering(bool enabled) public virtual async Task VarCreate(string expression, int threadId, uint frameLevel, enum_EVALFLAGS dwFlags, ResultClass resultClass = ResultClass.done) { string quoteEscapedExpression = EscapeQuotes(HandleInvalidChars(expression)); - string command = string.Format(CultureInfo.InvariantCulture, "-var-create - * \"{0}\"", quoteEscapedExpression); - Results results = await ThreadFrameCmdAsync(command, resultClass, threadId, frameLevel); + string command = "-var-create"; + string args = string.Format(CultureInfo.InvariantCulture, $" - * \"{quoteEscapedExpression}\""); + Results results = await ThreadFrameCmdAsync(command, args, resultClass, threadId, frameLevel); return results; } @@ -646,8 +660,8 @@ internal string HandleInvalidChars(string str) #region Other - abstract protected Task ThreadFrameCmdAsync(string command, ResultClass expectedResultClass, int threadId, uint frameLevel); - abstract protected Task ThreadCmdAsync(string command, ResultClass expectedResultClass, int threadId); + abstract protected Task ThreadFrameCmdAsync(string command, string args, ResultClass expectedResultClass, int threadId, uint frameLevel); + abstract protected Task ThreadCmdAsync(string command, string args, ResultClass expectedResultClass, int threadId); abstract public string GetSetEnvironmentVariableCommand(string name, string value); diff --git a/src/MICore/CommandFactories/gdb.cs b/src/MICore/CommandFactories/gdb.cs index 636a8a275..83100ab3e 100644 --- a/src/MICore/CommandFactories/gdb.cs +++ b/src/MICore/CommandFactories/gdb.cs @@ -48,7 +48,7 @@ public override bool AllowCommandsWhileRunning() return false; } - protected override async Task ThreadFrameCmdAsync(string command, ResultClass expectedResultClass, int threadId, uint frameLevel) + protected override async Task ThreadFrameCmdAsync(string command, string args, ResultClass expectedResultClass, int threadId, uint frameLevel) { // first aquire an exclusive lock. This is used as we don't want to fight with other commands that also require the current // thread to be set to a particular value @@ -56,8 +56,20 @@ protected override async Task ThreadFrameCmdAsync(string command, Resul try { - await ThreadSelect(threadId, lockToken); - await StackSelectFrame(frameLevel, lockToken); + + string threadFrameCommand; + // With source code of gdb 7.0.0, the --thread and --frame options were introduced and -thread-select and + // -stack-select-frame were deprecated + if (MajorVersion < 7) + { + await ThreadSelect(threadId, lockToken); + await StackSelectFrame(frameLevel, lockToken); + threadFrameCommand = string.Format(CultureInfo.InvariantCulture, $@"{command} {args}"); + } + else + { + threadFrameCommand = string.Format(CultureInfo.InvariantCulture, $@"{command} --thread {threadId} --frame {frameLevel} {args}"); + } // Before we execute the provided command, we need to switch to a shared lock. This is because the provided // command may be an expression evaluation command which could be long running, and we don't want to hold the @@ -65,7 +77,7 @@ protected override async Task ThreadFrameCmdAsync(string command, Resul lockToken.ConvertToSharedLock(); lockToken = null; - return await _debugger.CmdAsync(command, expectedResultClass); + return await _debugger.CmdAsync(threadFrameCommand, expectedResultClass); } finally { @@ -82,7 +94,7 @@ protected override async Task ThreadFrameCmdAsync(string command, Resul } } - protected override async Task ThreadCmdAsync(string command, ResultClass expectedResultClass, int threadId) + protected override async Task ThreadCmdAsync(string command, string args, ResultClass expectedResultClass, int threadId) { // first aquire an exclusive lock. This is used as we don't want to fight with other commands that also require the current // thread to be set to a particular value @@ -90,7 +102,18 @@ protected override async Task ThreadCmdAsync(string command, ResultClas try { - await ThreadSelect(threadId, lockToken); + string threadCommand; + // With source code of gdb 7.0.0, the --thread option was introduced and -thread-select + // was deprecated + if (MajorVersion < 7) + { + await ThreadSelect(threadId, lockToken); + threadCommand = string.Format(CultureInfo.InvariantCulture, $@"{command} {args}"); + } + else + { + threadCommand = string.Format(CultureInfo.InvariantCulture, $@"{command} --thread {threadId} {args}"); ; + } // Before we execute the provided command, we need to switch to a shared lock. This is because the provided // command may be an expression evaluation command which could be long running, and we don't want to hold the @@ -98,7 +121,7 @@ protected override async Task ThreadCmdAsync(string command, ResultClas lockToken.ConvertToSharedLock(); lockToken = null; - return await _debugger.CmdAsync(command, expectedResultClass); + return await _debugger.CmdAsync(threadCommand, expectedResultClass); } finally { @@ -301,12 +324,13 @@ public override async Task Catch(string name, bool onlyOnce = false, ResultClass public override async Task AutoComplete(string command, int threadId, uint frameLevel) { - command = "-complete \"" + command + "\""; + string cmd = "-complete"; + string args = $"\"{command}\""; Results res; if (threadId == -1) - res = await _debugger.CmdAsync(command, ResultClass.done); + res = await _debugger.CmdAsync($"{cmd} {args}", ResultClass.done); else - res = await ThreadFrameCmdAsync(command, ResultClass.done, threadId, frameLevel); + res = await ThreadFrameCmdAsync(cmd, args, ResultClass.done, threadId, frameLevel); var matchlist = res.Find("matches"); diff --git a/src/MICore/CommandFactories/lldb.cs b/src/MICore/CommandFactories/lldb.cs index 738a47f5a..b430f3257 100644 --- a/src/MICore/CommandFactories/lldb.cs +++ b/src/MICore/CommandFactories/lldb.cs @@ -76,9 +76,10 @@ public async override Task BuildBreakInsert(string condition, boo public override async Task VarCreate(string expression, int threadId, uint frameLevel, enum_EVALFLAGS dwFlags, ResultClass resultClass = ResultClass.done) { + string command = "-var-create"; string quoteEscapedExpression = EscapeQuotes(expression); - string command = string.Format(CultureInfo.InvariantCulture, "-var-create - - \"{0}\"", quoteEscapedExpression); // use '-' to indicate that "--frame" should be used to determine the frame number - Results results = await ThreadFrameCmdAsync(command, resultClass, threadId, frameLevel); + string args = string.Format(CultureInfo.InvariantCulture, $"- - \"{quoteEscapedExpression}\""); // use '-' to indicate that "--frame" should be used to determine the frame number + Results results = await ThreadFrameCmdAsync(command, args, resultClass, threadId, frameLevel); return results; } @@ -94,16 +95,16 @@ public override async Task VarListChildren(string variableReference, en return results; } - protected override async Task ThreadFrameCmdAsync(string command, ResultClass exepctedResultClass, int threadId, uint frameLevel) + protected override async Task ThreadFrameCmdAsync(string command, string args, ResultClass exepctedResultClass, int threadId, uint frameLevel) { - string threadFrameCommand = string.Format(CultureInfo.InvariantCulture, @"{0} --thread {1} --frame {2}", command, threadId, frameLevel); + string threadFrameCommand = string.Format(CultureInfo.InvariantCulture, $@"{command} {args} --thread {threadId} --frame {frameLevel}"); return await _debugger.CmdAsync(threadFrameCommand, exepctedResultClass); } - protected override async Task ThreadCmdAsync(string command, ResultClass expectedResultClass, int threadId) + protected override async Task ThreadCmdAsync(string command, string args, ResultClass expectedResultClass, int threadId) { - string threadCommand = string.Format(CultureInfo.InvariantCulture, @"{0} --thread {1}", command, threadId); + string threadCommand = string.Format(CultureInfo.InvariantCulture, $@"{command} {args} --thread {threadId}"); return await _debugger.CmdAsync(threadCommand, expectedResultClass); } diff --git a/src/MICore/Debugger.cs b/src/MICore/Debugger.cs index 00acc2d0d..c3367de6b 100755 --- a/src/MICore/Debugger.cs +++ b/src/MICore/Debugger.cs @@ -980,6 +980,13 @@ public void OnDebuggerProcessExit(/*OPTIONAL*/ string exitCode) MIDebuggerInitializeFailedException exception; string version = GdbVersionFromLog(); + int majorVersion = -1; + if (!string.IsNullOrWhiteSpace(version)) + { + int.TryParse(version.Split('.').FirstOrDefault(), out majorVersion); + } + MICommandFactory.MajorVersion = majorVersion; + // We can't use IsMinGW or IsCygwin because we never connected to the debugger bool isMinGWOrCygwin = _launchOptions is LocalLaunchOptions && PlatformUtilities.IsWindows() && From c713778504efc712b802a964d3470ec2f07af287 Mon Sep 17 00:00:00 2001 From: Andrew Wang Date: Fri, 7 Jul 2023 15:57:39 -0700 Subject: [PATCH 9/9] Fix Rank > 1 Display Strings for Natvis (#1406) * Fix Rank > 1 Display Strings for Natvis This PR fixes the display string for ArrayItems with Rank > 1 when the "[More...]" is expanded. Before "[More...]" will expand starting at [0,0] instead of [0,50] for the first expansion since the offsets are at 50. --------- Co-authored-by: Marco Peyrot --- src/MIDebugEngine/Natvis.Impl/Natvis.cs | 8 ++----- test/CppTests/Tests/NatvisTests.cs | 3 ++- .../debuggees/natvis/src/SimpleMatrix.h | 21 +++++++------------ test/CppTests/debuggees/natvis/src/main.cpp | 4 ++-- .../natvis/src/visualizer_files/Simple.natvis | 2 +- .../src/visualizer_files/Simple2.natvis | 12 ----------- 6 files changed, 14 insertions(+), 36 deletions(-) diff --git a/src/MIDebugEngine/Natvis.Impl/Natvis.cs b/src/MIDebugEngine/Natvis.Impl/Natvis.cs index afe8ed237..5091a78ae 100755 --- a/src/MIDebugEngine/Natvis.Impl/Natvis.cs +++ b/src/MIDebugEngine/Natvis.Impl/Natvis.cs @@ -676,12 +676,8 @@ private IVariableInformation[] ExpandVisualized(IVariableInformation variable) for (uint index = 0; index < requestedSize; ++index) { - string displayName = (startIndex + index).ToString(CultureInfo.InvariantCulture); - if (rank > 1) - { - displayName = GetDisplayNameFromArrayIndex(index, rank, dimensions, isForward); - } - + uint currentOffsetIndex = startIndex + index; + string displayName = rank > 1 ? GetDisplayNameFromArrayIndex(currentOffsetIndex, rank, dimensions, isForward) : currentOffsetIndex.ToString(CultureInfo.InvariantCulture); children.Add(new SimpleWrapper("[" + displayName + "]", _process.Engine, arrayExpr.Children[index])); } diff --git a/test/CppTests/Tests/NatvisTests.cs b/test/CppTests/Tests/NatvisTests.cs index 279af0664..d7fdf5d12 100644 --- a/test/CppTests/Tests/NatvisTests.cs +++ b/test/CppTests/Tests/NatvisTests.cs @@ -181,7 +181,8 @@ public void TestArrayItems(ITestSettings settings) // Multi-dimensional array var matrix = currentFrame.GetVariable("matrix"); - Assert.Equal("3", matrix.GetVariable("[1,1]").Value); + Assert.Equal("1", matrix.GetVariable("[0,1]").Value); + Assert.Equal("51", matrix.GetVariable("[More...]").GetVariable("[0,51]").Value); } runner.Expects.ExitedEvent(exitCode: 0).TerminatedEvent().AfterContinue(); diff --git a/test/CppTests/debuggees/natvis/src/SimpleMatrix.h b/test/CppTests/debuggees/natvis/src/SimpleMatrix.h index e315e749b..4889358ed 100644 --- a/test/CppTests/debuggees/natvis/src/SimpleMatrix.h +++ b/test/CppTests/debuggees/natvis/src/SimpleMatrix.h @@ -1,27 +1,20 @@ class SimpleMatrix { public: - int m_size1; - int m_size2; - bool m_fUseSize1; + int m_rows; + int m_cols; int* m_pData; - SimpleMatrix(int size1, int size2, bool fUseSize1) + SimpleMatrix(int row, int col) { - m_size1 = size1; - m_size2 = size2; - m_fUseSize1 = fUseSize1; + m_rows = row; + m_cols = col; - m_pData = new int[GetSize()]; + m_pData = new int[row * col]; - for (int i = 0; i < GetSize(); i++) + for (int i = 0; i < row * col; i++) { m_pData[i] = i; } } - - int GetSize() - { - return m_fUseSize1 ? m_size1 : m_size2; - } }; \ No newline at end of file diff --git a/test/CppTests/debuggees/natvis/src/main.cpp b/test/CppTests/debuggees/natvis/src/main.cpp index 8cc695507..0563e0c5c 100644 --- a/test/CppTests/debuggees/natvis/src/main.cpp +++ b/test/CppTests/debuggees/natvis/src/main.cpp @@ -46,7 +46,7 @@ int main(int argc, char** argv) SimpleClass* simpleClass = nullptr; simpleClass = new SimpleClass(); - SimpleMatrix matrix(5, 8, false); + SimpleMatrix matrix(2, 256); return 0; -} \ No newline at end of file +} diff --git a/test/CppTests/debuggees/natvis/src/visualizer_files/Simple.natvis b/test/CppTests/debuggees/natvis/src/visualizer_files/Simple.natvis index 0c3df50fb..775290ebb 100644 --- a/test/CppTests/debuggees/natvis/src/visualizer_files/Simple.natvis +++ b/test/CppTests/debuggees/natvis/src/visualizer_files/Simple.natvis @@ -64,7 +64,7 @@ Forward 2 - ($i == 1) ? 2 : m_size2/2 + ($i == 0) ? m_rows : m_cols m_pData diff --git a/test/CppTests/debuggees/natvis/src/visualizer_files/Simple2.natvis b/test/CppTests/debuggees/natvis/src/visualizer_files/Simple2.natvis index 959a3ed54..adfcf967a 100644 --- a/test/CppTests/debuggees/natvis/src/visualizer_files/Simple2.natvis +++ b/test/CppTests/debuggees/natvis/src/visualizer_files/Simple2.natvis @@ -27,16 +27,4 @@ - - - SimpleMatrix - - - Forward - 2 - ($i == 1) ? 2 : m_size2/2 - m_pData - - - \ No newline at end of file