Joe*_*ite 5 debugging mixed-mode visual-studio
我想调试[MethodImpl(MethodImplOptions.InternalCall)]BCL方法的实现,这可能是用C++实现的.(在这种特殊情况下,我正在看System.String.nativeCompareOrdinal.)这主要是因为我很爱管闲事,想知道它是如何实现的.
但是,Visual Studio调试器拒绝进入该方法.我可以在这个电话上设置一个断点:
"Hello".Equals("hello", StringComparison.OrdinalIgnoreCase);
Run Code Online (Sandbox Code Playgroud)
然后调出Debug> Windows> Disassembly,进入Equals调用,然后逐步进入callx86指令.但是当我尝试使用"Step Into"时call(我从Reflector知道是nativeCompareOrdinal调用),它不会像我想要的那样步入nativeCompareOrdinal中的第一条指令 - 它会转而直接进入等于的下一个x86指令.
我正在构建为x86,因为x64应用程序不支持混合模式调试.我在工具>选项>调试中取消选中"只是我的代码",并且在项目属性>调试选项卡中选中了"启用非托管代码调试",但它仍然会跳过call.我还尝试启动该过程,然后附加调试器,并显式附加托管和本机调试器,但它仍然不会进入该InternalCall方法.
如何让Visual Studio调试器进入非托管方法?
是的,这很棘手.您在CALL指令中看到的偏移量是假的.此外,当当前焦点位于托管功能时,它不会让您导航到非托管代码地址.
首先启用非托管代码调试并在调用上设置断点.运行代码,当断点命中时,使用Debug + Windows + Disassembly:
"Hello".Equals("hello", StringComparison.OrdinalIgnoreCase);
00000025 call 6E53D5D0
0000002a nop
Run Code Online (Sandbox Code Playgroud)
调试器尝试显示绝对地址但是错误,因为它使用伪造的增量地址而不是真实的指令地址.因此,首先恢复真正的相对值:0x6E53D5D0 - 0x2A = 0x6E53D5A6.
接下来,您需要找到真正的代码地址.调试+ Windows +寄存器并查看EIP寄存器的值.在我的情况下0x009A0095.添加5以获取nop,然后添加相对偏移量:0x9A0095 + 5 + 0x6E53D5A6 = 0x6EEDD640.该函数的真实地址.
调试+ Windows +调用堆栈,然后双击非托管堆栈框架.现在,您可以在"反汇编"窗口的"地址"框中输入计算出的地址,前缀为0x.
6EEDD640 push ebp
6EEDD641 mov ebp,esp
6EEDD643 push edi
6EEDD644 push esi
6EEDD645 push ebx
6EEDD646 sub esp,18h
etc...
Run Code Online (Sandbox Code Playgroud)
宾果,如果你看到堆栈框架设置代码,你就会知道你很好.在其上设置断点并按F5.
当然,由于没有可用的源代码,您将成为步进机器代码.通过查看SSCLI20源代码,您将更好地了解此代码的作用.不能保证它将与当前版本的CLR中的实际代码匹配,但我的经验是,自1.0以来一直存在的这些低级代码块是高度保守的.实现在clr\src\classlibnative \nls中,不确定哪个源代码文件.它不会被命名为"nativeCompareOrdinal",这只是ecall.cpp使用的内部名称.
| 归档时间: |
|
| 查看次数: |
392 次 |
| 最近记录: |