Windbg 사용법

Posted by 빵빵빵
2013/02/28 17:17 전산(컴퓨터)/PC-Windows



출처 : http://epicros.tistory.com/category/%EA%B2%8C%EC%9E%84%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D

덤프파일을 분석하려면 우선은 덤프파일을 생성할 줄 알아야 한다.

- Dr.Wtson을 이용한 덤프파일만들기
     http://epicros.tistory.com/category/게임프로그래밍/기타?page=2

그 다음으로는 WinDbg 설치하기
     http://epicros.tistory.com/category/게임프로그래밍/기타?page=3


위의 과정들이 모두 준비 되면은 분석을 시작 할 수 있다.

1. 준비물 - PDB파일, User.dmp파일, WinDbg
     * PDB파일 만드는 법은   ->  
http://epicros.tistory.com/?page=5  을 참고

2. WinDbg를 실행하자.
사용자 삽입 이미지



실행을 하게 되면 아래와 같은 화면이 뜬다.

사용자 삽입 이미지


우선은 우저 덤프파일을 열어야 하므로 메뉴 -> File -> OpenCrashDump로 덤프파일( User.dmp )을 열어준다.
   ** 덤프파일은 Dr.Watson 으로 만들 수 있다.

걍 파일을 갖다가 끌어서 놓아도 잘 열린다.. 그래도 혹시 모르니까 ㅎㅅㅎ;

덤프파일을 열면 아래와 같이 열리는데 (이미지를 클릭하면 큰 이미지로 나옵니다.)

사용자 삽입 이미지


빨간 박스 안에 있는 정보는 이 덤프파일이 미니덤프인지 전체 덤프인지 나타내는것이다.
- 전체덤프 -
   User Mini Dump File with Full Memory : Only application data i available
- 미니덤프 -
   User Mini Dump File : Only registers, stack and portions of memory are available

그러므로 위의 예제 덤프는 전체 덤프이다.

덤프의 종류 아래에는 운영체제의 종류를 알 수 있다.
Executable search path is:
Windows 2000 Version 2195 UP Free x86 compatible

이렇게 운영체제의 정보를 나타내고 있다.

그 다음 덤프는 덤프가 발생한 시간을 표시한 것이다.
Debug session time: Thu Mar 18 23:48:45.093 2010 (GMT+9)

그 아래의 Process Uptime은 프로세스 실행 후 시간이 얼마나 지났는지를 나타내 준다.
System Uptime: 22 days 16:30:32.921
Process Uptime: not available
위의 예제에서는 얼마나 진행되다 죽었는지 알 수 없다 =ㅂ=;

덤프파일을 해석해 보았으니 이제 명령어를 사용해보자.
명령어는 맨 아래의 박스에 넣을 수 있다.  0:000>  이렇게 쓰여진 박스 부분이다.

.ecxr - 명령을 수행하면서 문제가 발생했던 당시의 레지스터들을 보여준다.
0:000> .ecxr
Unable to get exception context, HRESULT 0x8000FFFF
해당 명령을 실행했을때 나온 예제이다. 이 덤프파일에서는 레지 정보를 알 수 없지만 다른 덤프 파일에서는 레지 정보를 알 수 있다.

k - 콜스택을 살펴본다.
0:000> k
ChildEBP RetAddr 
WARNING: Stack unwind information not available. Following frames may be wrong.
0011c55c 005a1388 SO_Server+0x1a4d40
0011c5b4 00451a46 SO_Server+0x1a1388
0011ff40 004630a8 SO_Server+0x51a46
0011ffc4 00448763 SO_Server+0x630a8
00120028 0044716e SO_Server+0x48763
001210c0 00419903 SO_Server+0x4716e
0012113c 0047df92 SO_Server+0x19903
00121194 0047d606 SO_Server+0x7df92
00121270 004b93bb SO_Server+0x7d606
0012ff80 006076bc SO_Server+0xb93bb
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for KERNEL32.dll -
0012ffc0 77e789d5 SO_Server+0x2076bc
0012fff0 00000000 KERNEL32!ProcessIdToSessionId+0x17d

맨 윗부분이 제일 마지막에 호출된 부분이므로 해당 위치에서 문제가 발생했음을 알 수 있다.
하지만 어느 함수에서 오류가 발생했는지는 알 수 없다.
어느 소스코드의 몇번째 라인인지는 더욱 많은 정보가 필요하다.

3. 모듈 정보 보기

lmvm SO_Server - SO_Server의 모듈정보를 본다는 뜻이다.
** lmvm 이 모듈정보를 보겠다는 명령어이고 뒤에 SO_Server 는 모듈정보를 꺼내올 프로그램이름이다.

0:000> lmvm SO_Server
start    end        module name
00400000 007fb000   SO_Server C (no symbols)          
    Loaded symbol image file: SO Server.exe
    Image path: c:\GameServer\SO Server\data\SO Server.exe
    Image name: SO Server.exe
    Timestamp:        Thu Mar 18 13:42:46 2010 (4BA1AF46)
    CheckSum:         00000000
    ImageSize:        003FB000
    Translations:     0000.04b0 0000.04e0 0409.04b0 0409.04e0

Timestamp : 파일이 생성된 날짜 / 시간을 나타낸다.
이 시간 정보는 상당히 중요한 정보인데 해당 exe파일이 컴파일 될때 당시에 만들어진 pdb파일이 필요하기 때문이다.
대부분은 릴리즈로 컴파일 할 시에 만들어진 pdb파일을 같이 보관하고 있지만 그렇지 않을 경우엔 시간 정보가 유용하게 쓰인다.

그리고 (no symbols) 부분은 exe와 일치하는 심볼파일이 로드되면 심볼파일의 경로가 표시되는 곳이지만 현재는 심볼파일이 연결되어있지 않으므로 (no symbols)로 표시되는 것이다.

4. 심볼 맞추기
심볼맞추기 라고 하지만 사실은 exe와 pdb 파일은 연결시켜 주기와 같다.

우선 심볼을 맞추기 위해서는 운영체제 심볼설정부터 해 주어야 한다.
.symfix c:\OsSymbols - 운영체제 심볼 맞추기

해당 명령을 내리면 C드라이브에 OsSymbols폴더에 운영체제 심볼파일이 로드된것을 알 수 있다.
운영체제 심볼을 맞추는 것은 굉장히 중요한 부분이다 .
나중에 오류가 발생한 함수의 라인을 찾아갈때 다른 OS의 심볼파일로 맞추어져 있다면 엉뚱한 곳에서 오류가 발생했다고 나올 수 있지 때문이다.
같은 시간에 컴파일된 exe파일과 pdb파일도 마찬가지이다. 같은 프로그램으로 컴파일된 파일이라도 다른 시간에 컴파일된 pdb파일은 엉뚱한 곳을 가르키기 때문이다.

운영체제 심볼을 맞췄다면 이제 pdb파일과 exe파일을 연결해야한다.
c:\MySymbols 해당경로에 해당이름의 폴더를 만들어 준다. 그 폴더 안에 pdb파일을 넣어준다.

.sympath+ c:\MySymbols  명령을 실행하면
0:000> .sympath+ c:\MySymbols
Symbol search path is: SRV*c:\OsSymbols*http://msdl.microsoft.com/download/symbols;c:\MySymbols

이런 메세지가 뜨게 된다.
그 후엔 .reload 명령을 내리자.
0:000> .reload
................................................
*** WARNING: Unable to verify checksum for SO Server.exe
위의 예제에서는 이런식으로 나오지만 각각 프로그램 마다 다르게 나올 수 있다.
심볼이 제대로 맞춰 졌는지 확인을 하려면

lmvm SO_Server 를 입력~!
0:000> lmvm SO_Server
start    end        module name
00400000 007fb000   SO_Server M (private pdb symbols)  c:\MySymbols\SO Server.pdb
    Loaded symbol image file: SO Server.exe
    Image path: c:\GameServer\SO Server\data\SO Server.exe
    Image name: SO Server.exe
    Timestamp:        Thu Mar 18 13:42:46 2010 (4BA1AF46)
    CheckSum:         00000000
    ImageSize:        003FB000
    Translations:     0000.04b0 0000.04e0 0409.04b0 0409.04e0


위를 보면 (no symbols)이 였던 부분이 (private pdb symbols)로 바뀌었다는 걸 알 수 있다.
심볼이 이제 연결된 것이다.

이제 심볼이 연결된 상태에서 k 콜스택을 호출해 보면 훨씬 더 많은 정보를 갖고 있는 콜스택을 호출 할 수 있다.
예제를 넣을 수도 있지만 보안을 위해서 넣지 않는다 .
위의 사항을 제대로 따라왔다면은 제대로 된 콜스택이 호출되었을 것이다.
콜스택의 제일 위에 함수를 보면 어디에서 오류 발생했는지 알 수 있을테지만 여기에 소스를 붙이게 되면은 더욱 자세한 정보를 볼 수 있다.
해당 함수의 몇번째 라인에서 오류가 발생했는지 알 수 있기때문이다.

5. 소스 연결하기
File ->Open Source File 로 들어가서 해당 프로그램의 소스 실행파일을 연결해 주면 옆에 소스가 뜨게 된다. 해당 소스의 오류가 난 라인에 가서 다른 색으로 표시해 주니 그 부분을 본다면 오류가 발생하는 부분을 쉽게 찾을 수 있을 것이다.

그리고 재밌는 점 WinDbg에서는 오류가 발생할 당시의 메모리 값도 알 수 있다.
View -> Locals 를 누르면 오류가 난 함수의 변수 값을 볼 수 있다.

**** 주의점 ****
* 같은 시간에 컴파일 된 ex와 pdb가 필요하다. 파일이 틀리면 엉뚱한 함수의 라인에서 오류가 발생했다고 할 수 있다.
* 소스를 붙여서 해당 라인을 찾는다면은 컴파일 이후 변경되지 않은 소스로 해야한다.
  소스가 한 줄이라도 변경되면은 엉뚱한 곳을 가리킬 수 있다.

2013/02/28 17:17 2013/02/28 17:17

Tags

이 글에는 트랙백을 보낼 수 없습니다