Browse Source

add "debug executable"

pull/48/head
Siegfried Pammer 12 years ago
parent
commit
e67c669eb1
  1. 9
      src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.addin
  2. 4
      src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.csproj
  3. 10
      src/AddIns/Debugger/Debugger.AddIn/Options/DebuggingOptions.cs
  4. 8
      src/AddIns/Debugger/Debugger.AddIn/Options/DebuggingOptionsPanel.xaml
  5. 42
      src/AddIns/Debugger/Debugger.AddIn/Service/DebuggerCommands.cs
  6. 113
      src/AddIns/Debugger/Debugger.AddIn/Service/ExecuteProcessWindow.xaml
  7. 84
      src/AddIns/Debugger/Debugger.AddIn/Service/ExecuteProcessWindow.xaml.cs
  8. 2
      src/AddIns/Debugger/Debugger.AddIn/Service/WindowsDebugger.cs
  9. 35
      src/AddIns/Debugger/Debugger.Core/PdbSymbolSource.cs

9
src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.addin

@ -68,6 +68,15 @@ @@ -68,6 +68,15 @@
</MenuItem>
</Path>
<Path name="/SharpDevelop/Workbench/MainMenu/Debug">
<Condition name = "IsProcessRunning" isdebugging="False" action="Disable">
<MenuItem id = "DebugExecutable"
insertbefore = "ExecutionControlSeparator"
label = "${res:MainWindow.Windows.Debug.DebugExecutable}"
class = "Debugger.AddIn.DebugExecutableMenuCommand"/>
</Condition>
</Path>
<Path name = "/SharpDevelop/Workbench/Pads">
<Pad id = "BreakPointsPad"
category = "Debugger"

4
src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.csproj

@ -139,6 +139,9 @@ @@ -139,6 +139,9 @@
<DependentUpon>EditBreakpointScriptWindow.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="Service\ExecuteProcessWindow.xaml.cs">
<DependentUpon>ExecuteProcessWindow.xaml</DependentUpon>
</Compile>
<Compile Include="Tooltips\DebuggerTooltipControl.xaml.cs" />
<Compile Include="Tooltips\VisualizerPicker.cs" />
<Compile Include="TreeModel\SharpTreeNodeAdapter.cs" />
@ -312,6 +315,7 @@ @@ -312,6 +315,7 @@
<Page Include="Options\DebuggingSymbolsPanel.xaml" />
<Page Include="Pads\CommonResources.xaml" />
<Page Include="Service\EditBreakpointScriptWindow.xaml" />
<Page Include="Service\ExecuteProcessWindow.xaml" />
<Page Include="Tooltips\DebuggerTooltipControl.xaml" />
<Page Include="Tooltips\VisualizerPicker.xaml" />
<Page Include="Visualizers\GraphVisualizer\Presentation\NodeControlResources.xaml" />

10
src/AddIns/Debugger/Debugger.AddIn/Options/DebuggingOptions.cs

@ -69,6 +69,16 @@ namespace ICSharpCode.SharpDevelop.Services @@ -69,6 +69,16 @@ namespace ICSharpCode.SharpDevelop.Services
set { PS.Set<bool>("Debugger.PauseOnHandledExceptions", value); }
}
public bool AskForArguments {
get { return PS.Get<bool>("Debugger.AskForArguments", false); }
set { PS.Set<bool>("Debugger.AskForArguments", value); }
}
public bool BreakAtBeginning {
get { return PS.Get<bool>("Debugger.BreakAtBeginning", false); }
set { PS.Set<bool>("Debugger.BreakAtBeginning", value); }
}
public ShowIntegersAs ShowIntegersAs {
get { return PS.Get<ShowIntegersAs>("Debugger.ShowIntegersAs", ShowIntegersAs.Decimal); }
set { PS.Set<ShowIntegersAs>("Debugger.ShowIntegersAs", value); }

8
src/AddIns/Debugger/Debugger.AddIn/Options/DebuggingOptionsPanel.xaml

@ -34,5 +34,13 @@ @@ -34,5 +34,13 @@
IsChecked="{sd:OptionBinding debugger:DebuggingOptions.SuppressNGENOptimization}" />
</widgets:StackPanelWithSpacing>
</GroupBox>
<GroupBox Margin="5" Header="{sd:Localize Dialog.Options.IDEOptions.Debugging.WithoutSource}">
<widgets:StackPanelWithSpacing SpaceBetweenItems="5">
<CheckBox Content="{sd:Localize Dialog.Options.IDEOptions.Debugging.AskForArguments}"
IsChecked="{sd:OptionBinding debugger:DebuggingOptions.AskForArguments}" />
<CheckBox Content="{sd:Localize Dialog.Options.IDEOptions.Debugging.BreakAtBeginning}"
IsChecked="{sd:OptionBinding debugger:DebuggingOptions.BreakAtBeginning}" />
</widgets:StackPanelWithSpacing>
</GroupBox>
</StackPanel>
</gui:OptionPanel>

42
src/AddIns/Debugger/Debugger.AddIn/Service/DebuggerCommands.cs

@ -3,11 +3,14 @@ @@ -3,11 +3,14 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Debugging;
using ICSharpCode.SharpDevelop.Editor;
using Microsoft.Win32;
using ICSharpCode.SharpDevelop.Services;
namespace Debugger.AddIn
@ -28,7 +31,7 @@ namespace Debugger.AddIn @@ -28,7 +31,7 @@ namespace Debugger.AddIn
public override void Run()
{
ITextEditor textEditor = SD.GetActiveViewContentService<ITextEditor>();
if (textEditor == null || DebuggerService.CurrentDebugger == null)
return;
@ -97,4 +100,41 @@ namespace Debugger.AddIn @@ -97,4 +100,41 @@ namespace Debugger.AddIn
return BreakpointUtil.BreakpointsOnCaret.Any();
}
}
public class DebugExecutableMenuCommand : AbstractMenuCommand
{
public override void Run()
{
if (DebuggingOptions.Instance.AskForArguments) {
var window = new ExecuteProcessWindow { Owner = SD.Workbench.MainWindow };
if (window.ShowDialog() == true) {
string fileName = window.SelectedExecutable;
// execute the process
StartExecutable(fileName, window.WorkingDirectory, window.Arguments);
}
} else {
OpenFileDialog dialog = new OpenFileDialog() {
Filter = ".NET Executable (*.exe) | *.exe",
RestoreDirectory = true,
DefaultExt = "exe"
};
if (dialog.ShowDialog() == true) {
string fileName = dialog.FileName;
// execute the process
StartExecutable(fileName);
}
}
}
void StartExecutable(string fileName, string workingDirectory = null, string arguments = null)
{
DebuggerService.CurrentDebugger.BreakAtBeginning = DebuggingOptions.Instance.BreakAtBeginning;
DebuggerService.CurrentDebugger.Start(new ProcessStartInfo {
FileName = fileName,
WorkingDirectory = workingDirectory ?? Path.GetDirectoryName(fileName),
Arguments = arguments
});
}
}
}

113
src/AddIns/Debugger/Debugger.AddIn/Service/ExecuteProcessWindow.xaml

@ -0,0 +1,113 @@ @@ -0,0 +1,113 @@
<?xml version="1.0" encoding="utf-8"?>
<Window
x:Class="ICSharpCode.SharpDevelop.Services.ExecuteProcessWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Select process to debug..."
WindowStartupLocation="CenterOwner"
WindowState="Normal"
WindowStyle="ToolWindow"
ShowInTaskbar="False"
Height="250"
Width="596">
<Grid
Height="217">
<Grid.RowDefinitions>
<RowDefinition
Height="1.4*" />
<RowDefinition
Height="0.2*" />
</Grid.RowDefinitions>
<Label
Content="Executable"
Grid.Column="0"
Grid.Row="0"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Margin="19.5,28.5,0,0"
Width="92"
Height="25" />
<TextBox
Grid.Column="0"
Grid.Row="0"
HorizontalAlignment="Right"
VerticalAlignment="Top"
Margin="0,28.5,84.5,0"
Width="368"
Height="25"
Name="pathTextBox" />
<Button
Grid.Column="0"
Grid.Row="0"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Margin="502.5,28.5,0,0"
Width="25"
Height="25"
Content="..."
Name="pathButton"
Click="pathButton_Click" />
<TextBox
Grid.Column="0"
Grid.Row="0"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Margin="133.5,81,0,0"
Width="368"
Height="25"
Name="argumentsTextBox" />
<Label
Content="Arguments"
Grid.Column="0"
Grid.Row="0"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Margin="19.5,81,0,0"
Width="92"
Height="31" />
<Button
Content="..."
Grid.Column="0"
Grid.Row="0"
HorizontalAlignment="Left"
Width="25"
Click="workingDirectoryButton_Click"
Height="25"
VerticalAlignment="Bottom"
Margin="502.5,0,0,30.875"
Name="workingDirectoryButton" />
<TextBox
Grid.Column="0"
Grid.Row="0"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Margin="133.5,134,0,0"
Width="368"
Height="25"
Name="workingDirectoryTextBox" />
<Label
Content="Working directory"
Grid.Column="0"
Grid.Row="0"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Margin="19.5,134,0,0"
Width="113"
Height="31" />
<DockPanel
Grid.Row="1"
LastChildFill="False">
<Button
DockPanel.Dock="Left"
HorizontalAlignment="Center"
x:Name="ExecuteButton"
Click="ExecuteButton_Click"
Content="Execute"
Width="100" />
<Button
DockPanel.Dock="Right"
x:Name="CancelButton"
Content="Cancel"
Click="CancelButton_Click"
Width="100" />
</DockPanel>
</Grid>
</Window>

84
src/AddIns/Debugger/Debugger.AddIn/Service/ExecuteProcessWindow.xaml.cs

@ -0,0 +1,84 @@ @@ -0,0 +1,84 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Windows;
using System.Windows.Forms;
namespace ICSharpCode.SharpDevelop.Services
{
/// <summary>
/// Interaction logic for ExecuteProcessWindow.xaml
/// </summary>
public partial class ExecuteProcessWindow : Window
{
public ExecuteProcessWindow()
{
InitializeComponent();
}
public string SelectedExecutable {
get {
return pathTextBox.Text;
}
set {
pathTextBox.Text = value;
workingDirectoryTextBox.Text = Path.GetDirectoryName(value);
}
}
public string WorkingDirectory {
get {
return workingDirectoryTextBox.Text;
}
set {
workingDirectoryTextBox.Text = value;
}
}
public string Arguments {
get {
return argumentsTextBox.Text;
}
}
void pathButton_Click(object sender, RoutedEventArgs e)
{
OpenFileDialog dialog = new OpenFileDialog() {
Filter = ".NET Executable (*.exe) | *.exe",
InitialDirectory = workingDirectoryTextBox.Text,
RestoreDirectory = true,
DefaultExt = "exe"
};
if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK) {
SelectedExecutable = dialog.FileName;
}
}
void ExecuteButton_Click(object sender, RoutedEventArgs e)
{
if (string.IsNullOrEmpty(SelectedExecutable))
return;
this.DialogResult = true;
}
void CancelButton_Click(object sender, RoutedEventArgs e)
{
this.Close();
}
void workingDirectoryButton_Click(object sender, RoutedEventArgs e)
{
FolderBrowserDialog dialog = new FolderBrowserDialog() {
SelectedPath = workingDirectoryTextBox.Text
};
if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK) {
workingDirectoryTextBox.Text = dialog.SelectedPath;
}
}
}
}

2
src/AddIns/Debugger/Debugger.AddIn/Service/WindowsDebugger.cs

@ -466,7 +466,7 @@ namespace ICSharpCode.SharpDevelop.Services @@ -466,7 +466,7 @@ namespace ICSharpCode.SharpDevelop.Services
CurrentProcess = e.Process;
CurrentThread = e.Thread;
CurrentStackFrame = CurrentThread != null ? CurrentThread.MostRecentUserStackFrame : null;
CurrentStackFrame = CurrentThread != null ? CurrentThread.MostRecentStackFrame : null;
// We can have several events happening at the same time
bool breakProcess = e.Break;

35
src/AddIns/Debugger/Debugger.Core/PdbSymbolSource.cs

@ -12,7 +12,7 @@ using Debugger.Interop.CorSym; @@ -12,7 +12,7 @@ using Debugger.Interop.CorSym;
using ICSharpCode.NRefactory.TypeSystem;
namespace Debugger
{
{
public class SequencePoint
{
public uint MethodDefToken { get; set; }
@ -88,7 +88,9 @@ namespace Debugger @@ -88,7 +88,9 @@ namespace Debugger
{
public bool Handles(IMethod method)
{
return method.ParentAssembly.GetModule().SymReader != null;
return method.ParentAssembly.GetModule().HasSymbols
&& !IsCompilerGenerated(method)
&& GetSequencePoint(method, 0) != null;
}
public bool IsCompilerGenerated(IMethod method)
@ -119,7 +121,7 @@ namespace Debugger @@ -119,7 +121,7 @@ namespace Debugger
static IEnumerable<string> RelocatePath(string basePath, string origPath)
{
if (!string.IsNullOrEmpty(origPath)) {
if (Path.IsPathRooted(origPath)) {
if (Path.IsPathRooted(origPath)) {
// Try without relocating
yield return origPath;
@ -169,18 +171,19 @@ namespace Debugger @@ -169,18 +171,19 @@ namespace Debugger
// Find point for which (ilstart <= iloffset < ilend) or fallback to the next valid sequence point
var sequencePoint = realSeqPoints.FirstOrDefault(p => p.ILRanges.Any(r => r.From <= iloffset && iloffset < r.To)) ??
realSeqPoints.FirstOrDefault(p => iloffset <= p.ILOffset);
// VB.NET sometimes produces temporary files which it then deletes
// (eg 17d14f5c-a337-4978-8281-53493378c1071.vb)
string name = Path.GetFileName(sequencePoint.Filename);
if (name.Length == 40 && name.EndsWith(".vb")) {
if (name.Substring(0, name.Length - 3).All(c => ('0' <= c && c <= '9') || ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F') || (c == '-'))) {
return null;
}
}
realSeqPoints.FirstOrDefault(p => iloffset <= p.ILOffset);
if (sequencePoint != null) {
// VB.NET sometimes produces temporary files which it then deletes
// (eg 17d14f5c-a337-4978-8281-53493378c1071.vb)
string name = Path.GetFileName(sequencePoint.Filename);
if (name.Length == 40 && name.EndsWith(".vb")) {
if (name.Substring(0, name.Length - 3).All(c => ('0' <= c && c <= '9') || ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F') || (c == '-'))) {
return null;
}
}
sequencePoint.Filename = GetSourceCodePath(method.ParentAssembly.GetModule().Process, sequencePoint.Filename);
}
@ -195,7 +198,7 @@ namespace Debugger @@ -195,7 +198,7 @@ namespace Debugger
ISymUnmanagedReader symReader = module.SymReader;
if (symReader == null)
return null; // No symbols
// Find ISymUnmanagedDocument which excactly matches the filename.
var symDoc = module.SymDocuments.FirstOrDefault(d => string.Equals(filename, d.GetURL(), StringComparison.OrdinalIgnoreCase));
@ -218,7 +221,7 @@ namespace Debugger @@ -218,7 +221,7 @@ namespace Debugger
SequencePoint seqPoint = null;
if (column != 0) {
seqPoint = seqPoints.FirstOrDefault(s => (s.StartLine < line || (s.StartLine == line && s.StartColumn <= column)) &&
(line < s.EndLine || (line == s.EndLine && column <= s.EndColumn)));
(line < s.EndLine || (line == s.EndLine && column <= s.EndColumn)));
}
seqPoint = seqPoint ?? seqPoints.FirstOrDefault(s => line <= s.StartLine);
return seqPoint;
@ -252,7 +255,7 @@ namespace Debugger @@ -252,7 +255,7 @@ namespace Debugger
Type = method.GetLocalVariableType(index),
Name = symVar.GetName(),
IsCompilerGenerated = (symVar.GetAttributes() & 1) == 1,
// symVar also has Get*Offset methods, but the are not implemented
// symVar also has Get*Offset methods, but the are not implemented
ILRanges = new [] { new ILRange() { From = (int)scope.GetStartOffset(), To = (int)scope.GetEndOffset() } }
});
}

Loading…
Cancel
Save