如何用 WinDbg 调试Linux上的 .NET程序

news2024/9/21 15:37:56

一:背景

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 点赞!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1943633.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数据结构C++——二叉树和树

文章目录 一、树二、二叉树三、二叉树的特性特性1. 包含n (n> 0 )个元素的二叉树边数为n-1特性 2: 若二叉树的高度为h,h≥0,则该二叉树最少有h个元素,最多有2^h-1 个元素特性3:包含n(n≥0)个元素的二叉树的高度最大为n,最小为ceiling(log2(n+1))特性4. 完全二叉树四、二…

基于微信小程序+SpringBoot+Vue的高校校园交友(带1w+文档)

基于微信小程序SpringBootVue的高校校园交友(带1w文档) 基于微信小程序SpringBootVue的高校校园交友(带1w文档) 在目前的情况下,可以引进一款高校校园交友微信小程序这样的现代化管理工具,这个工具就是解决上述问题的最好的解决方案。它不仅可以实时完成…

代码随想录 day 21 二叉树

第六章 二叉树part08 669. 修剪二叉搜索树 这道题目比较难,比 添加增加和删除节点难的多,建议先看视频理解。 题目链接/文章讲解: https://programmercarl.com/0669.%E4%BF%AE%E5%89%AA%E4%BA%8C%E5%8F%89%E6%90%9C%E7%B4%A2%E6%A0%91.html…

行业、客户双认可!路凯智行精彩亮相新疆煤博会

7月18日,2024丝路矿业合作论坛、第14届中国新疆国际矿业与装备博览会、第19届中国新疆国际煤炭工业博览会在新疆国际会展中心举行,此次论坛和展会吸引了全国26个省区市和德国、美国、日本、挪威、芬兰、法国、巴基斯坦、俄罗斯、白俄罗斯、乌兹别克斯坦等…

企业如何应对大模型落地的四大挑战?

近年来,人工智能(AI)和机器学习(ML)技术取得了突飞猛进的发展,其中大模型(如GPT-3、GPT-4、BERT等)因其强大的数据处理和分析能力,受到了企业的高度重视。大模型在自然语…

使用nginx实现一个端口和ip访问多个vue前端

前言:由于安全组要求,前端页面只开放一个端口,但是项目有多个前端,此前一直使用的是一个前端使用单独一个端口进行访问,现在需要调整。 需要实现:这里以80端口为例,两个前端分别是:p…

[用AI日进斗金系列]用码上飞在企微接单开发一个项目管理系统!

今天是【日进斗金】系列的第二期文章。 先给不了解这个系列的朋友们介绍一下,在这个系列的文章中,我们将会在企微的工作台的“需求发布页面”中寻找有软件开发需求的用户 并通过自研的L4级自动化智能软件开发平台「码上飞CodeFlying」让AI生成应用以解…

可以免费合并pdf的软件 合并pdf文件的软件免费 合并pdf的软件免费

在数字化办公的今天,pdf格式因其稳定性和跨平台兼容性被广泛使用。然而,当我们需要将多个 pdf 文件合并为一个时,却往往感到力不从心。本文将为你介绍几款强大的pdf文件合并软件,让你轻松管理文档。 方法一、使用pdf转换器 步骤1…

Vue3 对比 Vue2

相关信息简介2020年9月18日,Vue.js发布3.0版本,代号:One Piece(海贼王) 2 年多开发, 100位贡献者, 2600次提交, 600次 PR、30个RFC Vue3 支持 vue2 的大多数特性 可以更好的支持 Typescript,提供了完整的…

亚马逊跟卖北美选品ERP操作注意事项,商标自动查询,可...

新手在美国站选品有哪几种方式呢?美国商标局复查未备案准确度100%。 今天来讲下美国品牌未备案准不准确。 点开采集任务,站点选择美国,有五种采集方式:关键词、店铺链接、类目asin,选择完之后点确定。 选择asin采集…

【Docker】Docker-consul容器服务自动发现与注册

目录 一.Consul概述 1.解决了什么问题 2.什么叫微服务或者注册与发现 3.consul的模式 4.相关命令 二.consul 部署 1.consul服务器部署 2.部署docker容器 3.Nginx负载均衡器 3.1.安装启动nginx 3.2.配置nginx负载均衡 3.3.创建配置consul complate模板文件 3.4.添加…

只需三步,即可使用 Kafka 托管服务快速部署微服务架构应用

微服务架构的应用程序的特点是将其组件组织得能够独立地进行开发、测试、部署和扩展。DigitalOcean App Platform(应用平台)的目标是通过允许用户在同一应用上添加多个组件,简化这一架构模型,使其更加平滑和易于管理。 一个简单的…

【Zotero插件】Zotero Tag为文献设置阅读状态 win11下相关设置

【Zotero插件设置】Zotero Tag为文献设置阅读状态 win11下相关设置 1.安装Zotero Tag1.1安装1.2配置1.3 win11的相关设置1.3.1 字体安装 参考教程 2.支持排序的标注参考教程 1.安装Zotero Tag 1.1安装 Zotero Tag插件下载链接安装方法:Zotero–》工具–》附加组件…

day1 测试基础知识

1. 阐述软件生命周期都有哪些阶段?常见的软件生命周期模型有哪些? 2.常见测试模型有哪些? 参考链接:系统测试中的W模型---测试和开发相结合_开发和测试同时进行-CSDN博客 V模型 W模型(测试与开发并行) …

【ROS2】高级:安全-部署指南

目标:了解将安全工件部署到生产系统时的最佳实践。 教程级别:高级 时间:20 分钟 内容 背景 先决条件 一般准则构建部署场景 生成 Docker 镜像理解 compose 文件 运行示例 检查容器 背景 典型的部署场景通常涉及将容器化的应用程序或软件包发送…

高校体育场小程序的设计

管理员账户功能包括:系统首页,个人中心,状态管理,学生管理,用户管理,体育场管理,用户订单管理,学生订单管理,评价信息管理,交流论坛,系统管理 微…

4 种在 Windows 11/10/8/7 上恢复永久删除文件的可靠方法

您是否在 Windows 11/10/8/7 中从桌面永久删除了重要文件?当您不小心删除文件然后意识到以后需要它们时,这可能是一个真正的痛苦。但别担心,您可以使用多种方法从Windows PC恢复永久删除的文件。在这篇博文中,我们将为您提供 4 种…

机器学习 | 回归算法原理——最小二乘法

Hi,大家好,我是半亩花海。很早便想学习并总结一本很喜欢的机器学习图书——立石贤吾的《白话机器学习的数学》,可谓通俗易懂,清晰形象。那就在此分享并作为学习笔记来记录我的学习过程吧!本章的回归算法原理基于《基于…

Flutter Hive NoSql 数据库使用指南

Flutter Hive NoSql 数据库使用指南 视频 https://www.bilibili.com/video/BV1yJ4m1u7P2/ https://youtu.be/UJobRKdp68k 前言 原文 https://ducafecat.com/blog/flutter-hive-nosql-guide 本文将会写一个 Hive CURD 的例子,详细介绍 Hive 这个轻量级的 Flutter …

解决element-plus的Date Picker日期选择器组件禁用时间的坑

目前需求是有一个表单,其中有多个日期组件需要选择时间范围,并且选择的范围不可以有交集重复,所以这里需要用到Date Picker中的disabled-date属性,来判断该日期是否被禁用。 直接上代码,这个是我写的demo代码&#xf…