教你打入clr内部: 配置windows上的windbg,linux上的lldb

一:背景

1. 讲故事

前几天公众号里有位兄弟看了几篇文章之后,也准备用windbg试试看,结果这一配就花了好几天,(づ╥﹏╥)づ,我想也有很多跃跃欲试的朋友在配置的时候肯定会遇到这样和那样的问题,所以我觉得有必要整理一下,让大家少走弯路。

二:一些基础概念

1. 在哪下载

现在安装windbg越来越麻烦,还要安装Windows 10 SDK,很多人就栽在这里,其实大家可以直接在网上找一键打包的windbg 6.0版本即可,才30多M,调生产调本地都很方便,顺带还可以练练SOS命令。

云盘:https://pan.baidu.com/s/1VqXVIGVHxAZVPNds1525Jg 提取码:mahg

外网:http://www.33lc.com/soft/96743.html

2. 版本问题

解压打开会有一个x64和x86文件夹,很显然,32位的程序用x86下的windbg调试,64位的程序用x64的windbg调试,如下图:

3. 其他的问题

我比较喜欢用64bit程序,所以这里使用64位的windbg。

<1> 配置微软公有符号

符号其实就是pdb文件,我们在debug模式下编译项目都会看到这个,它的作用会对dll进行打标,这样在调试时通过pdb就能看到局部变量,全局变量,行号等等其他信息,在FCL类库中的pdb文件就放在微软的公有服务器上,SRV*C:\mysymbols*http://msdl.microsoft.com/download/symbols

<2> 理解sos.dll和clr.dll

很多时候大家都是事后调试,所以需要在生产上抓一个dump文件,为了将dump文件逆向到clr上的运行时状态,你必须要寻找到当时运行程序clr版本,同时也要找到对应clr版本的sos.dll,他们通常是在一起的,sos 就是 你 和 clr交互的渠道,很多人都卡在寻找正确版本的sos和clr版本上。。。如果不清楚,我可以画张图。

有了这个前置基础,接下来就可以在windows和centos上进行配置实践了。。。????????????

三. windows上的 netcore 3.1 配置

为了演示,我先上一段简单的代码:

static void Main(string[] args){var info = "hello world!";Console.WriteLine(info);Console.ReadLine();}

1. 寻找clr.dll

在netcore中,clr的名字变成了 coreclr.dll,路径:C:\Program Files\dotnet\shared\Microsoft.NETCore.App\3.1.3

2. 寻找sos.dll

netcore3.0开始,sos就没有放在版本号文件下了,详见 SOS_README.md 内容。


SOS and other diagnostic tools now ship of band and work with any version of the .NET Core runtime.
SOS has moved to the diagnostics repo here: https://github.com/dotnet/diagnostics.git.
Instructions to install SOS: https://github.com/dotnet/diagnostics#installing-sos.

看了上面文档,大概意思就是说老版本的windbg,需要通过小工具dotnet-sos 自己生成一个sos.dll,那就按照文档来吧


PS C:\WINDOWS\system32> dotnet tool install -g dotnet-sos
You can invoke the tool using the following command: dotnet-sos
Tool 'dotnet-sos' (version '3.1.122203') was successfully installed.
PS C:\WINDOWS\system32> dotnet-sos install
Installing SOS to C:\Users\hxc\.dotnet\sos from C:\Users\hxc\.dotnet\tools\.store\dotnet-sos\3.1.122203\dotnet-sos\3.1.122203\tools\netcoreapp2.1\any\win-x64
Installing over existing installation...
Creating installation directory...
Copying files...
Execute '.load C:\Users\hxc\.dotnet\sos\sos.dll' to load SOS in your Windows debugger.
Cleaning up...
SOS install succeeded
PS C:\WINDOWS\system32>

仔细看输出,sos.dll 已经生成好了,接下来在任务管理器中生成一个dump文件,然后使用 .load 命令把 coreclr 和 sos 加载进去即可。


.load C:\Users\hxc\.dotnet\sos\sos.dll
.load C:\Program Files\dotnet\shared\Microsoft.NETCore.App\3.1.3\coreclr.dll

最后我们抓一下 info 变量在堆上的分布。

0:000> ~0s
ntdll!ZwReadFile+0x14:
00007ff8`3228aa64 c3              ret0:000> !clrstack -l
OS Thread Id: 0x41d4 (0)000000246097EA40 00007FFF89C50F97 Error: Fail to initialize CoreCLR 80131022
ConsoleApp5.Program.Main(System.String[])LOCALS:0x000000246097EA68 = 0x0000021d8141aba80:000> !do 0x0000021d8141aba8
Name:        System.String
MethodTable: 00007fff89cd1e18
EEClass:     00007fff89cc2128
Size:        46(0x2e) bytes
File:        C:\Program Files\dotnet\shared\Microsoft.NETCore.App\3.1.3\System.Private.CoreLib.dll
String:      hello world!
Fields:MT    Field   Offset                 Type VT     Attr            Value Name
00007fff89c1b1e8  4000242        8         System.Int32  1 instance               12 _stringLength
00007fff89c18000  4000243        c          System.Char  1 instance               68 _firstChar
00007fff89cd1e18  4000244      110        System.String  0   static 0000021d81411360 Empty

好了,windows上的netcore调试就这么简单,希望这些配置能节省您的时间。

四. windows 上的 netframework 配置

framework程序比netcore配置要方便的多,不需要自己去生成sos了,如下代码所示:


64位程序加载路径.load C:\Windows\Microsoft.NET\Framework64\v4.0.30319\sos.dll.load C:\Windows\Microsoft.NET\Framework64\v4.0.30319\clr.dll32位程序加载路径.load C:\Windows\Microsoft.NET\Framework\v4.0.30319\sos.dll.load C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll

五. centos 上的 netcore 3.1 配置

首先要明白,对于linux内核windbg就失效了,那怎么调试呢?有两种方式。

1. 使用netcore内置的dotnet-dump 小工具

这个工具????????的地方在于,sos和clr都不需要你配置,直接使用它生成dump,然后直接调试,方便至极,下面看看怎么安装,开两个terminal,如下代码:


terminal 1:[root@10-25-198-96 data]# dotnet build
[root@10-25-198-96 netcoreapp3.1]# dotnet data.dll
hello worldterminal 2:[root@10-25-198-96 cs2]# ps -ef | grep dotnet
root     31555 31247  0 22:28 pts/0    00:00:00 dotnet cs2.dll
root     32112 31995  0 22:29 pts/2    00:00:00 grep --color=auto dotnet[root@10-25-198-96 cs2]# dotnet tool install -g dotnet-dump
You can invoke the tool using the following command: dotnet-dump
Tool 'dotnet-dump' (version '3.1.122203') was successfully installed.
[root@10-25-198-96 cs2]# export PATH=$PATH:$HOME/.dotnet/tools
[root@10-25-198-96 cs2]# dotnet-dump collect --process-id 31555
Writing full to /cs2/core_20200508_223204
Complete

可以看到dump文件已经好了 /cs2/core_20200508_223204 ,接下来用 dotnet-dump 对dump文件调试。


[root@10-25-198-96 cs2]# dotnet-dump analyze /cs2/core_20200508_223204
Loading core dump: /cs2/core_20200508_223204 ...
Ready to process analysis commands. Type 'help' to list available commands or 'help [command]' to get detailed help on a command.
Type 'quit' or 'exit' to exit the session.
> clrstack -l
OS Thread Id: 0x7b43 (0)Child SP               IP Call Site
00007FFDFCABF2D0 00007fb0397af7fd [InlinedCallFrame: 00007ffdfcabf2d0] Interop+Sys.ReadStdin(Byte*, Int32)
00007FFDFCABF2D0 00007fafbebbb4db [InlinedCallFrame: 00007ffdfcabf2d0] Interop+Sys.ReadStdin(Byte*, Int32)
00007FFDFCABF2C0 00007FAFBEBBB4DB ILStubClass.IL_STUB_PInvoke(Byte*, Int32)00007FFDFCABF9D0 00007FAFBECF844D System.Console.ReadLine()00007FFDFCABF9E0 00007FAFBEBB037D cs2.Program.Main(System.String[]) [/cs2/Program.cs @ 13]LOCALS:0x00007FFDFCABF9F0 = 0x00007faf980081d800007FFDFCABFD08 00007fb037fc0f7f [GCFrame: 00007ffdfcabfd08]
00007FFDFCAC01F0 00007fb037fc0f7f [GCFrame: 00007ffdfcac01f0]
> dumpobj 0x00007faf980081d8                                                                               
Name:        System.String
MethodTable: 00007fafbec30f90
EEClass:     00007fafbeb9e1b0
Size:        44(0x2c) bytes
File:        /usr/share/dotnet/shared/Microsoft.NETCore.App/3.1.3/System.Private.CoreLib.dll
String:      hello world
Fields:MT    Field   Offset                 Type VT     Attr            Value Name
00007fafbec2a0e8  400022a        8         System.Int32  1 instance               11 _stringLength
00007fafbec26f00  400022b        c          System.Char  1 instance               68 _firstChar
00007fafbec30f90  400022c      108        System.String  0   static 00007faf97fff360 Empty
>

就这么简单,不过这个工具虽好,但是不能调试非托管堆,而且命令也不是太多,当然够我们平时用了。

2. 使用linux专属的lldb调试器

要想实现windbg级别的调试,可以使用lldb调试器,这个非常强大,这里我也来介绍一下吧。

<1> 安装lldb

lldb是使用C++写的,也可以在 https://github.com/dotnet/diagnostics/blob/master/documentation/building/linux-instructions.md 寻找安装办法。


sudo yum install centos-release-SCL epel-release
sudo yum install cmake cmake3 gcc gcc-c++ gdb git libicu libunwind make python27 tar wget which zip
cd $HOME
git clone https://github.com/dotnet/diagnostics.git
$HOME/diagnostics/documentation/lldb/centos7/build-install-lldb.sh

一阵抽搐后就安装好了,从下面可以看到目前版本是3.9.1。


[root@10-25-198-96 cs2]# lldb -v
lldb version 3.9.1 ( revision )

<2> 寻找sos.dll

跟windbg一样,你需要生成一个sos.dll 。。。同样也是使用 dotnet-sos 生成。


[root@10-25-198-96 cs2]# dotnet tool install -g dotnet-sos
You can invoke the tool using the following command: dotnet-sos
Tool 'dotnet-sos' (version '3.1.122203') was successfully installed.
[root@10-25-198-96 cs2]# dotnet-sos install
Installing SOS to /root/.dotnet/sos from /root/.dotnet/tools/.store/dotnet-sos/3.1.122203/dotnet-sos/3.1.122203/tools/netcoreapp2.1/any/linux-x64
Installing over existing installation...
Creating installation directory...
Copying files...
Updating existing /root/.lldbinit file - LLDB will load SOS automatically at startup
Cleaning up...
SOS install succeeded

从上面信息看,sos 是安装在 /root/.dotnet/sos 目录下,同时也看到在lldb启动的时候会自动加载sos.dll 。。。

<3> 使用createdump 生成dump文件

每个dotnet版本下都有一个createdump程序,可以用它生成dump文件,具体配置文档可以参见:

https://github.com/dotnet/diagnostics/blob/master/documentation/debugging-coredump.md

https://github.com/dotnet/runtime/blob/master/docs/design/coreclr/botr/xplat-minidump-generation.md#configurationpolicy

[root@10-25-198-96 cs2]# ps -ef | grep dotnet
root     31555 31247  0 22:28 pts/0    00:00:00 dotnet cs2.dll
root     32112 31995  0 22:29 pts/2    00:00:00 grep --color=auto dotnet[root@10-25-198-96 cs2]# find / -name createdump
/usr/share/dotnet/shared/Microsoft.NETCore.App/3.1.3/createdump[root@10-25-198-96 3.1.3]# ./createdump 31555  -f /lldb/test.dump
Writing minidump with heap to file /lldb/test.dump
Written 84692992 bytes (20677 pages) to core file[root@10-25-198-96 3.1.3]# lldb --core /lldb/test.dump
(lldb) target create --core "/lldb/test.dump"
Core file '/lldb/test.dump' (x86_64) was loaded.
(lldb) clrstack -l
OS Thread Id: 0x7b43 (1)
00007FFDFCABF9E0 00007FAFBEBB037D cs2.Program.Main(System.String[]) [/cs2/Program.cs @ 13]LOCALS:0x00007FFDFCABF9F0 = 0x00007faf980081d800007FFDFCABFD08 00007fb037fc0f7f [GCFrame: 00007ffdfcabfd08]
00007FFDFCAC01F0 00007fb037fc0f7f [GCFrame: 00007ffdfcac01f0]
(lldb) dumpobj 0x00007faf980081d8
Name:        System.String
MethodTable: 00007fafbec30f90
EEClass:     00007fafbeb9e1b0
Size:        44(0x2c) bytes
File:        /usr/share/dotnet/shared/Microsoft.NETCore.App/3.1.3/System.Private.CoreLib.dll
String:      hello world
Fields:MT    Field   Offset                 Type VT     Attr            Value Name
00007fafbec2a0e8  400022a        8         System.Int32  1 instance               11 _stringLength
00007fafbec26f00  400022b        c          System.Char  1 instance               68 _firstChar
00007fafbec30f90  400022c      108        System.String  0   static 00007faf97fff360 Empty
(lldb)

可以看到,通过lldb也可以直接打入clr内部啦。。。

六:总结

我觉得这篇文章肯定能给很多朋友节省不少的时间,想起朱一旦的那句话:有钱人的快乐,就是这么朴实无华且枯燥, 哈哈~~~

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

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

相关文章

leetcode周赛6076. 表示一个折线图的最少线段数

气死爹了 用C过不去 换成Java 过了 一:题目 二:上码 class Solution {public int minimumLines(int[][] stockPrices) {Arrays.sort(stockPrices,(o1,o2)->o1[0]-o2[0]);int n stockPrices.length;if (n 1) return 0;int ans 1;for (int i 0; i < n-2; i) {int k1 …

使用代码片段的正确姿势,打造高效的vscode开发环境

全文3928字&#xff0c;阅读时间 10分钟&#xff0c;未来节约时间 15分钟/每天代码片段&#xff08;code snippet&#xff09; 相信大家都或多或少有接触过。在完成一个项目以后&#xff0c;往往都会写出许多有价值的代码&#xff0c;或是绞尽脑汁解决的难题&#xff0c;或是灵…

leetcode周赛6074. 字母在字符串中的百分比

这个简单题也比较狗 上午做的时候一直有个测试点不过 但是题目不给出什么测试点不过 原来是100这个答案 给跪了 一:题目 二:上码 class Solution { public:int percentageLetter(string s, char letter) {if (s.size() 0) return 0;int count 0;for (int i 0; i < s.si…

leetcode周赛6075. 装满石头的背包的最大数量

一:题目 二:上码 class Solution { public:/**思路:求差&#xff0c;将结果放到一个容器当中&#xff0c;然后的话&#xff0c;排序&#xff0c;*/int maximumBags(vector<int>& capacity, vector<int>& rocks, int additionalRocks) {vector<int> …

学完这篇依赖注入,与面试官扯皮就没有问题了。

IOC: Inversion Of Control 控制反转DI: Dependency Injection 依赖注入1.控制反转 Inversion Of Control 的前世今生1.1 IOC理论产生的背景讨论控制反转之前&#xff0c;先看看软件系统提出控制反转的前世今生。一个完整精密的软件系统&#xff0c;组件之间就像齿轮&…

SpringCloud微服之Nacos的学习

1:使用前提 第一步:解压启动Nocos SpringCloudAlibaba 推出了一个名为 Nacos 的注册中心&#xff0c;在国外也有大量的使用。 startup.cmd -m standalone 访问http://localhost:8848/nacos/ 第二步:服务注册 工程目录 在父工程中添加依赖 <dependency><groupI…

前端大佬谈国产开源:VUE 的成功在于社区运营

喜欢就关注我们吧&#xff01;近日&#xff0c;国内首个开源软件基金会 —— 开放原子基金会在深圳国际开源谷举办了 TOC 圆桌论坛。论坛上&#xff0c;基金会 TOC 之一、国内知名前端大佬贺师俊表达了一些有趣的观点&#xff0c;阐述了自己对于国内开源生态的见解。贺师俊认为…

停止精神内耗 每日分享

停止反复犹豫 作家脱不花曾说&#xff1a;“人总是有很多左右为难的事情&#xff0c;如果你在做与不做之间来回纠结&#xff0c;那就停止来回推演&#xff0c;立即去做” 所谓三思而后行 那么如果只停留在三思 那么所有的愿景都将成为遗憾 放弃脑海当中左右不定的想法 扔掉徘…

eShopOnContainers 知多少[12]:Envoy gateways

1. 引言在最新的eShopOnContainers 3.0 中Ocelot 网关被Envoy Proxy 替换。下面就来简要带大家了解下Envoy&#xff0c;并尝试梳理下为什么要使用Envoy替代Ocelot。2. Hello EnvoyENVOY IS AN OPEN SOURCE EDGE AND SERVICE PROXY, DESIGNED FOR CLOUD-NATIVE APPLICATIONS.En…

为啥 Response.Write 后,View就不渲染了?

一&#xff1a;背景 1. 讲故事前几天群里有一位朋友聊到&#xff0c;为什么我在 Action 中执行一句 Response.Write 之后&#xff0c;后续的 View 就不呈现了&#xff0c;如果脑子中没有画面&#xff0c;那就上测试代码&#xff1a;public class HomeController : Controller{p…

3. 无重复字符的最长子串(滑动窗口详解版)

一:题目 二&#xff1a;上码 class Solution {/**分析&#xff1a;1.滑动窗口问题2.何时更改窗口的起点位置当出现重复的时候 需要从重复的字符的下一个字符开始计算*/public int lengthOfLongestSubstring(String s) {if (s.length() < 1) {return s.length();}int slowIn…

121. 买卖股票的最佳时机

一:题目 二:上码 class Solution {// public int maxProfit(int[] prices) {// int max 0;// for (int i 0; i < prices.length; i) {// //求出i后面的最大值// int temp 0;// for (int j i 1; j < prices.length; j) {// …

IdentityServer4系列 | 快速搭建简易项目

一 、前言从上一篇关于 常见术语说明中&#xff0c;主要是对「IdentityServer4」的说明&#xff0c;以及其中涉及常见的术语的表述说明&#xff0c;包括对身份认证服务器、用户、客户端、资源以及各个令牌等进行对比区别说明。而在这一篇中&#xff0c;我们将尝试通过简单的方式…

136. 只出现一次的数字(hot100)

一:题目 二:上码 class Solution {public int singleNumber(int[] nums) {int ans -100;Arrays.sort(nums);for (int i 0; i < nums.length-1; i2) {if (nums[i] ! nums [i1]) {ans nums[i];break;}}return ans -100 ? nums[nums.length-1] : ans;} }

高并发项目Java是标配?.NET Core要将它拉下“神坛”!

电商的秒杀和抢购&#xff0c;对我们来说&#xff0c;都不是一个陌生的东西。然而&#xff0c;从技术的角度来说&#xff0c;这对于Web系统是一个巨大的考验。当一个Web系统&#xff0c;在一秒钟内收到数以万计甚至更多请求时&#xff0c;系统的优化和稳定至关重要。缓存技术是…

141. 环形链表(hot100)

一:题目 二:上码 /*** Definition for singly-linked list.* class ListNode {* int val;* ListNode next;* ListNode(int x) {* val x;* next null;* }* }*/ public class Solution {public boolean hasCycle(ListNode head) {ListNode fa…

程序员修神之路--分布式系统使用网关到底是好还是坏?

“灵魂拷问分布式系统需要统一的网关吗&#xff1f;网关会带来哪些优势&#xff1f;引入网关会带来灾难吗&#xff1f;分布式系统的设计大体上分为中心化和非中心化&#xff0c;像现在流行的微服务模式&#xff0c;本质上是把各种业务拆分为独立的进程来实现业务的扩展性。伴随…

160. 相交链表(hot100)

一:题目 二:上码 /*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode(int x) : val(x), next(NULL) {}* };*/ class Solution { public:ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {ListN…

.NET Core开源任务调度平台ScheduleMaster上新了

ScheduleMaster上一次比较大的更新还是在6月份&#xff0c;转眼已经快过去4个月了&#xff0c;这段时间比较忙&#xff0c;中间只更新过一次修复了几个小bug。要总结这次更新的话&#xff0c;必须要用“千呼万唤始出来”了&#xff0c;因为这次不仅经历的时间比较久&#xff0c…

234. 回文链表(hot100)

一:题目 二:上码 /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode() {}* ListNode(int val) { this.val val; }* ListNode(int val, ListNode next) { this.val val; this.next next; }* }*/ …