首页 > 编程语言 >AOT漫谈专题(第一篇): 如何调试C# AOT程序

AOT漫谈专题(第一篇): 如何调试C# AOT程序

时间:2024-10-11 10:45:40浏览次数:7  
标签:__ 10 ConsoleApp1 C# 漫谈 AOT 00007ff6 Program rsp

一:背景

1. 讲故事

上个月接到了二个C# AOT程序的故障分析,发现如今的C# AOT程序也开始在各个领域开枝散叶了,这是一件非常好的事情,本着对这类程序有一个专业的维修态度,开一个系列好好聊一聊吧,当然我这里是漫谈,文章没有先后顺序,先从如何调试开始吧。

二:如何调试AOT程序

1. 一个简单的例子

现在的VS非常强大,新建模板的时候就有一个 Enable native AOT publish 选项,勾完之后就会自动的在项目的 csproj 中添加配置节 <PublishAot>true</PublishAot> ,截图如下:

勾选的好处就是可以在编码阶段就能感知到AOT不允许的东西,方便及时告警,生成完之后参考代码如下:


        static void Main(string[] args)
        {
            var i = 10;
            var j = 20;
            var sum = i + j;
            Console.WriteLine($"{i}+{j}={sum}");
            Console.ReadLine();
        }

代码有了之后,可以借助dotnet cli的 publish 命令直接发布成nativeaot程序,这里先使用 Debug 模式,这样就生成好了一个完整的程序,参考如下:

dotnet publish -r win-x64 -c Debug -o D:\testdump

当然你也可以带上 PublishAot=true 参数,即:

dotnet publish -r win-x64 -c Debug /p:PublishAot=true -o D:\testdump

2. 使用VS调试

用 VS调试非常简单,直接将 ConsoleApp1.exe 拖到 VS 中即可,对,就是拖到VS中,然后在源码的相应位置下个断点,接下来在 ConsoleApp1.exe 上右键 -> Debug -> Start New Instance 即可启动调试,截图如下:

大家看到命中断点了也不要高兴的太早,VS只适合调试Debug模式发布出来的程序,而实际情况大家更多的是以Release模式发布的,这种模式下用 VS 就不能很好的调试了。

为了验证,我们简单的修改一下 Debug 改成 Release 模式,参考如下:


PS D:\skyfly\18.20241010\src\Example\ConsoleApp1> dotnet publish -r win-x64 -c Release -o D:\testdump
  正在确定要还原的项目…
  所有项目均是最新的,无法还原。
  ConsoleApp1 -> D:\skyfly\18.20241010\src\Example\ConsoleApp1\bin\Release\net8.0\win-x64\ConsoleApp1.dll
  ConsoleApp1 -> D:\testdump\

有可用的工作负载更新。有关详细信息,请运行 `dotnet workload list`。

程序运行以来之后,可以看到那些 i,j,sum 都不见了踪影,无语了,截图如下:

3. WinDbg调试

水到绝境是风景,人到绝境是重生。当你绝望的时候一定要知道有WinDbg这种通杀一切之工具的存在,所以这次我们要祭出 WinDbg。

那用 windbg 如何调试呢?非常简单,直接对 Main 方法下断点即可,毕竟AOT程序在 ilc 阶段就已经编译成完整的 机器码,参考命令如下:

bp ConsoleApp1!ConsoleApp1_ConsoleApp1_Program__Main

这个命令的格式如下:

bp 模块名!模块名_命名空间_类名__方法名

参考汇编代码如下:


0:000> uf ConsoleApp1!ConsoleApp1_ConsoleApp1_Program__Main
ConsoleApp1!ConsoleApp1_ConsoleApp1_Program__Main [D:\skyfly\18.20241010\src\Example\ConsoleApp1\Program.cs @ 9]:
    9 00007ff6`e4836d20 4883ec48        sub     rsp,48h
    9 00007ff6`e4836d24 0f57e4          xorps   xmm4,xmm4
    9 00007ff6`e4836d27 0f29642420      movaps  xmmword ptr [rsp+20h],xmm4
    9 00007ff6`e4836d2c 0f29642430      movaps  xmmword ptr [rsp+30h],xmm4
    9 00007ff6`e4836d31 33c0            xor     eax,eax
    9 00007ff6`e4836d33 4889442440      mov     qword ptr [rsp+40h],rax
   10 00007ff6`e4836d38 488d4c2420      lea     rcx,[rsp+20h]
   10 00007ff6`e4836d3d ba02000000      mov     edx,2
   10 00007ff6`e4836d42 41b803000000    mov     r8d,3
   10 00007ff6`e4836d48 e823f10200      call    ConsoleApp1!S_P_CoreLib_System_Runtime_CompilerServices_DefaultInterpolatedStringHandler___ctor (00007ff6`e4865e70)
   10 00007ff6`e4836d4d 488d4c2420      lea     rcx,[rsp+20h]
   10 00007ff6`e4836d52 ba0a000000      mov     edx,0Ah
   10 00007ff6`e4836d57 e8a48e0500      call    ConsoleApp1!S_P_CoreLib_System_Runtime_CompilerServices_DefaultInterpolatedStringHandler__AppendFormatted<Int32> (00007ff6`e488fc00)
   10 00007ff6`e4836d5c 8b4c2430        mov     ecx,dword ptr [rsp+30h]
   10 00007ff6`e4836d60 8b542440        mov     edx,dword ptr [rsp+40h]
   10 00007ff6`e4836d64 3bca            cmp     ecx,edx
   10 00007ff6`e4836d66 0f87c9000000    ja      ConsoleApp1!ConsoleApp1_ConsoleApp1_Program__Main+0x115 (00007ff6`e4836e35)  Branch

ConsoleApp1!ConsoleApp1_ConsoleApp1_Program__Main+0x4c [D:\skyfly\18.20241010\src\Example\ConsoleApp1\Program.cs @ 10]:
   10 00007ff6`e4836d6c 488b442438      mov     rax,qword ptr [rsp+38h]
   10 00007ff6`e4836d71 448bc1          mov     r8d,ecx
   10 00007ff6`e4836d74 4a8d0440        lea     rax,[rax+r8*2]
   10 00007ff6`e4836d78 2bd1            sub     edx,ecx
   10 00007ff6`e4836d7a 83fa01          cmp     edx,1
   10 00007ff6`e4836d7d 721d            jb      ConsoleApp1!ConsoleApp1_ConsoleApp1_Program__Main+0x7c (00007ff6`e4836d9c)  Branch

ConsoleApp1!ConsoleApp1_ConsoleApp1_Program__Main+0x5f [D:\skyfly\18.20241010\src\Example\ConsoleApp1\Program.cs @ 10]:
   10 00007ff6`e4836d7f 488d0d4a180600  lea     rcx,[ConsoleApp1!_Str___206014A4266C2082B9433011FB2991059F972D570A8B3C976E5B2B8DFCFBFC8D (00007ff6`e48985d0)]
   10 00007ff6`e4836d86 4883c10c        add     rcx,0Ch
   10 00007ff6`e4836d8a 0fb711          movzx   edx,word ptr [rcx]
   10 00007ff6`e4836d8d 668910          mov     word ptr [rax],dx
   10 00007ff6`e4836d90 8b4c2430        mov     ecx,dword ptr [rsp+30h]
   10 00007ff6`e4836d94 ffc1            inc     ecx
   10 00007ff6`e4836d96 894c2430        mov     dword ptr [rsp+30h],ecx
   10 00007ff6`e4836d9a eb11            jmp     ConsoleApp1!ConsoleApp1_ConsoleApp1_Program__Main+0x8d (00007ff6`e4836dad)  Branch

ConsoleApp1!ConsoleApp1_ConsoleApp1_Program__Main+0x7c [D:\skyfly\18.20241010\src\Example\ConsoleApp1\Program.cs @ 10]:
   10 00007ff6`e4836d9c 488d4c2420      lea     rcx,[rsp+20h]
   10 00007ff6`e4836da1 488d1528180600  lea     rdx,[ConsoleApp1!_Str___206014A4266C2082B9433011FB2991059F972D570A8B3C976E5B2B8DFCFBFC8D (00007ff6`e48985d0)]
   10 00007ff6`e4836da8 e893f20200      call    ConsoleApp1!S_P_CoreLib_System_Runtime_CompilerServices_DefaultInterpolatedStringHandler__GrowThenCopyString (00007ff6`e4866040)

ConsoleApp1!ConsoleApp1_ConsoleApp1_Program__Main+0x8d [D:\skyfly\18.20241010\src\Example\ConsoleApp1\Program.cs @ 10]:
   10 00007ff6`e4836dad 488d4c2420      lea     rcx,[rsp+20h]
   10 00007ff6`e4836db2 ba14000000      mov     edx,14h
   10 00007ff6`e4836db7 e8448e0500      call    ConsoleApp1!S_P_CoreLib_System_Runtime_CompilerServices_DefaultInterpolatedStringHandler__AppendFormatted<Int32> (00007ff6`e488fc00)
   10 00007ff6`e4836dbc 8b4c2430        mov     ecx,dword ptr [rsp+30h]
   10 00007ff6`e4836dc0 8b542440        mov     edx,dword ptr [rsp+40h]
   10 00007ff6`e4836dc4 3bca            cmp     ecx,edx
   10 00007ff6`e4836dc6 776d            ja      ConsoleApp1!ConsoleApp1_ConsoleApp1_Program__Main+0x115 (00007ff6`e4836e35)  Branch

ConsoleApp1!ConsoleApp1_ConsoleApp1_Program__Main+0xa8 [D:\skyfly\18.20241010\src\Example\ConsoleApp1\Program.cs @ 10]:
   10 00007ff6`e4836dc8 488b442438      mov     rax,qword ptr [rsp+38h]
   10 00007ff6`e4836dcd 448bc1          mov     r8d,ecx
   10 00007ff6`e4836dd0 4a8d0440        lea     rax,[rax+r8*2]
   10 00007ff6`e4836dd4 2bd1            sub     edx,ecx
   10 00007ff6`e4836dd6 83fa01          cmp     edx,1
   10 00007ff6`e4836dd9 721d            jb      ConsoleApp1!ConsoleApp1_ConsoleApp1_Program__Main+0xd8 (00007ff6`e4836df8)  Branch

ConsoleApp1!ConsoleApp1_ConsoleApp1_Program__Main+0xbb [D:\skyfly\18.20241010\src\Example\ConsoleApp1\Program.cs @ 10]:
   10 00007ff6`e4836ddb 488d0dee1f0600  lea     rcx,[ConsoleApp1!_Str___E7DAC261E841E53EB65AC8C2A0E56544DF49C46D71E8002D7764F92C66C4C868 (00007ff6`e4898dd0)]
   10 00007ff6`e4836de2 4883c10c        add     rcx,0Ch
   10 00007ff6`e4836de6 0fb711          movzx   edx,word ptr [rcx]
   10 00007ff6`e4836de9 668910          mov     word ptr [rax],dx
   10 00007ff6`e4836dec 8b4c2430        mov     ecx,dword ptr [rsp+30h]
   10 00007ff6`e4836df0 ffc1            inc     ecx
   10 00007ff6`e4836df2 894c2430        mov     dword ptr [rsp+30h],ecx
   10 00007ff6`e4836df6 eb11            jmp     ConsoleApp1!ConsoleApp1_ConsoleApp1_Program__Main+0xe9 (00007ff6`e4836e09)  Branch

ConsoleApp1!ConsoleApp1_ConsoleApp1_Program__Main+0xd8 [D:\skyfly\18.20241010\src\Example\ConsoleApp1\Program.cs @ 10]:
   10 00007ff6`e4836df8 488d4c2420      lea     rcx,[rsp+20h]
   10 00007ff6`e4836dfd 488d15cc1f0600  lea     rdx,[ConsoleApp1!_Str___E7DAC261E841E53EB65AC8C2A0E56544DF49C46D71E8002D7764F92C66C4C868 (00007ff6`e4898dd0)]
   10 00007ff6`e4836e04 e837f20200      call    ConsoleApp1!S_P_CoreLib_System_Runtime_CompilerServices_DefaultInterpolatedStringHandler__GrowThenCopyString (00007ff6`e4866040)

ConsoleApp1!ConsoleApp1_ConsoleApp1_Program__Main+0xe9 [D:\skyfly\18.20241010\src\Example\ConsoleApp1\Program.cs @ 10]:
   10 00007ff6`e4836e09 488d4c2420      lea     rcx,[rsp+20h]
   10 00007ff6`e4836e0e ba1e000000      mov     edx,1Eh
   10 00007ff6`e4836e13 e8e88d0500      call    ConsoleApp1!S_P_CoreLib_System_Runtime_CompilerServices_DefaultInterpolatedStringHandler__AppendFormatted<Int32> (00007ff6`e488fc00)
   10 00007ff6`e4836e18 488d4c2420      lea     rcx,[rsp+20h]
   10 00007ff6`e4836e1d e8def00200      call    ConsoleApp1!S_P_CoreLib_System_Runtime_CompilerServices_DefaultInterpolatedStringHandler__ToStringAndClear (00007ff6`e4865f00)
   10 00007ff6`e4836e22 488bc8          mov     rcx,rax
   10 00007ff6`e4836e25 e856080000      call    ConsoleApp1!System_Console_System_Console__WriteLine_12 (00007ff6`e4837680)
   13 00007ff6`e4836e2a e831080000      call    ConsoleApp1!System_Console_System_Console__ReadLine (00007ff6`e4837660)
   14 00007ff6`e4836e2f 90              nop
   14 00007ff6`e4836e30 4883c448        add     rsp,48h
   14 00007ff6`e4836e34 c3              ret

仔细观察上面的汇编代码,你会发现 i,j 根本就没有作为栈变量使用,而是直接放到了寄存器中传给了 AppendFormatted 方法。

这里要提醒一点就是 DefaultInterpolatedStringHandler 是 C# 中 string 拼接的一种底层优化实现,所以最后代码被优化成了 Console.WriteLine($"{10}+{20}={30}"); 这样的句子,这也是 Release 的威力所在。

当然 WinDbg 的功能不限于此,后面还有更多牛叉的功能,在系列文章后面再展开吧。

三:总结

工欲善其事必先利其器,对未知知识的探索必然需要一个好的工具,希望本篇给大家带来一些灵感吧。
图片名称

标签:__,10,ConsoleApp1,C#,漫谈,AOT,00007ff6,Program,rsp
From: https://www.cnblogs.com/huangxincheng/p/18457932

相关文章

  • 修复HTTPS升级后出现 Mixed Content: The page at 'https://xxx' was loaded over HTT
    背景由于需要使用摄像头拍照,需要将原来的http升级到https,通过一顿捣鼓,升级成功。不过页面加载出现了问题,具体的提示是说:你的页面是在https环境,但是你访问了一个资源(我这里是iframe,也可能是stylesheet等其他资源),而这个资源是在http环境下的,浏览器不给你这样玩。https只能访问h......
  • 康达新材: 以CRM丰富数字化转型助推业务全面升级
    康达新材料(集团)股份有限公司(简称“康达新材”)成立于1998年,深交所主板上市,公司管理总部位于上海浦东新区,拥有500余人的研发团队,2023年集团总人数超过1700人,产值近28亿元。康达新材主营胶粘剂与特种树脂新材料、显示材料、电磁兼容设备、电源模块技术,多个系列产品性能处于国内......
  • 引领行业数字变革,天翼云出席IDC年度盛典暨颁奖典礼!
    近日,2024IDC中国年度盛典暨颁奖典礼在上海隆重开幕。天翼云出席大会数字工业行业峰会及金融行业峰会,分享了天翼云的智算布局及在行业数字化转型方面的技术探索和实践成果。天翼云全面升级产品及生态矩阵,迈入智能云的新发展阶段。天翼云积极布局智算产业,提供丰富的智能资源供给,打......
  • Oracle中alter table的常用用法
    首发微信公众号:SQL数据库运维原文链接:https://mp.weixin.qq.com/s?__biz=MzI1NTQyNzg3MQ==&mid=2247486440&idx=1&sn=b8a50ce5e993b4ab196ddda705077d95&chksm=ea375f98dd40d68ea079d90ac6084078e8ec9e1a4b1f4cc266fb97976dc2c72f452a61f55850&token=1175589249&la......
  • 2024-10-11 自定义渲染之arco-design-vue table的columns的title ==》使用DOM插入子元
    嗯...不知我没找到arco对应tabletitle的自定义渲染的正确方式 但我已经找了1个小时了,既然没找到就自己插入吧业务场景如下: 给表头插入一个必填的符号*,就这么简单的需求。代码如下:constelements:any=document.querySelectorAll('.arco-table-th-title');elements.f......
  • Leetcode 839. 相似字符串组【附并查集模板】
    1.题目基本信息1.1.题目描述如果交换字符串X中的两个不同位置的字母,使得它和字符串Y相等,那么称X和Y两个字符串相似。如果这两个字符串本身是相等的,那它们也是相似的。例如,”tars”和“rats”是相似的(交换0与2的位置);“rats”和“arts”也是相似的,但是“s......
  • 实现远距离通信 PS304数字接口转发器实现UART转换为I2C、SPI、1Wire等多种数字接口!
    实现远距离通信PS304数字接口转发器实现UART转换为I2C、SPI、1Wire等多种数字接口!PS304多种数字接口物理层协议转发器,能够实现UART转换为I2C、SPI、1Wire等其他数字接口,以实现远距离通信。该转发器具备内嵌磁隔离双电源及辅助增强电源电路、自适应线缆算法和强大灵活的S2S协议......
  • idea数据库图形化窗口连接数据库报错:Driver class ‘com.mysql.cj.jdbc.Driver‘ not
    报错信息在idea中数据库图形化窗口中,创建下图数据库连接点击测试连接后,发生报错:Driverclass'com.mysql.cj.jdbc.Driver'notfoundNodriverfilesprovided.报错界面:原因出现此错误的原因通常是数据库驱动程序尚未下载或未正确配置到IDEA中。解决方案......
  • selenium.comon.exceptionsSessioMotcreatedException: Message: session not created
    这个错误是因为您的ChromeDriver版本不支持当前安装的Chrome浏览器版本。错误信息指出,您的ChromeDriver只支持Chrome版本127,但您当前的Chrome浏览器版本是129.0.6068.90。要解决此问题,可以尝试以下步骤:更新ChromeDriver:下载与您当前Chrome浏览器版本兼容的ChromeDriver。可以......
  • 【C/C++内存管理】
    【知识预告】C/C++内存分布C语言中动态内存管理方式C++内存管理new和delete的实现原理常见面试题内存泄漏1C/C++内存分布intglobalVar=1;staticintstaticGlobalVar=1;voidTest(){ staticintstaticVar=1; intlocalVar=1; intnum1[10]={1,2,3,......