【问题标题】:How do I debug IL code generated at runtime using Reflection.Emit如何使用 Reflection.Emit 调试运行时生成的 IL 代码
【发布时间】:2008-11-26 15:57:14
【问题描述】:

我试图在运行时使用 Reflection.Emit 命名空间中的 DynamicMethod 类生成一些代码,但由于某种原因它抛出了“VerificationException”。这是我正在尝试使用的 IL 代码...

ldarg.1
ldarg.0
ldfld, System.String FirstName
callvirt, Void Write(System.String)
ldarg.1
ldarg.0
ldfld, System.String LastName
callvirt, Void Write(System.String)
ldarg.1
ldarg.0
ldfld, Int32 Age
callvirt, Void Write(Int32)
ret

我需要一种方法来调试生成的 IL 代码。我有什么选择?我用的是VS2008专业版。

【问题讨论】:

    标签: c# .net vb.net


    【解决方案1】:

    我在这里找到了更多帮助...

    DebuggerVisualizer for DynamicMethod (Show me the IL) 这是一个调试器可视化工具,您可以使用它在运行时查看生成的 IL!

    更好的是Debugging LCG,它允许您在运行时使用 Windbg 调试生成的代码!

    【讨论】:

      【解决方案2】:

      尝试使用peverify 工具检查IL。来自 MSDN:

      peverify.exe 执行全面 MSIL 验证检查基于 数据流分析加上列表 数百条有效规则 元数据。有关详细信息 Peverify.exe 执行的检查,请参阅 “元数据验证 规范”和“MSIL 指令集规范”在 Tools Developers Guide 文件夹中的 .NET 框架 SDK。

      您需要将生成的代码作为程序集保存到磁盘上才能使用。

      【讨论】:

        【解决方案3】:

        在使用调试器(至少不是内置的)的意义上,没有办法直接调试 IL。你真的只有两个选择

        1. 建议询问 Rob。手动将 IL 和 ilasm 键入 DLL/EXE。然后在生成的 DLL 上运行 peverify 以查看您的错误。
        2. 如果您确实想要调试 IL,那么您可能会坚持使用原始汇编。

        【讨论】:

          【解决方案4】:

          这在调试端可能对您没有帮助,但 RunSharp 是生成 IL 的好工具,可以帮助您避免常见的陷阱。它让编写 IL 感觉更像是编写 C#。

          以下是示例概述:http://www.codeproject.com/KB/dotnet/runsharp.aspx

          【讨论】:

          • 我尝试过 RunSharp,我必须说我印象深刻,但最后我决定以艰难的方式去做,因为它似乎已被放弃。例如,您无法检查方法调用的返回值(Invoke 没有返回返回值的机制)!
          【解决方案5】:

          您需要发出符号信息才能调试 IL。

          Emitting Symbolic Information with Reflection Emit

          并将发出的操作码与文件中发出它的对应位置进行匹配。(ILGenerator.Emit() 调用所在的位置)。

          但这当然不是一件小事。

          编辑:

          您无法调试无法验证的代码,它根本不会被 Jit-ed。你需要检查你对 IL ops 的正确使用。堆栈中是否每个都具有它期望的所需类型的正确操作数?

          编辑 2:

          简单的方法是使用 C# 创建代码,然后使用 Reflector 或其他一些 IL 反汇编程序查看 IL 并将其与您的进行比较。

          编辑 3:不幸的是,无法使用 DynamicMethod 发出调试信息,但 WinDBG 可用于转储 IL,Jose Fco Bonnin 在他的博客中解释了这一点。 Executing dynamic IL with DynamicMethod:

          我们遇到的主要问题 DynamicMethod是我们没有的 生成调试信息的能力 对于 LCG,因为调试 API 是 基于 LCG 所做的元数据 没有。无论如何,并非一切都丢失了 因为我们可以继续调试 WinDBG。 ...

          该过程在帖子中进一步解释。

          【讨论】:

          • 我可以将符号信息与动态方法 (LCG) 一起使用吗?我已经根据反射器检查了我的 IL,它们是相同的。但我不确定生成的 IL 实际上是否相同。
          【解决方案6】:
          ldarg.1
          ldarg.0
          ldfld, System.String FirstName
          callvirt, Void Write(System.String)
          

          在这个阶段你仍然有 arg1 在堆栈上。

          【讨论】:

          • 是的,它用作调用 BinaryWriter::Write 的参数。它是对 BinaryWriter 对象的引用,并作为“this 指针”传入。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-10-02
          • 1970-01-01
          • 1970-01-01
          • 2014-12-02
          相关资源
          最近更新 更多