【问题标题】:Cannot get line number of Instruction using Mono.Cecil 0.10.2无法使用 Mono.Cecil 0.10.2 获取指令的行号
【发布时间】:2019-02-11 21:56:34
【问题描述】:

我试图在下面的方法中获取与指令对象关联的行号。 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 选项。我做错了什么?

【问题讨论】:

  • 你可以从源代码编译Mono Cecil,然后调试进去,github.com/jbevain/cecil我想知道你是否使用了错误的API。
  • 我使用 Nuget 添加了最新的稳定 Mono.Cecil。

标签: c# mono.cecil


【解决方案1】:

你的代码没问题。

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 知道的关于它们的序列点,对于它们中的每一个,您都可以看到它映射到它的指令,因此您可以检查方法中的哪个调用指令具有序列点。

【讨论】:

    猜你喜欢
    • 2019-06-25
    • 2011-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多