從 WinDbg 角度理解 .NET7 的AOT玩法

一:背景

1.講故事

前幾天 B 站上有位朋友讓我從高級調試的角度來解讀下 .NET7 新出來的 AOT,畢竟這東西是新的,所以這一篇我就簡單摸索一下。

二:AOT 的幾個問題

1. 如何在 .NET7 中開啟 AOT 功能

在 .NET7 中開啟 AOT 非常方便,先來段測試代碼。

internal?class?Program{static?void?Main(string[]?args){Console.WriteLine("hello?world!");Debugger.Break();}}

然后在項目配置上新增 <PublishAot>true</PublishAot> 節點,如下輸出:

<Project?Sdk="Microsoft.NET.Sdk"><PropertyGroup><OutputType>Exe</OutputType><TargetFramework>net7.0</TargetFramework><ImplicitUsings>enable</ImplicitUsings><Nullable>enable</Nullable><PublishAot>true</PublishAot></PropertyGroup>
</Project>

接下來在項目中右鍵選擇 發布,選擇一個輸出地,這樣一個 AOT 程序就完成了。

115f224eae1adab52bdf626a2ecfd08d.png

2. SOS 可以調試 AOT 程序嗎

這是很多朋友關心的話題,我們都知道 SOS 是用來撬開 CoreCLR 的,只要能看到 CoreCLR.dll,那 SOS 就能用,接下來用 WinDbg 附加到 ConsoleApp2.exe 上,使用 lm 觀察。

0:000>?lm
start?????????????end?????????????????module?name
00007ff6`11680000?00007ff6`1196f000???ConsoleApp2?C?(private?pdb?symbols)??C:\test\ConsoleApp2.pdb
00007ffe`692b0000?00007ffe`692c3000???kernel_appcore???(deferred)?????????????
00007ffe`6b3e0000?00007ffe`6b47d000???msvcp_win???(deferred)?????????????
00007ffe`6b480000?00007ffe`6b4ff000???bcryptPrimitives???(deferred)?????????????
00007ffe`6b660000?00007ffe`6b687000???bcrypt?????(deferred)?????????????
00007ffe`6b690000?00007ffe`6b6b2000???win32u?????(deferred)?????????????
00007ffe`6b720000?00007ffe`6b82a000???gdi32full???(deferred)?????????????
00007ffe`6b830000?00007ffe`6b930000???ucrtbase???(deferred)?????????????
00007ffe`6b9e0000?00007ffe`6bca7000???KERNELBASE???(deferred)?????????????
00007ffe`6bcb0000?00007ffe`6bd5a000???ADVAPI32???(deferred)?????????????
00007ffe`6be50000?00007ffe`6be7a000???GDI32??????(deferred)?????????????
00007ffe`6be80000?00007ffe`6bf1b000???sechost????(deferred)?????????????
00007ffe`6c180000?00007ffe`6c2a3000???RPCRT4?????(deferred)?????????????
00007ffe`6c440000?00007ffe`6c470000???IMM32??????(deferred)?????????????
00007ffe`6c600000?00007ffe`6c729000???ole32??????(deferred)?????????????
00007ffe`6c730000?00007ffe`6c7ce000???msvcrt?????(deferred)?????????????
00007ffe`6cc50000?00007ffe`6cfa4000???combase????(deferred)?????????????
00007ffe`6d160000?00007ffe`6d300000???USER32?????(deferred)?????????????
00007ffe`6d410000?00007ffe`6d4cd000???KERNEL32???(deferred)?????????????
00007ffe`6dc50000?00007ffe`6de44000???ntdll??????(pdb?symbols)??????????c:\mysymbols\ntdll.pdb\63E12347526A46144B98F8CF61CDED791\ntdll.pdb

從上面的輸出中驚訝的發現,居然沒有 clrjit.dllcoreclr.dll,前者沒有很好理解,后者沒有就很奇怪了。。。

既然沒看到 coreclr.dll 這個動態鏈接庫,那至少目前用 sos 肯定是無法調試的,即使你強制加載也會報錯。

0:000>?.load??C:\Users\Administrator\.dotnet\sos64\sos.dll
0:000>?!t
Failed?to?find?runtime?module?(coreclr.dll?or?clr.dll?or?libcoreclr.so),?0x80004002
Extension?commands?need?it?in?order?to?have?something?to?do.
For?more?information?see?https://go.microsoft.com/fwlink/?linkid=2135652

到這里我的個人結論是:目前SOS無法對這類程序進行調試,如果大家用在生產上出現各種內存暴漲CPU爆高問題,就要當心了。

3. AOT 真的沒有 CoreCLR 嗎

其實仔細想一想,這是不可能的,C# 的出發點就是作為一門托管語言而存在,再怎么發展也不會忘記這個初衷,所謂不忘初心,方得始終。

我們回過頭看下 ConsoleApp.exe 這個程序,有沒有發現,它居然有 3M 大小。

de983be422b9dccdc7668340c79827d4.png

聰明的朋友應該猜到了,對,就是把 CoreCLR 打包到 exe 中了,這個太牛了,那怎么驗證呢?可以用 IDA 打開一下。

14fcaf547a2c8f56e32355be3b9e6f9c.png

從圖中可以清晰的看到各種 gc_heap 相關的函數,這也驗證了為什么一個簡簡單單的 ConsoleApp.exe 有這么大Size的原因。

4. 真的無法調試 AOT 程序嗎

在 Windows 平臺上就沒有 WinDbg 不能調試的程序,所以 AOT 程序自然不在話下,畢竟按托管不行,大不了按非托管調試,這里我們舉一個 GC.Collect() 的源碼調試吧。

  1. 一段簡單的測試代碼。

internal?class?Program{static?void?Main(string[]?args){Debugger.Break();GC.Collect();}}
  1. 下斷點

熟悉 GC 的朋友應該知道我只需用 bp coreclr!WKS::GCHeap::GarbageCollect 下一個斷點就可以了,但剛才我也說了,內存中并沒有 coreclr 模塊,下面的 x 寫法肯定會報錯。

0:000>?x?coreclr!WKS::GCHeap::GarbageCollect^?Couldn't?resolve?'x?coreclr'

那怎么下呢?先輸個 k 觀察下調用棧有沒有什么新發現。

0:000>?k#?Child-SP??????????RetAddr???????????????Call?Site
00?00000011`5e52f628?00007ff6`7f288c5a?????ConsoleApp2!RhDebugBreak+0x2?[D:\a\_work\1\s\src\coreclr\nativeaot\Runtime\MiscHelpers.cpp?@?45]?
01?00000011`5e52f630?00007ff6`7f2f0e28?????ConsoleApp2!S_P_CoreLib_System_Diagnostics_Debugger__Break+0x3a?[/_/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Diagnostics/Debugger.cs?@?17]?
02?00000011`5e52f6c0?00007ff6`7f1fe37e?????ConsoleApp2!ConsoleApp2__Module___StartupCodeMain+0x118
03?00000011`5e52f720?00007ff6`7f1f9540?????ConsoleApp2!wmain+0xae?[D:\a\_work\1\s\src\coreclr\nativeaot\Bootstrap\main.cpp?@?205]?
04?(Inline?Function)?--------`--------?????ConsoleApp2!invoke_main+0x22?[D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl?@?90]?
05?00000011`5e52f770?00007ffe`6d426fd4?????ConsoleApp2!__scrt_common_main_seh+0x10c?[D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl?@?288]?
06?00000011`5e52f7b0?00007ffe`6dc9cec1?????KERNEL32!BaseThreadInitThunk+0x14
07?00000011`5e52f7e0?00000000`00000000?????ntdll!RtlUserThreadStart+0x21

我去,int 3 函數也換了,成了 ConsoleApp2!RhDebugBreak+0x2,不過也能看出來,應該將 coreclr 改成 ConsoleApp2 即可,輸出如下:

0:000>?bp?ConsoleApp2!WKS::GCHeap::GarbageCollect
breakpoint?0?redefined
0:000>?g
Breakpoint?0?hit
ConsoleApp2!WKS::GCHeap::GarbageCollect:
00007ff6`7f1a9410?48894c2408??????mov?????qword?ptr?[rsp+8],rcx?ss:00000011`5e52f5f0=0000000000000000

源碼也看的清清楚楚,路徑也是在 gc 目錄下。如下圖所示:

0ad8d822cb3dcdc68ef9ba614432a64a.png

4. AOT 的實現源碼在哪里

觀察剛才的線程棧中的 D:\a\_work\1\s\src\coreclr\nativeaot\Bootstrap\main.cpp 可以發現,新增了一個名為 nativeaot 的目錄,這在 .NET 6 的 coreclr 源碼中是沒有的。

47029b5a90fd84f6fbbbe900e9883da5.png

如果有感興趣的朋友,可以研究下源碼。

三:總結

總的來說,AOT 目前還是一個雛形階段,大家慎用吧,一旦出了問題,可不好事后調試哦,希望后續加強對 SOS 的支持。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/281201.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/281201.shtml
英文地址,請注明出處:http://en.pswp.cn/news/281201.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

.NET Core C#系列之XiaoFeng.ToCast萬能類型轉換器

數據類型相互轉換如&#xff1a;字符串轉整型&#xff0c;字符串轉日期首先要引用 XiaoFeng命名空間下邊三個擴展方法 就是類型轉換的方法最常用的就是 ToCast<T>方法/// <summary> /// 類型相互轉換 /// </summary> /// <typeparam name"T">…

利用 Git OpenSSH 查看/生成 本機 ssh 公鑰

查看本機公鑰 本機公鑰文件一般用戶目錄下的.ssh文件夾&#xff0c;文件夾下有三個文件&#xff0c;分別是 id_rsa 私鑰密碼id_rsa.pub 公鑰內容known_hosts 允許的host地址 使用文本編輯器查看文件id_rsa.pub文件即可 或者使用cat命令查看 # 任意位置打開 Git bash cd ~/.…

高斯消元法

有點線代的知識&#xff1a; const double EPS 1e-8; typedef vector<double> vec; typedef vector<vec> mat; //Ax b vec gauss_jordan(const mat &A, const vec &b) {int n A.size();mat B(n,vec(n1)); //定義大小for(int i0;i < n;i)for(int j0…

判斷對象是否存在某個屬性

JavaScript判斷對象是否存在某個屬性或者方法&#xff0c;常用方法有兩種hasOwnProperty和in hasOwnProperty是Object原型對象上的一個方法&#xff0c;用來判斷對象自身屬性中是否具有指定的屬性。 這個方法可以用來檢測一個對象是否含有特定的自身屬性&#xff1b;和 in 運…

【PPT】適配器模式 和 橋接模式

【PPT】適配器模式 和 橋接模式目錄【PPT】適配器模式 和 橋接模式一、PPT 截圖1.0、封面和目錄1.1、設計模式概述1.2、結構型模式特點1.3、適配器模式1.4、橋接模式二、參考資料及 PPT 獲取方法獨立觀察員 2022 年 11 月 15 日為之前公司準備的分享PPT&#xff0c;后來沒用上。…

Flask 【第七篇】Flask中的wtforms使用

一、簡單介紹flask中的wtforms WTForms是一個支持多個web框架的form組件&#xff0c;主要用于對用戶請求數據進行驗證。 安裝&#xff1a; pip3 install wtforms 二、簡單使用wtforms組件 1、用戶登錄 具體代碼&#xff1a; from flask import Flask,render_template,request,…

CSS自定義滾動條樣式

css通過滾動條偽類來修改滾動條樣式&#xff0c;偽類名稱如下 ::-webkit-scrollbar 滾動條整體部分 ::-webkit-scrollbar-track 滾動條軌道&#xff08;里面裝有滑塊 thumb&#xff09; ::-webkit-scrollbar-thumb 滾動條滑塊 ::-webkit-scrollbar-button 滾動條軌道兩端按鈕 …

為了避免內存攻擊,美國國家安全局提倡Rust、C#、Go、Java、Ruby 和 Swift,但將 C 和 C++ 置于一邊...

本文翻譯自兩篇文章&#xff0c;第一篇是對美國國家安全局在“軟件內存安全”網絡安全信息表的解讀&#xff0c;第二篇是普及什么是內存安全&#xff0c;為什么它很重要&#xff1f;第一篇 為了避免內存攻擊&#xff0c;美國國家安全局提倡Rust、C#、Go、Java、Ruby 和 Swift&a…

自學python(一)

一、入門儀式 學習一門新語言必不可少的一件事&#xff1a; print("Hello world!")二、基礎知識 1、注釋&#xff1a; 單行注釋&#xff1a; 1 print("Hello world!") #輸出Hello world! 多行注釋&#xff1a; 這是多行注釋 這是多行注釋 這是多行注釋…

.NET周報【11月第2期 2022-11-15】

國內文章統一的開發平臺.NET 7正式發布https://www.cnblogs.com/shanyou/archive/2022/11/09/16871945.html在 2020 年規劃的.NET 5功能終于在.NET 7 完成了&#xff0c;為微軟和社區一起為多年來將不同的開發產品統一起來的努力加冕&#xff0c;未來只有一個.NET, 回顧.NET 20…

如何像使用AspNetCore中的Controllers 和 Actions一樣處理MQTT消息

在物聯網項目中&#xff0c; 處理MQTT的topic時費工費力&#xff0c; 代碼一團亂&#xff0c; 什么才是最好的姿勢&#xff1f;這里面我們極力介紹 MQTTnet.AspNetCore.Routing 項目&#xff0c;MQTTnet AspNetCore Routing 是https://github.com/Atlas-LiftTech/MQTTnet.AspN…

chrome 懸停大圖插件_Google Chrome瀏覽器的懸停卡:我不想要的我最喜歡的新東西

chrome 懸停大圖插件If you only have a handful of open tabs in Google Chrome, it’s easy to tell what they are. But as you start to collect more tabs (or make the window smaller), it gets harder. That’s where Hover Cards come in. 如果您在Google Chrome瀏覽器…

GitHub Codespaces 安裝 .NET 7

本文主要介紹如何在 GitHub Codespaces 這個云上 IDE 環境中安裝 .NET 7背景GitHub 的 Codespaces 可以讓我們隨時隨地編寫代碼&#xff0c;一些簡單的修改也非常方便快捷。特別是 .NET 7 發布后&#xff0c;一些可以直接升級的小項目只需要更改配置就可以了&#xff0c;我們可…

chrome怎么隱藏瀏覽器_如何使用Google Chrome的隱藏閱讀器模式

chrome怎么隱藏瀏覽器Chrome 75 has a hidden “Reader” mode that strips web pages down to the bare minimum to make them easier to, well, read. But it’s not enabled by default—here’s how to get it now. Chrome 75具有隱藏的“閱讀器”模式&#xff0c;可將網頁…

angularjs中使用swiper時不起作用,最后出現空白位

controller.js中定義swipers指令&#xff1a; var moduleCtrl angular.module(newscontroller,[infinite-scroll,ngTouch,news.service]) .directive(swipers,swipers); swipers.$inject [$timeout]; function swipers($timeout) {return {restrict: "EA",scope: {…

使用Jupyter記事本記錄和制作.NET可視化筆記

前言&#xff1a;對于記錄筆記的工具特別多&#xff0c;不過對于程序員來說&#xff0c;記錄筆記程序代碼運行結果演示可以同時存在&#xff0c;無疑會極大增加我們的筆記的可讀性和體驗感。以前在寫python的時候&#xff0c;使用jupyter的體驗很好&#xff0c;所以此處做一個基…

火狐上如何使用谷歌翻譯插件_將Google翻譯功能添加到Firefox

火狐上如何使用谷歌翻譯插件Are you looking for a quick no-fuss way to translate webpages? Then you will want to take a good look at the Translate extension for Firefox. 您是否正在尋找一種快速簡便的方法來翻譯網頁&#xff1f; 然后&#xff0c;您將需要很好地了…

Android 4.X 系統加載 so 失敗的原因分析

1 so 加載過程 so 加載的過程可以參考小米的系統工程師的文章loadLibrary動態庫加載過程分析 2 問題分析 2.1 問題 年前項目里新加了一個 so庫&#xff0c;但發現native 方法的找不到的 crash 好多&#xff0c;好些都是報了java.lang.unsatisfiedlinkerror native method not f…

桌面顯示激活windows_愚蠢的怪胎技巧:如何在桌面上顯示Windows版本

桌面顯示激活windowsHave you ever noticed during all the beta releases of Windows, there’s always a Windows version on the desktop in the lower right-hand corner? Here’s how that “feature” is enabled or disabled. 您是否曾經在Windows的所有beta版本中都注…

服務網格:限流保護 (上)

背景限流是服務治理中保護服務的重要手段之一&#xff0c;也是最直接有效的手段&#xff0c;它可以保護服務不被瞬間的大流量沖垮&#xff0c;類似電路中的“保險絲”。在服務上線前&#xff0c;我們都會對服務進行基準測試&#xff0c;來了解可通過的最大“電流”。上面所說的…