.net - 为什么在调试/反汇编期间我不能进入调用指令?

标签 .net x86-64 cil reflection.emit disassembly

反汇编看起来像:

                methShort( ref x, ref y );
000007FF00163F67  lea         r8,[rsp+34h]  
000007FF00163F6C  lea         rdx,[rsp+30h]  
000007FF00163F71  mov         rcx,qword ptr [rsp+20h]  
000007FF00163F76  mov         rcx,qword ptr [rcx+8]  
000007FF00163F7A  mov         rax,qword ptr [rsp+20h]  
000007FF00163F7F  call        qword ptr [rax+18h]  

方法“methShort”是在 .NET 中使用 Reflection.Emit 动态创建的。它采用两个 Int32 参数作为“byRef”值。这被调试为“ Release模式”构建。

我可以逐步完成程序集,直到“调用”指令。 R8 和 RDX(参数)指向的内存内容看起来不错。我不知道什么样的魔法允许 JIT 使用寄存器而不是堆栈进行调用,但这不是重点。

当我尝试“步入”调用指令时,调试器会“跳过”它。该例程确实被调用了——该方法正确地执行了它的功能。但我似乎无法拆卸也无法进入该方法。

在调用之前的点,RAX 包含值 00000000025C67A8h。加上 18h 后,间接地址变为 00000000025C67C0h。这个地址的 QWORD 是 000000001b64dc48h。

如果我尝试反汇编这个地址(000000001b64dc48h),调试器会返回“无法显示指定的地址。提供的位置没有代码”。

作为 Hail Mary 的尝试,我尝试在没有间接的情况下在 RAX 上反汇编代码,但正如我预期的那样,这也失败了。

谁能告诉我如何获取地址中的任何代码,或者是否需要在地址 (RAX+18h) 上执行类似于 LEA 的操作,然后再分解那里的代码?

最佳答案

您需要记住,调试器正试图让您免于浪费几个小时的生命。 methShort()是委托(delegate)调用,在该调用完成之前仍需要完成大量工作。您不会喜欢单步执行将动态方法编译为机器代码、CAS 检查链接需求、CLR 创建委托(delegate) stub 并将其绑定(bind)到调用站点的单步调试。

我将回答发布的问题,调试器不会向您显示调用目标代码,因为它是非托管代码。您可以从地址中看出,远离您的 jit 代码的位置。说服它你想看到它需要几个技巧:

  • 项目+属性,调试选项卡,勾选“启用 native 代码调试”选项
  • 您必须将调试器从托管模式切换到非托管模式。没有明确的命令,我知道如何做到这一点的最简单方法是使用调用堆栈窗口。双击底部框架 (__RtlUserThreadStart@8)。
  • 单击“源不可用”弹出窗口中的“查看反汇编”链接,以便您返回“反汇编”窗口。调试器现在处于非托管模式。请注意,您无法再使用新的调试引擎轻松分辨,因为它现在显示正确的代码地址。
  • 现在您可以在地址框中输入您发现的地址。一定要在它前面加上“0x”。

  • 否则对调试动态方法不太可能有用,尽管我在尝试时很快就放弃了。通过两次调用该方法,您可能领先,因此您可以绕过第二次调用的所有开销。

    一种完全不同的方法是暂时向方法发出对 Debugger.Break() 的调用,现在它更容易了。

    关于.net - 为什么在调试/反汇编期间我不能进入调用指令?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29973311/

    相关文章:

    c# - 从事件中获取事件处理程序?

    c# - Convert.ToBase64String 是否返回与其源字节数组相同的长度?

    assembly - System V ABI - AMD64 - GCC 发出的程序集中的堆栈对齐

    windows - 免费的 64 位反汇编程序?

    .net - let_ 属性方法的好奇

    c# - CLR 如何知道静态字段是否已被初始化?

    c# - 如何在类库 C# 中使用 Messagebox?

    .net - HTTPS 和摘要认证

    gcc - 在扩展内联 ASM 中调用 printf

    c# - 在结构上调用内部方法