一:背景
1. 講故事
前段時(shí)間在用 騰訊會(huì)議
直播的時(shí)候,居然意外崩潰了,還好不是在訓(xùn)練營(yíng)上課,不然又得重錄了,崩完之后發(fā)現(xiàn) 騰訊會(huì)議
的 bugreport 組件會(huì)自動(dòng)生成一個(gè) minidump,截圖如下:
作為一個(gè).NET高級(jí)調(diào)試的技術(shù)博主,非 .NET
的程序也得要研究研究哈??????,有了這個(gè)好奇心,也有了這個(gè) dump,接下來用 windbg 看一看吧。
二:WinDbg 分析
1. 為什么會(huì)崩潰
在 Windows 平臺(tái)上不管是硬件異常
還是軟件異常
操作系統(tǒng)都會(huì)幫忙構(gòu)造一個(gè) EXCEPTION_POINTERS
結(jié)構(gòu)體,這里面就包含了程序的崩潰點(diǎn),錯(cuò)誤碼等各種非常有價(jià)值的信息,要想洞察這個(gè)結(jié)構(gòu)體,要么在棧上提取,要么用 !analyze -v
自動(dòng)化提取,這里采用后者。
0:000> !analyze -v
CONTEXT: (.ecxr)
eax=008fdfe4 ebx=00000001 ecx=00000000 edx=2d692620 esi=3c4e1818 edi=3207f464
eip=1c5b34aa esp=008fe034 ebp=008fe094 iopl=0 nv up ei pl nz ac pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010216
meeting_dashboard_module+0x34aa:
1c5b34aa 8b01 mov eax,dword ptr [ecx] ds:002b:00000000=????????
Resetting default scope
EXCEPTION_RECORD: (.exr -1)
ExceptionAddress: 1c5b34aa (meeting_dashboard_module+0x000034aa)
ExceptionCode: c0000005 (Access violation)
ExceptionFlags: 00000000
NumberParameters: 2
Parameter[0]: 00000000
Parameter[1]: 00000000
Attempt to read from address 00000000
PROCESS_NAME: wemeetapp.exe
READ_ADDRESS: 00000000
ERROR_CODE: (NTSTATUS) 0xc0000005 - 0x%p 0x%p %s
EXCEPTION_CODE_STR: c0000005
EXCEPTION_PARAMETER1: 00000000
EXCEPTION_PARAMETER2: 00000000
STACK_TEXT:
WARNING: Stack unwind information not available. Following frames may be wrong.
008fe094 7ad808f4 008fe320 00000000 ec0d8f9b meeting_dashboard_module+0x34aa
008fe214 7ad80617 008fe2f0 ec0d89ef 4ee246d8 desktop_common+0x108f4
008fe460 7ad7f4d7 776f6873 008fe400 79641fe1 desktop_common+0x10617
008fe5ec 7ad7ae62 008fe9d0 008fe76c 79bce43a desktop_common+0xf4d7
008fe5f8 79bce43a 008fe6b8 a0f1fbb4 326aed58 desktop_common+0xae62
008fe76c 7ad7de66 00000000 008fe9d0 ec0d8a63 wemeet_framework+0x2e43a
008fe7ec 7ad7deed 00000000 008fe9d0 008fe808 desktop_common+0xde66
008fe7fc 7ad7ae62 008fe9d0 008fe97c 79bce43a desktop_common+0xdee
...
從上面的 ExceptionCode: c0000005
來看,這是一個(gè)經(jīng)典的訪問違例,從崩潰匯編的 mov eax,dword ptr [ecx] ds:002b:00000000=????????
來看,當(dāng)前的 ecx 中存放的是 0 ,從 0 上取內(nèi)容自然就是訪問違例。
2. 為什么會(huì)訪問違例
要想知道訪問違例的原因,就需要分析一下附近的匯編代碼,用 .ecxr ; k
切到異常前的崩潰上下文。
0:000> .ecxr ; k
eax=008fdfe4 ebx=00000001 ecx=00000000 edx=2d692620 esi=3c4e1818 edi=3207f464
eip=1c5b34aa esp=008fe034 ebp=008fe094 iopl=0 nv up ei pl nz ac pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010216
meeting_dashboard_module+0x34aa:
1c5b34aa 8b01 mov eax,dword ptr [ecx] ds:002b:00000000=????????
*** Stack trace for last set context - .thread/.cxr resets it
# ChildEBP RetAddr
WARNING: Stack unwind information not available. Following frames may be wrong.
00 008fe094 7ad808f4 meeting_dashboard_module+0x34aa
01 008fe214 7ad80617 desktop_common+0x108f4
02 008fe460 7ad7f4d7 desktop_common+0x10617
03 008fe5ec 7ad7ae62 desktop_common+0xf4d7
04 008fe5f8 79bce43a desktop_common+0xae62
05 008fe76c 7ad7de66 wemeet_framework+0x2e43a
06 008fe7ec 7ad7deed desktop_common+0xde66
07 008fe7fc 7ad7ae62 desktop_common+0xdeed
08 008fe808 79bce43a desktop_common+0xae62
09 008fe97c 79bc784c wemeet_framework+0x2e43a
0a 008fe98c 79bc821f wemeet_framework+0x2784c
0b 008fe9a0 79bdac53 wemeet_framework+0x2821f
0c 008fea1c 79bdb791 wemeet_framework+0x3ac53
...
由于沒有這些 dll 的符號(hào),windbg 為了定義代碼行數(shù),就只能用 module + 0xxxxx
作為偏移來定位。
現(xiàn)在我們知道 ecx=0,那為什么會(huì)是 0 呢?接下來用 ub
觀察下匯編代碼邏輯,截圖如下:
0:000> ub 1c5b34aa L20
meeting_dashboard_module+0x3449:
1c5b3449 00c6 add dh,al
1c5b344b 45 inc ebp
1c5b344c b000 mov al,0
1c5b344e e8cde2ffff call meeting_dashboard_module+0x1720 (1c5b1720)
1c5b3453 8d45b0 lea eax,[ebp-50h]
1c5b3456 c645fc04 mov byte ptr [ebp-4],4
1c5b345a 50 push eax
1c5b345b 8bce mov ecx,esi
1c5b345d ff15a8cb611c call dword ptr [meeting_dashboard_module+0x6cba8 (1c61cba8)]
1c5b3463 8d4db0 lea ecx,[ebp-50h]
1c5b3466 8945c8 mov dword ptr [ebp-38h],eax
1c5b3469 c645fc00 mov byte ptr [ebp-4],0
1c5b346d e8feebffff call meeting_dashboard_module+0x2070 (1c5b2070)
1c5b3472 51 push ecx
1c5b3473 8b4d0c mov ecx,dword ptr [ebp+0Ch]
1c5b3476 8bd4 mov edx,esp
1c5b3478 c7450c00000000 mov dword ptr [ebp+0Ch],0
1c5b347f 890a mov dword ptr [edx],ecx
1c5b3481 8bcf mov ecx,edi
1c5b3483 e8d8010000 call meeting_dashboard_module+0x3660 (1c5b3660)
1c5b3488 837dc801 cmp dword ptr [ebp-38h],1
1c5b348c 8b4f08 mov ecx,dword ptr [edi+8]
1c5b348f 8b01 mov eax,dword ptr [ecx]
1c5b3491 7509 jne meeting_dashboard_module+0x349c (1c5b349c)
1c5b3493 6a01 push 1
1c5b3495 6a01 push 1
1c5b3497 ff507c call dword ptr [eax+7Ch]
1c5b349a eb2b jmp meeting_dashboard_module+0x34c7 (1c5b34c7)
1c5b349c ff5048 call dword ptr [eax+48h]
1c5b349f 8bc8 mov ecx,eax
1c5b34a1 ff15ccc6611c call dword ptr [meeting_dashboard_module+0x6c6cc (1c61c6cc)]
1c5b34a7 8b4f08 mov ecx,dword ptr [edi+8]
1c5b34aa 8b01 mov eax,dword ptr [ecx]
...
從匯編代碼看,當(dāng)前的 ecx 是來自于地址 edi+8
,edi 的值有可能會(huì)在 meeting_dashboard_module+0x6c6cc (1c61c6cc)
方法中被修改,我們一并觀察下。
0:000> dp @edi+8 L2
3207f46c ???????? ????????
0:000> u 1c61c6cc
meeting_dashboard_module+0x6c6cc:
1c61c6cc ?? ???
^ Memory access error in 'u 1c61c6cc'
我去,都是 ???
,這表示當(dāng)前的數(shù)據(jù)和機(jī)器指令
都沒有納入到 dump 中,這也就是為什么 dump 小的原因。
到這里好像就沒法繼續(xù)分析了,天要絕人之路嗎?
3. 還有希望嗎
雖然被當(dāng)頭一棒,但總得要掙扎一下吧,突破口也只能是匯編代碼了,通過仔細(xì)觀察,由于倒數(shù)第五行是一個(gè) jmp 指令,所以語(yǔ)句指令 1c5b349c
肯定是從別的地方飛躍過來的,翻譯成 C 代碼就是一個(gè) if else
的判斷,截圖如下:
既然走到了 else 的邏輯,那必然 ebp-38h
上的值肯定不是 1,那到底是多少呢?可以來查一查。
0:000> dp @ebp-38h L1
008fe05c 00000000
那 @ebp-38h
是誰(shuí)給的呢?繼續(xù)觀察匯編代碼,發(fā)現(xiàn)是 meeting_dashboard_module+0x6cba8
函數(shù)的返回值 eax 給的 ,從匯編邏輯看, 0 是一種異常狀態(tài)。
4. 為什么會(huì)返回 0
返回 0 也暗示了代碼在哪里報(bào)了一些錯(cuò),可以用 GetLastError()
來獲取可能調(diào)用 win32api 出錯(cuò)時(shí)設(shè)置的錯(cuò)誤碼,用 !teb
觀察里面的 LastErrorValue
值。
0:000> !teb
TEB at 0078a000
ExceptionList: 008fcf94
StackBase: 00900000
StackLimit: 008ee000
SubSystemTib: 00000000
FiberData: 00001e00
ArbitraryUserPointer: 00000000
Self: 0078a000
EnvironmentPointer: 00000000
ClientId: 00003ccc . 00004484
Real ClientId: 00000000 . 00000000
RpcHandle: 00000000
Tls Storage: 40a94180
PEB Address: 00787000
LastErrorValue: 18
LastStatusValue: 0
Count Owned Locks: 0
HardErrorMode: 0
這里的 18 是一個(gè)十進(jìn)制,十六進(jìn)制就是 0x12
,那這個(gè)錯(cuò)誤碼代表什么意思呢? !error
已經(jīng)不支持了,只能上 msdn 上找答案,截圖如下:
匯總一下:在騰訊會(huì)議錄制期間,可能是處理什么文件拋了一個(gè) There are no more files.
錯(cuò)誤,在錯(cuò)誤處理的后續(xù)邏輯中拋了崩潰。
有了這個(gè)信息之后,可以到外網(wǎng)搜一下 (https://windowsreport.com/there-are-no-more-files),常見的解決辦法如下:
- Solution 1 — Remove folder lock
- Solution 2 – Repair your registry
- Solution 3 — Run a full system scan
- Solution 4 — Update your OS
- Solution 5 — Remove recently installed software
- Solution 6 — Uninstall Comodo Cleaner/ ASUS security data manager
- Solution 7 — Boot into Safe Mode
具體是什么原因,由于缺少符號(hào)再深入分析下去得要花一些時(shí)間了,這里就到此為止吧。文章來源:http://www.zghlxwxcb.cn/news/detail-419354.html
三:總結(jié)
崩潰的 dump 已經(jīng)第一時(shí)間提交上去了,相信騰訊會(huì)議
的研發(fā)團(tuán)隊(duì)能夠很快解決,作為一個(gè)付費(fèi)會(huì)員,真心希望在下次錄制的時(shí)候不要再崩了。文章來源地址http://www.zghlxwxcb.cn/news/detail-419354.html

到了這里,關(guān)于記一次 騰訊會(huì)議 的意外崩潰分析的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!