mirror of https://github.com/icsharpcode/ILSpy.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
223 lines
5.0 KiB
223 lines
5.0 KiB
// 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.Runtime.InteropServices; |
|
|
|
using Debugger.Interop.CorDebug; |
|
|
|
namespace Debugger |
|
{ |
|
public class Breakpoint: DebuggerObject |
|
{ |
|
NDebugger debugger; |
|
|
|
string fileName; |
|
byte[] checkSum; |
|
int line; |
|
int column; |
|
bool enabled; |
|
|
|
protected SourcecodeSegment originalLocation; |
|
|
|
protected List<ICorDebugFunctionBreakpoint> corBreakpoints = new List<ICorDebugFunctionBreakpoint>(); |
|
|
|
public event EventHandler<BreakpointEventArgs> Hit; |
|
public event EventHandler<BreakpointEventArgs> Set; |
|
|
|
[Debugger.Tests.Ignore] |
|
public NDebugger Debugger { |
|
get { return debugger; } |
|
protected set { debugger = value; } |
|
} |
|
|
|
public string FileName { |
|
get { return fileName; } |
|
} |
|
|
|
public byte[] CheckSum { |
|
get { return checkSum; } |
|
} |
|
|
|
public int Line { |
|
get { return line; } |
|
set { line = value; } |
|
} |
|
|
|
public int Column { |
|
get { return column; } |
|
protected set { column = value; } |
|
} |
|
|
|
public bool Enabled { |
|
get { return enabled; } |
|
set { |
|
enabled = value; |
|
foreach(ICorDebugFunctionBreakpoint corBreakpoint in corBreakpoints) { |
|
corBreakpoint.Activate(enabled ? 1 : 0); |
|
} |
|
} |
|
} |
|
|
|
public SourcecodeSegment OriginalLocation { |
|
get { return originalLocation; } |
|
} |
|
|
|
public bool IsSet { |
|
get { |
|
return corBreakpoints.Count > 0; |
|
} |
|
} |
|
|
|
protected virtual void OnHit(BreakpointEventArgs e) |
|
{ |
|
if (Hit != null) { |
|
Hit(this, e); |
|
} |
|
} |
|
|
|
internal void NotifyHit() |
|
{ |
|
OnHit(new BreakpointEventArgs(this)); |
|
debugger.Breakpoints.OnHit(this); |
|
} |
|
|
|
protected virtual void OnSet(BreakpointEventArgs e) |
|
{ |
|
if (Set != null) { |
|
Set(this, e); |
|
} |
|
} |
|
|
|
public Breakpoint(NDebugger debugger, ICorDebugFunctionBreakpoint corBreakpoint) |
|
{ |
|
this.debugger = debugger; |
|
this.corBreakpoints.Add(corBreakpoint); |
|
} |
|
|
|
public Breakpoint() { } |
|
|
|
public Breakpoint(NDebugger debugger, string fileName, byte[] checkSum, int line, int column, bool enabled) |
|
{ |
|
this.debugger = debugger; |
|
this.fileName = fileName; |
|
this.checkSum = checkSum; |
|
this.line = line; |
|
this.column = column; |
|
this.enabled = enabled; |
|
} |
|
|
|
internal bool IsOwnerOf(ICorDebugBreakpoint breakpoint) |
|
{ |
|
foreach(ICorDebugFunctionBreakpoint corFunBreakpoint in corBreakpoints) { |
|
if (((ICorDebugBreakpoint)corFunBreakpoint).Equals(breakpoint)) return true; |
|
} |
|
return false; |
|
} |
|
|
|
internal void Deactivate() |
|
{ |
|
foreach(ICorDebugFunctionBreakpoint corBreakpoint in corBreakpoints) { |
|
#if DEBUG |
|
// Get repro |
|
corBreakpoint.Activate(0); |
|
#else |
|
try { |
|
corBreakpoint.Activate(0); |
|
} catch(COMException e) { |
|
// Sometimes happens, but we had not repro yet. |
|
// 0x80131301: Process was terminated. |
|
if ((uint)e.ErrorCode == 0x80131301) |
|
continue; |
|
throw; |
|
} |
|
#endif |
|
} |
|
corBreakpoints.Clear(); |
|
} |
|
|
|
internal void MarkAsDeactivated() |
|
{ |
|
corBreakpoints.Clear(); |
|
} |
|
|
|
internal virtual bool SetBreakpoint(Module module) |
|
{ |
|
if (this.fileName == null) |
|
return false; |
|
|
|
SourcecodeSegment segment = SourcecodeSegment.Resolve(module, FileName, CheckSum, Line, Column); |
|
if (segment == null) return false; |
|
|
|
originalLocation = segment; |
|
|
|
ICorDebugFunctionBreakpoint corBreakpoint = segment.CorFunction.GetILCode().CreateBreakpoint((uint)segment.ILStart); |
|
corBreakpoint.Activate(enabled ? 1 : 0); |
|
|
|
corBreakpoints.Add(corBreakpoint); |
|
|
|
OnSet(new BreakpointEventArgs(this)); |
|
|
|
return true; |
|
} |
|
|
|
/// <summary> Remove this breakpoint </summary> |
|
public void Remove() |
|
{ |
|
debugger.Breakpoints.Remove(this); |
|
} |
|
} |
|
|
|
public class ILBreakpoint : Breakpoint |
|
{ |
|
public ILBreakpoint(NDebugger debugger, int line, uint metadataToken, int ilOffset, bool enabled) |
|
{ |
|
this.Debugger = debugger; |
|
this.Line = line; |
|
this.MetadataToken = metadataToken; |
|
this.ILOffset = ilOffset; |
|
this.Enabled = enabled; |
|
} |
|
|
|
public uint MetadataToken { get; private set; } |
|
|
|
public int ILOffset { get; private set; } |
|
|
|
internal override bool SetBreakpoint(Module module) |
|
{ |
|
SourcecodeSegment segment = SourcecodeSegment.CreateForIL(module, this.Line, (int)MetadataToken, ILOffset); |
|
|
|
try { |
|
ICorDebugFunctionBreakpoint corBreakpoint = segment.CorFunction.GetILCode().CreateBreakpoint((uint)segment.ILStart); |
|
corBreakpoint.Activate(Enabled ? 1 : 0); |
|
|
|
corBreakpoints.Add(corBreakpoint); |
|
|
|
OnSet(new BreakpointEventArgs(this)); |
|
|
|
return true; |
|
} |
|
catch (COMException) { |
|
return false; |
|
} |
|
} |
|
} |
|
|
|
[Serializable] |
|
public class BreakpointEventArgs : DebuggerEventArgs |
|
{ |
|
Breakpoint breakpoint; |
|
|
|
public Breakpoint Breakpoint { |
|
get { |
|
return breakpoint; |
|
} |
|
} |
|
|
|
public BreakpointEventArgs(Breakpoint breakpoint): base(breakpoint.Debugger) |
|
{ |
|
this.breakpoint = breakpoint; |
|
} |
|
} |
|
}
|
|
|