ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

.Net GC 结构体GCInfo剖析,

2022-05-29 14:35:19  阅读:183  来源: 互联网

标签:GCInfo rbp Program 线程 GC Net size


前言:
dotnet已经发展到了 preview 7的版本,这个GC回收的文章或者视频非常少,几乎没有看到,有个别的也是模糊不清或者三言两语,或者太过于笼统,或者作者自己都没搞明白为啥是这样。至于深入到GC里面的GCinfo结构体就更少见了。因为这个结构体里面包含了根对象所在的地址,对于垃圾回收的第一个阶段标记至关重要的一环。这篇文章来解构下这个结构体。

本文以二进制和Windbg来分析下

概念:
GCInfo实际上是一个位数组,以一个位或者多个位来标记包含的字段的意义。
如何解析这个位数组呢?


代码:

     static void Main(string[] args)
     {
         Program pm = new Program();
         GC.Collect();
         Console.ReadLine();
     }

反汇编GCInfo命令:Windbg !u -gcinfo MethodDesc
以上代码编译成exe,放在windbg里面也只能仅仅看到残缺不齐的信息,只有所谓的根对象距离Rbp寄存器的偏移位置,而且它也没有说明这些信息是如何得到的。如下所示:00007ffead724918是Program.Main的MethodDesc

0:000> !u -gcinfo 00007ffead724918
Normal JIT generated code
ConsoleApp11.Program.Main(System.String[])
ilAddr is 0000025D05E82050 pImport is 0000021EE1FFB040
Begin 00007FFEAD685EC0, size 67

F:\Visual Studio Project\ConsoleApp7\ConsoleApp11\Program.cs @ 40:
Prolog size: 0
Security object: <none>
GS cookie: <none>
PSPSym: <none>
Generics inst context: <none>
PSP slot: <none>
GenericInst slot: <none>
Varargs: 0
Frame pointer: rbp
Wants Report Only Leaf: 0
Size of parameter area: 20
Return Kind: Scalar
Code size: 67
Untracked: +rbp+10 +rbp-8 +rbp-10 +rbp-18
00007ffe`ad685ec0 55              push    rbp
00007ffe`ad685ec1 4883ec40        sub     rsp,40h
00007ffe`ad685ec5 488d6c2440      lea     rbp,[rsp+40h]
00007ffe`ad685eca c5d857e4        vxorps  xmm4,xmm4,xmm4
00007ffe`ad685ece c5fa7f65e8      vmovdqu xmmword ptr [rbp-18h],xmm4
//此处省略部分汇编

字段
比如以下这些字段的值从何而来,代表什么意义?

Prolog size: 0
Security object: <none>
GS cookie: <none>
PSPSym: <none>
Generics inst context: <none>
PSP slot: <none>
GenericInst slot: <none>
Varargs: 0
Frame pointer: rbp
Wants Report Only Leaf: 0
Size of parameter area: 20
Return Kind: Scalar
Code size: 67

解析
要理清楚这些,必须通过CLR源码来解构。
可以参考:
https://github.com/dotnet/runtime/blob/main/src/coreclr/vm/gcinfodecoder.cpp

一.在厘清如何结构GCInfo之前,需要知道是如何获取到GCInfo的。其实原理很简单
1.遍历所有的托管线程
2.通过托管线程找到托管线程变量Frame(也就是帧栈)
3.通过线程的帧栈找到线程对应的寄存器的值,比如Rip,Rsp,Rbp 等关键信息
4.当Rip被找到可以通过相应的API 寻找Rip所在的函数以及函数范围,也就是实例化EECodeInfo。调用函数为EECodeInfo::Init,而参数则为Rip。这一步是比较重要的。
5.当初始化EECodeInfo之后,就可以计算出,当前函数里面包含的变量信息,字段信息,函数信息等等。
6.GCInfo就是初始化EECodeInfo在此阶段被找到,但是GCInfo的初始化则是在RyuJiit里面执行。这个点要注意。
7.有了关键信息之后,就可以通过API函数RtlVirtualUnwind来回滚帧栈,循环找到需要的各种GC信息
具体的文章可以参考:
https://mp.weixin.qq.com/s?__biz=Mzg5NDYwNjU4MA==&mid=2247483946&idx=1&sn=6da6e76b7799ed818a6ff35affa27de0&chksm=c01c4fb1f76bc6a7cadc7e79f10dcb6a776b476a82e8628567ac178a82f44886e9190b706718&token=916104265&lang=zh_CN#rd
注意这里面包含了两个循环,一个是托管线程的循环,然后是每一个托管线程里面的帧栈循环。

标签:GCInfo,rbp,Program,线程,GC,Net,size
来源: https://www.cnblogs.com/tangyanzhi1111/p/16319763.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有