溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

如何為WinDbg編寫ClrMD插件

發(fā)布時(shí)間:2021-12-22 16:21:48 來源:億速云 閱讀:130 作者:柒染 欄目:網(wǎng)絡(luò)安全

這篇文章給大家介紹如何為WinDbg編寫ClrMD插件,內(nèi)容非常詳細(xì),感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。

當(dāng)遷移到Linux時(shí),由于LLDB是Linux上.NET網(wǎng)絡(luò)核心的通用調(diào)試器,因此我決定編寫一個(gè)兼容層,以便能夠在新環(huán)境中加載擴(kuò)展。

什么是ClrMD插件

如何創(chuàng)建一個(gè)適用于WinDbg和LLDB的擴(kuò)展?第一步仍然是創(chuàng)建一個(gè)新的類庫項(xiàng)目。無論是.NET Framework和.NET Standard都可以,但有些事情需要注意:

1.如果選擇.NET Framework,請確保不要使用與.NET Core不兼容的任何功能(例如AppDomain),否則您將無法在LLDB中運(yùn)行擴(kuò)展;

2.如果選擇.NET Standard,請記住發(fā)布項(xiàng)目以將所有依賴項(xiàng)包含在一個(gè)文件夾中,因?yàn)樵诰幾g時(shí)默認(rèn)情況下不會(huì)這樣做

創(chuàng)建項(xiàng)目后,添加對ClrMDExports nuget包的引用。它會(huì)自動(dòng)將ClrMD和UnmanagedExports.Repack作為依賴項(xiàng)。UnmanagedExports.Repack是UnmanagedExports的一個(gè)分支,它增加了與.NET    Framework 4.7+和.NET Standard的兼容性,并支持PackageReference。

請注意,新的Init.cs文件將添加到您的項(xiàng)目中(如果您使用包引用,則不應(yīng)該看到它)。不要對此文件進(jìn)行任何更改。每次更新nuget包時(shí)都會(huì)被覆蓋。

Init文件負(fù)責(zé)導(dǎo)出WinDbg所需的DebugExtensionInitialize方法,并設(shè)置所有內(nèi)容,只要依賴項(xiàng)與擴(kuò)展位于相同的文件夾中,就可以正確加載它們。

下一步是添加自定義命令。您需要為每個(gè)命令創(chuàng)建一個(gè)靜態(tài)方法,并使用以下簽名:

public static void HelloWorld(IntPtr client, [MarshalAs(UnmanagedType.LPStr)] string args)
{
}

然后使用UnmanagedExports附帶的DllExport屬性裝飾它。您可以使用ExportName屬性的參數(shù)來定義WinDbg / LLDB可見的命令名稱。請記住,名稱區(qū)分大小寫!

[DllExport("helloworld")]
public static void HelloWorld(IntPtr client, [MarshalAs(UnmanagedType.LPStr)] string args)
{
}

在該方法中,您應(yīng)該只調(diào)用DebuggingContext.Execute由ClrMDExports提供的方法。它接受clientargs作為參數(shù)的值,以及帶有(ClrRuntime runtime, string args)簽名的另一個(gè)靜態(tài)方法的委托。在靜態(tài)回調(diào)方法中,實(shí)現(xiàn)命令。

[DllExport("helloworld")]
public static void HelloWorld(IntPtr client, [MarshalAs(UnmanagedType.LPStr)] string args)
{
    DebuggingContext.Execute(client, args, HelloWorld);
}

private static void HelloWorld(ClrRuntime runtime, string args)
{
    Console.WriteLine("The first 10 types on the heap are: ");

    foreach (var type in runtime.Heap.EnumerateTypes().Take(10))
    {
        Console.WriteLine(type);
    }
}

為方便起見,控制臺(tái)輸出會(huì)自動(dòng)重定向到調(diào)試器。

您可以直接在WinDbg中加載和使用您的擴(kuò)展:

如何為WinDbg編寫ClrMD插件

在Linux上運(yùn)行LLDB

由于擴(kuò)展是為WinDbg API編寫的,因此無法直接加載到LLDB中。相反,    我編寫了一個(gè)進(jìn)行翻譯的插件。

首先,下載最新版本的LLDB-LoadManaged元插件并將其解壓縮到一個(gè)文件夾中。

然后啟動(dòng)LLDB并附加到目標(biāo):

./lldb -c dump.dmp

接下來,加載元插件:

plugin load ./loadmanaged/libloadmanaged.so

確保Mono.Cecil.dll和PluginInterop.dll文件與libloadmanaged.so位于同一文件夾中。

加載后,LLDB-LoadManaged將嘗試通過瀏覽調(diào)試目標(biāo)中加載的模塊來定位CoreCLR。如果失?。ɡ纾?yàn)槟谂c目標(biāo)不同的機(jī)器上運(yùn)行l(wèi)ldb),您可以通過調(diào)用SetClrPath以下命令手動(dòng)設(shè)置路徑:

SetClrPath /usr/local/share/dotnet/shared/Microsoft.NETCore.App/2.2.0/

最后,使用以下LoadManaged命令加載WinDbg擴(kuò)展:

LoadManaged /home/k.gosse/TestExtension.dll

(該LoadManaged命令尚不支持相對路徑)

就是這樣!現(xiàn)在,您可以像在WinDbg中一樣調(diào)用擴(kuò)展程序。

如何為WinDbg編寫ClrMD插件

WinDbg的ClrMD擴(kuò)展在Linux上的LLDB中完美運(yùn)行

注意:libloadmanaged.so和libsosplugin.so都會(huì)根據(jù)自己的需要托管CLR。但是,.NET Core CLR不支持并排方案。這意味著我們不能同時(shí)使用LoadManaged和SOS插件。這可以講是一個(gè)限制,它不太可能在.NET Core端修復(fù)。我們這里有一種解決方法,可以通過LoadManaged加載并替換libsosplugin.so的SOS托管版本。

關(guān)于如何為WinDbg編寫ClrMD插件就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學(xué)到更多知識。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI