| Index: visual_studio/NativeClientVSAddIn/NativeClientVSAddIn/PluginDebuggerHelper.cs
|
| diff --git a/visual_studio/NativeClientVSAddIn/NativeClientVSAddIn/PluginDebuggerHelper.cs b/visual_studio/NativeClientVSAddIn/NativeClientVSAddIn/PluginDebuggerHelper.cs
|
| index 071d63e9234ee15f06377e54d14a6048f38d2143..d954b507478fb8880ff9ab29a91f99dc6db398c9 100644
|
| --- a/visual_studio/NativeClientVSAddIn/NativeClientVSAddIn/PluginDebuggerHelper.cs
|
| +++ b/visual_studio/NativeClientVSAddIn/NativeClientVSAddIn/PluginDebuggerHelper.cs
|
| @@ -91,12 +91,12 @@ namespace NativeClientVSAddIn
|
| /// <summary>
|
| /// When debugging is started this is the web server process object.
|
| /// </summary>
|
| - private System.Diagnostics.Process webServer_ = null;
|
| + private System.Diagnostics.Process webServer_;
|
|
|
| /// <summary>
|
| /// Visual Studio output window pane that captures output from the web server.
|
| /// </summary>
|
| - private OutputWindowPane webServerOutputPane_ = null;
|
| + private OutputWindowPane webServerOutputPane_;
|
|
|
| /// <summary>
|
| /// Path to the web server executable.
|
| @@ -125,6 +125,11 @@ namespace NativeClientVSAddIn
|
| private ProcessSearcher processSearcher_;
|
|
|
| /// <summary>
|
| + /// The main process of chrome that was started by Visual Studio during debugging.
|
| + /// </summary>
|
| + private System.Diagnostics.Process debuggedChromeMainProcess_;
|
| +
|
| + /// <summary>
|
| /// Constructs the PluginDebuggerHelper.
|
| /// Object is not usable until LoadProjectSettings() is called.
|
| /// </summary>
|
| @@ -225,21 +230,20 @@ namespace NativeClientVSAddIn
|
| if (Utility.IsVisualCProject(startProject))
|
| {
|
| VCConfiguration config = Utility.GetActiveVCConfiguration(startProject);
|
| - VCProject vcproj = (VCProject)startProject.Object;
|
| + IVCRulePropertyStorage general = config.Rules.Item("ConfigurationGeneral");
|
| VCLinkerTool linker = config.Tools.Item("VCLinkerTool");
|
| - pluginProjectDirectory_ = vcproj.ProjectDirectory; // Macros not allowed here.
|
| - pluginAssembly_ = config.Evaluate(linker.OutputFile);
|
| + VCProject vcproj = (VCProject)startProject.Object;
|
| + sdkRootDirectory_ = general.GetEvaluatedPropertyValue("VSNaClSDKRoot");
|
| pluginOutputDirectory_ = config.Evaluate(config.OutputDirectory);
|
| + pluginAssembly_ = config.Evaluate(linker.OutputFile);
|
| + pluginProjectDirectory_ = vcproj.ProjectDirectory; // Macros not allowed here.
|
| }
|
| else
|
| {
|
| return false;
|
| }
|
|
|
| - // TODO(tysand): Add user option to specify this.
|
| - int webServerPort = 5103;
|
| - sdkRootDirectory_ = Environment.GetEnvironmentVariable(Strings.SDKPathEnvironmentVariable);
|
| - if (sdkRootDirectory_ == null)
|
| + if (string.IsNullOrEmpty(sdkRootDirectory_))
|
| {
|
| MessageBox.Show(
|
| string.Format(Strings.SDKPathNotSetFormat, Strings.SDKPathEnvironmentVariable));
|
| @@ -248,6 +252,8 @@ namespace NativeClientVSAddIn
|
|
|
| sdkRootDirectory_ = sdkRootDirectory_.TrimEnd("/\\".ToArray<char>());
|
|
|
| + // TODO(tysand): Add user option to specify this.
|
| + int webServerPort = 5103;
|
| webServerExecutable_ = "python.exe";
|
| webServerArguments_ = string.Format(
|
| "{0}\\examples\\httpd.py --no_dir_check {1}",
|
| @@ -255,9 +261,11 @@ namespace NativeClientVSAddIn
|
| webServerPort);
|
|
|
| // TODO(tysand): Update this to nacl-gdb when it is ready. Should be able to remove irtPath_.
|
| - gdbPath_ = sdkRootDirectory_ + @"\customGDB\gdb.exe";
|
| + gdbPath_ = sdkRootDirectory_ + @"\gdb-remote-x86-64\gdb.exe";
|
| irtPath_ = sdkRootDirectory_ + @"\tools\irt_x86_64.nexe";
|
|
|
| + debuggedChromeMainProcess_ = null;
|
| +
|
| isProperlyInitialized_ = true;
|
| return true;
|
| }
|
| @@ -329,54 +337,68 @@ namespace NativeClientVSAddIn
|
|
|
| /// <summary>
|
| /// This is called periodically by the Visual Studio UI thread to look for our plug-in process
|
| - /// and attach the debugger to it. The call is triggered by the pluginFinderTimer_ object
|
| + /// and attach the debugger to it. The call is triggered by the pluginFinderTimer_ object.
|
| /// </summary>
|
| /// <param name="unused">The parameter is not used.</param>
|
| /// <param name="unused1">The parameter is not used.</param>
|
| private void FindAndAttachToPlugin(object unused, EventArgs unused1)
|
| {
|
| - string processNameTarget;
|
| - string typeFlagTarget;
|
| - string identifierFlagTarget;
|
| + StringComparison ignoreCase = StringComparison.InvariantCultureIgnoreCase;
|
| +
|
| + // Set the main chrome process that was started by visual studio. If it's not chrome
|
| + // or not found then we have no business attaching to any plug-ins so return.
|
| + if (debuggedChromeMainProcess_ == null)
|
| + {
|
| + foreach (Process proc in dte_.Debugger.DebuggedProcesses)
|
| + {
|
| + if (proc.Name.EndsWith(Strings.ChromeProcessName, ignoreCase))
|
| + {
|
| + debuggedChromeMainProcess_ = System.Diagnostics.Process.GetProcessById(proc.ProcessID);
|
| + break;
|
| + }
|
| + }
|
| +
|
| + return;
|
| + }
|
| +
|
| + // Get the list of all descendants of the main chrome process.
|
| + uint mainChromeProcId = (uint)debuggedChromeMainProcess_.Id;
|
| + List<ProcessInfo> chromeDescendants = processSearcher_.GetDescendants(mainChromeProcId);
|
| +
|
| + // From the list of descendants, find the plug-in by it's command line arguments and
|
| + // process name as well as not being attached to already.
|
| + List<ProcessInfo> plugins;
|
| switch (projectPlatformType_)
|
| {
|
| case ProjectPlatformType.Pepper:
|
| - processNameTarget = Strings.PepperProcessName;
|
| - typeFlagTarget = Strings.PepperProcessTypeFlag;
|
| - identifierFlagTarget =
|
| + string identifierFlagTarget =
|
| string.Format(Strings.PepperProcessPluginFlagFormat, pluginAssembly_);
|
| + plugins = chromeDescendants.FindAll(p =>
|
| + p.Name.Equals(Strings.ChromeProcessName, ignoreCase) &&
|
| + p.CommandLine.Contains(Strings.ChromeRendererFlag, ignoreCase) &&
|
| + p.CommandLine.Contains(identifierFlagTarget, ignoreCase) &&
|
| + !pluginFinderForbiddenPids_.Contains(p.ID));
|
| break;
|
| case ProjectPlatformType.NaCl:
|
| - processNameTarget = Strings.NaClProcessName;
|
| - typeFlagTarget = Strings.NaClProcessTypeFlag;
|
| - identifierFlagTarget = Strings.NaClDebugFlag;
|
| + plugins = chromeDescendants.FindAll(p =>
|
| + p.Name.Equals(Strings.NaClProcessName, ignoreCase) &&
|
| + p.CommandLine.Contains(Strings.NaClLoaderFlag, ignoreCase) &&
|
| + !pluginFinderForbiddenPids_.Contains(p.ID));
|
| break;
|
| default:
|
| return;
|
| }
|
|
|
| - // To identify our target plug-in we look for: its process name (e.g. chrome.exe),
|
| - // identifying command line arguments (e.g. --type=renderer), not already attached
|
| - // to by us, and must be a descendant process of this instance of Visual Studio.
|
| - List<ProcessInfo> results = processSearcher_.GetResultsByName(processNameTarget);
|
| - uint currentProcessId = (uint)System.Diagnostics.Process.GetCurrentProcess().Id;
|
| - StringComparison ignoreCase = StringComparison.InvariantCultureIgnoreCase;
|
| - foreach (ProcessInfo process in results)
|
| + // Attach to all plug-ins that we found.
|
| + foreach (ProcessInfo process in plugins)
|
| {
|
| - if (!pluginFinderForbiddenPids_.Contains(process.ID) &&
|
| - !string.IsNullOrEmpty(process.CommandLine) &&
|
| - process.CommandLine.Contains(typeFlagTarget, ignoreCase) &&
|
| - process.CommandLine.Contains(identifierFlagTarget, ignoreCase) &&
|
| - Utility.IsDescendantOfProcess(processSearcher_, process.ID, currentProcessId))
|
| - {
|
| - // If we are attaching to a plug-in, add it to the forbidden list to ensure we
|
| - // don't try to attach again later.
|
| - pluginFinderForbiddenPids_.Add(process.ID);
|
| - PluginFoundEvent.Invoke(this, new PluginFoundEventArgs(process.ID));
|
| + // If we are attaching to a plug-in, add it to the forbidden list to ensure we
|
| + // don't try to attach again later.
|
| + pluginFinderForbiddenPids_.Add(process.ID);
|
| + PluginFoundEvent.Invoke(this, new PluginFoundEventArgs(process.ID));
|
|
|
| - // Slow down the frequency of checks for new plugins.
|
| - pluginFinderTimer_.Interval = RelaxedPluginCheckFrequency;
|
| - }
|
| + // Slow down the frequency of checks for new plugins.
|
| + pluginFinderTimer_.Interval = RelaxedPluginCheckFrequency;
|
| }
|
| }
|
|
|
| @@ -432,11 +454,11 @@ namespace NativeClientVSAddIn
|
| contents.AppendLine();
|
|
|
| // TODO(tysand): Nacl-gdb should handle the offset automatically. Remove 0xC00020080.
|
| - contents.AppendFormat("add-symbol-file {0} 0xC00020080", pluginAssemblyEscaped);
|
| + contents.AppendFormat("add-symbol-file \"{0}\" 0xC00020080", pluginAssemblyEscaped);
|
| contents.AppendLine();
|
|
|
| // TODO(tysand): Nacl-gdb should handle loading the irt automatically. Remove this line.
|
| - contents.AppendFormat("add-symbol-file {0} 0xC0fc00080", irtPathEscaped);
|
| + contents.AppendFormat("add-symbol-file \"{0}\" 0xC0fc00080", irtPathEscaped);
|
| contents.AppendLine();
|
|
|
| // Insert breakpoints from Visual Studio project.
|
| @@ -537,7 +559,6 @@ namespace NativeClientVSAddIn
|
| private void WebServerWriteLine(string message)
|
| {
|
| webServerOutputPane_.OutputString(message + "\n");
|
| - webServerOutputPane_.Activate();
|
| }
|
|
|
| /// <summary>
|
|
|