WinDbg 디버깅2014. 1. 5. 14:04
반응형

프로세스 내의 크리티컬 섹션들을 보여주는 명령입니다.

유저모드 덤프, 커널모드 덤프에서 모두 사용할 수 있는데 여기선 커널 덤프에서의 사용예를 보여 드립니다.


기본적인 사용법은 다음과 같습니다.


!cs [-l] [-o]



예제 1) !cs

프로세스 내의 모든 크리티컬 섹션을 보여줍니다.

크리티컬 섹션을 다 볼 필요는 거의 없지만 기본 사용법이므로 적어봅니다.


1: kd> !cs

-----------------------------------------

DebugInfo          = 0x6A261D60

Critical section   = 0x6A262820 (ntdll!RtlCriticalSectionLock+0x0)

LOCKED

LockCount          = 0x0

OwningThread       = 0x460

RecursionCount     = 0x1

LockSemaphore      = 0x0

SpinCount          = 0x0

-----------------------------------------

DebugInfo          = 0x6A261D80

Critical section   = 0x6A262580 (ntdll!DeferedCriticalSection+0x0)

NOT LOCKED

LockSemaphore      = 0x7FC

SpinCount          = 0x0

-----------------------------------------

DebugInfo          = 0x6A262600

Critical section   = 0x6A26074C (ntdll!LoaderLock+0x0)

NOT LOCKED

LockSemaphore      = 0x0

SpinCount          = 0x0

-----------------------------------------

...



예제2) !cs -l -o

현재 락이 걸려있는 크리티컬 섹션만 보여줍니다.

크리티컬 섹션에 의한 대드락 분석시 유용합니다.


-l 은 락이 걸린 것만 보여주는 옵션이구요.

-o는 소유자의 스택을 볼 수 있게 해 주는 옵션입니다.


1: kd> !cs -l -o

-----------------------------------------

DebugInfo          = 0x77725760

Critical section   = 0x77725300 (ntdll!LdrpLoaderLock+0x0)

LOCKED

LockCount          = 0x4

WaiterWoken        = No

OwningThread       = 0x00000df4

RecursionCount     = 0x1

LockSemaphore      = 0x148

SpinCount          = 0x00000000

OwningThread       = .thread 86f27030

-----------------------------------------

DebugInfo          = 0x0033dbd8

Critical section   = 0x6f7f80c4 (WSCAPI!g_EventManager+0x2C)

LOCKED

LockCount          = 0x0

WaiterWoken        = No

OwningThread       = 0x00000e90

RecursionCount     = 0x2

LockSemaphore      = 0x18C

SpinCount          = 0x00000000

OwningThread       = .thread 8f693450

-----------------------------------------

DebugInfo          = 0x0033dca0

Critical section   = 0x71af50cc (wscisvif!g_critSecWscCallback+0x0)

LOCKED

LockCount          = 0x1

WaiterWoken        = No

OwningThread       = 0x00000e98

RecursionCount     = 0x1

LockSemaphore      = 0x14C

SpinCount          = 0x00000000

OwningThread       = .thread 86f2dd78



여러 스레드의 콜스택이 크리티컬 섹션에서 멈춰 있는 경우 어떤 스레드가 크리티컬 섹션을 소유하고 놓아주지 않는지를 찾아야 하는데요.

위와 같이 LOCKED 크리티컬 섹션을 찾아서 관심있는 크리티컬 섹션을 보면 OwningThread를 찾을 수 있습니다. 


Critical section 0x71af50cc를 추적한다고 가정하면 .thread 86f2dd78로 해당 스레드 콘텍스트로 변경하고 kv로 콜스택을 볼 수 있습니다.


그냥 다음과 같이 !thread 86f2dd78 명령을 바로 사용해서 볼 수도 있습니다.


1: kd> !thread 86f2dd78

THREAD 86f2dd78  Cid 0df0.0e98  Teb: 7ffd9000 Win32Thread: 00000000 WAIT: (Executive) UserMode Non-Alertable

    86f2df8c  Semaphore Limit 0x1

Not impersonating

DeviceMap                 84a07d60

Owning Process            9c55e7c0       Image:         MyApp.exe

Attached Process          N/A            Image:         N/A

Wait Start TickCount      14578          Ticks: 60781 (0:00:15:48.189)

Context Switch Count      17             IdealProcessor: 1             

UserTime                  00:00:00.000

KernelTime                00:00:00.000

Win32 Start Address ntdll!TppWorkerThread (0x776a2990)

Stack Init 9887b000 Current 9887ac30 Base 9887b000 Limit 98878000 Call 0

Priority 9 BasePriority 8 PriorityDecrement 0 IoPriority 2 PagePriority 5

Kernel stack not resident.

ChildEBP RetAddr  Args to Child              

9887ac48 818e91ba 86f2dd78 86f2de00 805d1120 nt!KiSwapContext+0x26 

9887ac8c 81884ef8 86f2dd78 00000000 86f2dd78 nt!KiSwapThread+0x44f

9887ace4 81a37be1 86f2df8c 00000000 81870c01 nt!KeWaitForSingleObject+0x492

9887ad4c 81887c56 000000f8 025ffa60 00000000 nt!NtWaitForKeyedEvent+0x1c1

9887ad4c 776c5cd4 000000f8 025ffa60 00000000 nt!KiSystemServicePostCall 

025ffa20 776c5540 77669767 000000f8 025ffa60 ntdll!KiFastSystemCallRet (FPO: [0,0,0])

025ffa24 77669767 000000f8 025ffa60 00000000 ntdll!NtWaitForKeyedEvent+0xc (FPO: [4,0,0])

025ffa68 776780b3 00000000 776780b3 00337150 ntdll!TppBarrierAdjust+0x18f (FPO: [Non-Fpo])

025ffa90 77678119 00337130 00000000 77696100 ntdll!TppCleanupGroupMemberWait+0x54 

025ffaa8 776781e5 00337130 00000000 00000000 ntdll!TppWorkWait+0x85 (FPO: [Non-Fpo])

025ffb14 77677e72 00337130 00000000 752ee9ce ntdll!TpWaitForWait+0xea (FPO: [Non-Fpo])

025ffb58 777f9851 0031fca8 ffffffff 025ffbac ntdll!RtlDeregisterWaitEx+0xd0 (FPO: [Non-Fpo])

025ffb68 6f7f533c 0031fca8 ffffffff 4ce62565 kernel32!UnregisterWaitEx+0x17 (FPO: [Non-Fpo])

025ffbac 6f7f5416 00000000 025ffbdc 6f7f3659 WSCAPI!CServiceMonitor::~CServiceMonitor+0x36 

025ffbb8 6f7f3659 00000001 7782b08d 00000000 WSCAPI!CServiceMonitor::`scalar deleting destructor'+0xd 

025ffbdc 6f7f5179 00000170 00000000 009d2498 WSCAPI!CEventManager::UnSubscribe+0xa1 

025ffbfc 71af1c0d 009d2508 71af509c 71af5020 WSCAPI!WscUnRegisterChanges+0xb6 

025ffc24 71af1f76 025ffc50 7767a637 025ffc8c wscisvif!CWscIsv::UnregisterWscServiceNotifications+0x15

025ffc2c 7767a637 025ffc8c 009d2498 00318fb8 wscisvif!WscNotificationThreadProcInternal+0xd 

025ffc50 776a2c1f 025ffc8c 00319018 752eef16 ntdll!TppWorkpExecuteCallback+0xf2 

025ffd80 7782d2e9 00343d20 025ffdcc 776a1603 ntdll!TppWorkerThread+0x545 (FPO: [Non-Fpo])

025ffd8c 776a1603 00343d20 752eef5a 00000000 kernel32!BaseThreadInitThunk+0xe (FPO: [Non-Fpo])

025ffdcc 776a15d6 776a2990 00343d20 00000000 ntdll!__RtlUserThreadStart+0x23 (FPO: [Non-Fpo])

025ffde4 00000000 776a2990 00343d20 00000000 ntdll!_RtlUserThreadStart+0x1b (FPO: [Non-Fpo])




Critical section 0x71af50cc를 소유하고 있는 thread 86f2dd78이 Semaphore 86f2df8c를 무한정 기다리면서...

다른 스레드가 Critical section 0x71af50cc를 얻지 못해 대드락에 빠져 있는 상황입니다.


반응형
Posted by GreeMate