안녕하세요 갱주니입니다.
처음으로 MSDN 포럼에 개발 관련 글을 정확하게 표현하면 디버깅 관련 글을 하나 올립니다.
WinDbg 버전이 계속해서 올라가면서 내부적으로 업데이트가 많이 됩니다. 예를 들어 가장 많이 사용하는 !analyze -v 명령이 몇년전에 비해 눈에 띄게 crash 원인을 찾아 주고 좀 더 많은 유용한 정보를 보여 줍니다. 이와 같은 맥락으로 계속해서 새로운 명령어들도 추가 되고 있습니다. 오늘은 새로 추가된 명령 중에 유용하다고 생각하는 2개 명령에 대해서 소개 할려고 합니다.
1) !dml_proc
!dml_proc is a new extension which
displays current processes and allows drilling into processes for more
information. The top-level process links go to more-detailed process
information, such as a thread list. Thread list entries link to thread
information and potentially stack information down to individual
frames. Kernel-mode process displays allow setting and resetting
user-mode state – embedded .process exec tags – and full !process 0 7
output. !dml_proc works for both user- and kernel-mode, auto-selecting
what information to display.
!dml_proc 는 새로 추가된 확장 명령이다. 이 명령은 현재 프로세스에 대해서 허용한 수준까지 깊게 프로세스 정보를 알아 옵니다. top-level에 있는 프로세스가 링크로 연결해서 좀더 깊이 있게 프로세스 정보를 알수 있습니다. 예를 들어 스레드 리스트 정보 같은 것입니다. 스레스 리스트 entry가 연결된 링크 정보를 통해서 스레드 스택 정보는 물론 개별 프레임 정보도 확인 할 수있습니다. User Mode Kernel Mode 둘다 사용할 수 있고 커널 모드에서는 보여주는 셋팅에 따라서 유저 모드 프로세스 정보가 나타 납니다.
[WinDbg에서 notepad 사용한 예]
노트 패드에 대한 정보가 나타난다. 특히 유용한 정보는 스레드 리스트 정보와 있는 파란색 글씨(<No name>) 를 클릭하면 나오는 스레드 스택 정보 이다.
0:001> !dml_proc 0x0
DbgId PID Image file name
0 9c8 C:\Windows\System32\notepad.exe
Browse module list
Threads:
DbgId TID Name (if available)
0 e24 <No name>
1 b70 <No name>
아래 내용은 파란색 글씨(<No name>) 를 클릭해서 나온 스레드 ID 0 스택 정보 이다.
0:001> ~[0x0]s;kM
eax=00497b48 ebx=00010619 ecx=0015eff8 edx=00000011 esi=0015f700 edi=75dafef7
eip=77315e74 esp=0015f6c0 ebp=0015f6dc iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
ntdll!KiFastSystemCallRet:
77315e74 c3 ret
# ChildEBP RetAddr
00 0015f6bc 75dafeef ntdll!KiFastSystemCallRet
01 0015f6c0 75daff22 USER32!NtUserGetMessage+0xc
02 0015f6dc 00621418 USER32!GetMessageW+0x33
03 0015f71c 0062195d notepad!WinMain+0xec
04 0015f7ac 75a8d0e9 notepad!_initterm_e+0x1a1
05 0015f7b8 772f19bb kernel32!BaseThreadInitThunk+0xe
06 0015f7f8 772f198e ntdll!__RtlUserThreadStart+0x23
07 0015f810 00000000 ntdll!_RtlUserThreadStart+0x1b
0:000> .frame 0n0;dv
00 0015f6bc 75dafeef ntdll!KiFastSystemCallRet
Unable to enumerate locals, HRESULT 0x80004005
Private symbols (symbols.pri) are required for locals.
Type ".hh dbgerr005" for details.
아래 내용은 파란색 글씨(<No name>) 를 클릭해서 나온 스레드 ID 1 스택 정보 이다.
0:000> ~[0x1]s;kM
eax=7ffde000 ebx=00000000 ecx=00000000 edx=7733c964 esi=00000000 edi=00000000
eip=772f8b2e esp=01c4f780 ebp=01c4f7ac iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
ntdll!DbgBreakPoint:
772f8b2e cc int 3
# ChildEBP RetAddr
00 01c4f77c 7733c9a0 ntdll!DbgBreakPoint
01 01c4f7ac 75a8d0e9 ntdll!DbgUiRemoteBreakin+0x3c
02 01c4f7b8 772f19bb kernel32!BaseThreadInitThunk+0xe
03 01c4f7f8 772f198e ntdll!__RtlUserThreadStart+0x23
04 01c4f810 00000000 ntdll!_RtlUserThreadStart+0x1b
0:001> .frame 0n0;dv
00 01c4f77c 7733c9a0 ntdll!DbgBreakPoint
Unable to enumerate locals, HRESULT 0x80004005
Private symbols (symbols.pri) are required for locals.
Type ".hh dbgerr005" for details.
2)lmD
lm has a new DML mode where module names
link to an lmv command giving details on a particular module. The
column headers are also active links to allow for selection of sorting
by name or by start address.
여러분들은 lm, lmvm, lm l 등의 명령어들을 정말 많이 사용했을 것이다. 특히 lm으로 로드되어 있는 모듈 리스트를 얻은 후 lmvm으로 각각 모듈에 있는 자세한 정보를 확인 했을 것이다. 나도 그랬다. 이 2가지 작업을 한번에 해주는 명령이 lmD이다.
[WinDbg에서 notepad 사용한 예]
0:001> lmD
start end module name
00620000 00648000 notepad (pdb symbols) C:\WinDDK\7100.0.0\Debuggers\sym\notepad.pdb\7DAC7B3D7D1D4E68BE2132EAB080D42C2\notepad.pdb
6cee0000 6cf85000 IMETIP (deferred)
6cf90000 6d02a000 IMKRTIP (deferred)
6db10000 6db3d000 IMJKAPI (deferred)
6db40000 6db62000 IMKRAPI (deferred)
772b0000 773d7000 ntdll (pdb symbols) C:\WinDDK\7100.0.0\Debuggers\sym\ntdll.pdb\2A581B1A8A244C51992668A826BF4FBB2\ntdll.pdb
773f0000 773f9000 LPK (deferred)
...
77440000 77503000 RPCRT4 (deferred)
lmD 명령을 통해서 로드되어 있는 모듈 리스트를 구한 후에 자세한 정보를 원하는 모듈을 클릭하기만 하면 된다.
나는 ntdll 을 클릭해 보았다. 그 결과 아래처럼 ntdll에 대해서 자세한 정보를 볼 수 있다.
0:001> lmDvmntdll
Browse full module list
start end module name
772b0000
773d7000 ntdll (pdb symbols)
C:\WinDDK\7100.0.0\Debuggers\sym\ntdll.pdb\2A581B1A8A244C51992668A826BF4FBB2\ntdll.pdb
Loaded symbol image file: C:\Windows\system32\ntdll.dll
Image path: C:\Windows\system32\ntdll.dll
Image name: ntdll.dll
Browse all global symbols functions data
Timestamp: Sat Apr 11 15:26:41 2009 (49E03821)
CheckSum: 0012C163
ImageSize: 00127000
File version: 6.0.6002.18005
Product version: 6.0.6002.18005
File flags: 0 (Mask 3F)
File OS: 40004 NT Win32
File type: 2.0 Dll
File date: 00000000.00000000
Translations: 0409.04b0
CompanyName: Microsoft Corporation
ProductName: Microsoft® Windows® Operating System
InternalName: ntdll.dll
OriginalFilename: ntdll.dll
ProductVersion: 6.0.6002.18005
FileVersion: 6.0.6002.18005 (lh_sp2rtm.090410-1830)
FileDescription: NT Layer DLL
LegalCopyright: © Microsoft Corporation. All rights reserved.
위에 설명한 명령은 아쉽게도 windbg help에 없다. MS가 왜 추가를 안했는지 나도 궁금해요. 여하튼 위 2가지 명령을 잘 사용하셔서 Happy Debugging 하는데 도움이 되기를 기대합니다.
출처 : 다년간의 프로그램밍 경험(삽질) 및 최근 디버깅에 도움을 주신 울트라 초특급 슈퍼 김 연구원님 정말 감사합니다.
펌 : http://social.msdn.microsoft.com/Forums/ko-KR/visualcplusko/thread/e8b70a59-b088-4f41-96a6-a4cd92811dce