DllMain中不当操作导致死锁问题的分析--导致DllMain中死锁的关键隐藏因子2
? ? ? ? 本文介紹使用Windbg去驗證《DllMain中不當操作導致死鎖問題的分析--導致DllMain中死鎖的關鍵隱藏因子》中的結論,調試對象是文中剛開始那個例子。(轉載請指明出于breaksoftware的csdn博客)
? ? ? ? 1 g 讓程序運行起來
? ? ? ? 2 ctrl+break 中斷程序
? ? ? ? 3 ~ 查看線程數
? ? ? ? 其實該程序自己運行起來的線程只有ID為0、TID為afc的線程。18c4線程是我們在windbg中輸入ctrl+break,導致windbg在我們調試的進程中插入的一個中斷線程。以后我們看到是這個線程的操作,就可以忽略。
? ? ? ? 4 dd fs:[0] 尋找主線程TEB起始地址(7ffde000)
? ? ? 5 dt _TEB 7ffde000 查看主線程中PEB結構指針(0x7ffdc000)
? ? ? ? 6 dt _PEB 0x7ffdc000 尋找LoaderLock的指針(0x7c99e0174)
? ? ? ? 7 ?dt_RTL_CRITICAL_SECTION 0x7c99e174 查看臨界區狀態,我們看到看到LockCount值為-1,那么我們通過給它設置“寫”斷點,從而在每次“關鍵”時刻予以監控。
? ? ? ? 8?baw2 0x7c99e178 對LockCount設置寫斷點
? ? ? ? 9?g?
? ? ? ??10kb?我們看到線程號是1,即Windbg插入的線程導致的斷點,我們忽略之(我們看到關閉線程時也會進入臨界區)
? ? ? ? 11 g
? ? ? ? 12 kb 同上,忽略之
? ? ? ? 13?g
? ? ? ? 14 kb 這次是主線程(0)觸發了斷點,斷點原因是LdrLoadDll中要加鎖。
? ? ? ? 我們使用IDA反編譯LdrLoadDll,可以看到調用的位置
v4 = RtlDosApplyFileIsolationRedirection_Ustr(1, a3, &unk_7C99E214, &v11, &v14, &v17, 0, 0, 0);v5 = v4;if ( v4 >= 0 ){v9 = 1;}else{if ( v4 != -1072365560 )goto LABEL_6;}LdrLockLoaderLock(1, 0, &v10);ms_exc.disabled = 0;
? ? ? ? 15 g
? ? ? ? 16 kb 還是主線程(0)觸發了斷點,原因是LdrLoadDll中調用了LdrpLoadDll,該函數中需要進入臨界區,這是第二次進臨界區了。在《Best Practices for Creating DLLs》中有對這種現象允許的說明
The loader lock is recursive, which means that it can be acquired again by the same thread.
? ? ? ? 在LdrLoadDll中我們看到
LdrLockLoaderLock(1, 0, &v10);ms_exc.disabled = 0;if ( LdrpTopLevelDllBeingLoaded ){if ( ShowSnaps || LdrpShowRecursiveDllLoads || LdrpBreakOnRecursiveDllLoads ){DbgPrint("[%lx,%lx] LDR: Recursive DLL load\n");DbgPrint("[%lx,%lx] Previous DLL being loaded: \"%wZ\"\n");DbgPrint("[%lx,%lx] DLL being requested: \"%wZ\"\n");if ( LdrpCurrentDllInitializer )DbgPrint("[%lx,%lx] DLL whose initializer was currently running: \"%wZ\"\n");elseDbgPrint("[%lx,%lx] No DLL initializer was running\n");}}LdrpTopLevelDllBeingLoaded = v17;v6 = LdrpLoadDll(v9, a1, a2, v17, a4, 1);
? ? ? ? 在LdrpLoadDll中我們看到
? ? ? ? 17 g
? ? ? ? 18 kb 第三次進入臨界區
? ? ? ? 19 g 主線程第一次退出臨界區
? ? ? ? 20 kb 主線程第四次進入臨界區
? ? ? ? 21 g 主線程第二次退出臨界區
? ? ? ? 22?g 有線程要進入臨界區
? ? ? ? 23 kb 這次是我們在代碼中啟動的工作線程(1)要嘗試進入臨界區
? ? ? ? 24?~ 查看線程 確定有兩個線程了
? ? ? ? 25?g?
? ? ? ? 26 kb?工作線程(1)要進入臨界區,可是它不會進去的,因為它會被掛起
? ? ? ? 27 g 死鎖了
? ? ? ? 28?control+break windbg要啟動一個中斷線程,中斷線程觸發了斷點
? ? ? ? 29?~ 查看線程,ID為2的就是windbg插入的線程
? ? ? ?30?~0s 切換到主線程(0),發現主線程在內核態中出不來了
? ? ? ? 31 kb 查看主線程調用堆棧,確實是在等工作線程結束
? ? ? ? 32 ~1s 切換到工作線程,發現它也在內核態中出不來了
? ? ? ? 33 kb 查看工作線程調用堆棧
? ? ? ? 34?dt _RTL_CRITICAL_SECTION 0x7c99e174 ?查看臨界區所有權,從線程TID中我們可以看到,臨界區的確是被主線程占著。
總結
以上是生活随笔為你收集整理的DllMain中不当操作导致死锁问题的分析--导致DllMain中死锁的关键隐藏因子2的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: DllMain中不当操作导致死锁问题的分
- 下一篇: DllMain中不当操作导致死锁问题的分