一:背景 1. 讲故事 上篇聊到了 C#程序编译成Native代码 的宏观过程,有粉丝朋友提了一个问题,能不能在 dotnet publish 发布的过程中对AOT编译器拦截进行源码级调试,这是一个好问题,也是深度研究的必经之路,这篇我们就来分享下吧。 二:托管和非托管调试器 1. 调试器介绍 相信
上篇文章介绍了C#程序编译成Native代码的宏观过程。有粉丝朋友提出了一个问题:是否能够在dotnet publish发布的过程中对AOT编译器进行源码级调试? 这是一个极具挑战性的问题,也是深度研究的必经之路。在本文中,我们将分享如何实现这一过程。
上篇文章中我们讨论了C#程序编译成Native代码的宏观过程。其中有一位粉丝朋友提出了一个问题:在dotnet publish发布的过程中是否能对AOT编译器进行源码级调试?这是一个极具挑战性的问题,也是深度研究的必经之路。在本文中,我们将分享如何实现这一过程。
大家都知道AOT Compiler (ilc.exe) 是用C#代码写的,因此它是一个托管程序。托管程序的调试有两种调试器:
总的来说,各有利弊。接下来,我们将通过Visual Studio和Windbg实现各自的拦截。
作为Windows平台上非托管调试器的代表,使用它来劫持ilc.exe非常方便。只需在注册表的HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\ilc.exe下配置Debugger键值即可。接下来使用dotnet publish发布程序,稍等片刻,Windbg将立即启动拦截ilc.exe,然后通过ctrl+o打开需要下断点的cs文件,如核心的Compilation方法。Windbg的使用虽然简单粗暴,但用非托管调试器调试C#总显得不够规范,更好的方式应该是使用专业级的Visual Studio。
上一篇文章谈到,执行dotnet publish调用的ilc.exe来自目录.nuget\packages\runtime.win-x64.microsoft.dotnet.ilcompiler\8.0.8\tools。为了使用托管调试器,我们将ilc.sln项目手工编译出一个ilc.exe,然后将其替换原有的ilc.exe。ilc提供了一个--waitfordebugger参数,通过Console.ReadLine让程序暂停,好让你用VS去Attach。然而,在手工编译的ilc.exe上使用Console.ReadLine貌似拦不住,因此需要稍作修改。重新编译项目,将生成目录runtime\artifacts\bin\coreclr\windows.x64.Debug\ilc\net8.0下的所有文件复制到.nugut目录下,一切准备就绪后使用dotnet publish重新发布程序,从cmd输出中可以看到正在等待attach附加。在VS菜单上Debug -> Attach to Process到我们的ilc.exe进程,可以看到命中了断点。
每一次AOT编译之前在native目录下都会有一个xxx.ilc.rsp,这个文件是AOT Compiler的输入来源。因此我们可以将它作为ilc.sln项目的启动参数。将@xxx.ilc.rsp文件放到ILCompiler项目的command line中,配置好之后可以轻松成功调试。
以劫持的方式对AOT Compiler自身进行源码级调试,这本身就是一个极具意义的话题。不断的介入Compiler编译的各个阶段,相信能给大家深度学习AOT提供了一些不同以往的手段。
棋迹软件库app 官方版正版下载 3.0 11.07 MB
下载
湘ICP备2022002427号-10湘公网安备:43070202000427号
© 2013~2019 haote.com 好特网