gpt4 book ai didi

visual-studio - 如何调试非托管 BCL (InternalCall) 方法?

转载 作者:行者123 更新时间:2023-12-03 01:37:50 26 4
gpt4 key购买 nike

我想调试 [MethodImpl(MethodImplOptions.InternalCall)] BCL 方法的实现,该方法可能是用 C++ 实现的。 (在本例中,我正在查看 System.String.nativeCompareOrdinal。)这主要是因为我很爱管闲事,想知道它是如何实现的。

但是,Visual Studio 调试器拒绝单步执行该方法。我可以在此调用上设置断点:

"Hello".Equals("hello", StringComparison.OrdinalIgnoreCase);

然后调出“调试”>“窗口”>“反汇编”,单步执行 Equals 调用,然后单步执行,直到到达 call x86 指令。但是,当我尝试在该调用上使用“Step Into”(我从 Reflector 知道是 nativeCompareOrdinal 调用)时,它不会像我想要的那样单步执行到 nativeCompareOrdinal 内的第一条指令 - 它会步进而是直接转到 Equals 中的下一个 x86 指令。

我正在构建为 x86,因为 x64 应用程序不支持混合模式调试。我已在“工具”>“选项”>“调试”中取消选中“仅我的代码”,并在“项目属性”>“调试”选项卡中选中“启用非托管代码调试”,但它仍然跳过调用。我还尝试启动该进程,然后附加调试器,并显式附加托管调试器和 native 调试器,但它仍然不会进入该 InternalCall 方法。

如何让 Visual Studio 调试器单步执行非托管方法?

最佳答案

是的,这很棘手。您看到的 CALL 指令的偏移量是假的。另外,当当前焦点位于托管函数上时,它不会让您导航到非托管代码地址。

首先启用非托管代码调试并在调用上设置断点。运行代码,当断点命中时使用“调试”+“Windows”+“反汇编”:

            "Hello".Equals("hello", StringComparison.OrdinalIgnoreCase);
00000025 call 6E53D5D0
0000002a nop

调试器尝试显示绝对地址,但结果错误,因为它使用了伪造的增量地址而不是真实的指令地址。所以首先恢复真实的相对值:0x6E53D5D0 - 0x2A = 0x6E53D5A6。

接下来你需要找到真实的代码地址。 Debug + Windows + Registers 并查看 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...

宾果,如果您看到堆栈帧设置代码,您就知道自己做得很好。在其上设置断点并按 F5。

<小时/>

当然,由于没有可用的源代码,您将逐步执行机器代码。通过查看 SSCLI20 源代码,您将更好地了解此代码的用途。不能保证它将与您当前版本的 CLR 中的实际代码匹配,但我的经验是,这些自 1.0 以来就存在的低级代码块是高度保守的。实现在clr\src\classlibnative\nls中,不确定是哪个源代码文件。它不会被命名为“nativeCompareOrdinal”,这只是 ecall.cpp 使用的内部名称。

关于visual-studio - 如何调试非托管 BCL (InternalCall) 方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3778568/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com