Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(176)

Side by Side Diff: visual_studio/NativeClientVSAddIn/NativeClientVSAddIn/PluginDebuggerHelper.cs

Issue 10830151: VS Add-in more properties and improvements (Closed) Base URL: https://nativeclient-sdk.googlecode.com/svn/trunk/src
Patch Set: Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 namespace NativeClientVSAddIn 5 namespace NativeClientVSAddIn
6 { 6 {
7 using System; 7 using System;
8 using System.Collections.Generic; 8 using System.Collections.Generic;
9 using System.IO; 9 using System.IO;
10 using System.Linq; 10 using System.Linq;
(...skipping 16 matching lines...) Expand all
27 /// </summary> 27 /// </summary>
28 private const int InitialPluginCheckFrequency = 1000; 28 private const int InitialPluginCheckFrequency = 1000;
29 29
30 /// <summary> 30 /// <summary>
31 /// After a plug-in has been found, we slow the frequency of checking 31 /// After a plug-in has been found, we slow the frequency of checking
32 /// for new ones. This value is in milliseconds. 32 /// for new ones. This value is in milliseconds.
33 /// </summary> 33 /// </summary>
34 private const int RelaxedPluginCheckFrequency = 5000; 34 private const int RelaxedPluginCheckFrequency = 5000;
35 35
36 /// <summary> 36 /// <summary>
37 /// The web server port to default to if the user does not specify one.
38 /// </summary>
39 private const int DefaultWebServerPort = 5103;
40
41 /// <summary>
37 /// The main visual studio object through which all Visual Studio functions are executed. 42 /// The main visual studio object through which all Visual Studio functions are executed.
38 /// </summary> 43 /// </summary>
39 private DTE2 dte_; 44 private DTE2 dte_;
40 45
41 /// <summary> 46 /// <summary>
42 /// Indicates the PluginDebuggerHelper is configured properly to run. 47 /// Indicates the PluginDebuggerHelper is configured properly to run.
43 /// </summary> 48 /// </summary>
44 private bool isProperlyInitialized_ = false; 49 private bool isProperlyInitialized_ = false;
45 50
46 /// <summary> 51 /// <summary>
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after
226 projectPlatformType_ = ProjectPlatformType.NaCl; 231 projectPlatformType_ = ProjectPlatformType.NaCl;
227 PluginFoundEvent += new EventHandler<PluginFoundEventArgs>(AttachNaClGDB ); 232 PluginFoundEvent += new EventHandler<PluginFoundEventArgs>(AttachNaClGDB );
228 } 233 }
229 else 234 else
230 { 235 {
231 projectPlatformType_ = ProjectPlatformType.Other; 236 projectPlatformType_ = ProjectPlatformType.Other;
232 return false; 237 return false;
233 } 238 }
234 239
235 // We only support certain project types (e.g. C/C++ projects). Otherwise we fail. 240 // We only support certain project types (e.g. C/C++ projects). Otherwise we fail.
236 // If supported, extract necessary information from specific project type. 241 if (!Utility.IsVisualCProject(startProject))
237 if (Utility.IsVisualCProject(startProject))
238 {
239 VCConfiguration config = Utility.GetActiveVCConfiguration(startProject);
240 IVCRulePropertyStorage general = config.Rules.Item("ConfigurationGeneral ");
241 VCLinkerTool linker = config.Tools.Item("VCLinkerTool");
242 VCProject vcproj = (VCProject)startProject.Object;
243
244 sdkRootDirectory_ = general.GetEvaluatedPropertyValue("VSNaClSDKRoot");
245 platformToolset = general.GetEvaluatedPropertyValue("PlatformToolset");
246 pluginOutputDirectory_ = config.Evaluate(config.OutputDirectory);
247 pluginAssembly_ = config.Evaluate(linker.OutputFile);
248 pluginProjectDirectory_ = vcproj.ProjectDirectory; // Macros not allowe d here.
249
250 if (projectPlatformType_ == ProjectPlatformType.NaCl)
251 {
252 irtPath_ = general.GetEvaluatedPropertyValue("NaClIrtPath");
253 manifestPath_ = general.GetEvaluatedPropertyValue("NaClManifestPath");
254 }
255 }
256 else
257 { 242 {
258 return false; 243 return false;
259 } 244 }
260 245
246 // Extract necessary information from specific project type.
247 VCConfiguration config = Utility.GetActiveVCConfiguration(startProject);
248 IVCRulePropertyStorage general = config.Rules.Item("ConfigurationGeneral") ;
249 VCLinkerTool linker = config.Tools.Item("VCLinkerTool");
250 VCProject vcproj = (VCProject)startProject.Object;
251
252 sdkRootDirectory_ = general.GetEvaluatedPropertyValue("VSNaClSDKRoot");
253 platformToolset = general.GetEvaluatedPropertyValue("PlatformToolset");
254 pluginOutputDirectory_ = config.Evaluate(config.OutputDirectory);
255 pluginAssembly_ = config.Evaluate(linker.OutputFile);
256 pluginProjectDirectory_ = vcproj.ProjectDirectory; // Macros not allowed here.
257
258 if (projectPlatformType_ == ProjectPlatformType.NaCl)
259 {
260 irtPath_ = general.GetEvaluatedPropertyValue("NaClIrtPath");
261 manifestPath_ = general.GetEvaluatedPropertyValue("NaClManifestPath");
262 }
263
261 if (string.IsNullOrEmpty(sdkRootDirectory_)) 264 if (string.IsNullOrEmpty(sdkRootDirectory_))
262 { 265 {
263 MessageBox.Show( 266 MessageBox.Show(Strings.SDKPathNotSetError);
264 string.Format(Strings.SDKPathNotSetFormat, Strings.SDKPathEnvironmen tVariable));
265 return false; 267 return false;
266 } 268 }
267 269
268 sdkRootDirectory_ = sdkRootDirectory_.TrimEnd("/\\".ToArray<char>()); 270 sdkRootDirectory_ = sdkRootDirectory_.TrimEnd("/\\".ToArray<char>());
269 271
270 // TODO(tysand): Add user option to specify this. 272 // TODO(tysand): Move this code getting port to where the web server is st arted.
271 int webServerPort = 5103; 273 int webServerPort;
274 if (!int.TryParse(general.GetEvaluatedPropertyValue("NaClWebServerPort"), out webServerPort))
275 {
276 webServerPort = DefaultWebServerPort;
277 }
278
272 webServerExecutable_ = "python.exe"; 279 webServerExecutable_ = "python.exe";
273 webServerArguments_ = string.Format( 280 webServerArguments_ = string.Format(
274 "{0}\\examples\\httpd.py --no_dir_check {1}", 281 "{0}\\examples\\httpd.py --no_dir_check {1}", sdkRootDirectory_, webSe rverPort);
275 sdkRootDirectory_,
276 webServerPort);
277 282
278 gdbPath_ = Path.Combine( 283 gdbPath_ = Path.Combine(
279 sdkRootDirectory_, "toolchain", platformToolset, @"bin\x86_64-nacl-gdb .exe"); 284 sdkRootDirectory_, "toolchain", platformToolset, @"bin\x86_64-nacl-gdb .exe");
280 285
281 debuggedChromeMainProcess_ = null; 286 debuggedChromeMainProcess_ = null;
282 287
283 isProperlyInitialized_ = true; 288 isProperlyInitialized_ = true;
284 return true; 289 return true;
285 } 290 }
286 291
(...skipping 23 matching lines...) Expand all
310 315
311 // Remove all event handlers from the plug-in found event. 316 // Remove all event handlers from the plug-in found event.
312 if (PluginFoundEvent != null) 317 if (PluginFoundEvent != null)
313 { 318 {
314 foreach (Delegate del in PluginFoundEvent.GetInvocationList()) 319 foreach (Delegate del in PluginFoundEvent.GetInvocationList())
315 { 320 {
316 PluginFoundEvent -= (EventHandler<PluginFoundEventArgs>)del; 321 PluginFoundEvent -= (EventHandler<PluginFoundEventArgs>)del;
317 } 322 }
318 } 323 }
319 324
320 if (webServer_ != null) 325 Utility.EnsureProcessKill(ref webServer_);
321 { 326 WebServerWriteLine(Strings.WebServerStopMessage);
322 webServer_.Kill(); 327 CleanUpGDBProcess();
323 webServer_.Dispose();
324 webServer_ = null;
325 }
326
327 KillGDBProcess();
328 } 328 }
329 329
330 /// <summary> 330 /// <summary>
331 /// This function cleans up the started GDB process. 331 /// This function cleans up the started GDB process.
332 /// </summary> 332 /// </summary>
333 private void KillGDBProcess() 333 private void CleanUpGDBProcess()
334 { 334 {
335 if (gdbProcess_ != null) 335 Utility.EnsureProcessKill(ref gdbProcess_);
336 if (!string.IsNullOrEmpty(gdbInitFileName_) && File.Exists(gdbInitFileName _))
336 { 337 {
337 if (!gdbProcess_.HasExited) 338 File.Delete(gdbInitFileName_);
338 { 339 gdbInitFileName_ = null;
339 gdbProcess_.Kill();
340 gdbProcess_.Dispose();
341 }
342
343 if (!string.IsNullOrEmpty(gdbInitFileName_) && File.Exists(gdbInitFileNa me_))
344 {
345 File.Delete(gdbInitFileName_);
346 }
347
348 gdbProcess_ = null;
349 } 340 }
350 } 341 }
351 342
352 /// <summary> 343 /// <summary>
353 /// This is called periodically by the Visual Studio UI thread to look for o ur plug-in process 344 /// This is called periodically by the Visual Studio UI thread to look for o ur plug-in process
354 /// and attach the debugger to it. The call is triggered by the pluginFinde rTimer_ object. 345 /// and attach the debugger to it. The call is triggered by the pluginFinde rTimer_ object.
355 /// </summary> 346 /// </summary>
356 /// <param name="unused">The parameter is not used.</param> 347 /// <param name="unused">The parameter is not used.</param>
357 /// <param name="unused1">The parameter is not used.</param> 348 /// <param name="unused1">The parameter is not used.</param>
358 private void FindAndAttachToPlugin(object unused, EventArgs unused1) 349 private void FindAndAttachToPlugin(object unused, EventArgs unused1)
(...skipping 13 matching lines...) Expand all
372 } 363 }
373 } 364 }
374 365
375 return; 366 return;
376 } 367 }
377 368
378 // Get the list of all descendants of the main chrome process. 369 // Get the list of all descendants of the main chrome process.
379 uint mainChromeProcId = (uint)debuggedChromeMainProcess_.Id; 370 uint mainChromeProcId = (uint)debuggedChromeMainProcess_.Id;
380 List<ProcessInfo> chromeDescendants = processSearcher_.GetDescendants(main ChromeProcId); 371 List<ProcessInfo> chromeDescendants = processSearcher_.GetDescendants(main ChromeProcId);
381 372
373 // If we didn't start with debug flags then we should not attach.
374 string mainChromeFlags = chromeDescendants.Find(p => p.ID == mainChromePro cId).CommandLine;
375 if (projectPlatformType_ == ProjectPlatformType.NaCl &&
376 !mainChromeFlags.Contains(Strings.NaClDebugFlag))
377 {
378 return;
379 }
380
382 // From the list of descendants, find the plug-in by it's command line arg uments and 381 // From the list of descendants, find the plug-in by it's command line arg uments and
383 // process name as well as not being attached to already. 382 // process name as well as not being attached to already.
384 List<ProcessInfo> plugins; 383 List<ProcessInfo> plugins;
385 switch (projectPlatformType_) 384 switch (projectPlatformType_)
386 { 385 {
387 case ProjectPlatformType.Pepper: 386 case ProjectPlatformType.Pepper:
388 string identifierFlagTarget = 387 string identifierFlagTarget =
389 string.Format(Strings.PepperProcessPluginFlagFormat, pluginAssembl y_); 388 string.Format(Strings.PepperProcessPluginFlagFormat, pluginAssembl y_);
390 plugins = chromeDescendants.FindAll(p => 389 plugins = chromeDescendants.FindAll(p =>
391 p.Name.Equals(Strings.ChromeProcessName, ignoreCase) && 390 p.Name.Equals(Strings.ChromeProcessName, ignoreCase) &&
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
437 /// Attaches the NaCl GDB debugger to the NaCl plug-in process. Handles loa ding symbols 436 /// Attaches the NaCl GDB debugger to the NaCl plug-in process. Handles loa ding symbols
438 /// and breakpoints from Visual Studio. 437 /// and breakpoints from Visual Studio.
439 /// </summary> 438 /// </summary>
440 /// <param name="src">The parameter is not used.</param> 439 /// <param name="src">The parameter is not used.</param>
441 /// <param name="args"> 440 /// <param name="args">
442 /// Contains the process ID to attach to, unused since debug stub is already attached. 441 /// Contains the process ID to attach to, unused since debug stub is already attached.
443 /// </param> 442 /// </param>
444 private void AttachNaClGDB(object src, PluginFoundEventArgs args) 443 private void AttachNaClGDB(object src, PluginFoundEventArgs args)
445 { 444 {
446 // Clean up any pre-existing GDB process (can happen if user reloads page) . 445 // Clean up any pre-existing GDB process (can happen if user reloads page) .
447 KillGDBProcess(); 446 CleanUpGDBProcess();
448 447
449 gdbInitFileName_ = Path.GetTempFileName(); 448 gdbInitFileName_ = Path.GetTempFileName();
450 string pluginAssemblyEscaped = pluginAssembly_.Replace("\\", "\\\\"); 449 string pluginAssemblyEscaped = pluginAssembly_.Replace("\\", "\\\\");
451 string irtPathEscaped = irtPath_.Replace("\\", "\\\\"); 450 string irtPathEscaped = irtPath_.Replace("\\", "\\\\");
452 451
453 // Create the initialization file to read in on GDB start. 452 // Create the initialization file to read in on GDB start.
454 StringBuilder contents = new StringBuilder(); 453 StringBuilder contents = new StringBuilder();
455 454
456 if (!string.IsNullOrEmpty(manifestPath_)) 455 if (!string.IsNullOrEmpty(manifestPath_))
457 { 456 {
458 string manifestEscaped = manifestPath_.Replace("\\", "\\\\"); 457 string manifestEscaped = manifestPath_.Replace("\\", "\\\\");
459 contents.AppendFormat("nacl-manifest {0}\n", manifestEscaped); 458 contents.AppendFormat("nacl-manifest {0}\n", manifestEscaped);
460 } 459 }
461 else 460 else
462 { 461 {
463 contents.AppendFormat("file \"{0}\"\n", pluginAssemblyEscaped); 462 contents.AppendFormat("file \"{0}\"\n", pluginAssemblyEscaped);
464 } 463 }
465 464
466 contents.AppendFormat("nacl-irt {0}\n", irtPathEscaped); 465 contents.AppendFormat("nacl-irt {0}\n", irtPathEscaped);
467 contents.AppendFormat("target remote localhost:{0}\n", 4014); 466 contents.AppendFormat("target remote localhost:{0}\n", 4014);
468 467
469 // Insert breakpoints from Visual Studio project. 468 // Insert breakpoints from Visual Studio project.
470 foreach (Breakpoint bp in dte_.Debugger.Breakpoints) 469 foreach (Breakpoint bp in dte_.Debugger.Breakpoints)
471 { 470 {
472 if (bp.Enabled && 471 if (!bp.Enabled)
473 bp.LocationType == dbgBreakpointLocationType.dbgBreakpointLocationTy peFile)
474 { 472 {
475 contents.AppendFormat("b {0}:{1}", Path.GetFileName(bp.File), bp.FileL ine); 473 continue;
476 contents.AppendLine();
477 } 474 }
478 else if (bp.Enabled && 475
479 bp.LocationType == dbgBreakpointLocationType.dbgBreakpointLocationTy peFunction) 476 if (bp.LocationType == dbgBreakpointLocationType.dbgBreakpointLocationTy peFile)
480 { 477 {
481 contents.AppendFormat("b {0}", bp.FunctionName); 478 contents.AppendFormat("b {0}:{1}\n", Path.GetFileName(bp.File), bp.Fil eLine);
482 contents.AppendLine();
483 } 479 }
484 else if (bp.Enabled) 480 else if (bp.LocationType == dbgBreakpointLocationType.dbgBreakpointLocat ionTypeFunction)
481 {
482 contents.AppendFormat("b {0}\n", bp.FunctionName);
483 }
484 else
485 { 485 {
486 WebServerWriteLine( 486 WebServerWriteLine(
487 string.Format(Strings.UnsupportedBreakpointTypeFormat, bp.LocationTy pe.ToString())); 487 string.Format(Strings.UnsupportedBreakpointTypeFormat, bp.LocationTy pe.ToString()));
488 } 488 }
489 } 489 }
490 490
491 contents.AppendLine("continue"); 491 contents.AppendLine("continue");
492 File.WriteAllText(gdbInitFileName_, contents.ToString()); 492 File.WriteAllText(gdbInitFileName_, contents.ToString());
493 493
494 // Start NaCl-GDB. 494 // Start NaCl-GDB.
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
556 { 556 {
557 WebServerWriteLine(e.Data); 557 WebServerWriteLine(e.Data);
558 } 558 }
559 559
560 /// <summary> 560 /// <summary>
561 /// Helper function to write data to the Web Server Output Pane. 561 /// Helper function to write data to the Web Server Output Pane.
562 /// </summary> 562 /// </summary>
563 /// <param name="message">Message to write.</param> 563 /// <param name="message">Message to write.</param>
564 private void WebServerWriteLine(string message) 564 private void WebServerWriteLine(string message)
565 { 565 {
566 webServerOutputPane_.OutputString(message + "\n"); 566 if (webServerOutputPane_ != null)
567 {
568 webServerOutputPane_.OutputString(message + "\n");
569 }
567 } 570 }
568 571
569 /// <summary> 572 /// <summary>
570 /// The event arguments when a plug-in is found. 573 /// The event arguments when a plug-in is found.
571 /// </summary> 574 /// </summary>
572 public class PluginFoundEventArgs : EventArgs 575 public class PluginFoundEventArgs : EventArgs
573 { 576 {
574 /// <summary> 577 /// <summary>
575 /// Construct the PluginFoundEventArgs. 578 /// Construct the PluginFoundEventArgs.
576 /// </summary> 579 /// </summary>
577 /// <param name="pid">Process ID of the found plug-in.</param> 580 /// <param name="pid">Process ID of the found plug-in.</param>
578 public PluginFoundEventArgs(uint pid) 581 public PluginFoundEventArgs(uint pid)
579 { 582 {
580 this.ProcessID = pid; 583 this.ProcessID = pid;
581 } 584 }
582 585
583 /// <summary> 586 /// <summary>
584 /// Gets or sets process ID of the found plug-in. 587 /// Gets or sets process ID of the found plug-in.
585 /// </summary> 588 /// </summary>
586 public uint ProcessID { get; set; } 589 public uint ProcessID { get; set; }
587 } 590 }
588 } 591 }
589 } 592 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698