如何用 WinDbg 調試Linux上的 .NET程式

来源:https://www.cnblogs.com/huangxincheng/p/18315571
-Advertisement-
Play Games

一:背景 1. 講故事 最新版本 1.2402.24001.0 的WinDbg真的讓人很興奮,可以將自己偽裝成 GDB 來和遠程的 GDBServer 打通來實現對 Linux 上 .NET程式進行調試,這樣就可以繼續使用熟悉的WinDbg 命令,在這個版本中我覺得 WinDbg 不再是 WinDb ...


一:背景

1. 講故事

最新版本 1.2402.24001.0 的WinDbg真的讓人很興奮,可以將自己偽裝成 GDB 來和遠程的 GDBServer 打通來實現對 Linux 上 .NET程式進行調試,這樣就可以繼續使用熟悉的WinDbg 命令,在這個版本中我覺得 WinDbg 不再是 WinDbg,而是 XDbg 了,畫個簡圖如下:

簡圖有了,接下來就要付出實踐了。

二:實操 Linux 上 .NET調試

1. 測試程式

本想在 CentOS7 上安裝 .NET8,不大好裝,這裡就用一個現存的 .NETCore 3.1 吧,測試代碼如下:


    internal class Program
    {
        static void Main(string[] args)
        {
            while (true)
            {
                Console.WriteLine($"{DateTime.Now},tid={Thread.CurrentThread.ManagedThreadId}");
                Thread.Sleep(1000);
            }
        }
    }

代碼非常簡單,就是1s輸出一條記錄,接下來編譯成x64部署到 Centos7 上。


[root@localhost data]# ls
ConsoleApp7  ConsoleApp7.deps.json  ConsoleApp7.dll  ConsoleApp7.pdb  ConsoleApp7.runtimeconfig.json

2. 安裝GDBServer

在 linux 上安裝 gdbserver 比較簡單,使用 yum 安裝即可 yum install gdb-gdbserver ,輸出如下:


[root@localhost data]# yum install gdb-gdbserver
Loaded plugins: fastestmirror, langpacks
Loading mirror speeds from cached hostfile
 * base: mirror-hk.koddos.net
 * centos-sclo-rh: ftp.sjtu.edu.cn
 * centos-sclo-sclo: ftp.sjtu.edu.cn
 * epel: mirror.hoster.kz
 * extras: ftp.sjtu.edu.cn
 * updates: mirror-hk.koddos.net
Package gdb-gdbserver-7.6.1-120.el7.x86_64 already installed and latest version
Nothing to do
[root@localhost data]# gdbserver –version
Usage:	gdbserver [OPTIONS] COMM PROG [ARGS ...]
	gdbserver [OPTIONS] --attach COMM PID
	gdbserver [OPTIONS] --multi COMM

COMM may either be a tty device (for serial debugging), or 
HOST:PORT to listen for a TCP connection.

Options:
  --debug               Enable general debugging output.
  --remote-debug        Enable remote protocol debugging output.
  --version             Display version information and exit.
  --wrapper WRAPPER --  Run WRAPPER to start new programs.
  --once                Exit after the first connection has closed.

安裝好之後,接下來用 gdbserver 來啟動我們的程式,並啟動調試埠為 1234,參考如下:


[root@localhost data]# gdbserver 192.168.128.130:1234 dotnet ConsoleApp7.dll
Process dotnet created; pid = 3643
Listening on port 1234

3. 使用 windbg 連接

打開Windbg後,選擇 Connect to remote debugger 選項, 在連接字元串中填入 gdb:server=192.168.128.130,port=1234 即可,截圖如下:

連接好之後,會有一個初始中斷,直接輸入g就好了,輸出如下:


64-bit machine not using 64-bit API

************* Path validation summary **************
Response                         Time (ms)     Location
Deferred                                       SRV*C:\mysymbols*https://msdl.microsoft.com/download/symbols
Symbol search path is: SRV*C:\mysymbols*https://msdl.microsoft.com/download/symbols
Executable search path is: 
Unknown System Version 0 UP Free x64
System Uptime: not available
Process Uptime: not available
Reloading current modules
ModLoad: 00005555`55554000 00005555`555770cd   /usr/share/dotnet/dotnet
ModLoad: 00007fff`f7bbf000 00007fff`f7dda488   /lib64/libpthread.so.0
ModLoad: 00007fff`f79bb000 00007fff`f7bbe130   /lib64/libdl.so.2
ModLoad: 00007fff`f76b3000 00007fff`f79ba420   /lib64/libstdc++.so.6
ModLoad: 00007fff`f73b1000 00007fff`f76b2138   /lib64/libm.so.6
ModLoad: 00007fff`f719b000 00007fff`f73b0400   /lib64/libgcc_s.so.1
ModLoad: 00007fff`f6dcd000 00007fff`f719a200   /lib64/libc.so.6
ModLoad: 00007fff`f7ddb000 00007fff`f7ffe150   /lib64/ld-linux-x86-64.so.2
ModLoad: 00007fff`f7f72000 00007fff`f7fda288   /usr/share/dotnet/host/fxr/6.0.26/libhostfxr.so
ModLoad: 00007fff`f6b7c000 00007fff`f6dcc3b0   /usr/share/dotnet/shared/Microsoft.NETCore.App/3.1.32/libhostpolicy.so
ModLoad: 00007fff`f63e7000 00007fff`f6b7bac8   /usr/share/dotnet/shared/Microsoft.NETCore.App/3.1.32/libcoreclr.so
ModLoad: 00007fff`f61df000 00007fff`f63e6c38   /lib64/librt.so.1
ModLoad: 00007fff`f57d2000 00007fff`f59dd8c0   /lib64/libnuma.so.1
ModLoad: 00007fff`f3142000 00007fff`f3413dac   /usr/share/dotnet/shared/Microsoft.NETCore.App/3.1.32/libclrjit.so
ModLoad: 00007fff`f2f31000 00007fff`f3141468   /usr/share/dotnet/shared/Microsoft.NETCore.App/3.1.32/System.Native.so
ModLoad: 00007fff`f2d26000 00007fff`f2f30488   /usr/share/dotnet/shared/Microsoft.NETCore.App/3.1.32/System.Globalization.Native.so
ModLoad: 00007fff`f29ad000 00007fff`f2d25fe0   /lib64/libicuuc.so.50
ModLoad: 00007fff`f13da000 00007fff`f29ac030   /lib64/libicudata.so.50
ModLoad: 00007fff`f0fdb000 00007fff`f13d9340   /lib64/libicui18n.so.50
...................
ReadVirtual() failed in GetXStateConfiguration() first read attempt (error == 0.)
Unable to load image /lib64/libpthread.so.0, Win32 error 0n2
*** WARNING: Unable to verify timestamp for /lib64/libpthread.so.0
Unable to load image /usr/share/dotnet/shared/Microsoft.NETCore.App/3.1.32/libcoreclr.so, Win32 error 0n2
*** WARNING: Unable to verify timestamp for /usr/share/dotnet/shared/Microsoft.NETCore.App/3.1.32/libcoreclr.so
libpthread_so!_pthread_cond_timedwait+0x132:
00007fff`f7bcade2 4989c6          mov     r14,rax
0:000> g

有些人可能會好奇,為什麼 WinDbg 能偽裝成 GDB 來和 GDBServer 來通訊,這其實得益於 WinDbg 是一個宿主,它可以被很多外來的插件無線擴容自己的功能,這和 Linux 的分而治之恰恰相反。。。

接下來可以用 .chain 命令觀察插件列表,其中的 GDBServerCompositionELFBinComposition 讓這項功能得到實現。


0:000> .chain
Extension DLL chain:
    GDBServerComposition: image 10.0.27553.1004, API 0.0.0, 
        [path: C:\Program Files\WindowsApps\Microsoft.WinDbg_1.2402.24001.0_x64__8wekyb3d8bbwe\amd64\winext\GDBServerComposition.dll]
    ELFBinComposition: image 10.0.27553.1004, API 0.0.0, 
        [path: C:\Program Files\WindowsApps\Microsoft.WinDbg_1.2402.24001.0_x64__8wekyb3d8bbwe\amd64\winext\ELFBinComposition.dll]
    dbghelp: image 10.0.27553.1004, API 10.0.6, 
        [path: C:\Program Files\WindowsApps\Microsoft.WinDbg_1.2402.24001.0_x64__8wekyb3d8bbwe\amd64\dbghelp.dll]
    uext: image 10.0.27553.1004, API 1.0.0, 
        [path: C:\Program Files\WindowsApps\Microsoft.WinDbg_1.2402.24001.0_x64__8wekyb3d8bbwe\amd64\winext\uext.dll]

接下來就可以做驗證了,研究 coreclr 源碼,你會發現在 Linux 上 .NET 的 Sleep 函數是藉助於底層的 pthread_cond_timedwait 函數,Linux並沒有提供類似Windows 的SleepEx這樣的系統調用,這就比較坑了,參考如下:


PAL_ERROR CPalSynchronizationManager::ThreadNativeWait(
    ThreadNativeWaitData* ptnwdNativeWaitData,
    DWORD dwTimeout,
    ThreadWakeupReason* ptwrWakeupReason,
    DWORD* pdwSignaledObject)
{
	//...
    while (FALSE == ptnwdNativeWaitData->iPred)
    {
        if (INFINITE == dwTimeout)
        {
            iWaitRet = pthread_cond_wait(&ptnwdNativeWaitData->cond,
                &ptnwdNativeWaitData->mutex);
        }
        else
        {
            iWaitRet = pthread_cond_timedwait(&ptnwdNativeWaitData->cond,
                &ptnwdNativeWaitData->mutex,
                &tsAbsTmo);
        }
    }
	//...
}

不管怎麼說,我們用 WinDbg 調試 Linux 的 .NET 程式算是大功告成了。

三:總結

現在的 WinDbg 早已今非昔比,全平臺(MacOs,Linux,Windows) 通吃,這也得益於 Windbg 是一個宿主模式的架構體系,給 WinDbg 點贊!
圖片名稱


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 據最新數據顯示,京東員工總數已接近52萬人。這一數字是阿裡巴巴的2倍、騰訊的5倍、拼多多的30倍。對比其他互聯網公司普遍以降本增效為主基調,京東的員工數量反而增加。過去一年增加了66445人,近兩年總計增加13萬人。 ...
  • 正文 今天是 7 月 21 號,0721,然後柚子社入駐 B 站了,開始我以為是整活,結果發現是真的。草,這下 0721 真成柚子廚紀念日了。有點難綳又有點好笑。 睡覺的一天。我原以為 14:30 睡到 16:30 差不多了,結果一覺睡到 17:30。草。我想著周末,也就沒設鬧鐘了,睡到什麼時候隨緣 ...
  • 服務遠程調用-Open Feign-微服務核心組件【分散式微服務筆記04】 服務遠程調用-Open Feign Open Feign最大的價值就是,在不同的微服務中可以相互調用對方的介面 基本介紹 OpenFeign 是個聲明式WebService 客戶端,使用OpenFeign 讓編寫Web Se ...
  • 大家好,我是 Java陳序員。 現在的自媒體可謂是十分火熱,各個視頻剪輯軟體提供了文本生成語音的功能,但大多都是千篇一律的音色,比如“這個男人叫小帥”。 如果你想做自媒體,既不想錄製自己的語音,又想自己的視頻配音與他人不同,可以考慮使用大模型來訓練生成自己的語音。 今天,給大家介紹一個開源免費的文本 ...
  • 一次偶然看到了國外某機構針對 PHP 周邊生態框架及擴展的性能測試排行榜,看到 Workerman 竟遙遙領先 Swoole。 ...
  • [NOIP2016 提高組] 玩具謎題 題目背景 NOIP2016 提高組 D1T1 題目描述 小南有一套可愛的玩具小人,它們各有不同的職業。 有一天,這些玩具小人把小南的眼鏡藏了起來。小南發現玩具小人們圍成了一個圈,它們有的面朝圈內,有的面朝圈外。如下圖: 這時 singer 告訴小南一個謎題:“ ...
  • 力扣 704.二分查找 給定一個n個元素的有序的(升序)整型數組nums和一個目標值target,寫一個函數搜索nums中的target,如果目標值存在返回小標,否則返回-1。 思路:二分查找法,定義左右邊界[left,right);不斷取中值縮小查找範圍。 class Solution{ publ ...
  • 前言 本人在配置VsCode C++開發環境時,查看了很多的博客,內容參差不齊,尤其是關於json文件的配置,繞得人頭很暈,最終還是通過閱讀官方文檔,結合部分博客的指引,完成了環境的配置,在此記錄本人的配置過程,希望能幫助到大家。事先聲明,本文的內容大量引自Vs Code官方的文章:https:// ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...