|
|
|
|
@ -6,14 +6,13 @@
@@ -6,14 +6,13 @@
|
|
|
|
|
// </file>
|
|
|
|
|
|
|
|
|
|
using System; |
|
|
|
|
using System.Diagnostics.SymbolStore; |
|
|
|
|
using System.Collections.Generic; |
|
|
|
|
using System.Runtime.InteropServices; |
|
|
|
|
using System.Threading; |
|
|
|
|
|
|
|
|
|
using Debugger.Wrappers.CorDebug; |
|
|
|
|
using Debugger.Wrappers.CorSym; |
|
|
|
|
using Debugger.Wrappers.MetaData; |
|
|
|
|
using System.Collections.Generic; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace Debugger |
|
|
|
|
{ |
|
|
|
|
@ -146,7 +145,7 @@ namespace Debugger
@@ -146,7 +145,7 @@ namespace Debugger
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
internal ISymbolReader symReader { |
|
|
|
|
internal ISymUnmanagedReader symReader { |
|
|
|
|
get { |
|
|
|
|
if (module.SymbolsLoaded == false) return null; |
|
|
|
|
if (module.SymReader == null) return null; |
|
|
|
|
@ -154,13 +153,13 @@ namespace Debugger
@@ -154,13 +153,13 @@ namespace Debugger
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
internal ISymbolMethod symMethod { |
|
|
|
|
internal ISymUnmanagedMethod symMethod { |
|
|
|
|
get { |
|
|
|
|
if (symReader == null) { |
|
|
|
|
return null; |
|
|
|
|
} else { |
|
|
|
|
try { |
|
|
|
|
return symReader.GetMethod(new SymbolToken((int)methodProps.Token)); |
|
|
|
|
return symReader.GetMethod(methodProps.Token); |
|
|
|
|
} catch { |
|
|
|
|
return null; |
|
|
|
|
} |
|
|
|
|
@ -256,88 +255,72 @@ namespace Debugger
@@ -256,88 +255,72 @@ namespace Debugger
|
|
|
|
|
/// </summary>
|
|
|
|
|
SourcecodeSegment GetSegmentForOffet(uint offset) |
|
|
|
|
{ |
|
|
|
|
ISymbolMethod symMethod; |
|
|
|
|
ISymUnmanagedMethod symMethod; |
|
|
|
|
|
|
|
|
|
symMethod = this.symMethod; |
|
|
|
|
if (symMethod == null) { |
|
|
|
|
return null; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int sequencePointCount = symMethod.SequencePointCount; |
|
|
|
|
|
|
|
|
|
int[] offsets = new int[sequencePointCount]; |
|
|
|
|
int[] startLine = new int[sequencePointCount]; |
|
|
|
|
int[] startColumn = new int[sequencePointCount]; |
|
|
|
|
int[] endLine = new int[sequencePointCount]; |
|
|
|
|
int[] endColumn = new int[sequencePointCount]; |
|
|
|
|
|
|
|
|
|
ISymbolDocument[] Doc = new ISymbolDocument[sequencePointCount]; |
|
|
|
|
|
|
|
|
|
symMethod.GetSequencePoints( |
|
|
|
|
offsets, |
|
|
|
|
Doc, |
|
|
|
|
startLine, |
|
|
|
|
startColumn, |
|
|
|
|
endLine, |
|
|
|
|
endColumn |
|
|
|
|
); |
|
|
|
|
uint sequencePointCount = symMethod.SequencePointCount; |
|
|
|
|
SequencePoint[] sequencePoints = symMethod.SequencePoints; |
|
|
|
|
|
|
|
|
|
SourcecodeSegment retVal = new SourcecodeSegment(); |
|
|
|
|
|
|
|
|
|
// Get i for which: offsets[i] <= offset < offsets[i + 1]
|
|
|
|
|
// or fallback to first element if offset < offsets[0]
|
|
|
|
|
for (int i = sequencePointCount - 1; i >= 0; i--) // backwards
|
|
|
|
|
if (offsets[i] <= offset || i == 0) { |
|
|
|
|
for (int i = (int)sequencePointCount - 1; i >= 0; i--) // backwards
|
|
|
|
|
if (sequencePoints[i].Offset <= offset || i == 0) { |
|
|
|
|
// Set inforamtion about current IL range
|
|
|
|
|
int codeSize = (int)corFunction.ILCode.Size; |
|
|
|
|
|
|
|
|
|
retVal.ILOffset = (int)offset; |
|
|
|
|
retVal.ILStart = offsets[i]; |
|
|
|
|
retVal.ILEnd = (i + 1 < sequencePointCount) ? offsets[i + 1] : codeSize; |
|
|
|
|
retVal.ILStart = (int)sequencePoints[i].Offset; |
|
|
|
|
retVal.ILEnd = (i + 1 < sequencePointCount) ? (int)sequencePoints[i+1].Offset : codeSize; |
|
|
|
|
|
|
|
|
|
// 0xFeeFee means "code generated by compiler"
|
|
|
|
|
// If we are in generated sequence use to closest real one instead,
|
|
|
|
|
// extend the ILStart and ILEnd to include the 'real' sequence
|
|
|
|
|
|
|
|
|
|
// Look ahead for 'real' sequence
|
|
|
|
|
while (i + 1 < sequencePointCount && startLine[i] == 0xFeeFee) { |
|
|
|
|
while (i + 1 < sequencePointCount && sequencePoints[i].Line == 0xFeeFee) { |
|
|
|
|
i++; |
|
|
|
|
retVal.ILEnd = (i + 1 < sequencePointCount) ? offsets[i + 1] : codeSize; |
|
|
|
|
retVal.ILEnd = (i + 1 < sequencePointCount) ? (int)sequencePoints[i+1].Offset : codeSize; |
|
|
|
|
} |
|
|
|
|
// Look back for 'real' sequence
|
|
|
|
|
while (i - 1 >= 0 && startLine[i] == 0xFeeFee) { |
|
|
|
|
while (i - 1 >= 0 && sequencePoints[i].Line == 0xFeeFee) { |
|
|
|
|
i--; |
|
|
|
|
retVal.ILStart = offsets[i]; |
|
|
|
|
retVal.ILStart = (int)sequencePoints[i].Offset; |
|
|
|
|
} |
|
|
|
|
// Wow, there are no 'real' sequences
|
|
|
|
|
if (startLine[i] == 0xFeeFee) { |
|
|
|
|
if (sequencePoints[i].Line == 0xFeeFee) { |
|
|
|
|
return null; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
retVal.ModuleFilename = module.FullPath; |
|
|
|
|
|
|
|
|
|
retVal.SourceFullFilename = Doc[i].URL; |
|
|
|
|
retVal.SourceFullFilename = sequencePoints[i].Document.URL; |
|
|
|
|
|
|
|
|
|
retVal.StartLine = startLine[i]; |
|
|
|
|
retVal.StartColumn = startColumn[i]; |
|
|
|
|
retVal.EndLine = endLine[i]; |
|
|
|
|
retVal.EndColumn = endColumn[i]; |
|
|
|
|
retVal.StartLine = (int)sequencePoints[i].Line; |
|
|
|
|
retVal.StartColumn = (int)sequencePoints[i].Column; |
|
|
|
|
retVal.EndLine = (int)sequencePoints[i].EndLine; |
|
|
|
|
retVal.EndColumn = (int)sequencePoints[i].EndColumn; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
List<int> stepRanges = new List<int>(); |
|
|
|
|
for (int j = 0; j < sequencePointCount; j++) { |
|
|
|
|
// Step over compiler generated sequences and current statement
|
|
|
|
|
// 0xFeeFee means "code generated by compiler"
|
|
|
|
|
if (startLine[j] == 0xFeeFee || j == i) { |
|
|
|
|
if (sequencePoints[j].Line == 0xFeeFee || j == i) { |
|
|
|
|
// Add start offset or remove last end (to connect two ranges into one)
|
|
|
|
|
if (stepRanges.Count > 0 && stepRanges[stepRanges.Count - 1] == offsets[j]) { |
|
|
|
|
if (stepRanges.Count > 0 && stepRanges[stepRanges.Count - 1] == sequencePoints[j].Offset) { |
|
|
|
|
stepRanges.RemoveAt(stepRanges.Count - 1); |
|
|
|
|
} else { |
|
|
|
|
stepRanges.Add(offsets[j]); |
|
|
|
|
stepRanges.Add((int)sequencePoints[j].Offset); |
|
|
|
|
} |
|
|
|
|
// Add end offset | handle last sequence point
|
|
|
|
|
if (j + 1 < sequencePointCount) { |
|
|
|
|
stepRanges.Add(offsets[j + 1]); |
|
|
|
|
stepRanges.Add((int)sequencePoints[j+1].Offset); |
|
|
|
|
} else { |
|
|
|
|
stepRanges.Add(codeSize); |
|
|
|
|
} |
|
|
|
|
@ -470,7 +453,7 @@ namespace Debugger
@@ -470,7 +453,7 @@ namespace Debugger
|
|
|
|
|
public IEnumerable<Variable> LocalVariables { |
|
|
|
|
get { |
|
|
|
|
if (symMethod != null) { // TODO: Is this needed?
|
|
|
|
|
ISymbolScope symRootScope = symMethod.RootScope; |
|
|
|
|
ISymUnmanagedScope symRootScope = symMethod.RootScope; |
|
|
|
|
foreach(Variable var in GetLocalVariablesInScope(symRootScope)) { |
|
|
|
|
if (!var.Name.StartsWith("CS$")) { // TODO: Generalize
|
|
|
|
|
yield return var; |
|
|
|
|
@ -480,19 +463,19 @@ namespace Debugger
@@ -480,19 +463,19 @@ namespace Debugger
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
IEnumerable<Variable> GetLocalVariablesInScope(ISymbolScope symScope) |
|
|
|
|
IEnumerable<Variable> GetLocalVariablesInScope(ISymUnmanagedScope symScope) |
|
|
|
|
{ |
|
|
|
|
foreach (ISymbolVariable symVar in symScope.GetLocals()) { |
|
|
|
|
foreach (ISymUnmanagedVariable symVar in symScope.Locals) { |
|
|
|
|
yield return GetLocalVariable(symVar); |
|
|
|
|
} |
|
|
|
|
foreach(ISymbolScope childScope in symScope.GetChildren()) { |
|
|
|
|
foreach(ISymUnmanagedScope childScope in symScope.Children) { |
|
|
|
|
foreach(Variable var in GetLocalVariablesInScope(childScope)) { |
|
|
|
|
yield return var; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Variable GetLocalVariable(ISymbolVariable symVar) |
|
|
|
|
Variable GetLocalVariable(ISymUnmanagedVariable symVar) |
|
|
|
|
{ |
|
|
|
|
return new Variable(debugger, |
|
|
|
|
symVar.Name, |
|
|
|
|
|