From b76b8badfd2debe60a3a770081671a55afb4afd8 Mon Sep 17 00:00:00 2001 From: Andrew Wang Date: Tue, 19 Jun 2018 19:34:34 -0700 Subject: [PATCH 1/8] Use -- instead of -x for gnome-terminal (#733) (#735) The -x option is deprecated, so us -- instead. In Ubuntu 18.04, using the `-x` option results in the program being launched in a new tab in an existing terminal. This terminal is not brought to the foreground, nor is the tab activated, which makes a bunch of work for the user to find where there program is. Using the `--` option, on the other hand, results in the program opening in a new terminal and the new terminal is brought to the foreground as one might expect. --- src/MICore/TerminalLauncher.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/MICore/TerminalLauncher.cs b/src/MICore/TerminalLauncher.cs index 31249045a..9473169f5 100644 --- a/src/MICore/TerminalLauncher.cs +++ b/src/MICore/TerminalLauncher.cs @@ -179,7 +179,7 @@ public LinuxTerminalLauncher(string title, string initScript, ReadOnlyCollection if (File.Exists(GnomeTerminalPath)) { _terminalPath = GnomeTerminalPath; - _bashCommandPrefix = String.Format(CultureInfo.InvariantCulture, "--title {0} -x", _title); + _bashCommandPrefix = String.Format(CultureInfo.InvariantCulture, "--title {0} --", _title); } else if (File.Exists(XTermPath)) { From b1ddb5c356d1982d4dd47d89367cb23ffd88fed3 Mon Sep 17 00:00:00 2001 From: Andrew Wang Date: Mon, 2 Mar 2020 17:16:33 -0800 Subject: [PATCH 2/8] Merge master into release-cpptools (#978) * Add support for '`' instead of '-exec' prefaces for sending gdb commands (#976) * Add support for '`' instead of '-exec' prefaces for sending gdb commands * Fix FXCop error * Allow consoleCommand to exec while process run (#977) * Allow consoleCommand to exec while process run Added flag allowWhileRunning to consoleAsyncCmd since certain commands like 'version' do not require the process to be stopped in order to work Co-authored-by: Pierson Lee --- src/MICore/CommandFactories/gdb.cs | 4 +-- src/MICore/CommandFactories/lldb.cs | 3 +- src/MICore/Debugger.cs | 21 ++++++++++---- .../Engine.Impl/DebugUnixChildProcess.cs | 10 +++---- .../Engine.Impl/DebuggedProcess.cs | 10 +++---- src/MIDebugEngine/Engine.Impl/Variables.cs | 29 ++++++++++++++++--- src/MIDebugEngine/MIDebugCommandDispatcher.cs | 2 +- src/OpenDebugAD7/AD7DebugSession.cs | 10 ++++--- 8 files changed, 62 insertions(+), 27 deletions(-) diff --git a/src/MICore/CommandFactories/gdb.cs b/src/MICore/CommandFactories/gdb.cs index bde421d1c..3382fbfe0 100644 --- a/src/MICore/CommandFactories/gdb.cs +++ b/src/MICore/CommandFactories/gdb.cs @@ -158,7 +158,7 @@ public override async Task ThreadInfo(uint? threadId = null) public override async Task> StartAddressesForLine(string file, uint line) { string cmd = "info line " + file + ":" + line; - var result = await _debugger.ConsoleCmdAsync(cmd); + var result = await _debugger.ConsoleCmdAsync(cmd, allowWhileRunning: false); List addresses = new List(); using (StringReader stringReader = new StringReader(result)) { @@ -276,7 +276,7 @@ public override async Task Signal(string sig) public override async Task Catch(string name, bool onlyOnce = false, ResultClass resultClass = ResultClass.done) { string command = onlyOnce ? "tcatch " : "catch "; - await _debugger.ConsoleCmdAsync(command + name); + await _debugger.ConsoleCmdAsync(command + name, allowWhileRunning: false); } } } diff --git a/src/MICore/CommandFactories/lldb.cs b/src/MICore/CommandFactories/lldb.cs index 682958c5f..e571841ca 100644 --- a/src/MICore/CommandFactories/lldb.cs +++ b/src/MICore/CommandFactories/lldb.cs @@ -225,7 +225,8 @@ private async Task RequiresOnKeywordForBreakInsert() private async Task Version() { - return await _debugger.ConsoleCmdAsync("version"); + // 'Version' does not require the debuggee to be stopped. + return await _debugger.ConsoleCmdAsync("version", allowWhileRunning: true); } } } diff --git a/src/MICore/Debugger.cs b/src/MICore/Debugger.cs index f6a3a3a58..800749d95 100755 --- a/src/MICore/Debugger.cs +++ b/src/MICore/Debugger.cs @@ -794,11 +794,20 @@ private string Escape(string str) return outStr.ToString(); } - public async Task ConsoleCmdAsync(string cmd, bool ignoreFailures = false) + /// + /// Sends 'cmd' to the debuggee as a console command. + /// + /// The command to send. + /// Set to 'true' if the process can be running while the command is executed. + /// Ignore any failure that occur when executing the command. + /// + public async Task ConsoleCmdAsync(string cmd, bool allowWhileRunning, bool ignoreFailures = false) { - if (this.ProcessState != ProcessState.Stopped && this.ProcessState != ProcessState.NotConnected) + if (!(this.ProcessState == ProcessState.Running && allowWhileRunning) && + this.ProcessState != ProcessState.Stopped && + this.ProcessState != ProcessState.NotConnected) { - if (this.ProcessState == MICore.ProcessState.Exited) + if (this.ProcessState == ProcessState.Exited) { throw new DebuggerDisposedException(GetTargetProcessExitedReason()); } @@ -811,9 +820,11 @@ public async Task ConsoleCmdAsync(string cmd, bool ignoreFailures = fals using (ExclusiveLockToken lockToken = await _commandLock.AquireExclusive()) { // check again now that we have the lock - if (this.ProcessState != MICore.ProcessState.Stopped && this.ProcessState != ProcessState.NotConnected) + if (!(this.ProcessState == ProcessState.Running && allowWhileRunning) && + this.ProcessState != ProcessState.Stopped && + this.ProcessState != ProcessState.NotConnected) { - if (this.ProcessState == MICore.ProcessState.Exited) + if (this.ProcessState == ProcessState.Exited) { throw new DebuggerDisposedException(GetTargetProcessExitedReason()); } diff --git a/src/MIDebugEngine/Engine.Impl/DebugUnixChildProcess.cs b/src/MIDebugEngine/Engine.Impl/DebugUnixChildProcess.cs index a90ab8740..87e55a776 100644 --- a/src/MIDebugEngine/Engine.Impl/DebugUnixChildProcess.cs +++ b/src/MIDebugEngine/Engine.Impl/DebugUnixChildProcess.cs @@ -64,7 +64,7 @@ private async Task ProcessChild(ThreadProgress state) uint inf = _process.InferiorByPid(state.Newpid); if (inf != 0) { - await _process.ConsoleCmdAsync("inferior " + inf.ToString()); + await _process.ConsoleCmdAsync("inferior " + inf.ToString(), allowWhileRunning: false); if (!string.IsNullOrEmpty(_mainBreak)) { await _process.MICommandFactory.BreakDelete(_mainBreak); @@ -84,7 +84,7 @@ private async Task RunChildToMain(ThreadProgress state) uint inf = _process.InferiorByPid(state.Newpid); if (inf != 0) { - await _process.ConsoleCmdAsync("inferior " + inf.ToString()); + await _process.ConsoleCmdAsync("inferior " + inf.ToString(), allowWhileRunning: false); await SetBreakAtMain(); state.State = State.AtExec; await _process.MICommandFactory.ExecContinue(); // run the child @@ -100,7 +100,7 @@ private async Task ContinueTheChild(ThreadProgress state) uint inf = _process.InferiorByPid(state.Newpid); if (inf != 0) { - await _process.ConsoleCmdAsync("inferior " + inf.ToString()); + await _process.ConsoleCmdAsync("inferior " + inf.ToString(), allowWhileRunning: false); await _process.MICommandFactory.ExecContinue(); // run the child } } @@ -147,9 +147,9 @@ private async Task DetachFromChild(ThreadProgress state) uint inf = _process.InferiorByPid(state.Newpid); if (inf == 0) return false; // cannot process the child - await _process.ConsoleCmdAsync("inferior " + inf.ToString()); + await _process.ConsoleCmdAsync("inferior " + inf.ToString(), allowWhileRunning: false); await _process.MICommandFactory.TargetDetach(); // detach from the child - await _process.ConsoleCmdAsync("inferior 1"); + await _process.ConsoleCmdAsync("inferior 1", allowWhileRunning: false); return true; } diff --git a/src/MIDebugEngine/Engine.Impl/DebuggedProcess.cs b/src/MIDebugEngine/Engine.Impl/DebuggedProcess.cs index f7fcb9004..d310d2c47 100755 --- a/src/MIDebugEngine/Engine.Impl/DebuggedProcess.cs +++ b/src/MIDebugEngine/Engine.Impl/DebuggedProcess.cs @@ -611,7 +611,7 @@ public async Task Initialize(HostWaitLoop waitLoop, CancellationToken token) } else { - string resultString = await ConsoleCmdAsync(command.CommandText, command.IgnoreFailures); + string resultString = await ConsoleCmdAsync(command.CommandText, allowWhileRunning: false, ignoreFailures: command.IgnoreFailures); if (command.SuccessHandler != null) { await command.SuccessHandler(resultString); @@ -1317,7 +1317,7 @@ private async Task OnEntrypointHit() // When the terminal window is closed, a SIGHUP is sent to lldb-mi and LLDB's default is to stop. // We want to not stop (break) when this happens and the SIGHUP to be sent to the debuggee process. // LLDB requires this command to be issued after the process has started. - await ConsoleCmdAsync("process handle --pass true --stop false --notify false SIGHUP", true); + await ConsoleCmdAsync("process handle --pass true --stop false --notify false SIGHUP", allowWhileRunning: false, ignoreFailures: true); } if (this._deleteEntryPointBreakpoint && !String.IsNullOrWhiteSpace(this._entryPointBreakpoint)) @@ -1483,7 +1483,7 @@ internal void LoadSymbols(DebuggedModule module) private async Task LoadSymbols(string filename) { - return await ConsoleCmdAsync("sharedlibrary " + filename); + return await ConsoleCmdAsync("sharedlibrary " + filename, allowWhileRunning: false); } private async Task CheckModules() @@ -1491,7 +1491,7 @@ private async Task CheckModules() // NOTE: The version of GDB that comes in the Android SDK doesn't support -file-list-shared-library // so we need to use the console command //string results = await MICommandFactory.GetSharedLibrary(); - string results = await ConsoleCmdAsync("info sharedlibrary"); + string results = await ConsoleCmdAsync("info sharedlibrary", allowWhileRunning: false); using (StringReader stringReader = new StringReader(results)) { @@ -2244,7 +2244,7 @@ public async Task> StartAddressesForLine(string file, uint line) /// private Task ResetConsole() { - return ConsoleCmdAsync(@"shell echo -e \\033c 1>&2"); + return ConsoleCmdAsync(@"shell echo -e \\033c 1>&2", allowWhileRunning: false); } public bool IsChildProcessDebugging => _childProcessHandler != null; diff --git a/src/MIDebugEngine/Engine.Impl/Variables.cs b/src/MIDebugEngine/Engine.Impl/Variables.cs index 14455eb0b..1aab34563 100644 --- a/src/MIDebugEngine/Engine.Impl/Variables.cs +++ b/src/MIDebugEngine/Engine.Impl/Variables.cs @@ -421,20 +421,41 @@ public string EvalDependentExpression(string expr) return val; } + /// + /// This allows console commands to be sent through the eval channel via a '-exec ' or '`' preface + /// + /// raw command + /// command stripped of the preface ('-exec ' or '`') + /// true if it is a console command + private bool IsConsoleExecCmd(string command, out string strippedCommand) + { + strippedCommand = string.Empty; + string execCommandString = "-exec "; + if (command.StartsWith(execCommandString, StringComparison.Ordinal)) + { + strippedCommand = command.Substring(execCommandString.Length); + return true; + } + else if (command[0] == '`') + { + strippedCommand = command.Substring(1).TrimStart(); // remove spaces if any + return true; + } + return false; + } + internal async Task Eval(enum_EVALFLAGS dwFlags = 0) { this.VerifyNotDisposed(); await _engine.UpdateRadixAsync(_engine.CurrentRadix()); // ensure the radix value is up-to-date - string execCommandString = "-exec "; - try { - if (_strippedName.StartsWith(execCommandString)) + string consoleCommand; + if (IsConsoleExecCmd(_strippedName, out consoleCommand)) { // special case for executing raw mi commands. - string consoleCommand = _strippedName.Substring(execCommandString.Length); string consoleResults = null; consoleResults = await MIDebugCommandDispatcher.ExecuteCommand(consoleCommand, _debuggedProcess, ignoreFailures: true); diff --git a/src/MIDebugEngine/MIDebugCommandDispatcher.cs b/src/MIDebugEngine/MIDebugCommandDispatcher.cs index fb8d69619..ed178309c 100644 --- a/src/MIDebugEngine/MIDebugCommandDispatcher.cs +++ b/src/MIDebugEngine/MIDebugCommandDispatcher.cs @@ -47,7 +47,7 @@ internal static Task ExecuteCommand(string command, DebuggedProcess proc } else { - return process.ConsoleCmdAsync(command, ignoreFailures); + return process.ConsoleCmdAsync(command, allowWhileRunning: false, ignoreFailures: ignoreFailures); } } diff --git a/src/OpenDebugAD7/AD7DebugSession.cs b/src/OpenDebugAD7/AD7DebugSession.cs index 54a938ec3..10f905902 100644 --- a/src/OpenDebugAD7/AD7DebugSession.cs +++ b/src/OpenDebugAD7/AD7DebugSession.cs @@ -527,7 +527,7 @@ private void StepInternal(int threadId, enum_STEPKIND stepKind, enum_STEPUNIT st #region DebugAdapterBase protected override void HandleInitializeRequestAsync(IRequestResponder responder) - { + { InitializeArguments arguments = responder.Arguments; m_engineConfiguration = EngineConfiguration.TryGet(arguments.AdapterID); @@ -1825,10 +1825,12 @@ protected override void HandleEvaluateRequestAsync(IRequestResponder Date: Mon, 19 Jul 2021 15:57:31 -0700 Subject: [PATCH 3/8] Publish OpenDebugAD7: Don't create folder in zip Change from `$(Build.StagingDirectory)\debugAdapters\${{ parameters.RuntimeID }}\.` to `$(Build.StagingDirectory)\debugAdapters\${{ parameters.RuntimeID }}\*` to only zip up contents, not the current folder. --- eng/pipelines/steps/PublishOpenDebugAD7.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/eng/pipelines/steps/PublishOpenDebugAD7.yml b/eng/pipelines/steps/PublishOpenDebugAD7.yml index a4d900cbc..22d89bf6d 100644 --- a/eng/pipelines/steps/PublishOpenDebugAD7.yml +++ b/eng/pipelines/steps/PublishOpenDebugAD7.yml @@ -34,11 +34,11 @@ steps: # Publishing for non-macOS - ${{ if not(startsWith(parameters.RuntimeID, 'osx-')) }}: - powershell: | - Compress-Archive -Path $(Build.StagingDirectory)\debugAdapters\${{ parameters.RuntimeID }}\. -DestinationPath $(Build.StagingDirectory)\zips\${{ parameters.RuntimeID }}.zip + Compress-Archive -Path $(Build.StagingDirectory)\debugAdapters\${{ parameters.RuntimeID }}\* -DestinationPath $(Build.StagingDirectory)\zips\${{ parameters.RuntimeID }}.zip displayName: "Create ${{ parameters.RuntimeID}}.zip" - template: ../tasks/PublishPipelineArtifact.yml parameters: displayName: 'Publish ${{ parameters.RuntimeID }}' path: '$(Build.StagingDirectory)\zips\${{ parameters.RuntimeID }}.zip' - artifactName: '${{ parameters.RuntimeID }}_zip' \ No newline at end of file + artifactName: '${{ parameters.RuntimeID }}_zip' From f68f605ad88c11a97b92a6c0d6b6ea0018902a97 Mon Sep 17 00:00:00 2001 From: Andrew Wang Date: Mon, 19 Jul 2021 17:08:14 -0700 Subject: [PATCH 4/8] Fix macOS publishing: zip without absolute paths Zip using `*` after `cd $(Pipeline.Workspace)/Artifacts/` to prevent full paths appearing in the zip. Before it would produce: `osx-x64.zip\Users\runner\work\1\Artifacts\OpenDebugAD7` we want: `osx-x64.zip\OpenDebugAD7` --- eng/pipelines/templates/VSCode-codesign-osx.template.yml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/eng/pipelines/templates/VSCode-codesign-osx.template.yml b/eng/pipelines/templates/VSCode-codesign-osx.template.yml index 57961471f..6f5266b92 100644 --- a/eng/pipelines/templates/VSCode-codesign-osx.template.yml +++ b/eng/pipelines/templates/VSCode-codesign-osx.template.yml @@ -11,13 +11,16 @@ steps: - script: | echo "#[command] codesign -s - -f --entitlements $(Build.SourcesDirectory)/eng/Signing/macOS/debugger-entitlements.plist $(Pipeline.Workspace)/Artifacts/OpenDebugAD7" codesign -s - -f --entitlements $(Build.SourcesDirectory)/eng/Signing/macOS/debugger-entitlements.plist $(Pipeline.Workspace)/Artifacts/OpenDebugAD7 + + echo "#[command] cd $(Pipeline.Workspace)/Artifacts/" + cd $(Pipeline.Workspace)/Artifacts/ - echo "#[command] zip -r $(Pipeline.Workspace)/osx-x64.zip $(Pipeline.Workspace)/Artifacts/" - zip -r $(Pipeline.Workspace)/osx-x64.zip $(Pipeline.Workspace)/Artifacts/ + echo "#[command] zip -r $(Pipeline.Workspace)/osx-x64.zip *" + zip -r $(Pipeline.Workspace)/osx-x64.zip * - template: ../tasks/PublishPipelineArtifact.yml parameters: displayName: 'Publish Binaries' path: '$(Pipeline.Workspace)/osx-x64.zip' artifactName: 'unsigned_osx-x64_zip' -... \ No newline at end of file +... From 557d42b8a9c7caca3450385fe5902da7e6529ba1 Mon Sep 17 00:00:00 2001 From: Andrew Wang Date: Tue, 20 Jul 2021 10:16:11 -0700 Subject: [PATCH 5/8] Fix Zip Structure (#1176) vscode-cpptools expects OpenDebugAD7 to be in debugAdapters/bin This PR fixes the folder structure --- eng/pipelines/steps/PublishOpenDebugAD7.yml | 20 +++++++++---------- .../VSCode-codesign-osx.template.yml | 12 +++++------ 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/eng/pipelines/steps/PublishOpenDebugAD7.yml b/eng/pipelines/steps/PublishOpenDebugAD7.yml index 22d89bf6d..a680b3e9d 100644 --- a/eng/pipelines/steps/PublishOpenDebugAD7.yml +++ b/eng/pipelines/steps/PublishOpenDebugAD7.yml @@ -5,22 +5,22 @@ parameters: steps: - script: | - dotnet publish $(Build.SourcesDirectory)\src\OpenDebugAD7\OpenDebugAD7.csproj -c ${{ parameters.Configuration }} -r ${{ parameters.RuntimeID }} --self-contained -o $(Build.StagingDirectory)\debugAdapters\${{ parameters.RuntimeID }} - copy ${{ parameters.SignedBinariesFolder }}\Release\vscode\OpenDebugAD7.dll "$(Build.StagingDirectory)\debugAdapters\${{ parameters.RuntimeID }}\. - copy ${{ parameters.SignedBinariesFolder }}\Release\vscode\Microsoft.DebugEngineHost.dll $(Build.StagingDirectory)\debugAdapters\${{ parameters.RuntimeID }}\. - copy ${{ parameters.SignedBinariesFolder }}\Release\Microsoft.MIDebugEngine.dll $(Build.StagingDirectory)\debugAdapters\${{ parameters.RuntimeID }}\. - copy ${{ parameters.SignedBinariesFolder }}\Release\Microsoft.MICore.dll $(Build.StagingDirectory)\debugAdapters\${{ parameters.RuntimeID }}\. + dotnet publish $(Build.SourcesDirectory)\src\OpenDebugAD7\OpenDebugAD7.csproj -c ${{ parameters.Configuration }} -r ${{ parameters.RuntimeID }} --self-contained -o $(Build.StagingDirectory)\${{ parameters.RuntimeID }}\debugAdapters\bin + copy ${{ parameters.SignedBinariesFolder }}\Release\vscode\OpenDebugAD7.dll "$(Build.StagingDirectory)\${{ parameters.RuntimeID }}\debugAdapters\bin\. + copy ${{ parameters.SignedBinariesFolder }}\Release\vscode\Microsoft.DebugEngineHost.dll $(Build.StagingDirectory)\${{ parameters.RuntimeID }}\debugAdapters\bin\. + copy ${{ parameters.SignedBinariesFolder }}\Release\Microsoft.MIDebugEngine.dll $(Build.StagingDirectory)\${{ parameters.RuntimeID }}\debugAdapters\bin\. + copy ${{ parameters.SignedBinariesFolder }}\Release\Microsoft.MICore.dll $(Build.StagingDirectory)\${{ parameters.RuntimeID }}\debugAdapters\bin\. displayName: "Publish OpenDebugAD7 ${{ parameters.RuntimeID }}" # Windows Steps for copying over the exe and verify the windows binaries. -- ${{ if startsWith(parameters.RuntimeID, 'win-') }}: +- ${{ if startsWith(parameters.RuntimeID, 'win') }}: - script: | - copy ${{ parameters.SignedBinariesFolder }}\Release\vscode\OpenDebugAD7.exe $(Build.StagingDirectory)\debugAdapters\${{ parameters.RuntimeID }}\. + copy ${{ parameters.SignedBinariesFolder }}\Release\vscode\OpenDebugAD7.exe $(Build.StagingDirectory)\${{ parameters.RuntimeID }}\debugAdapters\bin\. displayName: "Copy OpenDebugAD7.exe" - template: ../tasks/SignVerify.yml parameters: - TargetFolders: $(Build.StagingDirectory)\debugAdapters\${{ parameters.RuntimeID }}\. + TargetFolders: $(Build.StagingDirectory)\${{ parameters.RuntimeID }}\debugAdapters\bin\. ExcludeSNVerify: true # Ignore CrossGen'ed .NET binaries # macOS Steps since we need to harden and sign the binary. @@ -28,13 +28,13 @@ steps: - template: ../tasks/PublishPipelineArtifact.yml parameters: displayName: 'Publish Unsigned ${{ parameters.RuntimeID }}' - path: '$(Build.StagingDirectory)\debugAdapters\${{ parameters.RuntimeID }}' + path: '$(Build.StagingDirectory)\${{ parameters.RuntimeID }}' artifactName: 'unsigned_${{ parameters.RuntimeID }}_binaries' # Publishing for non-macOS - ${{ if not(startsWith(parameters.RuntimeID, 'osx-')) }}: - powershell: | - Compress-Archive -Path $(Build.StagingDirectory)\debugAdapters\${{ parameters.RuntimeID }}\* -DestinationPath $(Build.StagingDirectory)\zips\${{ parameters.RuntimeID }}.zip + Compress-Archive -Path $(Build.StagingDirectory)\${{ parameters.RuntimeID }}\debugAdapters -DestinationPath $(Build.StagingDirectory)\zips\${{ parameters.RuntimeID }}.zip displayName: "Create ${{ parameters.RuntimeID}}.zip" - template: ../tasks/PublishPipelineArtifact.yml diff --git a/eng/pipelines/templates/VSCode-codesign-osx.template.yml b/eng/pipelines/templates/VSCode-codesign-osx.template.yml index 6f5266b92..c2b7187b9 100644 --- a/eng/pipelines/templates/VSCode-codesign-osx.template.yml +++ b/eng/pipelines/templates/VSCode-codesign-osx.template.yml @@ -9,14 +9,14 @@ steps: artifact: 'unsigned_osx-x64_binaries' - script: | - echo "#[command] codesign -s - -f --entitlements $(Build.SourcesDirectory)/eng/Signing/macOS/debugger-entitlements.plist $(Pipeline.Workspace)/Artifacts/OpenDebugAD7" - codesign -s - -f --entitlements $(Build.SourcesDirectory)/eng/Signing/macOS/debugger-entitlements.plist $(Pipeline.Workspace)/Artifacts/OpenDebugAD7 - + echo "#[command] codesign -s - -f --entitlements $(Build.SourcesDirectory)/eng/Signing/macOS/debugger-entitlements.plist $(Pipeline.Workspace)/Artifacts/debugAdapters/bin/OpenDebugAD7" + codesign -s - -f --entitlements $(Build.SourcesDirectory)/eng/Signing/macOS/debugger-entitlements.plist $(Pipeline.Workspace)/Artifacts/debugAdapters/bin/OpenDebugAD7 + echo "#[command] cd $(Pipeline.Workspace)/Artifacts/" - cd $(Pipeline.Workspace)/Artifacts/ + cd $(Pipeline.Workspace)/Artifacts - echo "#[command] zip -r $(Pipeline.Workspace)/osx-x64.zip *" - zip -r $(Pipeline.Workspace)/osx-x64.zip * + echo "#[command] zip -r $(Pipeline.Workspace)/osx-x64.zip ./debugAdapters" + zip -r $(Pipeline.Workspace)/osx-x64.zip ./debugAdapters - template: ../tasks/PublishPipelineArtifact.yml parameters: From 8abca80a195d9d8060b73d01bf726e16fb9348ce Mon Sep 17 00:00:00 2001 From: Andrew Wang Date: Tue, 20 Jul 2021 15:19:40 -0700 Subject: [PATCH 6/8] Add WindowsDebugLauncher.exe to Windows zips (#1178) --- eng/pipelines/steps/PublishOpenDebugAD7.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/eng/pipelines/steps/PublishOpenDebugAD7.yml b/eng/pipelines/steps/PublishOpenDebugAD7.yml index a680b3e9d..b8443b7d9 100644 --- a/eng/pipelines/steps/PublishOpenDebugAD7.yml +++ b/eng/pipelines/steps/PublishOpenDebugAD7.yml @@ -12,11 +12,12 @@ steps: copy ${{ parameters.SignedBinariesFolder }}\Release\Microsoft.MICore.dll $(Build.StagingDirectory)\${{ parameters.RuntimeID }}\debugAdapters\bin\. displayName: "Publish OpenDebugAD7 ${{ parameters.RuntimeID }}" -# Windows Steps for copying over the exe and verify the windows binaries. +# Windows Steps for copying over OpenDebugAD7.exe, WindowsDebugLauncher.exe, and verify the windows binaries. - ${{ if startsWith(parameters.RuntimeID, 'win') }}: - script: | copy ${{ parameters.SignedBinariesFolder }}\Release\vscode\OpenDebugAD7.exe $(Build.StagingDirectory)\${{ parameters.RuntimeID }}\debugAdapters\bin\. - displayName: "Copy OpenDebugAD7.exe" + copy ${{ parameters.SignedBinariesFolder }}\Release\vscode\WindowsDebugLauncher.exe $(Build.StagingDirectory)\${{ parameters.RuntimeID }}\debugAdapters\bin\. + displayName: "Copy OpenDebugAD7.exe and WindowsDebugLauncher.exe" - template: ../tasks/SignVerify.yml parameters: From 7ae9e4a569c1df007fd4fc5b3d0ce38cc9ddc168 Mon Sep 17 00:00:00 2001 From: gc46 Date: Wed, 8 Feb 2023 13:22:19 -0800 Subject: [PATCH 7/8] Merge main into 'release-cpptools' for v1.15.0 (#1384) --- src/AndroidDebugLauncher/Launcher.cs | 2 +- src/DebugEngineHost/HostNatvisProject.cs | 2 +- src/DebugEngineHost/RegistryMonitor.cs | 78 ++++++++--------- src/MICore/JsonLaunchOptions.cs | 40 ++++++++- src/MICore/LaunchOptions.cs | 26 +++--- src/MICore/MICoreResources.Designer.cs | 9 ++ src/MICore/MICoreResources.resx | 3 + .../BasicLaunchOptionsTests.cs | 2 +- .../Engine.Impl/DebuggedProcess.cs | 2 +- src/MIDebugEngine/Natvis.Impl/Natvis.cs | 83 +++++++++++-------- test/CppTests/CppTests.csproj | 5 +- .../OpenDebug/CrossPlatCpp/LaunchCommand.cs | 13 ++- test/CppTests/Tests/NatvisTests.cs | 68 +++++++++++++++ .../src/visualizer_files/Simple1.natvis | 33 ++++++++ .../src/visualizer_files/Simple2.natvis | 42 ++++++++++ 15 files changed, 305 insertions(+), 103 deletions(-) create mode 100644 test/CppTests/debuggees/natvis/src/visualizer_files/Simple1.natvis create mode 100644 test/CppTests/debuggees/natvis/src/visualizer_files/Simple2.natvis diff --git a/src/AndroidDebugLauncher/Launcher.cs b/src/AndroidDebugLauncher/Launcher.cs index 0730aef67..2a20a296e 100644 --- a/src/AndroidDebugLauncher/Launcher.cs +++ b/src/AndroidDebugLauncher/Launcher.cs @@ -459,7 +459,7 @@ private LaunchOptions SetupForDebuggingWorker(CancellationToken token) launchOptions.DebuggerMIMode = MIMode.Gdb; - launchOptions.VisualizerFile = "Microsoft.Android.natvis"; + launchOptions.VisualizerFiles.Add("Microsoft.Android.natvis"); launchOptions.WaitDynamicLibLoad = _launchOptions.WaitDynamicLibLoad; return launchOptions; diff --git a/src/DebugEngineHost/HostNatvisProject.cs b/src/DebugEngineHost/HostNatvisProject.cs index 4c969b652..11c3510eb 100644 --- a/src/DebugEngineHost/HostNatvisProject.cs +++ b/src/DebugEngineHost/HostNatvisProject.cs @@ -104,7 +104,7 @@ public static IDisposable WatchNatvisOptionSetting(HostConfigurationStore config IDisposable disposable = rmw.CurrentMonitor; // Watch NatvisDiagnostic section - rmw = new RegisterMonitorWrapper(CreateAndStartNatvisDiagnosticMonitor(natvisDiagnosticSection, natvisLogger)); + rmw = new RegisterMonitorWrapper(CreateAndStartNatvisDiagnosticMonitor(checkForSection, natvisLogger)); disposable.Dispose(); } diff --git a/src/DebugEngineHost/RegistryMonitor.cs b/src/DebugEngineHost/RegistryMonitor.cs index 6c6f1dcc0..0281bc371 100644 --- a/src/DebugEngineHost/RegistryMonitor.cs +++ b/src/DebugEngineHost/RegistryMonitor.cs @@ -47,14 +47,15 @@ private static extern int RegNotifyChangeKeyValue(SafeRegistryHandle hKey, bool #endregion - private HostConfigurationSection _section; + private readonly HostConfigurationSection _section; private readonly bool _watchSubtree; - // Set when registry value is changed - private AutoResetEvent m_changeEvent; - // Set when monitoring is stopped - private AutoResetEvent m_stoppedEvent; + private AutoResetEvent _stoppedEvent; + + // Members to handle multiple stop calls. + private bool _isStopped = false; + private readonly object _stopLock = new object(); /// /// Occurs when the specified registry key has changed. @@ -80,9 +81,13 @@ public void Start() public void Stop() { - if (m_stoppedEvent != null) + lock (_stopLock) { - m_stoppedEvent.Set(); + if (!_isStopped) + { + _stoppedEvent?.Set(); + _isStopped = true; + } } } @@ -93,53 +98,52 @@ private void Monitor() bool stopped = false; try { - m_stoppedEvent = new AutoResetEvent(false); - m_changeEvent = new AutoResetEvent(false); - - IntPtr handle = m_changeEvent.SafeWaitHandle.DangerousGetHandle(); - - int errorCode = RegNotifyChangeKeyValue(_section.Handle, _watchSubtree, RegChangeNotifyFilter.REG_NOTIFY_CHANGE_NAME | RegChangeNotifyFilter.REG_NOTIFY_CHANGE_LAST_SET, handle, true); - if (errorCode != 0) // 0 is ERROR_SUCCESS - { - _nativsLogger?.WriteLine(LogLevel.Error, Resource.Error_WatchRegistry, errorCode); - } - else + _stoppedEvent = new AutoResetEvent(false); + using (AutoResetEvent registryChangedEvent = new AutoResetEvent(false)) { - while (!stopped) - { - int waitResult = WaitHandle.WaitAny(new WaitHandle[] { m_stoppedEvent, m_changeEvent }); + IntPtr handle = registryChangedEvent.SafeWaitHandle.DangerousGetHandle(); - if (waitResult == 0) - { - stopped = true; - } - else + int errorCode = RegNotifyChangeKeyValue(_section.Handle, _watchSubtree, RegChangeNotifyFilter.REG_NOTIFY_CHANGE_NAME | RegChangeNotifyFilter.REG_NOTIFY_CHANGE_LAST_SET, handle, true); + if (errorCode != 0) // 0 is ERROR_SUCCESS + { + _nativsLogger?.WriteLine(LogLevel.Error, Resource.Error_WatchRegistry, errorCode); + } + else + { + while (!stopped) { - errorCode = RegNotifyChangeKeyValue(_section.Handle, _watchSubtree, RegChangeNotifyFilter.REG_NOTIFY_CHANGE_NAME | RegChangeNotifyFilter.REG_NOTIFY_CHANGE_LAST_SET, handle, true); - if (errorCode != 0) // 0 is ERROR_SUCCESS + int waitResult = WaitHandle.WaitAny(new WaitHandle[] { _stoppedEvent, registryChangedEvent }); + + if (waitResult == 0) { - _nativsLogger?.WriteLine(LogLevel.Error, Resource.Error_WatchRegistry, errorCode); - break; + stopped = true; + } + else + { + errorCode = RegNotifyChangeKeyValue(_section.Handle, _watchSubtree, RegChangeNotifyFilter.REG_NOTIFY_CHANGE_NAME | RegChangeNotifyFilter.REG_NOTIFY_CHANGE_LAST_SET, handle, true); + if (errorCode != 0) // 0 is ERROR_SUCCESS + { + _nativsLogger?.WriteLine(LogLevel.Error, Resource.Error_WatchRegistry, errorCode); + break; + } + RegChanged?.Invoke(this, null); } - RegChanged?.Invoke(this, null); } } } } finally { - _section.Dispose(); - m_stoppedEvent?.Dispose(); - m_changeEvent?.Dispose(); + _stoppedEvent.Dispose(); + _stoppedEvent = null; - m_stoppedEvent = null; - m_changeEvent = null; + _section.Dispose(); } } public void Dispose() { - m_stoppedEvent?.Dispose(); + Stop(); // Stopping the monitor will dispose of the AutoResetEvent and HostConfigurationSection } } } diff --git a/src/MICore/JsonLaunchOptions.cs b/src/MICore/JsonLaunchOptions.cs index 76f3d4c26..5193234a8 100644 --- a/src/MICore/JsonLaunchOptions.cs +++ b/src/MICore/JsonLaunchOptions.cs @@ -39,10 +39,11 @@ public abstract partial class BaseOptions public string TargetArchitecture { get; set; } /// - /// .natvis file to be used when debugging this process. This option is not compatible with GDB pretty printing. Please also see "showDisplayString" if using this setting. + /// .natvis files to be used when debugging this process. This option is not compatible with GDB pretty printing. Please also see "showDisplayString" if using this setting. /// [JsonProperty("visualizerFile", DefaultValueHandling = DefaultValueHandling.Ignore)] - public string VisualizerFile { get; set; } + [JsonConverter(typeof(VisualizerFileConverter))] + public List VisualizerFile { get; set; } /// /// When a visualizerFile is specified, showDisplayString will enable the display string. Turning this option on can cause slower performance during debugging. @@ -123,6 +124,37 @@ public abstract partial class BaseOptions public UnknownBreakpointHandling? UnknownBreakpointHandling { get; set; } } + internal class VisualizerFileConverter : JsonConverter + { + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + { + List visualizerFile = new List(); + if (reader.TokenType == JsonToken.StartArray) + { + visualizerFile = serializer.Deserialize>(reader); + } + else if (reader.TokenType == JsonToken.String) + { + visualizerFile.Add(reader.Value.ToString()); + } + else + { + throw new JsonReaderException(MICoreResources.Error_IncorrectVisualizerFileFormat); + } + return visualizerFile; + } + + public override bool CanConvert(Type objectType) + { + throw new NotImplementedException(); + } + + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + { + throw new NotImplementedException(); + } + } + public partial class AttachOptions : BaseOptions { #region Public Properties for Serialization @@ -144,7 +176,7 @@ public AttachOptions( int processId, string type = null, string targetArchitecture = null, - string visualizerFile = null, + List visualizerFile = null, bool? showDisplayString = null, string additionalSOLibSearchPath = null, string MIMode = null, @@ -408,7 +440,7 @@ public LaunchOptions( List postRemoteConnectCommands = null, List customLaunchSetupCommands = null, LaunchCompleteCommand? launchCompleteCommand = null, - string visualizerFile = null, + List visualizerFile = null, bool? showDisplayString = null, List environment = null, string additionalSOLibSearchPath = null, diff --git a/src/MICore/LaunchOptions.cs b/src/MICore/LaunchOptions.cs index 6ba4b10c1..7c102711f 100644 --- a/src/MICore/LaunchOptions.cs +++ b/src/MICore/LaunchOptions.cs @@ -960,19 +960,10 @@ public string AdditionalSOLibSearchPath } } - private string _visualizerFile; /// - /// [Optional] Natvis file name - from install location + /// Collection of natvis files to use when evaluating /// - public string VisualizerFile - { - get { return _visualizerFile; } - set - { - VerifyCanModifyProperty(nameof(VisualizerFile)); - _visualizerFile = value; - } - } + public List VisualizerFiles { get; } = new List(); private bool _waitDynamicLibLoad = true; /// @@ -1579,9 +1570,9 @@ private void Merge(AttachOptionsForConnection suppOptions) { DebugChildProcesses = suppOptions.DebugChildProcesses; } - if (string.IsNullOrWhiteSpace(VisualizerFile)) + if (!this.VisualizerFiles.Contains(suppOptions.VisualizerFile)) { - VisualizerFile = suppOptions.VisualizerFile; + this.VisualizerFiles.Add(suppOptions.VisualizerFile); } if (suppOptions.ShowDisplayStringSpecified) { @@ -1771,7 +1762,10 @@ protected void InitializeCommonOptions(Json.LaunchOptions.BaseOptions options) this.TargetArchitecture = ConvertTargetArchitectureAttribute(options.TargetArchitecture); } - this.VisualizerFile = options.VisualizerFile; + if (options.VisualizerFile != null && options.VisualizerFile.Count > 0) + { + this.VisualizerFiles.AddRange(options.VisualizerFile); + } this.ShowDisplayString = options.ShowDisplayString.GetValueOrDefault(false); this.AdditionalSOLibSearchPath = String.IsNullOrEmpty(this.AdditionalSOLibSearchPath) ? @@ -1841,8 +1835,8 @@ protected void InitializeCommonOptions(Xml.LaunchOptions.BaseLaunchOptions sourc if (string.IsNullOrEmpty(this.WorkingDirectory)) this.WorkingDirectory = source.WorkingDirectory; - if (string.IsNullOrEmpty(this.VisualizerFile)) - this.VisualizerFile = source.VisualizerFile; + if (!string.IsNullOrEmpty(source.VisualizerFile)) + this.VisualizerFiles.Add(source.VisualizerFile); this.ShowDisplayString = source.ShowDisplayString; this.WaitDynamicLibLoad = source.WaitDynamicLibLoad; diff --git a/src/MICore/MICoreResources.Designer.cs b/src/MICore/MICoreResources.Designer.cs index 982f2d2ac..20e83aedb 100755 --- a/src/MICore/MICoreResources.Designer.cs +++ b/src/MICore/MICoreResources.Designer.cs @@ -185,6 +185,15 @@ public static string Error_FailedToEnterBreakState { } } + /// + /// Looks up a localized string similar to 'visualizerFile' must be a string or array of strings.. + /// + public static string Error_IncorrectVisualizerFileFormat { + get { + return ResourceManager.GetString("Error_IncorrectVisualizerFileFormat", resourceCulture); + } + } + /// /// Looks up a localized string similar to Internal file "{0}" could not be found.. /// diff --git a/src/MICore/MICoreResources.resx b/src/MICore/MICoreResources.resx index b1ff5f790..0421a7999 100755 --- a/src/MICore/MICoreResources.resx +++ b/src/MICore/MICoreResources.resx @@ -326,4 +326,7 @@ Error: {1} 'editorPath' can not be null or empty + + 'visualizerFile' must be a string or array of strings. + \ No newline at end of file diff --git a/src/MICoreUnitTests/BasicLaunchOptionsTests.cs b/src/MICoreUnitTests/BasicLaunchOptionsTests.cs index 0c4ab3bc0..14d9d70a2 100644 --- a/src/MICoreUnitTests/BasicLaunchOptionsTests.cs +++ b/src/MICoreUnitTests/BasicLaunchOptionsTests.cs @@ -263,7 +263,7 @@ internal void VerifyCoreApisPresent() launchOptions.WorkingDirectory = "/home/user"; launchOptions.DebuggerMIMode = MIMode.Gdb; launchOptions.WaitDynamicLibLoad = false; - launchOptions.VisualizerFile = @"c:\myproject\file.natvis"; + launchOptions.VisualizerFiles.Add(@"c:\myproject\file.natvis"); launchOptions.SourceMap = new ReadOnlyCollection(new List()); launchOptions.Environment = new ReadOnlyCollection(new List()); Microsoft.DebugEngineHost.HostConfigurationStore configStore = null; diff --git a/src/MIDebugEngine/Engine.Impl/DebuggedProcess.cs b/src/MIDebugEngine/Engine.Impl/DebuggedProcess.cs index 24141685c..f7b68e0fd 100755 --- a/src/MIDebugEngine/Engine.Impl/DebuggedProcess.cs +++ b/src/MIDebugEngine/Engine.Impl/DebuggedProcess.cs @@ -543,7 +543,7 @@ private async Task EnsureModulesLoaded() public async Task Initialize(HostWaitLoop waitLoop, CancellationToken token) { bool success = false; - Natvis.Initialize(_launchOptions.VisualizerFile); + Natvis.Initialize(_launchOptions.VisualizerFiles); int total = 1; await this.WaitForConsoleDebuggerInitialize(token); diff --git a/src/MIDebugEngine/Natvis.Impl/Natvis.cs b/src/MIDebugEngine/Natvis.Impl/Natvis.cs index 81b52ee84..afe8ed237 100755 --- a/src/MIDebugEngine/Natvis.Impl/Natvis.cs +++ b/src/MIDebugEngine/Natvis.Impl/Natvis.cs @@ -260,7 +260,7 @@ internal Natvis(DebuggedProcess process, bool showDisplayString, HostConfigurati _configStore = configStore; } - public void Initialize(string fileName) + private void InitializeNatvisServices() { try { @@ -271,52 +271,65 @@ public void Initialize(string fileName) { // failed to find the VS Service } + } - if (!string.IsNullOrEmpty(fileName)) + /* + * Handle multiple Natvis files + */ + public void Initialize(List fileNames) + { + InitializeNatvisServices(); + if (fileNames != null && fileNames.Count > 0) { - if (!Path.IsPathRooted(fileName)) + foreach (var fileName in fileNames) { - string globalVisualizersDirectory = _process.Engine.GetMetric("GlobalVisualizersDirectory") as string; - string globalNatVisPath = null; - if (!string.IsNullOrEmpty(globalVisualizersDirectory) && !string.IsNullOrEmpty(fileName)) - { - globalNatVisPath = Path.Combine(globalVisualizersDirectory, fileName); - } - - // For local launch, try and load natvis next to the target exe if it exists and if - // the exe is rooted. If the file doesn't exist, and also doesn't exist in the global folder fail. - if (_process.LaunchOptions is LocalLaunchOptions) + if (!string.IsNullOrEmpty(fileName)) { - string exePath = (_process.LaunchOptions as LocalLaunchOptions).ExePath; - if (Path.IsPathRooted(exePath)) + if (!Path.IsPathRooted(fileName)) { - string localNatvisPath = Path.Combine(Path.GetDirectoryName(exePath), fileName); + string globalVisualizersDirectory = _process.Engine.GetMetric("GlobalVisualizersDirectory") as string; + string globalNatVisPath = null; + if (!string.IsNullOrEmpty(globalVisualizersDirectory) && !string.IsNullOrEmpty(fileName)) + { + globalNatVisPath = Path.Combine(globalVisualizersDirectory, fileName); + } - if (File.Exists(localNatvisPath)) + // For local launch, try and load natvis next to the target exe if it exists and if + // the exe is rooted. If the file doesn't exist, and also doesn't exist in the global folder fail. + if (_process.LaunchOptions is LocalLaunchOptions) { - LoadFile(localNatvisPath); - return; + string exePath = (_process.LaunchOptions as LocalLaunchOptions).ExePath; + if (Path.IsPathRooted(exePath)) + { + string localNatvisPath = Path.Combine(Path.GetDirectoryName(exePath), fileName); + + if (File.Exists(localNatvisPath)) + { + LoadFile(localNatvisPath); + return; + } + else if (globalNatVisPath == null || !File.Exists(globalNatVisPath)) + { + // Neither local or global path exists, report an error. + _process.WriteOutput(String.Format(CultureInfo.CurrentCulture, ResourceStrings.FileNotFound, localNatvisPath)); + return; + } + } } - else if (globalNatVisPath == null || !File.Exists(globalNatVisPath)) + + // Local wasn't supported or the file didn't exist. Try and load from globally registered visualizer directory if local didn't work + // or wasn't supported by the launch options + if (!string.IsNullOrEmpty(globalNatVisPath)) { - // Neither local or global path exists, report an error. - _process.WriteOutput(String.Format(CultureInfo.CurrentCulture, ResourceStrings.FileNotFound, localNatvisPath)); - return; + LoadFile(globalNatVisPath); } } + else + { + // Full path to the natvis file.. Just try the load + LoadFile(fileName); + } } - - // Local wasn't supported or the file didn't exist. Try and load from globally registered visualizer directory if local didn't work - // or wasn't supported by the launch options - if (!string.IsNullOrEmpty(globalNatVisPath)) - { - LoadFile(globalNatVisPath); - } - } - else - { - // Full path to the natvis file.. Just try the load - LoadFile(fileName); } } } diff --git a/test/CppTests/CppTests.csproj b/test/CppTests/CppTests.csproj index 5611989e2..268ffe32c 100644 --- a/test/CppTests/CppTests.csproj +++ b/test/CppTests/CppTests.csproj @@ -45,10 +45,7 @@ - + diff --git a/test/CppTests/OpenDebug/CrossPlatCpp/LaunchCommand.cs b/test/CppTests/OpenDebug/CrossPlatCpp/LaunchCommand.cs index d5521a77e..06e37fb21 100644 --- a/test/CppTests/OpenDebug/CrossPlatCpp/LaunchCommand.cs +++ b/test/CppTests/OpenDebug/CrossPlatCpp/LaunchCommand.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.IO; using DebuggerTesting.OpenDebug.Commands; +using DebuggerTesting.OpenDebug.CrossPlatCpp; using DebuggerTesting.Utilities; using Newtonsoft.Json; @@ -34,7 +35,8 @@ public sealed class CppLaunchCommandArgs : LaunchCommandArgs public string MIMode; [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)] - public string VisualizerFile; + public object VisualizerFile; + [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)] public bool ShowDisplayString; @@ -50,8 +52,13 @@ public class LaunchCommand : LaunchCommand /// The full path to the program to launch /// The architecture of the program /// [OPTIONAL] Args to pass to the program - public LaunchCommand(IDebuggerSettings settings, string program, string visualizerFile = null, bool isAttach = false, params string[] args) + public LaunchCommand(IDebuggerSettings settings, string program, object visualizerFile = null, bool isAttach = false, params string[] args) { + if (!(visualizerFile == null || visualizerFile is string || visualizerFile is List)) + { + throw new ArgumentOutOfRangeException(nameof(visualizerFile)); + } + this.Timeout = TimeSpan.FromSeconds(15); this.Args.name = CreateName(settings); @@ -75,7 +82,7 @@ public LaunchCommand(IDebuggerSettings settings, string program, string visualiz this.Args.targetArchitecture = settings.DebuggeeArchitecture.ToArchitectureString(); this.Args.MIMode = settings.MIMode; this.Args.VisualizerFile = visualizerFile; - this.Args.ShowDisplayString = !string.IsNullOrEmpty(visualizerFile); + this.Args.ShowDisplayString = visualizerFile != null; } } diff --git a/test/CppTests/Tests/NatvisTests.cs b/test/CppTests/Tests/NatvisTests.cs index 69b2526c4..279af0664 100644 --- a/test/CppTests/Tests/NatvisTests.cs +++ b/test/CppTests/Tests/NatvisTests.cs @@ -480,6 +480,74 @@ public void TestCommaFormatWithSquareBrackets(ITestSettings settings) } } + [Theory] + [DependsOnTest(nameof(CompileNatvisDebuggee))] + [RequiresTestSettings] + // Disable on macOS + // Error: + // C-style cast from 'int' to 'int [10]' is not allowed + // (int[10])*(((vec)._start)) + [UnsupportedDebugger(SupportedDebugger.Lldb, SupportedArchitecture.x64 | SupportedArchitecture.x86)] + public void TestMultipleNatvisFiles(ITestSettings settings) + { + this.TestPurpose("This test checks if multiple Natvis files can be used."); + this.WriteSettings(settings); + + IDebuggee debuggee = Debuggee.Open(this, settings.CompilerSettings, NatvisName, DebuggeeMonikers.Natvis.Default); + + using (IDebuggerRunner runner = CreateDebugAdapterRunner(settings)) + { + this.Comment("Configure launch"); + List visFile = new List(); + visFile.Add(Path.Join(debuggee.SourceRoot, "visualizer_files", "Simple1.natvis")); + visFile.Add(Path.Join(debuggee.SourceRoot, "visualizer_files", "Simple2.natvis")); + + LaunchCommand launch = new LaunchCommand(settings.DebuggerSettings, debuggee.OutputPath, visFile, false); + runner.RunCommand(launch); + + this.Comment("Set Breakpoint"); + SourceBreakpoints writerBreakpoints = debuggee.Breakpoints(NatvisSourceName, ReturnSourceLine); + runner.SetBreakpoints(writerBreakpoints); + + runner.Expects.StoppedEvent(StoppedReason.Breakpoint).AfterConfigurationDone(); + + using (IThreadInspector threadInspector = runner.GetThreadInspector()) + { + IFrameInspector currentFrame = threadInspector.Stack.First(); + + // Simple1.natvis + this.Comment("Verifying ArrayItems natvis"); + var ll = currentFrame.GetVariable("vec"); + Assert.Equal("{ size=2000 }", ll.Value); + + // Custom Item in natvis + Assert.Equal("2000", ll.GetVariable("Size").Value); + + // Index element for ArrayItems + Assert.Equal("20", ll.GetVariable("[5]").Value); + Assert.Equal("51", ll.GetVariable("[More...]").GetVariable("[51]").Value); + + // Simple2.natvis + this.Comment("Verifying TreeItems natvis"); + var map = currentFrame.GetVariable("map"); + + // Custom Item in natvis + Assert.Equal("6", map.GetVariable("Count").Value); + + // Index element for TreeItems + // Visualized map will show the BST in a flat ordered list. + // Values are inserted as [0, -100, 15, -35, 4, -72] + // Expected visualize list to be [-100, -72, -35, 0, 4, 15] + Assert.Equal("-100", map.GetVariable("[0]").Value); + Assert.Equal("0", map.GetVariable("[3]").Value); + Assert.Equal("15", map.GetVariable("[5]").Value); + } + + runner.Expects.ExitedEvent(exitCode: 0).TerminatedEvent().AfterContinue(); + runner.DisconnectAndVerify(); + } + } + #endregion } } diff --git a/test/CppTests/debuggees/natvis/src/visualizer_files/Simple1.natvis b/test/CppTests/debuggees/natvis/src/visualizer_files/Simple1.natvis new file mode 100644 index 000000000..5d7f69d2c --- /dev/null +++ b/test/CppTests/debuggees/natvis/src/visualizer_files/Simple1.natvis @@ -0,0 +1,33 @@ + + + + + Hello DisplayString + + + + Null Class + Non-null Class + + + + {{ size={_size} }} + + _size + + _size + _start + + + + + + {{ size={_size} }} + + + _size + _array[_size - 1 - $i] + + + + \ No newline at end of file diff --git a/test/CppTests/debuggees/natvis/src/visualizer_files/Simple2.natvis b/test/CppTests/debuggees/natvis/src/visualizer_files/Simple2.natvis new file mode 100644 index 000000000..959a3ed54 --- /dev/null +++ b/test/CppTests/debuggees/natvis/src/visualizer_files/Simple2.natvis @@ -0,0 +1,42 @@ + + + + + {{ size={numElements} }} + + numElements + + numElements + head + next + data + + + + + + {{ size={numElements} }} + + numElements + + numElements + root + left + right + data + + + + + + SimpleMatrix + + + Forward + 2 + ($i == 1) ? 2 : m_size2/2 + m_pData + + + + \ No newline at end of file From 8e7e3bd607024f35da2617e963bd24fe75789413 Mon Sep 17 00:00:00 2001 From: gc46 Date: Wed, 8 Feb 2023 14:12:01 -0800 Subject: [PATCH 8/8] Revert "Merge main into 'release-cpptools' for v1.15.0 (#1384)" This reverts commit 7ae9e4a569c1df007fd4fc5b3d0ce38cc9ddc168. --- src/AndroidDebugLauncher/Launcher.cs | 2 +- src/DebugEngineHost/HostNatvisProject.cs | 2 +- src/DebugEngineHost/RegistryMonitor.cs | 78 +++++++++-------- src/MICore/JsonLaunchOptions.cs | 40 +-------- src/MICore/LaunchOptions.cs | 26 +++--- src/MICore/MICoreResources.Designer.cs | 9 -- src/MICore/MICoreResources.resx | 3 - .../BasicLaunchOptionsTests.cs | 2 +- .../Engine.Impl/DebuggedProcess.cs | 2 +- src/MIDebugEngine/Natvis.Impl/Natvis.cs | 83 ++++++++----------- test/CppTests/CppTests.csproj | 5 +- .../OpenDebug/CrossPlatCpp/LaunchCommand.cs | 13 +-- test/CppTests/Tests/NatvisTests.cs | 68 --------------- .../src/visualizer_files/Simple1.natvis | 33 -------- .../src/visualizer_files/Simple2.natvis | 42 ---------- 15 files changed, 103 insertions(+), 305 deletions(-) delete mode 100644 test/CppTests/debuggees/natvis/src/visualizer_files/Simple1.natvis delete mode 100644 test/CppTests/debuggees/natvis/src/visualizer_files/Simple2.natvis diff --git a/src/AndroidDebugLauncher/Launcher.cs b/src/AndroidDebugLauncher/Launcher.cs index 2a20a296e..0730aef67 100644 --- a/src/AndroidDebugLauncher/Launcher.cs +++ b/src/AndroidDebugLauncher/Launcher.cs @@ -459,7 +459,7 @@ private LaunchOptions SetupForDebuggingWorker(CancellationToken token) launchOptions.DebuggerMIMode = MIMode.Gdb; - launchOptions.VisualizerFiles.Add("Microsoft.Android.natvis"); + launchOptions.VisualizerFile = "Microsoft.Android.natvis"; launchOptions.WaitDynamicLibLoad = _launchOptions.WaitDynamicLibLoad; return launchOptions; diff --git a/src/DebugEngineHost/HostNatvisProject.cs b/src/DebugEngineHost/HostNatvisProject.cs index 11c3510eb..4c969b652 100644 --- a/src/DebugEngineHost/HostNatvisProject.cs +++ b/src/DebugEngineHost/HostNatvisProject.cs @@ -104,7 +104,7 @@ public static IDisposable WatchNatvisOptionSetting(HostConfigurationStore config IDisposable disposable = rmw.CurrentMonitor; // Watch NatvisDiagnostic section - rmw = new RegisterMonitorWrapper(CreateAndStartNatvisDiagnosticMonitor(checkForSection, natvisLogger)); + rmw = new RegisterMonitorWrapper(CreateAndStartNatvisDiagnosticMonitor(natvisDiagnosticSection, natvisLogger)); disposable.Dispose(); } diff --git a/src/DebugEngineHost/RegistryMonitor.cs b/src/DebugEngineHost/RegistryMonitor.cs index 0281bc371..6c6f1dcc0 100644 --- a/src/DebugEngineHost/RegistryMonitor.cs +++ b/src/DebugEngineHost/RegistryMonitor.cs @@ -47,15 +47,14 @@ private static extern int RegNotifyChangeKeyValue(SafeRegistryHandle hKey, bool #endregion - private readonly HostConfigurationSection _section; + private HostConfigurationSection _section; private readonly bool _watchSubtree; - // Set when monitoring is stopped - private AutoResetEvent _stoppedEvent; + // Set when registry value is changed + private AutoResetEvent m_changeEvent; - // Members to handle multiple stop calls. - private bool _isStopped = false; - private readonly object _stopLock = new object(); + // Set when monitoring is stopped + private AutoResetEvent m_stoppedEvent; /// /// Occurs when the specified registry key has changed. @@ -81,13 +80,9 @@ public void Start() public void Stop() { - lock (_stopLock) + if (m_stoppedEvent != null) { - if (!_isStopped) - { - _stoppedEvent?.Set(); - _isStopped = true; - } + m_stoppedEvent.Set(); } } @@ -98,52 +93,53 @@ private void Monitor() bool stopped = false; try { - _stoppedEvent = new AutoResetEvent(false); - using (AutoResetEvent registryChangedEvent = new AutoResetEvent(false)) - { - IntPtr handle = registryChangedEvent.SafeWaitHandle.DangerousGetHandle(); + m_stoppedEvent = new AutoResetEvent(false); + m_changeEvent = new AutoResetEvent(false); - int errorCode = RegNotifyChangeKeyValue(_section.Handle, _watchSubtree, RegChangeNotifyFilter.REG_NOTIFY_CHANGE_NAME | RegChangeNotifyFilter.REG_NOTIFY_CHANGE_LAST_SET, handle, true); - if (errorCode != 0) // 0 is ERROR_SUCCESS - { - _nativsLogger?.WriteLine(LogLevel.Error, Resource.Error_WatchRegistry, errorCode); - } - else + IntPtr handle = m_changeEvent.SafeWaitHandle.DangerousGetHandle(); + + int errorCode = RegNotifyChangeKeyValue(_section.Handle, _watchSubtree, RegChangeNotifyFilter.REG_NOTIFY_CHANGE_NAME | RegChangeNotifyFilter.REG_NOTIFY_CHANGE_LAST_SET, handle, true); + if (errorCode != 0) // 0 is ERROR_SUCCESS + { + _nativsLogger?.WriteLine(LogLevel.Error, Resource.Error_WatchRegistry, errorCode); + } + else + { + while (!stopped) { - while (!stopped) - { - int waitResult = WaitHandle.WaitAny(new WaitHandle[] { _stoppedEvent, registryChangedEvent }); + int waitResult = WaitHandle.WaitAny(new WaitHandle[] { m_stoppedEvent, m_changeEvent }); - if (waitResult == 0) - { - stopped = true; - } - else + if (waitResult == 0) + { + stopped = true; + } + else + { + errorCode = RegNotifyChangeKeyValue(_section.Handle, _watchSubtree, RegChangeNotifyFilter.REG_NOTIFY_CHANGE_NAME | RegChangeNotifyFilter.REG_NOTIFY_CHANGE_LAST_SET, handle, true); + if (errorCode != 0) // 0 is ERROR_SUCCESS { - errorCode = RegNotifyChangeKeyValue(_section.Handle, _watchSubtree, RegChangeNotifyFilter.REG_NOTIFY_CHANGE_NAME | RegChangeNotifyFilter.REG_NOTIFY_CHANGE_LAST_SET, handle, true); - if (errorCode != 0) // 0 is ERROR_SUCCESS - { - _nativsLogger?.WriteLine(LogLevel.Error, Resource.Error_WatchRegistry, errorCode); - break; - } - RegChanged?.Invoke(this, null); + _nativsLogger?.WriteLine(LogLevel.Error, Resource.Error_WatchRegistry, errorCode); + break; } + RegChanged?.Invoke(this, null); } } } } finally { - _stoppedEvent.Dispose(); - _stoppedEvent = null; - _section.Dispose(); + m_stoppedEvent?.Dispose(); + m_changeEvent?.Dispose(); + + m_stoppedEvent = null; + m_changeEvent = null; } } public void Dispose() { - Stop(); // Stopping the monitor will dispose of the AutoResetEvent and HostConfigurationSection + m_stoppedEvent?.Dispose(); } } } diff --git a/src/MICore/JsonLaunchOptions.cs b/src/MICore/JsonLaunchOptions.cs index 5193234a8..76f3d4c26 100644 --- a/src/MICore/JsonLaunchOptions.cs +++ b/src/MICore/JsonLaunchOptions.cs @@ -39,11 +39,10 @@ public abstract partial class BaseOptions public string TargetArchitecture { get; set; } /// - /// .natvis files to be used when debugging this process. This option is not compatible with GDB pretty printing. Please also see "showDisplayString" if using this setting. + /// .natvis file to be used when debugging this process. This option is not compatible with GDB pretty printing. Please also see "showDisplayString" if using this setting. /// [JsonProperty("visualizerFile", DefaultValueHandling = DefaultValueHandling.Ignore)] - [JsonConverter(typeof(VisualizerFileConverter))] - public List VisualizerFile { get; set; } + public string VisualizerFile { get; set; } /// /// When a visualizerFile is specified, showDisplayString will enable the display string. Turning this option on can cause slower performance during debugging. @@ -124,37 +123,6 @@ public abstract partial class BaseOptions public UnknownBreakpointHandling? UnknownBreakpointHandling { get; set; } } - internal class VisualizerFileConverter : JsonConverter - { - public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) - { - List visualizerFile = new List(); - if (reader.TokenType == JsonToken.StartArray) - { - visualizerFile = serializer.Deserialize>(reader); - } - else if (reader.TokenType == JsonToken.String) - { - visualizerFile.Add(reader.Value.ToString()); - } - else - { - throw new JsonReaderException(MICoreResources.Error_IncorrectVisualizerFileFormat); - } - return visualizerFile; - } - - public override bool CanConvert(Type objectType) - { - throw new NotImplementedException(); - } - - public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) - { - throw new NotImplementedException(); - } - } - public partial class AttachOptions : BaseOptions { #region Public Properties for Serialization @@ -176,7 +144,7 @@ public AttachOptions( int processId, string type = null, string targetArchitecture = null, - List visualizerFile = null, + string visualizerFile = null, bool? showDisplayString = null, string additionalSOLibSearchPath = null, string MIMode = null, @@ -440,7 +408,7 @@ public LaunchOptions( List postRemoteConnectCommands = null, List customLaunchSetupCommands = null, LaunchCompleteCommand? launchCompleteCommand = null, - List visualizerFile = null, + string visualizerFile = null, bool? showDisplayString = null, List environment = null, string additionalSOLibSearchPath = null, diff --git a/src/MICore/LaunchOptions.cs b/src/MICore/LaunchOptions.cs index 7c102711f..6ba4b10c1 100644 --- a/src/MICore/LaunchOptions.cs +++ b/src/MICore/LaunchOptions.cs @@ -960,10 +960,19 @@ public string AdditionalSOLibSearchPath } } + private string _visualizerFile; /// - /// Collection of natvis files to use when evaluating + /// [Optional] Natvis file name - from install location /// - public List VisualizerFiles { get; } = new List(); + public string VisualizerFile + { + get { return _visualizerFile; } + set + { + VerifyCanModifyProperty(nameof(VisualizerFile)); + _visualizerFile = value; + } + } private bool _waitDynamicLibLoad = true; /// @@ -1570,9 +1579,9 @@ private void Merge(AttachOptionsForConnection suppOptions) { DebugChildProcesses = suppOptions.DebugChildProcesses; } - if (!this.VisualizerFiles.Contains(suppOptions.VisualizerFile)) + if (string.IsNullOrWhiteSpace(VisualizerFile)) { - this.VisualizerFiles.Add(suppOptions.VisualizerFile); + VisualizerFile = suppOptions.VisualizerFile; } if (suppOptions.ShowDisplayStringSpecified) { @@ -1762,10 +1771,7 @@ protected void InitializeCommonOptions(Json.LaunchOptions.BaseOptions options) this.TargetArchitecture = ConvertTargetArchitectureAttribute(options.TargetArchitecture); } - if (options.VisualizerFile != null && options.VisualizerFile.Count > 0) - { - this.VisualizerFiles.AddRange(options.VisualizerFile); - } + this.VisualizerFile = options.VisualizerFile; this.ShowDisplayString = options.ShowDisplayString.GetValueOrDefault(false); this.AdditionalSOLibSearchPath = String.IsNullOrEmpty(this.AdditionalSOLibSearchPath) ? @@ -1835,8 +1841,8 @@ protected void InitializeCommonOptions(Xml.LaunchOptions.BaseLaunchOptions sourc if (string.IsNullOrEmpty(this.WorkingDirectory)) this.WorkingDirectory = source.WorkingDirectory; - if (!string.IsNullOrEmpty(source.VisualizerFile)) - this.VisualizerFiles.Add(source.VisualizerFile); + if (string.IsNullOrEmpty(this.VisualizerFile)) + this.VisualizerFile = source.VisualizerFile; this.ShowDisplayString = source.ShowDisplayString; this.WaitDynamicLibLoad = source.WaitDynamicLibLoad; diff --git a/src/MICore/MICoreResources.Designer.cs b/src/MICore/MICoreResources.Designer.cs index 20e83aedb..982f2d2ac 100755 --- a/src/MICore/MICoreResources.Designer.cs +++ b/src/MICore/MICoreResources.Designer.cs @@ -185,15 +185,6 @@ public static string Error_FailedToEnterBreakState { } } - /// - /// Looks up a localized string similar to 'visualizerFile' must be a string or array of strings.. - /// - public static string Error_IncorrectVisualizerFileFormat { - get { - return ResourceManager.GetString("Error_IncorrectVisualizerFileFormat", resourceCulture); - } - } - /// /// Looks up a localized string similar to Internal file "{0}" could not be found.. /// diff --git a/src/MICore/MICoreResources.resx b/src/MICore/MICoreResources.resx index 0421a7999..b1ff5f790 100755 --- a/src/MICore/MICoreResources.resx +++ b/src/MICore/MICoreResources.resx @@ -326,7 +326,4 @@ Error: {1} 'editorPath' can not be null or empty - - 'visualizerFile' must be a string or array of strings. - \ No newline at end of file diff --git a/src/MICoreUnitTests/BasicLaunchOptionsTests.cs b/src/MICoreUnitTests/BasicLaunchOptionsTests.cs index 14d9d70a2..0c4ab3bc0 100644 --- a/src/MICoreUnitTests/BasicLaunchOptionsTests.cs +++ b/src/MICoreUnitTests/BasicLaunchOptionsTests.cs @@ -263,7 +263,7 @@ internal void VerifyCoreApisPresent() launchOptions.WorkingDirectory = "/home/user"; launchOptions.DebuggerMIMode = MIMode.Gdb; launchOptions.WaitDynamicLibLoad = false; - launchOptions.VisualizerFiles.Add(@"c:\myproject\file.natvis"); + launchOptions.VisualizerFile = @"c:\myproject\file.natvis"; launchOptions.SourceMap = new ReadOnlyCollection(new List()); launchOptions.Environment = new ReadOnlyCollection(new List()); Microsoft.DebugEngineHost.HostConfigurationStore configStore = null; diff --git a/src/MIDebugEngine/Engine.Impl/DebuggedProcess.cs b/src/MIDebugEngine/Engine.Impl/DebuggedProcess.cs index f7b68e0fd..24141685c 100755 --- a/src/MIDebugEngine/Engine.Impl/DebuggedProcess.cs +++ b/src/MIDebugEngine/Engine.Impl/DebuggedProcess.cs @@ -543,7 +543,7 @@ private async Task EnsureModulesLoaded() public async Task Initialize(HostWaitLoop waitLoop, CancellationToken token) { bool success = false; - Natvis.Initialize(_launchOptions.VisualizerFiles); + Natvis.Initialize(_launchOptions.VisualizerFile); int total = 1; await this.WaitForConsoleDebuggerInitialize(token); diff --git a/src/MIDebugEngine/Natvis.Impl/Natvis.cs b/src/MIDebugEngine/Natvis.Impl/Natvis.cs index afe8ed237..81b52ee84 100755 --- a/src/MIDebugEngine/Natvis.Impl/Natvis.cs +++ b/src/MIDebugEngine/Natvis.Impl/Natvis.cs @@ -260,7 +260,7 @@ internal Natvis(DebuggedProcess process, bool showDisplayString, HostConfigurati _configStore = configStore; } - private void InitializeNatvisServices() + public void Initialize(string fileName) { try { @@ -271,65 +271,52 @@ private void InitializeNatvisServices() { // failed to find the VS Service } - } - /* - * Handle multiple Natvis files - */ - public void Initialize(List fileNames) - { - InitializeNatvisServices(); - if (fileNames != null && fileNames.Count > 0) + if (!string.IsNullOrEmpty(fileName)) { - foreach (var fileName in fileNames) + if (!Path.IsPathRooted(fileName)) { - if (!string.IsNullOrEmpty(fileName)) + string globalVisualizersDirectory = _process.Engine.GetMetric("GlobalVisualizersDirectory") as string; + string globalNatVisPath = null; + if (!string.IsNullOrEmpty(globalVisualizersDirectory) && !string.IsNullOrEmpty(fileName)) + { + globalNatVisPath = Path.Combine(globalVisualizersDirectory, fileName); + } + + // For local launch, try and load natvis next to the target exe if it exists and if + // the exe is rooted. If the file doesn't exist, and also doesn't exist in the global folder fail. + if (_process.LaunchOptions is LocalLaunchOptions) { - if (!Path.IsPathRooted(fileName)) + string exePath = (_process.LaunchOptions as LocalLaunchOptions).ExePath; + if (Path.IsPathRooted(exePath)) { - string globalVisualizersDirectory = _process.Engine.GetMetric("GlobalVisualizersDirectory") as string; - string globalNatVisPath = null; - if (!string.IsNullOrEmpty(globalVisualizersDirectory) && !string.IsNullOrEmpty(fileName)) - { - globalNatVisPath = Path.Combine(globalVisualizersDirectory, fileName); - } + string localNatvisPath = Path.Combine(Path.GetDirectoryName(exePath), fileName); - // For local launch, try and load natvis next to the target exe if it exists and if - // the exe is rooted. If the file doesn't exist, and also doesn't exist in the global folder fail. - if (_process.LaunchOptions is LocalLaunchOptions) + if (File.Exists(localNatvisPath)) { - string exePath = (_process.LaunchOptions as LocalLaunchOptions).ExePath; - if (Path.IsPathRooted(exePath)) - { - string localNatvisPath = Path.Combine(Path.GetDirectoryName(exePath), fileName); - - if (File.Exists(localNatvisPath)) - { - LoadFile(localNatvisPath); - return; - } - else if (globalNatVisPath == null || !File.Exists(globalNatVisPath)) - { - // Neither local or global path exists, report an error. - _process.WriteOutput(String.Format(CultureInfo.CurrentCulture, ResourceStrings.FileNotFound, localNatvisPath)); - return; - } - } + LoadFile(localNatvisPath); + return; } - - // Local wasn't supported or the file didn't exist. Try and load from globally registered visualizer directory if local didn't work - // or wasn't supported by the launch options - if (!string.IsNullOrEmpty(globalNatVisPath)) + else if (globalNatVisPath == null || !File.Exists(globalNatVisPath)) { - LoadFile(globalNatVisPath); + // Neither local or global path exists, report an error. + _process.WriteOutput(String.Format(CultureInfo.CurrentCulture, ResourceStrings.FileNotFound, localNatvisPath)); + return; } } - else - { - // Full path to the natvis file.. Just try the load - LoadFile(fileName); - } } + + // Local wasn't supported or the file didn't exist. Try and load from globally registered visualizer directory if local didn't work + // or wasn't supported by the launch options + if (!string.IsNullOrEmpty(globalNatVisPath)) + { + LoadFile(globalNatVisPath); + } + } + else + { + // Full path to the natvis file.. Just try the load + LoadFile(fileName); } } } diff --git a/test/CppTests/CppTests.csproj b/test/CppTests/CppTests.csproj index 268ffe32c..5611989e2 100644 --- a/test/CppTests/CppTests.csproj +++ b/test/CppTests/CppTests.csproj @@ -45,7 +45,10 @@ - + diff --git a/test/CppTests/OpenDebug/CrossPlatCpp/LaunchCommand.cs b/test/CppTests/OpenDebug/CrossPlatCpp/LaunchCommand.cs index 06e37fb21..d5521a77e 100644 --- a/test/CppTests/OpenDebug/CrossPlatCpp/LaunchCommand.cs +++ b/test/CppTests/OpenDebug/CrossPlatCpp/LaunchCommand.cs @@ -5,7 +5,6 @@ using System.Collections.Generic; using System.IO; using DebuggerTesting.OpenDebug.Commands; -using DebuggerTesting.OpenDebug.CrossPlatCpp; using DebuggerTesting.Utilities; using Newtonsoft.Json; @@ -35,8 +34,7 @@ public sealed class CppLaunchCommandArgs : LaunchCommandArgs public string MIMode; [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)] - public object VisualizerFile; - + public string VisualizerFile; [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)] public bool ShowDisplayString; @@ -52,13 +50,8 @@ public class LaunchCommand : LaunchCommand /// The full path to the program to launch /// The architecture of the program /// [OPTIONAL] Args to pass to the program - public LaunchCommand(IDebuggerSettings settings, string program, object visualizerFile = null, bool isAttach = false, params string[] args) + public LaunchCommand(IDebuggerSettings settings, string program, string visualizerFile = null, bool isAttach = false, params string[] args) { - if (!(visualizerFile == null || visualizerFile is string || visualizerFile is List)) - { - throw new ArgumentOutOfRangeException(nameof(visualizerFile)); - } - this.Timeout = TimeSpan.FromSeconds(15); this.Args.name = CreateName(settings); @@ -82,7 +75,7 @@ public LaunchCommand(IDebuggerSettings settings, string program, object visualiz this.Args.targetArchitecture = settings.DebuggeeArchitecture.ToArchitectureString(); this.Args.MIMode = settings.MIMode; this.Args.VisualizerFile = visualizerFile; - this.Args.ShowDisplayString = visualizerFile != null; + this.Args.ShowDisplayString = !string.IsNullOrEmpty(visualizerFile); } } diff --git a/test/CppTests/Tests/NatvisTests.cs b/test/CppTests/Tests/NatvisTests.cs index 279af0664..69b2526c4 100644 --- a/test/CppTests/Tests/NatvisTests.cs +++ b/test/CppTests/Tests/NatvisTests.cs @@ -480,74 +480,6 @@ public void TestCommaFormatWithSquareBrackets(ITestSettings settings) } } - [Theory] - [DependsOnTest(nameof(CompileNatvisDebuggee))] - [RequiresTestSettings] - // Disable on macOS - // Error: - // C-style cast from 'int' to 'int [10]' is not allowed - // (int[10])*(((vec)._start)) - [UnsupportedDebugger(SupportedDebugger.Lldb, SupportedArchitecture.x64 | SupportedArchitecture.x86)] - public void TestMultipleNatvisFiles(ITestSettings settings) - { - this.TestPurpose("This test checks if multiple Natvis files can be used."); - this.WriteSettings(settings); - - IDebuggee debuggee = Debuggee.Open(this, settings.CompilerSettings, NatvisName, DebuggeeMonikers.Natvis.Default); - - using (IDebuggerRunner runner = CreateDebugAdapterRunner(settings)) - { - this.Comment("Configure launch"); - List visFile = new List(); - visFile.Add(Path.Join(debuggee.SourceRoot, "visualizer_files", "Simple1.natvis")); - visFile.Add(Path.Join(debuggee.SourceRoot, "visualizer_files", "Simple2.natvis")); - - LaunchCommand launch = new LaunchCommand(settings.DebuggerSettings, debuggee.OutputPath, visFile, false); - runner.RunCommand(launch); - - this.Comment("Set Breakpoint"); - SourceBreakpoints writerBreakpoints = debuggee.Breakpoints(NatvisSourceName, ReturnSourceLine); - runner.SetBreakpoints(writerBreakpoints); - - runner.Expects.StoppedEvent(StoppedReason.Breakpoint).AfterConfigurationDone(); - - using (IThreadInspector threadInspector = runner.GetThreadInspector()) - { - IFrameInspector currentFrame = threadInspector.Stack.First(); - - // Simple1.natvis - this.Comment("Verifying ArrayItems natvis"); - var ll = currentFrame.GetVariable("vec"); - Assert.Equal("{ size=2000 }", ll.Value); - - // Custom Item in natvis - Assert.Equal("2000", ll.GetVariable("Size").Value); - - // Index element for ArrayItems - Assert.Equal("20", ll.GetVariable("[5]").Value); - Assert.Equal("51", ll.GetVariable("[More...]").GetVariable("[51]").Value); - - // Simple2.natvis - this.Comment("Verifying TreeItems natvis"); - var map = currentFrame.GetVariable("map"); - - // Custom Item in natvis - Assert.Equal("6", map.GetVariable("Count").Value); - - // Index element for TreeItems - // Visualized map will show the BST in a flat ordered list. - // Values are inserted as [0, -100, 15, -35, 4, -72] - // Expected visualize list to be [-100, -72, -35, 0, 4, 15] - Assert.Equal("-100", map.GetVariable("[0]").Value); - Assert.Equal("0", map.GetVariable("[3]").Value); - Assert.Equal("15", map.GetVariable("[5]").Value); - } - - runner.Expects.ExitedEvent(exitCode: 0).TerminatedEvent().AfterContinue(); - runner.DisconnectAndVerify(); - } - } - #endregion } } diff --git a/test/CppTests/debuggees/natvis/src/visualizer_files/Simple1.natvis b/test/CppTests/debuggees/natvis/src/visualizer_files/Simple1.natvis deleted file mode 100644 index 5d7f69d2c..000000000 --- a/test/CppTests/debuggees/natvis/src/visualizer_files/Simple1.natvis +++ /dev/null @@ -1,33 +0,0 @@ - - - - - Hello DisplayString - - - - Null Class - Non-null Class - - - - {{ size={_size} }} - - _size - - _size - _start - - - - - - {{ size={_size} }} - - - _size - _array[_size - 1 - $i] - - - - \ No newline at end of file diff --git a/test/CppTests/debuggees/natvis/src/visualizer_files/Simple2.natvis b/test/CppTests/debuggees/natvis/src/visualizer_files/Simple2.natvis deleted file mode 100644 index 959a3ed54..000000000 --- a/test/CppTests/debuggees/natvis/src/visualizer_files/Simple2.natvis +++ /dev/null @@ -1,42 +0,0 @@ - - - - - {{ size={numElements} }} - - numElements - - numElements - head - next - data - - - - - - {{ size={numElements} }} - - numElements - - numElements - root - left - right - data - - - - - - SimpleMatrix - - - Forward - 2 - ($i == 1) ? 2 : m_size2/2 - m_pData - - - - \ No newline at end of file