|
一:背景
1. 讲故事
过年喝了不少酒,脑子不灵光了,停了将近一个月没写博客,今天就当新年开工写一篇吧。
去年年初有位朋友找到我,说他们的系统会偶发性崩溃,在网上也发了不少帖子求助,没找到自己满意的答案,让我看看有没有什么线索,看样子这是一个牛皮藓的问题,既然对方有了dump,那就分析起来吧。
二:WinDbg分析
1.为什么会崩溃
不管是 windows 还是 linux 上的.net程序崩溃都会存在异常码,前者是ExceptionCode,后者是 SignalCode,所以先用 !analyze -v 观察看看。- 0:003> !analyze -v
- CONTEXT: (.ecxr)
- eax=00000008 ebx=00639498 ecx=00000001 edx=0c75e4c8 esi=0063ec88 edi=083d8f77
- eip=71ecaf96 esp=1ad2fa00 ebp=1ad2fa58 iopl=0 nv up ei pl nz na po nc
- cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010202
- clr!SVR::gc_heap::mark_object_simple1+0x382:
- 71ecaf96 f70000000080 test dword ptr [eax],80000000h ds:002b:00000008=????????
- Resetting default scope
- EXCEPTION_RECORD: (.exr -1)
- ExceptionAddress: 71ecaf96 (clr!SVR::gc_heap::mark_object_simple1+0x00000382)
- ExceptionCode: c0000005 (Access violation)
- ExceptionFlags: 00000001
- NumberParameters: 2
- Parameter[0]: 00000000
- Parameter[1]: 00000008
- Attempt to read from address 00000008
复制代码 从卦中信息看,程序崩在 clr!SVR::gc_heap::mark_object_simple1 方法里,这表示当前gc触发时clr在托管堆标记对象时发现堆损坏了,那到底是不是托管堆损坏呢?可以用 !verifyheap 命令验证下,输出如下:- 0:003> !verifyheap
- object 083d8f50: bad member 093D8F90 at 083D8F74
- Last good object: 083D8F3C.
- object 0c75e4c0: bad member 083D8F77 at 0C75E4C8
- Last good object: 0C75E454.
复制代码 从卦中信息看,确实存在着两个坏对象 083d8f50 和 0c75e4c0,接下来的研究重点就是为什么这两个对象会破坏?
2. 对象为什么损坏了
为了方便解读我们从 083d8f50 入手,先用 !do 观察它的布局。- 0:003> !do 083d8f50
- Name: System.Windows.DependencyProperty
- MethodTable: 727ebe60
- EEClass: 72708570
- Size: 44(0x2c) bytes
- Fields:
- MT Field Offset Type VT Attr Value Name
- ...
- 727e7f0c 40011fe 24 ....InsertionSortMap 1 instance 083d8f74 _metadataMap
- ...
- 0:003> !DumpVC /d 727e7f0c 083d8f74
- Name: MS.Utility.InsertionSortMap
- MethodTable: 727e7f0c
- EEClass: 72721ec8
- Size: 12(0xc) bytes
- Fields:
- MT Field Offset Type VT Attr Value Name
- 727e7f44 40007e9 0 ...geSortedObjectMap 0 instance 093d8f90 _mapStore
- 0:003> !DumpObj /d 093d8f90
- <Note: this object has an invalid CLASS field>
- Invalid object
复制代码 根据对象的布局知识,093d8f90 存放的是 mt,看样子是mt被损坏了,接下来用 dp 观察下这个地址的附近内存。- 0:003> dp 093d8f90-0x20 L10
- 093d8f70 727e8b50 032e3750 1085da60 04a46fd9
- 093d8f80 00000000 727e8b50 032e3a48 08157ef0
- 093d8f90 03217272 00000000 727e8b50 032e353c
- 093d8fa0 08079f9c 02c028d2 00000000 727e8b50
- 0:003> !lno 093d8f90
- Before: 093d8f84 20 (0x14) MS.Internal.WeakEventTable+EventKey
- After: 093d8f98 20 (0x14) MS.Internal.WeakEventTable+EventKey
- Heap local consistency confirmed.
- 0:003> !do 093d8f84
- Name: MS.Internal.WeakEventTable+EventKey
- MethodTable: 727e8b50
- EEClass: 727076c4
- Size: 20(0x14) bytes
- File: C:\Windows\Microsoft.Net\assembly\GAC_MSIL\WindowsBase\v4.0_4.0.0.0__31bf3856ad364e35\WindowsBase.dll
- Fields:
- MT Field Offset Type VT Attr Value Name
- 727ec0f4 4001a28 4 ....WeakEventManager 0 instance 032e3a48 _manager
- 7112dbd4 4001a29 8 System.Object 0 instance 08157ef0 _source
- 7112f6bc 4001a2a c System.Int32 1 instance 52523634 _hashcode
复制代码 从卦中信息看 mt=03217272 肯定是不对的,但奇怪的是这附近的内存并没有损坏,它是EventKey._hashcode的16进制表示,我去,这就奇葩了。。。一下子陷入了迷茫。
3. 内存为什么没坏
说实话分析了这么多的dump,这种情况还是第一次遇见,根据上一节的分析,现在可以怀疑 093d8f90 这个地址本身就是错的,接下来观察它的所属地址 083d8f74 附近的内存。- 0:003> dp 083d8f74 -0x40 L20
- 083d8f34 00000003 00000000 727e72c9 083d8ba4
- 083d8f44 083d8ec8 775e7de3 00000000 727ebe61
- 083d8f54 083d8ba4 0ec9e934 083d8ec8 083d8f20
- 083d8f64 00000000 00000000 00000000 00020368
- 083d8f74 093d8f90 00000000 727ee329 083d8ec8
- 083d8f84 0ec9eaf4 000000e0 00000000 727e7f45
- 083d8f94 083d8fa4 00000001 000000e0 00000000
- 083d8fa4 727e7fb1 00000002 083d8f04 000000e0
复制代码 如果你仔细观察卦中的区域内存地址,你会发现一个有意思的现象,它附近的对象都是 083 开头的,凭什么它是 093 开头的?对他产生了怀疑之后,我们观察下托管堆中 mt=727e7f44 下是否存在 093d8f90 的实例,截图如下:
从卦中可以清晰的看到确实不存在 093d8f90 对象,但存在一个将 9 -> 8 之隔的 083d8f90,有经验的朋友应该知道,这又是一例经典的bit位翻转导致的程序崩溃,可以用 .formats 命令观察下二进制的布局:
4. 另一个坏对象也是如此吗
刚才的 093d8f90 我们搞明白了是由于bit位翻转导致,那 083d8f77 也是如此吗?有了刚才的经验这个就比较好验证了,可以查一下 mt=727ee328 下是否有这个实例。- 0:003> !do 0c75e4c0
- Name: System.Windows.Media.Pen
- MethodTable: 6f38a110
- EEClass: 6f1568b4
- Size: 40(0x28) bytes
- File: C:\Windows\Microsoft.Net\assembly\GAC_32\PresentationCore\v4.0_4.0.0.0__31bf3856ad364e35\PresentationCore.dll
- Fields:
- MT Field Offset Type VT Attr Value Name
- ...
- 727ee328 40011dc 8 ...endencyObjectType 0 instance 083d8f77 _dType
- ...
- 0:003> !dumpheap -mt 727ee328
- Address MT Size
- ...
- 083d8db0 727ee328 20
- 083d8f7c 727ee328 20
- ...
复制代码
又是一个无语的结论,原来 083d8f7c 被错赋成了 083d8f77,用 .formats 命令观察之后发现有 3个bit的翻转。截图如下:
三:总结
有丰富经验的朋友肯定知道,bit翻转大多是辐射导致计算机数字信号偶发的紊乱,这也是为什么医院要加个铅版来阻隔,而这个程序所处的环境刚好是辐射比较多的高铁系。
所以分析完之后,非我等调试师能为之,远离辐射。。。
来源:https://www.cnblogs.com/huangxincheng/p/18025970
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作! |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
x
|