我正在尝试通过以下方法获取与Instruction对象关联的行号。应该为SequencePoint.StartLine提供我所需的信息,但是在方法的注释掉部分中seqPoint始终为空。
/// <summary>
/// Finds all places in code where one or more methods are called.
/// </summary>
/// <param name="classOfMethods">Full name of the class that contains the methods to find.</param>
/// <param name="methodNames">Names of the methods to find in code.</param>
public MethodCall[] FindAllMethodCalls(Type classOfMethods, params string[] methodNames)
{
#region Use Mono.Cecil to find all instances where methods are called
var methodCalls = new List<MethodCall>();
var ad = AssemblyDefinition.ReadAssembly(binaryFileToSearch, new ReaderParameters { ReadSymbols = true });
foreach (var module in ad.Modules)
{
foreach (var type in module.GetTypes())
{
foreach (var method in type.Methods.Where(x => x.HasBody))
{
var instrs = method.Body.Instructions.Where(x => x.OpCode == OpCodes.Call).ToArray();
foreach (var instr in instrs)
{
var mRef = instr.Operand as MethodReference;
if (mRef != null && mRef.DeclaringType.FullName == classOfMethods.FullName && methodNames.Contains(mRef.Name))
{
// this does not work -- always returns null
//var seqPoint = method.DebugInformation.GetSequencePoint(instr);
//if (seqPoint != null)
//{
//}
methodCalls.Add(new MethodCall
{
CodeFile = method.DebugInformation.SequencePoints.First().Document.Url,
MethodRef = mRef,
});
}
}
}
}
}
...
return methodCalls.ToArray();
}
我在其上调用AssemblyDefinition.ReadAssembly()的二进制文件具有相应的.pdb文件,并且我正在使用ReadSymbols = true选项。我在做什么错了?
答案 0 :(得分:0)
您的代码确定。
Cecil应该在何时读取PDB文件。在读取过程中,他将填充所有PDB函数:(这不是完整的真实代码,但用于演示,尽管实际代码相似)
private bool PopulateFunctions()
{
PdbFunction[] array = PdbFile.LoadFunctions(.....);
foreach (PdbFunction pdbFunction in array)
{
this.functions.Add(pdbFunction.token, pdbFunction);
}
}
然后,当他阅读MethodBody时,他会填充序列点:
private void ReadSequencePoints(PdbFunction function, MethodDebugInformation info)
{
foreach (PdbLines lines in function.lines)
{
this.ReadLines(lines, info);
}
}
然后
private static void ReadLine(PdbLine line, Document document, MethodDebugInformation info)
{
SequencePoint sequencePoint = new SequencePoint(ine.offset, document);
sequencePoint.StartLine = line.lineBegin;
sequencePoint.StartColumn = line.colBegin;
sequencePoint.EndLine = line.lineEnd;
sequencePoint.EndColumn = line.colEnd;
info.sequence_points.Add(sequencePoint);
}
如果找不到特定的序列点,则意味着它不存在于方法调试信息的序列点集合中。
无论如何,我怀疑您是否总是空空。
请写下:
method.DebugInformation.GetSequencePointMapping()
并将其与您的instrs
收藏集进行比较。
method.DebugInformation.GetSequencePointMapping()
是Cecil知道的序列点,对于每个序列点,您都可以看到它映射到的指令,因此您可以检查方法中的哪个调用指令具有序列点。 / p>