经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » ASP.net » 查看文章
记一次 .NET某列控连锁系统 崩溃分析
来源:cnblogs  作者:一线码农  时间:2024/2/23 8:59:31  对本文有异议

一:背景

1. 讲故事

过年喝了不少酒,脑子不灵光了,停了将近一个月没写博客,今天就当新年开工写一篇吧。

去年年初有位朋友找到我,说他们的系统会偶发性崩溃,在网上也发了不少帖子求助,没找到自己满意的答案,让我看看有没有什么线索,看样子这是一个牛皮藓的问题,既然对方有了dump,那就分析起来吧。

二:WinDbg分析

1.为什么会崩溃

不管是 windows 还是 linux 上的.net程序崩溃都会存在异常码,前者是ExceptionCode,后者是 SignalCode,所以先用 !analyze -v 观察看看。

  1. 0:003> !analyze -v
  2. CONTEXT: (.ecxr)
  3. eax=00000008 ebx=00639498 ecx=00000001 edx=0c75e4c8 esi=0063ec88 edi=083d8f77
  4. eip=71ecaf96 esp=1ad2fa00 ebp=1ad2fa58 iopl=0 nv up ei pl nz na po nc
  5. cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010202
  6. clr!SVR::gc_heap::mark_object_simple1+0x382:
  7. 71ecaf96 f70000000080 test dword ptr [eax],80000000h ds:002b:00000008=????????
  8. Resetting default scope
  9. EXCEPTION_RECORD: (.exr -1)
  10. ExceptionAddress: 71ecaf96 (clr!SVR::gc_heap::mark_object_simple1+0x00000382)
  11. ExceptionCode: c0000005 (Access violation)
  12. ExceptionFlags: 00000001
  13. NumberParameters: 2
  14. Parameter[0]: 00000000
  15. Parameter[1]: 00000008
  16. Attempt to read from address 00000008

从卦中信息看,程序崩在 clr!SVR::gc_heap::mark_object_simple1 方法里,这表示当前gc触发时clr在托管堆标记对象时发现堆损坏了,那到底是不是托管堆损坏呢?可以用 !verifyheap 命令验证下,输出如下:

  1. 0:003> !verifyheap
  2. object 083d8f50: bad member 093D8F90 at 083D8F74
  3. Last good object: 083D8F3C.
  4. object 0c75e4c0: bad member 083D8F77 at 0C75E4C8
  5. Last good object: 0C75E454.

从卦中信息看,确实存在着两个坏对象 083d8f500c75e4c0,接下来的研究重点就是为什么这两个对象会破坏?

2. 对象为什么损坏了

为了方便解读我们从 083d8f50 入手,先用 !do 观察它的布局。

  1. 0:003> !do 083d8f50
  2. Name: System.Windows.DependencyProperty
  3. MethodTable: 727ebe60
  4. EEClass: 72708570
  5. Size: 44(0x2c) bytes
  6. Fields:
  7. MT Field Offset Type VT Attr Value Name
  8. ...
  9. 727e7f0c 40011fe 24 ....InsertionSortMap 1 instance 083d8f74 _metadataMap
  10. ...
  11. 0:003> !DumpVC /d 727e7f0c 083d8f74
  12. Name: MS.Utility.InsertionSortMap
  13. MethodTable: 727e7f0c
  14. EEClass: 72721ec8
  15. Size: 12(0xc) bytes
  16. Fields:
  17. MT Field Offset Type VT Attr Value Name
  18. 727e7f44 40007e9 0 ...geSortedObjectMap 0 instance 093d8f90 _mapStore
  19. 0:003> !DumpObj /d 093d8f90
  20. <Note: this object has an invalid CLASS field>
  21. Invalid object

根据对象的布局知识,093d8f90 存放的是 mt,看样子是mt被损坏了,接下来用 dp 观察下这个地址的附近内存。

  1. 0:003> dp 093d8f90-0x20 L10
  2. 093d8f70 727e8b50 032e3750 1085da60 04a46fd9
  3. 093d8f80 00000000 727e8b50 032e3a48 08157ef0
  4. 093d8f90 03217272 00000000 727e8b50 032e353c
  5. 093d8fa0 08079f9c 02c028d2 00000000 727e8b50
  6. 0:003> !lno 093d8f90
  7. Before: 093d8f84 20 (0x14) MS.Internal.WeakEventTable+EventKey
  8. After: 093d8f98 20 (0x14) MS.Internal.WeakEventTable+EventKey
  9. Heap local consistency confirmed.
  10. 0:003> !do 093d8f84
  11. Name: MS.Internal.WeakEventTable+EventKey
  12. MethodTable: 727e8b50
  13. EEClass: 727076c4
  14. Size: 20(0x14) bytes
  15. File: C:\Windows\Microsoft.Net\assembly\GAC_MSIL\WindowsBase\v4.0_4.0.0.0__31bf3856ad364e35\WindowsBase.dll
  16. Fields:
  17. MT Field Offset Type VT Attr Value Name
  18. 727ec0f4 4001a28 4 ....WeakEventManager 0 instance 032e3a48 _manager
  19. 7112dbd4 4001a29 8 System.Object 0 instance 08157ef0 _source
  20. 7112f6bc 4001a2a c System.Int32 1 instance 52523634 _hashcode

从卦中信息看 mt=03217272 肯定是不对的,但奇怪的是这附近的内存并没有损坏,它是EventKey._hashcode的16进制表示,我去,这就奇葩了。。。一下子陷入了迷茫。

3. 内存为什么没坏

说实话分析了这么多的dump,这种情况还是第一次遇见,根据上一节的分析,现在可以怀疑 093d8f90 这个地址本身就是错的,接下来观察它的所属地址 083d8f74 附近的内存。

  1. 0:003> dp 083d8f74 -0x40 L20
  2. 083d8f34 00000003 00000000 727e72c9 083d8ba4
  3. 083d8f44 083d8ec8 775e7de3 00000000 727ebe61
  4. 083d8f54 083d8ba4 0ec9e934 083d8ec8 083d8f20
  5. 083d8f64 00000000 00000000 00000000 00020368
  6. 083d8f74 093d8f90 00000000 727ee329 083d8ec8
  7. 083d8f84 0ec9eaf4 000000e0 00000000 727e7f45
  8. 083d8f94 083d8fa4 00000001 000000e0 00000000
  9. 083d8fa4 727e7fb1 00000002 083d8f04 000000e0

如果你仔细观察卦中的区域内存地址,你会发现一个有意思的现象,它附近的对象都是 083 开头的,凭什么它是 093 开头的?对他产生了怀疑之后,我们观察下托管堆中 mt=727e7f44 下是否存在 093d8f90 的实例,截图如下:

从卦中可以清晰的看到确实不存在 093d8f90 对象,但存在一个将 9 -> 8 之隔的 083d8f90,有经验的朋友应该知道,这又是一例经典的bit位翻转导致的程序崩溃,可以用 .formats 命令观察下二进制的布局:

4. 另一个坏对象也是如此吗

刚才的 093d8f90 我们搞明白了是由于bit位翻转导致,那 083d8f77 也是如此吗?有了刚才的经验这个就比较好验证了,可以查一下 mt=727ee328 下是否有这个实例。

  1. 0:003> !do 0c75e4c0
  2. Name: System.Windows.Media.Pen
  3. MethodTable: 6f38a110
  4. EEClass: 6f1568b4
  5. Size: 40(0x28) bytes
  6. File: C:\Windows\Microsoft.Net\assembly\GAC_32\PresentationCore\v4.0_4.0.0.0__31bf3856ad364e35\PresentationCore.dll
  7. Fields:
  8. MT Field Offset Type VT Attr Value Name
  9. ...
  10. 727ee328 40011dc 8 ...endencyObjectType 0 instance 083d8f77 _dType
  11. ...
  12. 0:003> !dumpheap -mt 727ee328
  13. Address MT Size
  14. ...
  15. 083d8db0 727ee328 20
  16. 083d8f7c 727ee328 20
  17. ...

又是一个无语的结论,原来 083d8f7c 被错赋成了 083d8f77,用 .formats 命令观察之后发现有 3个bit的翻转。截图如下:

三:总结

有丰富经验的朋友肯定知道,bit翻转大多是辐射导致计算机数字信号偶发的紊乱,这也是为什么医院要加个铅版来阻隔,而这个程序所处的环境刚好是辐射比较多的高铁系。

所以分析完之后,非我等调试师能为之,远离辐射。。。

图片名称

原文链接:https://www.cnblogs.com/huangxincheng/p/18025970

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号