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/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).
+
+
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
diff --git a/src/MICore/CommandFactories/MICommandFactory.cs b/src/MICore/CommandFactories/MICommandFactory.cs
index 3529d37d3..7b8454857 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;
@@ -43,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;
@@ -108,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)
@@ -153,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");
}
@@ -169,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]
@@ -202,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");
}
@@ -215,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);
}
///
@@ -285,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");
}
@@ -333,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;
}
@@ -635,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);
@@ -652,19 +677,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")
{
- isAsyncBreak = true;
+ return MICore.AsyncBreakSignal.SIGTRAP;
+ }
+ else if (signalName == "SIGINT")
+ {
+ return MICore.AsyncBreakSignal.SIGINT;
}
}
- return isAsyncBreak;
+ return MICore.AsyncBreakSignal.None;
}
public Results IsModuleLoad(string cmd)
@@ -697,6 +725,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..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
{
@@ -198,6 +221,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
@@ -289,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 295b919ca..c3367de6b 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) =>
{
@@ -971,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() &&
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/MIDebugEngine/Engine.Impl/DebuggedProcess.cs b/src/MIDebugEngine/Engine.Impl/DebuggedProcess.cs
index f7b68e0fd..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)
{
@@ -1332,14 +1333,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
{
@@ -1981,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)
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/src/OpenDebugAD7/AD7DebugSession.cs b/src/OpenDebugAD7/AD7DebugSession.cs
index c49b7b0b6..bd22d1d05 100644
--- a/src/OpenDebugAD7/AD7DebugSession.cs
+++ b/src/OpenDebugAD7/AD7DebugSession.cs
@@ -128,8 +128,38 @@ 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();
+ // 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 ThreadId if passed
+ else if (null != responder.Arguments.ThreadId)
+ {
+ invalidated.ThreadId = responder.Arguments.ThreadId;
+ }
+ }
+
+ Protocol.SendEvent(invalidated);
+
+ }
#endregion
#region Utility
@@ -3874,4 +3904,21 @@ int IDebugSettingsCallback110.ShouldSuppressImplicitToStringCalls(out int pfSupp
}
}
}
+
+ internal class SendInvalidateRequest : DebugRequest
+ {
+
+ public SendInvalidateRequest(): base("sendInvalidate")
+ {
+ }
+ }
+
+ internal class SendInvalidateArguments : DebugRequestArguments
+ {
+
+ public List Areas { get; set; }
+ public int? ThreadId { get; set; }
+ public int? StackFrameId { 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")]
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