Skip to content

Commit 140f4da

Browse files
author
David Karlaš
authored
Merge pull request #1775 from JetBrains/corDebugBreakpointInsertionFixes
Fixed way of choosing best sequence point for breakpoints in CorDebuggerSession
2 parents ae74b2d + 7acfd74 commit 140f4da

File tree

1 file changed

+71
-34
lines changed

1 file changed

+71
-34
lines changed

Mono.Debugging.Win32/CorDebuggerSession.cs

Lines changed: 71 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1049,55 +1049,92 @@ protected override BreakEventInfo OnInsertBreakEvent (BreakEvent be)
10491049
binfo.SetStatus (BreakEventStatus.Invalid, string.Format("Invalid line {0}", bp.Line));
10501050
return binfo;
10511051
}
1052-
ISymbolMethod met = null;
1052+
ISymbolMethod[] methods = null;
10531053
if (doc.ModuleInfo.Reader is ISymbolReader2) {
1054-
var methods = ((ISymbolReader2)doc.ModuleInfo.Reader).GetMethodsFromDocumentPosition (doc.Document, line, 0);
1055-
if (methods != null && methods.Any ()) {
1056-
if (methods.Count () == 1) {
1057-
met = methods [0];
1058-
} else {
1059-
int deepest = -1;
1060-
foreach (var method in methods) {
1061-
var firstSequence = method.GetSequencePoints ().FirstOrDefault ((sp) => sp.StartLine != 0xfeefee);
1062-
if (firstSequence != null && firstSequence.StartLine >= deepest) {
1063-
deepest = firstSequence.StartLine;
1064-
met = method;
1065-
}
1066-
}
1067-
}
1068-
}
1054+
methods = ((ISymbolReader2)doc.ModuleInfo.Reader).GetMethodsFromDocumentPosition (doc.Document, line, 0);
10691055
}
1070-
if (met == null) {
1071-
met = doc.ModuleInfo.Reader.GetMethodFromDocumentPosition (doc.Document, line, 0);
1056+
if (methods == null || methods.Length == 0) {
1057+
var met = doc.ModuleInfo.Reader.GetMethodFromDocumentPosition (doc.Document, line, 0);
1058+
if (met != null)
1059+
methods = new ISymbolMethod[] {met};
10721060
}
1073-
if (met == null) {
1061+
1062+
if (methods == null || methods.Length == 0) {
10741063
binfo.SetStatus (BreakEventStatus.Invalid, "Unable to resolve method at position");
10751064
return binfo;
10761065
}
10771066

1078-
int offset = -1;
1079-
int firstSpInLine = -1;
1080-
foreach (SequencePoint sp in met.GetSequencePoints ()) {
1081-
if (sp.IsInside (doc.Document.URL, line, bp.Column)) {
1082-
offset = sp.Offset;
1083-
break;
1084-
} else if (firstSpInLine == -1
1085-
&& sp.StartLine == line
1086-
&& sp.Document.URL.Equals (doc.Document.URL, StringComparison.OrdinalIgnoreCase)) {
1087-
firstSpInLine = sp.Offset;
1067+
ISymbolMethod bestMethod = null;
1068+
ISymbolMethod bestLeftSideMethod = null;
1069+
ISymbolMethod bestRightSideMethod = null;
1070+
1071+
SequencePoint bestSp = null;
1072+
SequencePoint bestLeftSideSp = null;
1073+
SequencePoint bestRightSideSp = null;
1074+
1075+
foreach (var met in methods) {
1076+
foreach (SequencePoint sp in met.GetSequencePoints ()) {
1077+
if (sp.IsInside (doc.Document.URL, line, bp.Column)) { //breakpoint is inside current sequence point
1078+
if (bestSp == null || bestSp.IsInside (doc.Document.URL, sp.StartLine, sp.StartColumn)) { //and sp is inside of current candidate
1079+
bestSp = sp;
1080+
bestMethod = met;
1081+
break;
1082+
}
1083+
} else if (sp.StartLine == line
1084+
&& sp.Document.URL.Equals (doc.Document.URL, StringComparison.OrdinalIgnoreCase)
1085+
&& sp.StartColumn <= bp.Column) { //breakpoint is on the same line and on the right side of sp
1086+
if (bestLeftSideSp == null
1087+
|| bestLeftSideSp.EndColumn < sp.EndColumn) {
1088+
bestLeftSideSp = sp;
1089+
bestLeftSideMethod = met;
1090+
}
1091+
} else if (sp.StartLine >= line
1092+
&& sp.Document.URL.Equals (doc.Document.URL, StringComparison.OrdinalIgnoreCase)) { //sp is after bp
1093+
if (bestRightSideSp == null
1094+
|| bestRightSideSp.StartLine > sp.StartLine
1095+
|| (bestRightSideSp.StartLine == sp.StartLine && bestRightSideSp.StartColumn > sp.StartColumn)) { //and current candidate is on the right side of it
1096+
bestRightSideSp = sp;
1097+
bestRightSideMethod = met;
1098+
}
1099+
}
10881100
}
10891101
}
1090-
if (offset == -1) {//No exact match? Use first match in that line
1091-
offset = firstSpInLine;
1102+
1103+
SequencePoint bestSameLineSp;
1104+
ISymbolMethod bestSameLineMethod;
1105+
1106+
if (bestRightSideSp != null
1107+
&& (bestLeftSideSp == null
1108+
|| bestRightSideSp.StartLine > line)) {
1109+
bestSameLineSp = bestRightSideSp;
1110+
bestSameLineMethod = bestRightSideMethod;
1111+
}
1112+
else {
1113+
bestSameLineSp = bestLeftSideSp;
1114+
bestSameLineMethod = bestLeftSideMethod;
10921115
}
1093-
if (offset == -1) {
1116+
1117+
if (bestSameLineSp != null) {
1118+
if (bestSp == null) {
1119+
bestSp = bestSameLineSp;
1120+
bestMethod = bestSameLineMethod;
1121+
}
1122+
else {
1123+
if (bp.Line != bestSp.StartLine || bestSp.StartColumn != bp.Column) {
1124+
bestSp = bestSameLineSp;
1125+
bestMethod = bestSameLineMethod;
1126+
}
1127+
}
1128+
}
1129+
1130+
if (bestSp == null || bestMethod == null) {
10941131
binfo.SetStatus (BreakEventStatus.Invalid, "Unable to calculate an offset in IL code");
10951132
return binfo;
10961133
}
10971134

1098-
CorFunction func = doc.ModuleInfo.Module.GetFunctionFromToken (met.Token.GetToken ());
1135+
CorFunction func = doc.ModuleInfo.Module.GetFunctionFromToken (bestMethod.Token.GetToken ());
10991136
try {
1100-
CorFunctionBreakpoint corBp = func.ILCode.CreateBreakpoint (offset);
1137+
CorFunctionBreakpoint corBp = func.ILCode.CreateBreakpoint (bestSp.Offset);
11011138
breakpoints[corBp] = binfo;
11021139
binfo.Handle = corBp;
11031140
corBp.Activate (bp.Enabled);

0 commit comments

Comments
 (0)