diff --git a/src/AddIns/Debugger/Debugger.Core/Breakpoint.cs b/src/AddIns/Debugger/Debugger.Core/Breakpoint.cs
index 05b0c5ed99..f7be6faa83 100644
--- a/src/AddIns/Debugger/Debugger.Core/Breakpoint.cs
+++ b/src/AddIns/Debugger/Debugger.Core/Breakpoint.cs
@@ -70,8 +70,7 @@ namespace Debugger
public void SetBreakpoint(Module module)
{
foreach(var symbolSource in module.Process.Debugger.SymbolSources) {
- var seq = symbolSource.GetSequencePoint(module, this.FileName, this.Line, this.Column);
- if (seq != null) {
+ foreach (var seq in symbolSource.GetSequencePoints(module, this.FileName, this.Line, this.Column)) {
ICorDebugFunction corFunction = module.CorModule.GetFunctionFromToken(seq.MethodDefToken);
ICorDebugFunctionBreakpoint corBreakpoint = corFunction.GetILCode().CreateBreakpoint((uint)seq.ILOffset);
corBreakpoint.Activate(enabled ? 1 : 0);
diff --git a/src/AddIns/Debugger/Debugger.Core/Interop/CorSym.cs b/src/AddIns/Debugger/Debugger.Core/Interop/CorSym.cs
index 738bcd4ffb..4d3ae9c3f3 100644
--- a/src/AddIns/Debugger/Debugger.Core/Interop/CorSym.cs
+++ b/src/AddIns/Debugger/Debugger.Core/Interop/CorSym.cs
@@ -77,7 +77,7 @@ namespace Debugger.Interop.CorSym
public virtual extern ISymUnmanagedMethod __GetMethodFromDocumentPosition([In, MarshalAs(UnmanagedType.Interface)] ISymUnmanagedDocument document, [In] uint line, [In] uint column);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType=MethodCodeType.Runtime)]
- public virtual extern void __GetMethodsFromDocumentPosition([In, MarshalAs(UnmanagedType.Interface)] ISymUnmanagedDocument document, [In] uint line, [In] uint column, [In] uint cMethod, out uint pcMethod, [Out] IntPtr pRetVal);
+ public virtual extern void __GetMethodsFromDocumentPosition([In, MarshalAs(UnmanagedType.Interface)] ISymUnmanagedDocument document, [In] uint line, [In] uint column, [In] uint cMethod, out uint pcMethod, [Out, MarshalAs(UnmanagedType.LPArray)] ISymUnmanagedMethod[] pRetVal);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType=MethodCodeType.Runtime)]
public virtual extern void __GetMethodVersion([In, MarshalAs(UnmanagedType.Interface)] ISymUnmanagedMethod pMethod, out int version);
@@ -332,7 +332,7 @@ namespace Debugger.Interop.CorSym
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType=MethodCodeType.Runtime)]
void __GetSymbolStoreFileName([In] uint cchName, out uint pcchName, [Out] IntPtr szName);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType=MethodCodeType.Runtime)]
- void __GetMethodsFromDocumentPosition([In, MarshalAs(UnmanagedType.Interface)] ISymUnmanagedDocument document, [In] uint line, [In] uint column, [In] uint cMethod, out uint pcMethod, [Out] IntPtr pRetVal);
+ void __GetMethodsFromDocumentPosition([In, MarshalAs(UnmanagedType.Interface)] ISymUnmanagedDocument document, [In] uint line, [In] uint column, [In] uint cMethod, out uint pcMethod, [Out, MarshalAs(UnmanagedType.LPArray)] ISymUnmanagedMethod[] pRetVal);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType=MethodCodeType.Runtime)]
void __GetDocumentVersion([In, MarshalAs(UnmanagedType.Interface)] ISymUnmanagedDocument pDoc, out int version, out int pbCurrent);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType=MethodCodeType.Runtime)]
diff --git a/src/AddIns/Debugger/Debugger.Core/Interop/CorSymExtensionMethods.generated.cs b/src/AddIns/Debugger/Debugger.Core/Interop/CorSymExtensionMethods.generated.cs
index 137e8dd2ee..48e610beca 100644
--- a/src/AddIns/Debugger/Debugger.Core/Interop/CorSymExtensionMethods.generated.cs
+++ b/src/AddIns/Debugger/Debugger.Core/Interop/CorSymExtensionMethods.generated.cs
@@ -67,9 +67,14 @@ namespace Debugger.Interop.CorSym
return returnValue;
}
- public static void GetMethodsFromDocumentPosition(this CorSymReader_SxSClass instance, ISymUnmanagedDocument document, uint line, uint column, uint cMethod, out uint pcMethod, IntPtr pRetVal)
+ public static ISymUnmanagedMethod[] GetMethodsFromDocumentPosition(this CorSymReader_SxSClass instance, ISymUnmanagedDocument document, uint line, uint column)
{
- instance.__GetMethodsFromDocumentPosition(document, line, column, cMethod, out pcMethod, pRetVal);
+ uint count;
+ instance.__GetMethodsFromDocumentPosition(document, line, column, 0, out count, new ISymUnmanagedMethod[0]);
+ var methods = new ISymUnmanagedMethod[count];
+ instance.__GetMethodsFromDocumentPosition(document, line, column, count, out count, methods);
+ ProcessOutParameter(methods);
+ return methods;
}
public static int GetMethodVersion(this CorSymReader_SxSClass instance, ISymUnmanagedMethod pMethod)
@@ -485,9 +490,14 @@ namespace Debugger.Interop.CorSym
instance.__GetSymbolStoreFileName(cchName, out pcchName, szName);
}
- public static void GetMethodsFromDocumentPosition(this ISymUnmanagedReader instance, ISymUnmanagedDocument document, uint line, uint column, uint cMethod, out uint pcMethod, IntPtr pRetVal)
+ public static ISymUnmanagedMethod[] GetMethodsFromDocumentPosition(this ISymUnmanagedReader instance, ISymUnmanagedDocument document, uint line, uint column)
{
- instance.__GetMethodsFromDocumentPosition(document, line, column, cMethod, out pcMethod, pRetVal);
+ uint count;
+ instance.__GetMethodsFromDocumentPosition(document, line, column, 0, out count, new ISymUnmanagedMethod[0]);
+ var methods = new ISymUnmanagedMethod[count];
+ instance.__GetMethodsFromDocumentPosition(document, line, column, count, out count, methods);
+ ProcessOutParameter(methods);
+ return methods;
}
public static void GetDocumentVersion(this ISymUnmanagedReader instance, ISymUnmanagedDocument pDoc, out int version, out int pbCurrent)
diff --git a/src/AddIns/Debugger/Debugger.Core/PdbSymbolSource.cs b/src/AddIns/Debugger/Debugger.Core/PdbSymbolSource.cs
index c8d7aa7fa4..e70eaf9fe6 100644
--- a/src/AddIns/Debugger/Debugger.Core/PdbSymbolSource.cs
+++ b/src/AddIns/Debugger/Debugger.Core/PdbSymbolSource.cs
@@ -72,9 +72,9 @@ namespace Debugger
/// Find sequence point by IL offset
SequencePoint GetSequencePoint(IMethod method, int iloffset);
- /// Find sequence point by source code location
+ /// Find sequence points by source code location. Might find multiple methods at one location (lambda expressions, etc.)
/// Only source files corresponding to the given module are searched
- SequencePoint GetSequencePoint(Module module, string filename, int line, int column);
+ IEnumerable GetSequencePoints(Module module, string filename, int line, int column);
/// Get IL ranges that should be always stepped over by the debugger
/// This is used for compiler generated code
@@ -190,14 +190,14 @@ namespace Debugger
return sequencePoint;
}
- public SequencePoint GetSequencePoint(Module module, string filename, int line, int column)
+ public IEnumerable GetSequencePoints(Module module, string filename, int line, int column)
{
// Do not use ISymUnmanagedReader.GetDocument! It is broken if two files have the same name
// Do not use ISymUnmanagedMethod.GetOffset! It sometimes returns negative offset
ISymUnmanagedReader symReader = module.SymReader;
if (symReader == null)
- return null; // No symbols
+ yield break; // No symbols
// Find ISymUnmanagedDocument which excactly matches the filename.
var symDoc = module.SymDocuments.FirstOrDefault(d => string.Equals(filename, d.GetURL(), StringComparison.OrdinalIgnoreCase));
@@ -205,26 +205,31 @@ namespace Debugger
// Find the file even if the symbol is relative or if the file was moved
var symDocs = module.SymDocuments.Where(d => string.Equals(Path.GetFileName(filename), Path.GetFileName(d.GetURL()), StringComparison.OrdinalIgnoreCase));
symDoc = symDoc ?? symDocs.FirstOrDefault(d => string.Equals(GetSourceCodePath(module.Process, d.GetURL()), filename, StringComparison.OrdinalIgnoreCase));
- if (symDoc == null) return null; // Document not found
+ if (symDoc == null) yield break; // Document not found
- ISymUnmanagedMethod symMethod;
+ ISymUnmanagedMethod symMethod2;
+ ISymUnmanagedMethod[] symMethods;
try {
uint validLine = symDoc.FindClosestLine((uint)line);
- symMethod = symReader.GetMethodFromDocumentPosition(symDoc, (uint)validLine, (uint)column);
+ symMethods = symReader.GetMethodsFromDocumentPosition(symDoc, validLine, (uint)column);
+ symMethod2 = symReader.GetMethodFromDocumentPosition(symDoc, (uint)validLine, (uint)column);
} catch {
- return null; //Not found
+ yield break; //Not found
}
- var corFunction = module.CorModule.GetFunctionFromToken(symMethod.GetToken());
- int codesize = (int)corFunction.GetILCode().GetSize();
- var seqPoints = symMethod.GetSequencePoints(codesize).Where(s => s.StartLine != 0xFEEFEE);
- 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)));
+ foreach (ISymUnmanagedMethod symMethod in symMethods) {
+ var corFunction = module.CorModule.GetFunctionFromToken(symMethod.GetToken());
+ int codesize = (int)corFunction.GetILCode().GetSize();
+ var seqPoints = symMethod.GetSequencePoints(codesize).Where(s => s.StartLine != 0xFEEFEE);
+ 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)));
+ }
+ seqPoint = seqPoint ?? seqPoints.FirstOrDefault(s => line <= s.StartLine);
+ if (seqPoint != null)
+ yield return seqPoint;
}
- seqPoint = seqPoint ?? seqPoints.FirstOrDefault(s => line <= s.StartLine);
- return seqPoint;
}
public IEnumerable GetIgnoredILRanges(IMethod method)
diff --git a/src/AddIns/Debugger/Debugger.Core/Process.cs b/src/AddIns/Debugger/Debugger.Core/Process.cs
index ba27dccff5..934481da01 100644
--- a/src/AddIns/Debugger/Debugger.Core/Process.cs
+++ b/src/AddIns/Debugger/Debugger.Core/Process.cs
@@ -436,8 +436,7 @@ namespace Debugger
foreach(var symbolSource in this.Debugger.SymbolSources) {
foreach(Module module in this.Modules) {
// Note the we might get multiple matches
- SequencePoint seq = symbolSource.GetSequencePoint(module, fileName, line, column);
- if (seq != null) {
+ foreach (SequencePoint seq in symbolSource.GetSequencePoints(module, fileName, line, column)) {
ICorDebugFunction corFunction = module.CorModule.GetFunctionFromToken(seq.MethodDefToken);
ICorDebugFunctionBreakpoint corBreakpoint = corFunction.GetILCode().CreateBreakpoint((uint)seq.ILOffset);
corBreakpoint.Activate(1);
diff --git a/src/AddIns/Debugger/Debugger.Core/StackFrame.cs b/src/AddIns/Debugger/Debugger.Core/StackFrame.cs
index 298553d136..7f1732183e 100644
--- a/src/AddIns/Debugger/Debugger.Core/StackFrame.cs
+++ b/src/AddIns/Debugger/Debugger.Core/StackFrame.cs
@@ -198,21 +198,22 @@ namespace Debugger
this.Process.AssertPaused();
foreach(var symbolSource in this.Process.Debugger.SymbolSources) {
- var seq = symbolSource.GetSequencePoint(this.Module, filename, line, column);
- if (seq != null && seq.MethodDefToken == this.MethodInfo.GetMetadataToken()) {
- try {
- if (dryRun) {
- CorILFrame.CanSetIP((uint)seq.ILOffset);
- } else {
- CorILFrame.SetIP((uint)seq.ILOffset);
- // Invalidates all frames and chains for the current thread
- this.Process.NotifyResumed(DebuggeeStateAction.Keep);
- this.Process.NotifyPaused();
+ foreach (var seq in symbolSource.GetSequencePoints(this.Module, filename, line, column)) {
+ if (seq.MethodDefToken == this.MethodInfo.GetMetadataToken()) {
+ try {
+ if (dryRun) {
+ CorILFrame.CanSetIP((uint)seq.ILOffset);
+ } else {
+ CorILFrame.SetIP((uint)seq.ILOffset);
+ // Invalidates all frames and chains for the current thread
+ this.Process.NotifyResumed(DebuggeeStateAction.Keep);
+ this.Process.NotifyPaused();
+ }
+ } catch {
+ return false;
}
- } catch {
- return false;
+ return true;
}
- return true;
}
}
return false;
diff --git a/src/AddIns/DisplayBindings/ILSpyAddIn/ILSpySymbolSource.cs b/src/AddIns/DisplayBindings/ILSpyAddIn/ILSpySymbolSource.cs
index 738666b64d..5c82063f83 100644
--- a/src/AddIns/DisplayBindings/ILSpyAddIn/ILSpySymbolSource.cs
+++ b/src/AddIns/DisplayBindings/ILSpyAddIn/ILSpySymbolSource.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
@@ -57,13 +58,13 @@ namespace ICSharpCode.ILSpyAddIn
return null;
}
- public Debugger.SequencePoint GetSequencePoint(Module module, string filename, int line, int column)
+ public IEnumerable GetSequencePoints(Module module, string filename, int line, int column)
{
var content = DecompiledViewContent.Get(new FileName(filename));
if (content == null)
- return null;
+ yield break;
if (!FileUtility.IsEqualFileName(module.FullPath, content.AssemblyFile))
- return null;
+ yield break;
TextLocation loc = new TextLocation(line, column);
foreach(var symbols in content.DebugSymbols.Values.Where(s => s.StartLocation <= loc && loc <= s.EndLocation)) {
@@ -73,9 +74,8 @@ namespace ICSharpCode.ILSpyAddIn
if (seq == null)
seq = symbols.SequencePoints.FirstOrDefault(p => line <= p.StartLocation.Line);
if (seq != null)
- return seq.ToDebugger(symbols, content.VirtualFileName);
+ yield return seq.ToDebugger(symbols, content.VirtualFileName);
}
- return null;
}
public IEnumerable GetIgnoredILRanges(IMethod method)