为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中使用扩展

  1. 编译扩展项目
  2. 在WinDbg中加载扩展:
    .load YourExtension.dll
    
  3. 调用命令:
    !helloworld
    

5. 在LLDB中使用扩展

5.1 准备工作

  1. 下载并解压LLDB-LoadManaged元插件
  2. 启动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. 限制与注意事项

  1. SOS插件冲突

    • libloadmanaged.solibsosplugin.so都会托管CLR
    • .NET Core CLR不支持并排方案
    • 解决方法:使用可通过LoadManaged加载的SOS托管版本
  2. 实时进程调试

    • LLDB的主要优势是可以附加到实时进程
    • Linux上的ClrMD尚不支持附加到实时进程

7. 未来发展方向

  1. 改进错误处理
  2. 增强CLR路径检测智能度
  3. 与基于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扩展,实现跨平台的调试体验。

为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 命令方法签名 每个命令需要创建静态方法,使用以下签名: 3.2 添加DllExport属性 使用 DllExport 属性装饰方法,并通过 ExportName 参数定义调试器可见的命令名称: 3.3 实现命令逻辑 创建实际的命令实现方法: 注意 :控制台输出会自动重定向到调试器。 4. 在WinDbg中使用扩展 编译扩展项目 在WinDbg中加载扩展: 调用命令: 5. 在LLDB中使用扩展 5.1 准备工作 下载并解压LLDB-LoadManaged元插件 启动LLDB并附加到目标: 5.2 加载元插件 必需文件 :确保以下文件与 libloadmanaged.so 在同一目录: Mono.Cecil.dll PluginInterop.dll 5.3 设置CLR路径 如果自动检测失败,手动设置CoreCLR路径: 5.4 加载扩展 注意 :目前不支持相对路径。 6. 限制与注意事项 SOS插件冲突 : libloadmanaged.so 和 libsosplugin.so 都会托管CLR .NET Core CLR不支持并排方案 解决方法:使用可通过 LoadManaged 加载的SOS托管版本 实时进程调试 : LLDB的主要优势是可以附加到实时进程 Linux上的ClrMD尚不支持附加到实时进程 7. 未来发展方向 改进错误处理 增强CLR路径检测智能度 与基于ClrMD的跨平台REPL环境集成 8. 示例代码总结 完整示例: 通过以上步骤,您可以创建同时兼容WinDbg和LLDB的ClrMD扩展,实现跨平台的调试体验。