为WinDbg和LLDB编写ClrMD扩展
字数 1127 2025-08-05 19:10:02
为WinDbg和LLDB编写ClrMD扩展 - 详细教学文档
1. 概述
ClrMDExports是一个兼容层,允许开发者编写能在WinDbg和LLDB中运行的ClrMD扩展。本教程将详细介绍如何创建跨调试器的ClrMD扩展。
2. 项目创建与配置
2.1 项目类型选择
- 可选择.NET Framework或.NET Standard类库项目
- 注意事项:
- 使用.NET Framework时:避免使用与.NET Core不兼容的功能(如AppDomain)
- 使用.NET Standard时:发布项目以包含所有依赖项(默认编译不会自动包含)
2.2 添加NuGet包
添加对ClrMDExports NuGet包的引用,它会自动包含以下依赖:
- ClrMD
- UnmanagedExports.Repack(支持.NET Framework 4.7+和.NET Standard)
注意:项目会自动添加Init.cs文件,不要修改此文件,它会在包更新时被覆盖。
3. 创建自定义命令
3.1 命令方法签名
每个命令需要创建静态方法,使用以下签名:
public static void CommandName(IntPtr client, [MarshalAs(UnmanagedType.LPStr)] string args)
{
// 命令实现
}
3.2 添加DllExport属性
使用DllExport属性装饰方法,并通过ExportName参数定义调试器可见的命令名称:
[DllExport("helloworld")]
public static void HelloWorld(IntPtr client, [MarshalAs(UnmanagedType.LPStr)] string args)
{
DebuggingContext.Execute(client, args, HelloWorldImpl);
}
3.3 实现命令逻辑
创建实际的命令实现方法:
private static void HelloWorldImpl(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);
}
}
注意:控制台输出会自动重定向到调试器。
4. 在WinDbg中使用扩展
- 编译扩展项目
- 在WinDbg中加载扩展:
.load YourExtension.dll - 调用命令:
!helloworld
5. 在LLDB中使用扩展
5.1 准备工作
- 下载并解压LLDB-LoadManaged元插件
- 启动LLDB并附加到目标:
./lldb -c dump.dmp
5.2 加载元插件
plugin load ./loadmanaged/libloadmanaged.so
必需文件:确保以下文件与libloadmanaged.so在同一目录:
- Mono.Cecil.dll
- PluginInterop.dll
5.3 设置CLR路径
如果自动检测失败,手动设置CoreCLR路径:
SetClrPath /usr/local/share/dotnet/shared/Microsoft.NETCore.App/2.2.0/
5.4 加载扩展
LoadManaged /path/to/YourExtension.dll
注意:目前不支持相对路径。
6. 限制与注意事项
-
SOS插件冲突:
libloadmanaged.so和libsosplugin.so都会托管CLR- .NET Core CLR不支持并排方案
- 解决方法:使用可通过
LoadManaged加载的SOS托管版本
-
实时进程调试:
- LLDB的主要优势是可以附加到实时进程
- Linux上的ClrMD尚不支持附加到实时进程
7. 未来发展方向
- 改进错误处理
- 增强CLR路径检测智能度
- 与基于ClrMD的跨平台REPL环境集成
8. 示例代码总结
完整示例:
using System;
using System.Linq;
using System.Runtime.InteropServices;
using ClrMD.Extensions;
using Microsoft.Diagnostics.Runtime;
using RGiesecke.DllExport;
public class Commands
{
[DllExport("helloworld")]
public static void HelloWorld(IntPtr client, [MarshalAs(UnmanagedType.LPStr)] string args)
{
DebuggingContext.Execute(client, args, HelloWorldImpl);
}
private static void HelloWorldImpl(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);
}
}
}
通过以上步骤,您可以创建同时兼容WinDbg和LLDB的ClrMD扩展,实现跨平台的调试体验。