WinDbg 공부하면서 요약한 내용을 정리한 것인데…
하다보면 느끼는데… 이런거 정리할 시간에 글자 하나라도 더 보는게 좋은거 같다.. ^^;
WinDbg로 쉽게 배우는 Windows Debugging (요약)
- 에어컨 / 김성현, 이태화, 김희준 지음 -
1장. WinDbg에 대해
WinDbg 디버깅 종류
메모리 덤프 파일
응용프로그램에 문제가 발생할 때 상태가 저장된 파일, 오류가 발생했을 시점의 레지스터, 콜스택, 메모리, 프로세스, 스레드 정보 등이 저장되며 문제가 발생한 마지막 순간의 상태를 보존한다.
설정에 따른 메모리 덤프
(예) 메모리(1GB)
ㅇ 전체 메모리 덤프 => C:\Windows\MEMORY.dmp(1GB)
ㅇ 커널 메모리 덤프 => C:\Windows\MEMORY.dmp(300MB)
ㅇ 작은 메모리 덤프 => C:\Windows\Minidump\Mini022908-01.dmp(64KB)
유저모드 vs 커널모드 가상 메모리 공강


블루스크린 (BSOD) – Blue Screen of Death
BSOD는 커널모드에서 문제가 발생했을 때 나타난다. BSOD가 발생했을 때 가장 먼저 생각하는 것이 "최근에 새로 설치한 하드웨어가 무엇이었는가"이며, 새로 설치한 하드웨어가 없다면 새로 설치한 프로그램이 무엇인가를 살펴본다. 커널모드 드라이버를 포함하는 프로그램일 수 있기 때문이다.
커널모드가 유저모드 디버깅과 다른점은 디버거가 하나의 드라이버에 연결돼 디버깅하는 것이 아니라 운영체제 자체에 연결돼 커널모드 전체를 디버깅한다
라이브 디버깅 vs 덤프 디버깅
라이브 디버깅이란 프로그램 동작 중 디버깅을 하는 것, 직접 작성한 소스코드를 한줄한줄 수행하면서 디버깅하는 경우, 이미 작성된 프로그램의 버그를 확인하는 경우
포스트모텀 디버깅(PostMortem Debugging)
라이브 디버깅을 통해 문제를 해결하는 것이 아니라 문제가 발생한 순간이나 특정한 상황을 덤프 파일과 같은 스냅샷으로 생성하고 추후에 그것을 분석해 문제를 해결하는 과정
디버그 심볼 파일 (.pdb)
디버그 심볼 파일이란 실행 파일을 빌드할 때 생성되는 디버그용 정보 파일로 포함되는 디버그 정보는 실행 파일안에 존재하는 함수나 변수들의 이름과 위치, 소스파일, 소스 라인 정보이다.
심볼 파일이 없다면 소스 라인 디버깅이 불가능할 뿐만 아니라 함수나 변수 이름조차 파악이 어렵다.
윈도우 OS 버전별 정보

[그림 1-1] 윈도우 OS 버전 순서
WinDbg 명령
드라이버(Driver)
드라이버는 커널모드 드라이버나 장치 드라이버를 줄여서 사용하는 용어로 장치를 운전(동작)해주는 소프트웨어 프로그램을 의미한다.
2장. WinDbg 시작
유저모드 라이브 디버깅
특정 프로세스를 라이브 디버깅(Live Debugging)하는 것은 소프트웨어를 개발할 때 비주얼 스튜디오를 사용해서 디버깅하는 것과 같은 개념이다.
디버거 연결
WinDbg에서 MyApp.exe(예제)를 실행하면서 연결하는 방법
Main 함수부터 디버깅 하려고 할 때 사용, MyApp.exe가 실제로 실행되기 전부터 디버거가 붙어서 실행된다.
이미 MyApp.exe가 실행된 상태에서 WinDbg를 나중에 연결하는 방법
특별한 조건으로 실행된 상태의 응용프로그램을 디버깅해야 할 때나 서비스 프로세스를 디버깅해야 할 때 사용한다.
MyApp.exe가 먼저 실행된 상태에서 어떤 문제가 발생했을 때 자동으로 WinDbg가 연결
심볼 파일 로드
로드해야 하는 심볼 파일은 크게 운영체제 심볼 파일과 디버깅하려는 모듈의 심볼 파일
1) 운영체제 심볼(웹 심볼)
File 메뉴 → Symbol File Path… 에서 심볼 경로 추가
SRV*D:\MySymbols*http://msdl.microsoft.com/download/symbols
위에 보다 더 간단한 방법으로 명령창에서 아래 명령어 입력하면 자동
0:000> .sysmfix D:\MySymbols
0:000> .reload
2) 모듈 심볼 파일
File 메뉴 → Symbol File Path… 에서 심볼 경로 추가 (마지막에 ; 하고 추가하면 됨)
SRV*D:\OsSymbols*http://msdl.microsoft.com/download/symbols;D:\MySymbols
명령창 입력 방법
0:000> .sympath
0:000> .sympath+ D:\MySymbols
실행 : g / F5
정지 : Ctrl + break
MyApp.exe 에 MyApp!CMyAppDlg::OnBreakPoint() 함수에 브레이크 포인트 설정하기
브레이크 포인트 설정> bp MyApp!CMyAppDlg::OnBreakPoint
브레이크 포인트 확인> bl

0번 브레이크 포인트 disable> bd 0
0번 브레이크 포인트 enable> be 0
브레이크 포인트 해제(Breakpoint Clear)
> bc 0
> bc *
> bc 3-5
> bc 2,7,8
콜 스택 확인
어떤 함수들이 어떤 순서로 해당 함수를 호출했는지 확인하는 것
3장. WinDbg로 디버깅하기
디버거를 붙여놓지 않은 상황에서 응용프로그램이 갑자기 종료하거나 시스템이 재부팅될 때 디버거가 붙어있지 않았다면 윈도우는 크래시 덤프(Crash Dump) = 메모리 덤프 파일을 만들어 놓는다.
유저모드 덤프 디버깅
덤프 파일 수집 (입력: drwtsn32)



문제가 발생하면 이곳에 덤프 로그가 남는다.

덤프 파일 열기

Microsoft (R) Windows Debugger Version 6.11.0001.404 X86 Copyright (c) Microsoft Corporation. All rights reserved. Loading Dump File [C:\Users\msBang\Desktop\WinDbg 예제\Ch3\Dump\UserMode Crash\user.dmp] User Mini Dump File with Full Memory: Only application data is available Comment: 'Dr. Watson generated MiniDump'
Symbol search path is: SRV*D:\OsSymbols*http://msdl.microsoft.com/download/symbols;D:\MySymbols Executable search path is: Windows XP Version 2600 (Service Pack 2) UP Free x86 compatible
Product: WinNt, suite: SingleUserTS Machine Name:
Debug session time: Sun Jun 7 02:08:38.000 2009 (GMT+9) System Uptime: 0 days 0:02:44.356
Process Uptime: 0 days 0:01:29.000 .......................... This dump file has an exception of interest stored in it. The stored exception information can be accessed via .ecxr.
(3b8.3c0): Access violation - code c0000005 (first/second chance not available) eax=00000000 ebx=00000001 ecx=0042d1a0 edx=00000055 esi=00424778 edi=0012fea0 eip=00401baf esp=0012f8c8 ebp=0012f8d4 iopl=0 nv up ei pl nz na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206 *** WARNING: Unable to verify checksum for MyApp.exe MyApp!CMyAppDlg::MyStrCpy+0x40: 00401baf 8810 mov byte ptr [eax],dl ds:0023:00000000=?? |

콜 스택 확인 – 문제가 발생한 흐름 파악

모듈 정보 보기
> lmvm MyApp (특정 모듈 정보 자세히 보기)
심볼 맞추기 (os정보와 app정보를 심볼에 추가한다)



Private 심볼은 소스파일과 변수들의 정보를 모두 포함하는 심볼 파일이다.
심볼 설정후 콜 스택 보기
> k
심볼을 맞춰 놓은 상황이므로 운영체제 함수들과 MyApp.exe 함수들의 이름이 정확히 보인다.
콜 스택이 정확하게 보이므로 함수들의 호출 흐름을 보고 어디 근처에서 문제 발생했는지 알 수 있다.
콜 스택 창에서 마지막 함수 살펴보기
문제가 발생한 이유 추측하기
커널모드 덤프 디버깅
덤프 파일 수집
ㅇ 미니덤프 => C:\Windows\Minidump\Mini022608-01.dmp (08. 2. 26 첫번째 덤프)
ㅇ 전체덤프 => C:\Windows\MEMORY.dmp
덤프 파일 열어보기
File → Open Crash Dump (MEMORY.dmp)
Microsoft (R) Windows Debugger Version 6.11.0001.404 X86 Copyright (c) Microsoft Corporation. All rights reserved.
Loading Dump File [C:\Users\msBang\Desktop\WinDbg 예제\Ch3\Dump\BugCheck 0x8E\MEMORY.DMP]  Kernel Summary Dump File: Only kernel address space is available
Symbol search path is: SRV*D:\OsSymbols*http://msdl.microsoft.com/download/symbols;D:\MySymbols Executable search path is: Windows XP Kernel Version 2600 (Service Pack 2) UP Free x86 compatible Product: WinNt, suite: TerminalServer SingleUserTS Built by: 2600.xpsp_sp2_gdr.070227-2254 Machine Name: Kernel base = 0x804d9000 PsLoadedModuleList = 0x8055e700 Debug session time: Sun Jul 5 00:45:40.609 2009 (GMT+9) System Uptime: 0 days 0:01:06.234
Loading Kernel Symbols ............................................................... ........................................................... Loading User Symbols PEB is paged out (Peb.Ldr = 7ffd500c). Type ".hh dbgerr001" for details Loading unloaded module list ........ ******************************************************************************* * * * Bugcheck Analysis * * * ******************************************************************************* Use !analyze -v to get detailed debugging information. BugCheck 8E, {c0000005, f9f2463f, f7ae7c64, 0}
*** ERROR: Module load completed but symbols could not be loaded for MyDrv.sys PEB is paged out (Peb.Ldr = 7ffd500c). Type ".hh dbgerr001" for details PEB is paged out (Peb.Ldr = 7ffd500c). Type ".hh dbgerr001" for details Probably caused by : MyDrv.sys ( MyDrv+63f ) Followup: MachineOwner --------- |
!analyze –v 메시지 보기
도움말에서 버크체크번호 확인하기 (Bug Check 0x8e)

> !analyze –v
 kd> !analyze -v
: KERNEL_MODE_EXCEPTION_NOT_HANDLED (8e) : Some common problems are exception code 0x80000003. This means a hard : Arguments:
Arg1: c0000005, The exception code that was not handled Arg2: f9f2463f, The address that the exception occurred at Arg3: f7ae7c64, Trap Frame :
TRAP_FRAME: f7ae7c64 -- (.trap 0xfffffffff7ae7c64) : STACK_TEXT: f7ae782c 805006bb 0000008e c0000005 f9f2463f nt!KeBugCheckEx+0x1b f7ae7bf4 805432d5 f7ae7c10 00000000 f7ae7c64 nt!KiDispatchException+0x3b1 f7ae7c5c 80543286 f7ae7ce0 f9f2463f badb0d00 nt!CommonDispatchException+0x4d f7ae7c70 bf805a0c 815241a8 e19f96c0 f7ae7c9c nt!Kei386EoiHelper+0x18a f7ae7ce0 f9f246a0 00000000 f9f24830 00000001 win32k!FreeObject+0x25 WARNING: Stack unwind information not available. Following frames may be wrong. f7ae7cfc f9f24fb7 00000050 e14834a8 f8427000 MyDrv+0x6a0 f7ae8c40 804f1095 81561270 815908e0 806e6410 MyDrv+0xfb7 f7ae8c50 8058070a 81590950 814b4488 815908e0 nt!IopfCallDriver+0x31 f7ae8c64 8058156d 81561270 815908e0 814b4488 nt!IopSynchronousServiceTail+0x60 f7ae8d00 8057a0c2 000000b8 00000000 00000000 nt!IopXxxControlFile+0x5c5 f7ae8d34 8054286c 000000b8 00000000 00000000 nt!NtDeviceIoControlFile+0x2a f7ae8d34 7c93eb94 000000b8 00000000 00000000 nt!KiFastCallEntry+0xfc 0012f878 00000000 00000000 00000000 00000000 0x7c93eb94 : MODULE_NAME: MyDrv : |
> .trap 0xfffffffff7ae7c64 // 트랩 프레임 보기
> k // 문제가 발생했을 당시의 콜 스택 보기
kd> k *** Stack trace for last set context - .thread/.cxr resets it ChildEBP RetAddr WARNING: Stack unwind information not available. Following frames may be wrong. f7ae7ce0 f9f246a0 MyDrv+0x63f
f7ae7cfc f9f24fb7 MyDrv+0x6a0 f7ae8c40 804f1095 MyDrv+0xfb7 f7ae8c50 8058070a nt!IopfCallDriver+0x31 : |
모듈 정보 보기
파일이름, 파일버전, 파일날짜 등을 확인하고 모듈 소스코드와 심볼 파일을 찾는다.
>lmvm MyDrv
kd> lmvm MyDrv start end module name f9f24000 f9f25c80 MyDrv (no symbols) Loaded symbol image file: MyDrv.sys Image path: \??\C:\WinDbgCD\Ch2\Bin\MyDrv.sys Image name: MyDrv.sys Timestamp: Tue Jun 02 23:37:42 2009 (4A253936) : |
MyDrv의 시작주소와 끝주소, 실행위치, 파일이름, 만들어진 날짜/시간 확인
심볼 맞추기
파일 시간이 일치하는 MyDrv.pdb 파일을 D:\MySymbols에 복사후 심볼경로 설정
> .sympath // 현재 심볼경로 확인 후 미설정이면 아래처럼
> .symfix D:\OsSymbols
> .sympath+ D:\MySymbols
> .reload
※ 운영체제 심볼 설정하기 (3가지 방법)
ㅇ _NT_SYMBOL_PATH 환경변수 이용
내 컴퓨터 → 속성 → 고급 시스템 설정 → 환경변수
_NT_SYMBOL_PATH 생성 →
SRV*D:\OsSymbols*http://msdl.microsoft.com/download/symbols
이렇게 하면 WinDbg가 실행될 때 자동으로 해당 위치를 참고해 심볼 경로를 설정후 시작
ㅇ WinDbg 명령프롬프트 실행 (-y 옵션)
C:\windbg –y SRV*D:\OsSymbols*http://msdl.microsoft.com/download/symbols
ㅇ Workspace 저장
심볼 맞춘후 모듈 정보 다시보기
> lmvm MyDrv
kd> lmvm MyDrv start end module name f9f24000 f9f25c80 MyDrv (private pdb symbols) d:\mysymbols\MyDrv.pdb Loaded symbol image file: MyDrv.sys Image path: \??\C:\WinDbgCD\Ch2\Bin\MyDrv.sys Image name: MyDrv.sys Timestamp: Tue Jun 02 23:37:42 2009 (4A253936) CheckSum: 0000EF71 ImageSize: 00001C80 : |
콜 스택 다시보기 (심볼 맞췄으니 함수명이 보일 것이다.)
kd> k *** Stack trace for last set context - .thread/.cxr resets it ChildEBP RetAddr f7ae7ce0 f9f246a0 MyDrv!MyStrCpy+0x3f [e:\windbgcd\ch2\src\mydrv\mydrv.c @ 314] f7ae7cfc f9f24fb7 MyDrv!BugCheck8E+0x40 [e:\windbgcd\ch2\src\mydrv\mydrv.c @ 328] f7ae8c40 804f1095 MyDrv!MyDrvDeviceControl+0x357 [e:\windbgcd\ch2\src\mydrv\mydrv.c @ 540] f7ae8c50 8058070a nt!IopfCallDriver+0x31 f7ae8c64 8058156d nt!IopSynchronousServiceTail+0x60 f7ae8d00 8057a0c2 nt!IopXxxControlFile+0x5c5 f7ae8d34 8054286c nt!NtDeviceIoControlFile+0x2a : |
맨 마지막(제일 윗부분)에 호출된 부분들이 자신이 작성한(MyDrv) 모듈인 경우 여기가 문제가 발생한 곳이라 인정하면 된다.
콜 스택 창에서 마지막 함수 살펴보기

콜 스택에서 해당 함수 더블클릭 (File → Source File Path 설정되어 있어야 함)

소스코드 분석

문제가 발생한 이유 추측하기
로컬 창으로 변수 보기
와치 창으로 메모리 보기 (전역변수 확인)
★ 콜 스택을 보면서 분석을 시작하는 것이 중요!