Skip to content
This repository was archived by the owner on Oct 16, 2020. It is now read-only.

Commit e152b74

Browse files
fix calculation of sequence points for breakpoints in pdb files
1 parent d68d301 commit e152b74

2 files changed

Lines changed: 48 additions & 12 deletions

File tree

src/AddIns/Debugger/Debugger.Core/Breakpoint.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ internal void NotifyDebuggerTerminated()
8484

8585
public void SetBreakpoint(Module module)
8686
{
87-
foreach(var symbolSource in module.Process.Debugger.SymbolSources) {
87+
foreach (var symbolSource in module.Process.Debugger.SymbolSources) {
8888
foreach (var seq in symbolSource.GetSequencePoints(module, this.FileName, this.Line, this.Column)) {
8989
ICorDebugFunction corFunction = module.CorModule.GetFunctionFromToken(seq.MethodDefToken);
9090
ICorDebugFunctionBreakpoint corBreakpoint = corFunction.GetILCode().CreateBreakpoint((uint)seq.ILOffset);

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

Lines changed: 47 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,14 @@ public override string ToString()
4848
this.StartLine, this.StartColumn,
4949
this.EndLine, this.EndColumn);
5050
}
51+
52+
public bool ContainsLocation(int line, int column = 0)
53+
{
54+
if (column == 0)
55+
return line >= StartLine && line <= EndLine;
56+
return (StartLine < line || (StartLine == line && StartColumn <= column))
57+
&& (line < EndLine || (line == EndLine && column <= EndColumn));
58+
}
5159
}
5260

5361
public struct ILRange
@@ -185,14 +193,14 @@ public SequencePoint GetSequencePoint(IMethod method, int iloffset)
185193
var realSeqPoints = sequencePoints.Where(p => p.StartLine != 0xFEEFEE);
186194

187195
// Find point for which (ilstart <= iloffset < ilend) or fallback to the next valid sequence point
188-
var sequencePoint = realSeqPoints.FirstOrDefault(p => p.ILRanges.Any(r => r.From <= iloffset && iloffset < r.To)) ??
189-
realSeqPoints.FirstOrDefault(p => iloffset <= p.ILOffset);
196+
var sequencePoint = realSeqPoints.FirstOrDefault(p => p.ILRanges.Any(r => r.From <= iloffset && iloffset < r.To))
197+
?? realSeqPoints.FirstOrDefault(p => iloffset <= p.ILOffset);
190198

191199
if (sequencePoint != null) {
192200
// VB.NET sometimes produces temporary files which it then deletes
193201
// (eg 17d14f5c-a337-4978-8281-53493378c1071.vb)
194202
string name = Path.GetFileName(sequencePoint.Filename);
195-
if (name.Length == 40 && name.EndsWith(".vb")) {
203+
if (name.Length == 40 && name.EndsWith(".vb", StringComparison.OrdinalIgnoreCase)) {
196204
if (name.Substring(0, name.Length - 3).All(c => ('0' <= c && c <= '9') || ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F') || (c == '-'))) {
197205
return null;
198206
}
@@ -232,19 +240,47 @@ public IEnumerable<SequencePoint> GetSequencePoints(Module module, string filena
232240

233241
foreach (ISymUnmanagedMethod symMethod in symMethods) {
234242
var corFunction = module.CorModule.GetFunctionFromToken(symMethod.GetToken());
235-
int codesize = (int)corFunction.GetILCode().GetSize();
236-
var seqPoints = symMethod.GetSequencePoints(codesize).Where(s => s.StartLine != 0xFEEFEE);
237-
SequencePoint seqPoint = null;
238-
if (column != 0) {
239-
seqPoint = seqPoints.FirstOrDefault(s => (s.StartLine < line || (s.StartLine == line && s.StartColumn <= column)) &&
240-
(line < s.EndLine || (line == s.EndLine && column <= s.EndColumn)));
241-
}
242-
seqPoint = seqPoint ?? seqPoints.FirstOrDefault(s => line <= s.StartLine);
243+
int codeSize = (int)corFunction.GetILCode().GetSize();
244+
var seqPoints = symMethod.GetSequencePoints(codeSize).Where(s => s.StartLine != 0xFEEFEE).OrderBy(s => s.StartLine).ToArray();
245+
SequencePoint seqPoint = FindNearestMatchingSequencePoint(seqPoints, line, column);
243246
if (seqPoint != null)
244247
yield return seqPoint;
245248
}
246249
}
247250

251+
SequencePoint FindNearestMatchingSequencePoint(SequencePoint[] seqPoints, int line, int column)
252+
{
253+
// value is nearest offset in lines;
254+
// negative numbers: (Start|End)Line is same as line, value is offset in columns
255+
int nearestOffset = 0;
256+
SequencePoint bestMatch = null;
257+
for (int i = 0; i < seqPoints.Length; i++) {
258+
var s = seqPoints[i];
259+
if (s.ContainsLocation(line, column))
260+
return seqPoints[i];
261+
262+
if (bestMatch == null) {
263+
bestMatch = s;
264+
nearestOffset = GetOffsetValue(s, line, column);
265+
} else {
266+
int newOffset = GetOffsetValue(s, line, column);
267+
if ((newOffset < 0 && nearestOffset < 0 && newOffset > nearestOffset) || (newOffset < nearestOffset)) {
268+
bestMatch = s;
269+
nearestOffset = newOffset;
270+
}
271+
}
272+
}
273+
274+
return bestMatch;
275+
}
276+
277+
static int GetOffsetValue(SequencePoint s, int line, int column)
278+
{
279+
if (line == s.StartLine || s.EndLine == line)
280+
return -Math.Min(Math.Abs(s.StartColumn - column), Math.Abs(s.EndColumn - column));
281+
return Math.Min(Math.Abs(s.StartLine - line), Math.Abs(s.EndLine - line));
282+
}
283+
248284
public IEnumerable<ILRange> GetIgnoredILRanges(IMethod method)
249285
{
250286
var symMethod = method.GetSymMethod();

0 commit comments

Comments
 (0)