反汇编看起来像:
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 代码的位置。说服它你想看到它需要几个技巧:
否则对调试动态方法不太可能有用,尽管我在尝试时很快就放弃了。通过两次调用该方法,您可能领先,因此您可以绕过第二次调用的所有开销。
一种完全不同的方法是暂时向方法发出对 Debugger.Break() 的调用,现在它更容易了。
关于.net - 为什么在调试/反汇编期间我不能进入调用指令?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29973311/