在探讨C#程序编译成Native代码的宏观过程后,有读者提出了一个有趣的问题:是否能在dotnetpublish发布的过程中对AOT编译器进行源码级调试?这个问题不仅引发了我们的兴趣,也成为了深入研究的起点。接下来,我们将探讨如何进行这样的调试。
二:托管与非托管调试器在深入了解调试技术时,我们首先需要了解AOTCompiler(ilc.exe)是用C#编写的,这意味着它是一个托管程序。对于这类程序的调试,主要有两种调试器可供选择:
VisualStudio托管调试器:它专为调试C#代码而设计,功能强大。然而,它对非托管部分的查看能力相对较弱。WinDbg非托管调试器:主要用于调试C/C++代码,尽管它也可以用于调试托管的C#代码,但在变量显示等方面可能不够直观。
总的来说,这两种调试器各有千秋,选择哪种取决于你的具体需求。测试代码
为了更清晰地展示调试过程,我们首先提供一个简单的测试代码。这段代码仅仅是一个内部类Program,其中包含一个静态方法Main,该方法会在控制台输出"Hello,World!"并等待用户输入。
接下来,我们将深入探讨如何使用VisualStudio和WinDbg这两种调试器来对这段代码进行拦截和调试。
三:调试器拦截实战WinDbg拦截
WinDbg,作为Windows平台上功能强大的非托管调试器,轻松地实现对ilc.exe的拦截。你只需在注册表的HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsNT\CurntVersion\ImageFileExecutionOptions\ilc.exe路径下配置一个Debugger键值,即可完成拦截设置。接下来,我们使用dotnetpublish命令来发布这个程序。在等待片刻后,你会看到WinDbg立即启动并拦截了ilc.exe。然后,你可以通过Ctrl+O来打开你需要下断点的cs文件,例如核心的Compilation方法。在下完断点之后,直接按g键执行,就可以看到相应的调试结果,截图如下:从调试结果中,我们可以清晰地看到Compilation.ctor这个断点被成功命中,同时使用dv命令还能查看各个局部变量的内存地址,这无疑增加了调试的趣味性。虽然这种方式操作起来相对简单直接,但若要更专业地调试C#代码,使用如VisualStudio这样的专业级工具无疑是更合适的选择。毕竟,使用windbg这种非托管调试器来调试C#代码,总给人一种“名不正言不顺”的感觉,不是吗?
接下来,我们再来看看VisualStudio如何拦截.NET程序的执行。在执行dotnetpublish命令时,ilc.exe进程实际上是从.nuget\packages\runtime.win-xmicrosoft.dotnet.il