74
어플리케이션 디버깅 SeongKee, KIM Software Engineer KSP R&D Center [email protected]

어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

Embed Size (px)

Citation preview

Page 1: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

1

어플리케이션 디버깅

SeongKee, KIM

Software Engineer

KSP R&D Center

[email protected]

Page 2: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

2

Agenda1. 디버깅의 형태

1. 버그: 어떻게 발생하고 어떻게 해결하는가2. 디버깅 시작하기3. 코딩 하는 동안에 디버깅하기

2. 파워 디버깅1. 디버거는 어떻게 작동하는가?2. VC++ 디버거를 이용한 파워 디버깅3. x86 어셈블리 언어와 VC++ 디버기의 디셈블리 윈도우를 이용한

파워 디버깅

3. 강력한 도구와 기술들1. Crash 주소만 가지고 소스와 라인 정보 찾기2. Crash Handler

Page 3: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

3

디버깅의 형태

1. 버그: 어떻게 발생하고 어떻게해결하는가

2. 디버깅 시작하기3. 코딩 하는 동안에 디버깅하기

Page 4: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

4

A factor the root of a Bug

• 소프트웨어 엔지니어링1. 새롭고 아직 완성되지 않은 엔지니어링

2. 사용자들 제품에 버그가 있는 것을 수용하는 편

Page 5: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

5

A factor the root of a Bug

• What’s the Bug?

– 일관성 없는 UI

– 기대에 미치지 않는 것

– 낮은 성능

– Crash or Data Collision

Page 6: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

6

A factor the root of a Bug

• 버그의 원인들– 너무 짧거나 불가능한 기한

– “코드는 먼저 시작하고 생각은 나중에 한다"라는 식

– 잘못 이해된 사양

– 엔지니어의 무시와 부적절한 트레이닝

– 품질에 대한 책임의 부족

Page 7: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

7

A factor the root of a Bug

• 디버깅에 대한 사전지식– 기술

• 프로젝트를 알아야

• 언어를 알아야

• 기술을 알아야

• OS를 알아야

• CPU를 알아야

– 디버깅 프로세스1단계: 버그를 똑같이 만들어야 한다.

2단계: 버그를 설명한다.

3단계: 버그가 여러분의 것이라고 항상 가정한다.

4단계: 부분으로 나누어서 정복해 나간다.

5단계: 창의적으로 생각한다.

6단계: 도구를 잘 이용한다.

7단계: 본격적인 디버깅을 시작한다.

Page 8: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

8

디버깅 프로세스

버그가버그가여러분의여러분의것이라고것이라고항상항상 가정한다가정한다..

버그를버그를설명한다설명한다..

버그를버그를똑같이똑같이 만들어야만들어야 한다한다..

부분으로부분으로나누어서나누어서정복해정복해나간다나간다..

도구를도구를잘잘 이용한다이용한다..

창의적으로창의적으로 생각한다생각한다..

고쳐진고쳐진버그를버그를 검증한다검증한다..

본격적인본격적인디버깅을디버깅을시작한다시작한다..

배우려고배우려고하고하고 함께함께 나누려고나누려고 한다한다..

버그버그 수정수정

새로운새로운가정가정 생성생성

Page 9: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

9

디버깅의 형태

1. 버그: 어떻게 발생하고 어떻게해결하는가

2. 디버깅 시작하기3. 코딩 하는 동안에 디버깅하기

Page 10: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

10

디버깅 시작하기

• 프로젝트가 끝날 때까지는 변동사항을 추적한다.– 버전 컨트롤 시스템

• 라벨링의 중요성

– Microsoft Visual SourceSafe 라벨(이름표)

– MKS Source Integrity 체크포인트(확인점)

– PVCS Version Manager 버전 라벨

– 버그 트랙킹 시스템• 코드를 개발하고 있는 과정에 있을 때는 Reminder를 간단히

작성하고 해야 할 일 목록을 유지하는 도구

Page 11: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

11

디버깅 시작하기

• 디버깅 시스템을 만드는 시간을 계획한다.– COM 오류반환 기준 강요

– C++ 예외처리

– 오류를 되돌리는 3가지 방법• return 값

• setjmp/longjmp

• C run-time library 의 errno 변수

Page 12: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

12

디버깅 시작하기

• 디버깅 심벌로 모든 빌드를 만든다.– VB

[Project Properties] 대화상자의 [Compiler] 탭에서 Create Symblic Info]를 체크

– VC의 첫 번째 방법1.CL.EXE로 설정으로 디버그 심벌 생성2.OBJ 파일에 디버그 심벌들 추가3.[Project Settings] [Win32 Release] [Settings For] 4.[C/C++] [General Category]5.[Debug Info] [Program Database] (/ZI 스위치 추가와 같음)6.[Program Database For Edit And Continue]를 선택하면 안됨, 이 옵션은

바이너리에 패딩과 다른 정보를 추가하여 디버그하는 동안 소스 코드를 편집할 수있게 된다.

– VC의 두 번째 방법1.LINK.EXE로 설정하여 실제 디버그 심벌 생성2.[Settings For] [Win32 Release] 선택3.[Link]탭 [General Category] [Generate Debug Info] 체그

(/DEBUG 스위치를 링커에 넣게 되고 이것은 디버그 빌드에서도 작동)4.[/OPT:REF]를 [Link]탭의 [Project Options]편집 창에 입력

Page 13: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

13

디버깅 시작하기

• 기본적인 프로젝트에서의 컴파일러 경고 레벨– CL.EXE /W3

– /W3의 다음 수준 /W4

– /WX로 설정 모든 경로를 오류로…– #pragma 경고 지시문을 이용하여 특정한 오류에 대하여 넘어갈 수

있고 특정한 헤더에서 오류 수준을 조정할 수 있다.

#pragma waruning (disable : 4201)

struct S {

float x;

struct {

int a1;

int b2;

};

} *p_s;

#pragma warning (default : 4201)

#pragma warning (push, 3)

#include “IDoNotCompileAtWarning.h”#pragma warning (pop)

C4201 오류 시 무시하려는 경우일반적인 #pragma 설정

Page 14: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

14

디버깅 시작하기

• DLL 이 로드된 곳을 안다.– VB 0x11000000– C++ 0x10000000

• DLL의 로드 주소 충돌 메시지– LDR: Dll xxx base 10000000 relocated due to

collision with yyy

• Collision 해결 방법– Platform SDK\bin\rebase.exe 를 이용한 DLL

리베이싱예)

Apple.dll, dump.dll, ginger.dll, berries.dll 리베이싱Rebase /b 0x60000000 apple.dllRebase /b 0x61000000 dump.dllRebase /b 0x62000000 ginger.dll berries.dll

Page 15: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

15

?• CL.EXE의 컴파일러 스위치들

– /P 파일로 프리프로세스 하기

– /X 기본적인 include 경로 무시하기

– /Z 맴버 정렬 구조화하기

– /GZ 디버그 빌드에서 릴리즈 빌드의 오류를 잡기

– /O1 크기를 최소화하기

• LINK.EXE의 링커 스위치들– /MAP MAP 파일 생성

– /MAPINFO:LINES MAP 파일에 라인 번호 포함

– /MAPINFO:EXPORTS MAP 파일에 EXPORT 정보 포함

– /NODEFAULTLIB 라이브러리 무시하기

– /ORDER 함수를 순서대로 넣기

– /PDBTYPE:CON PDB files 확보하기

– /VERBOSE 진행 과정 메시지 출력하기

– /VERBOSE:LIB 진행 과정 메시지에 대한 라이브러리 출력하기

– /WARN:3

Page 16: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

16

디버깅의 형태

1. 버그: 어떻게 발생하고 어떻게해결하는가

2. 디버깅 시작하기3. 코딩 하는 동안에 디버깅하기

Page 17: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

17

코딩하는 동안에 디버깅하기

• Assertion– 프로그램의 어떤 지정에서 어떤 조건이 꼭 참이라고

단언하는 것

– 조건이 거짓이 된 경우에는 그 조건이 실패했다고 알림

– 함수, 매크로, 디버그 빌드에서만 실행

– 순차적인 프로그래밍의 중요한 요소 (오류여부확인가능)

– 확인하는 모든 데이터는 “읽 기 전 용”

Page 18: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

18

코딩하는 동안에 디버깅하기

• MFC ASSERT(조건);

{

int i=0;

ASSERT(i>0);

.

.

.

}

//위와 경우 i가 0보다 크면 오류라인 표시 및 오류 명시

ASSERT의 쓰임새에 대한 설명

BOOL GetInfo(int i, LPTSTR szItem)

{

ASSERT((i>0);

ASSERT(NULL!=szItem);

}

BOOL GetInfo(int i, LPTSTR szItem)

{

ASSERT((i>0)&&(NULL!=szItem));

}

ASSERT의 올바른 설정ASSERT의 그릇된 설정

Page 19: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

19

코딩하는 동안에 디버깅하기

• 완변한 오류 조건 확인BOOL EnumerateListItems(PFNELCALLBACK pfnCallback)

{

ASSERT(FALSE == IsBadCodePtr(pfnCallback);

}

HWND 매개변수가 사용 가능한 윈도우인지 확인한다.IsWindow

메모리 포인터가 명시된 바이트의 수에 대하여 기록할 수있는지 확인한다.

IsBadWritePtr

스트링 포인터가 명시된 캐랙터의 최대 수나 스트링의NULL 터미네이터까지 읽을 수 있는지 확인한다.

IsBadStringPtr

명시된 수의 바이트에 대하여 메모리 포인터가 읽을 수있는지 확인한다.

IsBadReadPtr

메모리가 실행될 수 있는지 함수IsBadCodePtr

GDI 핸들에 대한 타입을 반환하는 GDI 서브 시스템 함수GetObjectType

설 명함 수

Page 20: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

20

코딩하는 동안에 디버깅하기

• RETURN 값을 ASSERTION 하면 정상적인프로세싱 흐름에서 문제들을 확인할 수 있다.

• Sample Code 반환값의 ASSERTION 샘플.cpp

Page 21: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

21

파워 디버깅

1. 디버거는 어떻게 작동하는가?2. VC++ 디버거를 이용한 파워 디버깅3. x86 어셈블리 언어와 VC++ 디버기의

디셈블리 윈도우를 이용한 파워 디버깅

Page 22: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

22

디버거는 어떻게 작동하는가?

• Windows Debugger– 사용자 모드 디버거 : 애플리케이션 디버깅용(GUI 사용)

• IsDebuggerPresent API 함수 사용 디버거 작동 확인

• 해석된 언어 혹은 버추얼 머신 접근을 이용하는 런타임의 경우, 버츄얼머신 자체가 완벽한 디버깅 환경을 제공하기 때문에 Win32 Debugging API를 사용하지 않는다.

– 예) SUN의 VM, MS의 VB p-code 해석기, 스크립트 환경

• Windows Debugger : WinDBG

• Compuware NuMega : BoundsChecker

• Platform SDK : HeapWalker, Depends

• Delphi : C++ 빌더 디버거 & NT Symbolic Debugger

– 커널 모드 디버거 : 커널 레벨 디버깅용• CPU와 운영체제 사이에서 작동

• SoftICE를 제외하고는 다른 커널 디버거는 User 모드 디버깅 불가

• 커널 모드에서 시스템 정지 == OS 정지 타이머와 동기화 문제

• Windows 80386 Debugger : WDEB386

• Kernel Debugger : i386KD

• SoftICE, WinDBG

Page 23: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

23

디버거는 어떻게 작동하는가?• Kernel Mode Debugger

– WDEB386• Windows 98용 커널 모드 디버거• VxD 작성에 유용• 널 모뎀 케이블 필요, 즉 두 개의 머신 필요• DOT 명령• INT41 확장 디버깅 명령 추가 가능• 운영체제의 정확한 상태 관찰

– i386KD• Windows 2000용• OS의 디버그 빌드 및 릴리즈 빌드에서 모두 사용가능• BOOT.INI에 /DEBUG 옵션 설정• 기본 포트(COM1)외의 다른 포트로 커널 모드 디버거와 통신할 경우, /DEBUGPORT 추가• 권장할 만한 디버거는 못됨

– WinDBG• 혼합 디버거• [Command]윈도우 인터페이스는 막강한다.• MSDN에서 “Debugger Extension” 토픽 참조• BreakPoint 지원

– SoftICE• 유일한 사용 디버거• 단일 머신에서 작동하는 유일한 디버거• 혼합 디버거• 멀티스ㅜ레드 애플리케이션을 효과적으로 디버깅할 수 있는 유일한 디버거• 타이밍 문제 해결이 쉽다• i386KD와 WinDBG 보다 더 많은 정보를 볼 수 있다.• HWND, Thread에 대한 확장된 정보를 볼 수 있다.

Page 24: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

24

디버거는 어떻게 작동하는가?• Crash 발생시 OS가 사용할 기본 디버거 변경은?

– Windows 2000• HKLM\Software\Microsoft\Windows

NT\CurrentVersion\AeDebug

– Windows 98• Win.ini 의 [AeDebug]

-p : 크래시 프로세스에 대한 프로세서 아이디

-e : 디버거의 디버그 루프가 첫번째 스레드 종료 디버그 이벤트를 얻게 될때 신호를보내야할 이벤트 핸들값

0 이면, 기본적인 크래시 대화상자 생성

1이면 디버거 자동 시작

Auto

"C:\Program Files\Microsoft Visual Studio\Common\MSDev98\Bin\msdev.exe" -p %ld -e %ld

Debugger

"C:\Program Files\Microsoft Visual Studio\Common\MSDev98\Bin\msdev.exe" -p %ld -e %ld

UserDebuggerHotKey

설 명AeDebug 키

Page 25: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

25

디버거는 어떻게 작동하는가?

• Sample Code 단순 디버거 제작

• Code 분석

Page 26: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

26

디버거는 어떻게 작동하는가?

• Sample Code WDBG

• Code 분석

Page 27: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

27

파워 디버깅

1. 디버거는 어떻게 작동하는가?2. VC++ 디버거를 이용한 파워 디버깅3. x86 어셈블리 언어와 VC++ 디버기의

디셈블리 윈도우를 이용한 파워 디버깅

Page 28: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

28

VC++ 디버거의 파워 디버깅

• Breakpoint 의 구문– Context 부분

• 프로그래밍시 변수처럼 생각

• 디버거에게 Breakpoint에 대한 명확한 위치를 제공

– 위나, 표현식이나 변수 또는 Windows Message 조건

– Breakpoints Dialog• AdvencedBP.cpp의 20번째 줄에 Breakpoint 설정 옵션

{,AdvencedBP.cpp,}.20

• App 시작점 Breakpoint 설정 mainCRTStartup 시작

주소 0x401210

Page 29: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

29

VC++ 디버거의 파워 디버깅

• System 혹은 export된 함수의Breakpoint

– 시스템 DLL 함수에Breakpoint 설정은 Windows 2000에서만 가능

– Load COFF (Common Object File Format) & Export 를 Check해야 함

• 디버그 레지스터는 하나의주소와 그 주소에서 1바이트나2바이트 또는 4바이트만 볼 수있게 제한되어 있다.

– 표현식과 데이터 변경 위치에대한 실제 주소 값을 이용하는것이 최선의 방법

Page 30: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

30

VC++ 디버거의 파워 디버깅

• _stdcall 기본 호출 스타일, 접미사 ‘@’• 예)

– 하나의 매개변수를 취하는 LoadLibrary의 경우, _LoadLibrary@4

– 10개의 매개변수를 취하는 CreateProcess의 경우, _CreateProcessA@40

– 어떠한 매개변수도 갖지 않는 TlsAlloc의 경우, _TlsAlloc@0

Page 31: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

31

VC++ 디버거의 파워 디버깅

• Skip Count

i = 5에서 Breakpoint

Page 32: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

32

VC++ 디버거의 파워 디버깅• 조건 표현식

– C 스타일 조건 연산자만 이용

– Breakpoint 조건 표현식은 어떠한 함수도 호출 X

– Breakpoint 조건 표현식은 어떠한 매크로 값도 갖지 X

Intel CPU floating-point 레지스터@ST0, @ST1, @ST2, @ST3, @ST4, @ST5, @ST6, @ST7

Intel CPU 레지스터@EAX, @EBX, @ECX, @EDX, @ESI, @EDI, @EIP, @ESP, @EBP, @EFL

문서화되지 않은 클럭레지스터:[Watch]윈도우에서만 사용할 수 있음

@CLK

현재 스레드에 대한 thread information block: 디버거가 “FS:0” 포맷을 다루지 않기때문에 필요함

@TIB

마지막 오류값: GetLastError API 함수가반환하는 값과 같은 값

@ERR

설 명레지스터 표현

Page 33: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

33

VC++ 디버거의 파워 디버깅

• 원격 디버깅에 필요한 파일과 그것들의 VC++의 설치된 위치

%SYSTEMROOT%\System32PSAPI.DLL

(Windows 2000 only)

%SYSTEMROOT%\System32MSVCRT.DLL,

MSVCP60.DLL

<VS Common>\MSDEV98\BIN

MSVCMON.EXE,

TLN0T.DLL,

DM.DLL,

MSDIS110.DLL

VC++의 설치된 위치파 일

• 디버깅시 바이너리 파일 위치를 리셋하는 방법 opt 파일을 지우면 모든

Breakpoint들과 화면 배치들을 잃어 버리게 됨

Page 34: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

34

VC++ 디버거의 파워 디버깅

• Breakpoint 설정의 Tip & Trick– 위치 Breakpoint 설정 방법

1. Source Line

2. Dissembly

3. Call Stack

– [Watch] Window• 변수 값을 언제라도 바꿀 수 있다.

• @CLK 을 이용하여 코드의 시간을 잴 수 있다.

– 포맷 데이터와 표현식 평가• “@EAX,hr” @EAX는 return값이 저장되는 Intel CPU

레지스터임

Page 35: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

35

VC++ 디버거의 파워 디버깅• [Watch] Window 변수에 대한 포맷 심벌

WM_CLOSE0x0010,wmWindows 메시지 번호wm

WC_DEFULATCHAR(VC6에서안됨)0x00000040,wcWindows 클래스 플래그wc

S_OK0x00000000,hrHRESULT 또는 Win32 오류코드hr

유니코드 스트링이나 ANSI 스트링(AUTOEXP.DAT에 있는 설정의Unicode 스트링에 따라 결정됨)

st

“Hello world”szWHiWorld,su유니코드 스트링su

“Hello world”szHiWorld,s스트링s

‘e’0x0065,c단일 캐릭터c

1.53./2.,g부호가 있는 floating-point또는 부호가있는 과학 표기이고 모두 짧은 형태

g

1.500000e+0003./2.,e부호가 있는 과학표기e

1.5000003./2.,f부호가 있는 floating-pointf

0x0c220x00406042,hxD,I,u,o,x,X에 대한 long과short접두사

l,h

0x0000F06561541,X16진 정수x,X

01701450xF065,o부호가 없는 8진 정수o

1010x0065,u부호가 없는 십진 정수u

-268373915(int)0xF000F065,d부호가 있는 십진 정수d,I

디스플레이예 제포맷 설명심 벌

Page 36: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

36

VC++ 디버거의 파워 디버깅• [Watch] Window의 메모리 덤프에 대한 포맷 심벌

+/- expender를 이용한 10 캐릭터의 확장된 배열pCharArray,10(문서화 되지 않았음) 값들의 명시된수로 메모리 위치를 가리키는포인터를 확장함

#

0x0012ffac

34b3 00cb 3084 8094 22ff 308a 2657 0000

?.?????.

0x0012ffac,mu2byte character (UNICODE)mu

0x0012ffac

8094308400cb34b3 00002657308a22ff0x0012ffac,mq4 quadwordmq

0x0012ffac

00cb34b3 80943084 308a22ff 000026570x0012ffac,md4 double wordmd

0x0012ffac

34b3 00cb 3084 8094 22ff 308a 2657 00000x0012ffac,mw8 wordmw

0x0012ffac

b3 34 cb 00 84 30 94 80 ff 22 8a 30

57 26 00 00

.4…0…”.0W&…….

0x0012ffac,mb16 ASCII character 뒤에16진수의 16비트

mb

0x0012ffac

b3 34 cb 00 84 30 94 80 ff 22 8a 30

57 26 00 00

.4…0…”.0W&…….

0x0012ffac,m16 ASCII character 뒤에16진수의 16비트

m

0x0012ffac

.4…0…”.0W&…….1W&.0.:W..1

….”..1.JO&.1.2..”..1…0y….1

0x0012ffac,ma64 ASCII characterma

디스플레이예 제포맷 설명심벌

Page 37: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

37

VC++ 디버거의 파워 디버깅

• [Set Next Statement] Command– 디버깅시 소스 윈도우와 [Disassembly] 윈도우에서

마우스 오른 버튼을 누르면 메뉴에 나옴.

– CPU EIP 레지스터 직접 설정하여 바꿀 수 있다.

– 최적화된 릴리즈 빌드에서는 [Disassembly]윈도우에서만 사용하는 것이 가장 안전함.

– 오류 핸들러를 테스트할때 유용함.

– 테스트시 [Run To Cursor]도 유용함.

Page 38: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

38

파워 디버깅

1. 디버거는 어떻게 작동하는가?2. VC++ 디버거를 이용한 파워 디버깅3. x86 어셈블리 언어와 VC++ 디버기의

디셈블리 윈도우를 이용한 파워 디버깅

Page 39: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

39

ASM/DASM 의 파워 디버깅

• ASM은 언어의 마술인가? XXX

• [Disassembly]윈도우에서 어떻게 생존하는가?– 스택에서 매겨변수들을 찾아보는 방법

– [Disassembly]윈도우 안에서 돌아다니는 방법

Page 40: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

40

ASM/DASM 의 파워 디버깅

• 애플리케이션이 취급하는 데이터의 모든 비트가 한번이나 여러 번 레지스터를 통과 레지스터를통한 잘못 진행된 코드 분석 가능

• x86 CPU의 레지스터– 범용 레지스터 : EAX, EBX, ECX, EDX, ESI, EDI,

ESP, EBP

– 세그먼트 레지스터 : CS, DS, ES, SS, FS, GS

– 지시포인터 : EIP

– 플래그 레지스터 : EFLAGS

Page 41: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

41

ASM/DASM 의 파워 디버깅

베이스/프레임 포인터. 이 레지스터는프로시저에 대한 스택 프레임을 가지고 있음

BPEBP

스택 포인터. 함수를 호출할 때 지역변수를위해서 스택에 공간을 만들고 그 스택을지우면서 이 레지스터는 암시적으로 변경됨

SPESP

메모리 이동이나 비교 지시에서 수신지 주소가여기에 저장됨

DIEDI

메모리 이동이나 비교 지시에서 원천 주소가여기에 저장됨

SIESI

64비트 값의 높은 32비트들이 여기에 저장됨DHDLDXEDX

루프 지시 카운터를 세는데 이 레지스터를사용함

CHCLCXECX

BHBLBXEBX

정수 함수 반환값들이 여기에 저장됨AHALAXEAX

특수한 용도

높은 바이트액세스

(비트 8~15)

낮은 바이트액세스

(비트 0~7)

16비트액세스

32비트레지스터

• 범용 레지스터

Page 42: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

42

ASM/DASM 의 파워 디버깅

지시 결과의 가장 중요한 비트를 반영함. 0은 양의값을, 1은 음의 값을 의미함

SFSign 플래그PL

인터럽트가 가능하면 1로 설정됨. 이 플래그는사용자 모드에서는 항상 1로 설정되어 있음

IFInterrupt Enable 플래그

EI

스트링 지시가 가장 높은 주소에서 가장 낮은주소로 프로세스되면 1`로 설정됨(자동 내림 차순). 0은 스트링 지시가 낮은 주소에서 높은 주소로프로세스 되는 것을 의미함(자동 오름 차순)

DFDirection 플래그

UP

연산의 결과가 정수 overflow나 underflow일경우 1로 설정됨

OFOverflow 플래그

OV

노트인텔 매뉴얼의사 기호

의미[Registers]

윈도우 플래그

• [Registers] 윈도우의 플래그 값

Page 43: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

43

ASM/DASM 의 파워 디버깅

산술 연산이 carry나 borrow를 결과의 가장중요한 비트에서 생성하게 되면 1로 설정됨. 부호가 없는 정수 산술에 대한 overflow 조건에서는 1로 설정됨

SFCarry 플래그CY

결과의 중요한 바이트가 1로 설정된 짝수 비트를포함하고 있다면 1로 설정됨

PFParity 플래그PE

바이너리로 코딩 된 십진 연산이 carry(CPU내부에서 각종 연산이 수행된 후 올림이있었는지를 나타내는 플래그 비트)나borrow(뺄셈에서 아랫자리 숫자가 빼기에모자랄 때 윗자리 숫자에서 하나를 빌려오는 것)를생성했다면 1로 설정됨

AFAuxiliary Carry 플래그

AC

지시 결과가 0이면 1로 설정됨. 이 플래그는 비교지시에 있어서 중요함

ZFZero 플래그ZR

노트인텔 매뉴얼의사 기호

의미[Registers]

윈도우 플래그

• [Registers] 윈도우의 플래그 값

Page 44: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

44

ASM/DASM 의 파워 디버깅

• 메모리 어드레싱– Intel CPU는 원천과 수신지가 모두 메모리 참조가 되는

것을 허용하지 않는다.

– 메모리 참조 : 브랫킷 안에 있는 피연산자들을 의미한다.

– [EAX] : EAX의 주소에서 메모리를 얻으라는 것을 의미.

– [EAX+0Ch] : EAX의 값에 0xC를 추가하고 그메모리를 얻으라는 것을 의미

– 디셈블리가 포인터 크기를 지정하지 않으면, 크기는double word

Page 45: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

45

ASM/DASM 의 파워 디버깅

• VC++ inline ASM– Zoom

– __asm (실행하고 싶은 어셈블리 언어 입력)

• NOP : 아무 것도 하지 않는 지시

Page 46: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

46

ASM/DASM 의 파워 디버깅• PUSH : word/double word를 스택에 넣는다• POP : 스택에서 값을 꺼낸다

• Intel CPU는 스택을 광범위하게 사용한다.• CPU 스택의 특징 last in,first out(LIFO)

sample code…void PushPop(void){

__asm {//EAX,ECX,EDX 값을 저장PUSH EAXPUSH ECXPUSH EDX//스택에서 제거 : LIFO POP EDXPOP ECXPOP EAX

}}

0012FE14

0012FE10

0012FE0C

.

.

.

.

Stack

Page 47: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

47

ASM/DASM 의 파워 디버깅• 레지스터 값의 SWAP : POP 순서를 거꾸로

sample codevoid SwapRegistersWithPushAndPop(void){

__asm{//EAX,EBX 값들을 스택을 이용하여 스왑PUSH EAXPUSH EBX

POP EAXPOP EBX

}}

Page 48: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

48

ASM/DASM 의 파워 디버깅• MOV : CPU 의 가장 일반적인 명령, 이동

sample codevoid SwapRegisters(void){

__asm{//EAX : 레지스트 임시 저장소//ECX , EBX 값을 스왑MOV EAX, ECXMOV ECX, EBXMOV EBX, EAX

}}

• SUB : 뺀다• ADD : 더한다• INT 3 : Breakpoint, 컴파일러는 이 명령을 이용하여 파일에 있는 함수를 Pending• LEAVE : 높은 레벨 프로시저를 종료, 함수를 마칠 때 LEAVE 명령으로 CPU 상태 저장

Page 49: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

49

ASM/DASM 의 파워 디버깅• Entry & Exit

• 시작하는 것 : prolog, 종료하는 것 : epilog

• 컴파일러는 prolog와 epilog 모두 자동 생성

• prolog를 설정할 때 코드는 함수의 지역변수 와 매개변수를 액세스할수 있게 설정되며, 이러한 액세스를 스택 프레임이라고 함

• EBP 레지스터를 이용하여 스택 프레임을 가리키는 포인터를 가지고있게 함

sample code

__asm {

//기본 prolog 설정

PUSH EBP //스택 프레임 레지스터를 저장

MOV EBP, ESP //지역 함수 스택 프레임을 ESP로 설정

SUB ESP, 20h //지역변수를 위하여 0x20 바이트에 대하여스택에 공간을 만든다. SUB 지시는 함수가지역 변수를 가지고 있을 때만 나타난다.

Page 50: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

50

ASM/DASM 의 파워 디버깅

• epilog : prolog의 연산을 다시 되돌림

sample code

__asm {

//기본 epilog 분석

MOV ESP, EBP //스택값을 저장

POP EBP //스택 프레임 레지스터를 복구

}

• 릴리즈 빌드의 경우는 LEAVE 명령이 이용됨– 이유 : MOV/POP 보다 빠르다

• 컴파일러 코드 생성의 선택– 프로그램의 속도 인가? / 프로그램의 크기인가?

Page 51: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

51

ASM/DASM 의 파워 디버깅• 변수 액세스 : 전역변수, 매개변수, 지역변수

– 전역 변수 : 고정주소 ( 메모리 참조이기 때문에 액세스가 쉽다)

sample code (인라인 어셈블러에서 전역 변수 액세스 방법)

int g_iVal=0;

void AccessGlobalMemory(void)

{

__asm {

//전역 변수를 48,059h

MOV g_iVal, 0BBBBh

//심벌들이 로드되면, [Disassembly]윈도우

//MOV DWORD PTR [g_iVal (00403060)], 0BBBBh를 보여줌

//심벌들이 로드되지 않으면, [Disassembly]윈도우는

//MOV DWORD PTR [0040360], 0BBBBh를 보여줌

}

}

Page 52: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

52

ASM/DASM 의 파워 디버깅• 매개변수 액세스

sample codevoid AccessParameter(int iParam){

__asm {//EAX로 iParam 값을 이동MOV EAX, iParam

//심벌이 로드되면 [Disassembly]윈도우는//MOV EAX, DWORD PTR [iParam]

//심벌이 로드되지 않으면 [Disassembly]윈도우는//MOV EAX, DWORD PTR [EBP+8]

}}

Page 53: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

53

ASM/DASM 의 파워 디버깅• 지역변수 액세스

sample codevoid AccessLocalVariable(void){

int iLocal;__asm {

//지역 변수를 23으로 설정MOV iLocal, 017h

//심벌이 로드되면 [Disassembly]윈도우는//MOV DWORD PTR [iLocal], 017h

//심벌이 로드되지 않으면[Disassembly]윈도우는

//MOV [EBP-4], 017h}

}

Page 54: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

54

ASM/DASM 의 파워 디버깅• 기본 스택 프레임에 있어서 매개 변수들이 EBP에서 +의 오프셋으로 되는

이유와 지역변수들이 –의 오프셋으로 되는 이유

sample codevoid AccessLocallsAndPramsExample(int *pParam1, int *pParam2){

int iLocal1=3;int iLocal2=0x42;

iLocal1=*pParam1;iLocal2=*pParam2;

}

• AccessLocallsAndPramsExample에 있는 첫 번째 세 개의 어셈블리 언어지시들은 함수 prolog를 형성하고 있다.

• prolog가 실행되면, 스택과 베이스 포인터가 설정되고 매개변수는 EBP에서+의 오프셋로 액세스되고 지역변수는 EBP에서 –의 오프셋을 통해 액세스할 수있게 된다.

0x0012FF1C

0x0012FF70

ESP

EBP0x0012FF1C0x0012FE24 0x0012FF50

0x0040136B

0x0012FF28

반환주소

0x0012FF1C0x0012FE24

Page 55: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

55

ASM/DASM 의 파워 디버깅138: void AccessLocalsAndParamsExample ( int * pParam1 , int * pParam2 )139: {00401097 push ebp00401098 mov ebp,esp0040109A sub esp,8140: int iLocal1 = 3 ;0040109D mov dword ptr [iLocal1],3141: int iLocal2 = 0x42 ;004010A4 mov dword ptr [iLocal2],42h142:143: iLocal1 = *pParam1 ;004010AB mov eax,dword ptr [pParam1]004010AE mov ecx,dword ptr [eax]004010B0 mov dword ptr [iLocal1],ecx144: iLocal2 = *pParam2 ;004010B3 mov edx,dword ptr [pParam2]004010B6 mov eax,dword ptr [edx]004010B8 mov dword ptr [iLocal2],eax145: }004010BB mov esp,ebp004010BD pop ebp004010BE ret

Page 56: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

56

ASM/DASM 의 파워 디버깅• 프로시저 호출과 반환

– CALL / RETsample codevoid CallSomeFunctions(void){

__asm {//import 된 함수인 GetLastError를 호출하고 EAX에 반환값이 저장. //이것은 어떤 매개변수도 없는 IAT를 통한 호출이기 때문에 호출되는 것을 말한다.CALL DWORD PTR[GetLastError]

//심벌이 로드되면, [Disassembly]윈도우는//CALL DWORD PTR[__imp__GetLastError@0 (00402000)]를 보여줄 것임//심벌이 로드되지 않으면, [Disassembly]윈도우는//CALL DWORD PTR[00402000]을 보여줄 것이다.

//이 파일 안에서 함수를 호출한다.CALL NOPFuncOne

//심벌이 로드되면, [Disassembly]윈도우는//CALL NOPFuncOne (00401000)를 보여준다.//심벌이 로드되지 않으면, [Disassembly]윈도우는//CALL 00401000을 보여준다.

}}

Page 57: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

57

ASM/DASM 의 파워 디버깅• 호출 규약

Custom prolog와epilog가 필요한 경우에VxD에 의하여 사용된다.

없음호출자는 스택에서인자들을 제거한다.

L Rnaked

기본 호출을 명시하지 않는함, C++클래스 method 에서 자동으로 사용된다.

없음호출자는 스택에서인자들을 제거한다.

L R

this 매개변수 : ECX 레지스터

this

Intel CPU들에 유일하게적용된다. 이러한 호출규약은 Borland Delphi 컴파일러의 디폴트 호출규약이 된다.

@Foo@12에서처럼, “@”뒤에 이름이 오고그 뒤에 @와 인자목록을 십진 바이트숫자가 오게 된다.

호출자는 스택에서인자들을 제거한다.

첫번째 두 개: DWORD

매개변수들: ECX,EDX

나머지 : L R

__fastcall

거의 모든 시스템 함수가사용한다. VB내부함수들에서는 디폴트이다.

_Foo@12에서처럼이름 앞에 밑줄이나오고 그 뒤에는“@”이 십진 바이트의수를 가지고 붙게된다.

호출된 것은 그것은 자체인자들을 스택에서제거한다.

L R__stdcall

C와C++함수들에서는디폴트이다.

_Foo에서처럼밑줄이 함수 이름앞에 나오게 된다.

호출자는 스택에서인자들을 제거한다. 이러한호출 규약은 변수 인자목록을 허용하는 유일한것이다.

L R__cdecl

노트이름 표시스택 유지인자 흐름 방향호출 규약

Page 58: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

58

ASM/DASM 의 파워 디버깅

• sample code (호출 규약)

Page 59: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

59

강력한 도구와 기술들

1. Crash 주소로 소스와 라인 정보 찾기2. Crash Handler3. 다중 머신과 다중 프로세스4. 다중 스레드로 된 Deadlock5. 자동화된 테스트6. OutputDebugString 호출하기

Page 60: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

60

Crash 주소로 소스와 라인을…• 문제에 대한 주소밖에 없다

– MAP 파일 이용

– CrashFinder Utility

Page 61: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

61

Crash 주소로 소스와 라인을…• MAP 파일 만들기와 읽기

– 프로그램의 전역 심벌들과 소스, 라인 번호 정보에 대하여텍스트로 나타낼 수 있는유일한 방법

– [Project Settings] [Link]Tab [Project

Options] 에/MAPINFO:EXPORTS 와/MAPINFO:LINES 스위치입력으로 만든다.

– [Category]목록상자[Debug] [Generate

Mapfile] 체크

Page 62: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

62

Crash 주소로 소스와 라인을…• MAP 파일 내용(1)

MapDLLTimestamp is 40c461a7 (Mon Jun 07 21:37:59 2004)Preferred load address is 03900000

Start Length Name Class0001:00000000 00001421H .text CODE0002:00000000 0000012cH .rdata DATA0002:00000130 00000193H .edata DATA0003:00000000 00000104H .CRT$XCA DATA0003:00000104 00000104H .CRT$XCZ DATA0003:00000208 00000104H .CRT$XIA DATA0003:0000030c 00000104H .CRT$XIZ DATA0003:00000410 00000176H .data DATA0003:00000588 00000030H .bss DATA0004:00000000 00000014H .idata$2 DATA0004:00000014 00000014H .idata$3 DATA0004:00000028 00000050H .idata$4 DATA0004:00000078 00000050H .idata$5 DATA0004:000000c8 00000179H .idata$6 DATA

Address Publics by Value Rva+Base Lib:Object0001:00000030 _DllMain@12 03901030 f MapDLL.obj0001:0000004c ?MapDLLFunction@@YAHXZ 0390104c f MapDLL.obj

Page 63: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

63

Crash 주소로 소스와 라인을…• MAP 파일 내용(2)

.

.

.

0004:00000090 __imp____dllonexit 03905090 MSVCRTD:MSVCRTD.dll

0004:00000094 __imp___onexit 03905094 MSVCRTD:MSVCRTD.dll

0004:00000098 \177MSVCRTD_NULL_THUNK_DATA 03905098 MSVCRTD:MSVCRTD.dll

entry point at 0001:00000220Line numbers for .\Debug\MapDLL.obj(D:\My Docs\KSP 교육

자료\Debugging Applications 소스 코드\MapFile\MapDLL\MapDLL.cpp) segment .text

10 0001:00000030 12 0001:0000003b 19 0001:00000041 20 0001:00000046

24 0001:0000004c 25 0001:00000050 26 0001:00000067 27 0001:0000006c

35 0001:00000076 36 0001:0000007a 37 0001:0000007f 38 0001:00000096

39 0001:0000009c 40 0001:0000009f 30 0001:000000a9 31 0001:000000ad

32 0001:000000c4

Page 64: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

64

Crash 주소로 소스와 라인을…• MAP 파일 내용(3)

.

.

.

Exports

ordinal name

1 ?MapDLLFunction@@YAHXZ (int __cdeclMapDLLFunction(void))

2 ?MapDLLHappyFunc@@YAPADPAD@Z (char * __cdecl MapDLLHappyFunc(char *))

모듈이 export 된 함수들을 포함하면 MAP 파일의 마지막 섹셕은export 들의 목록을 가지고 있다.

Page 65: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

65

Crash 주소로 소스와 라인을…• 함수와 소스 파일 & 라인 번호 찾기

– 예) MAPDLL.DLL의 Crash가 0x03901099 주소에서 일어 났을 경우1. MAP 파일에서 preferred load address 확인

2. public 함수 섹션에 있는 마지막 주소 확인

3. C 정적 함수에서 Crash가 일어났을 경우, Crash 주소보다 큰첫 번째 함수 주소를 찾을 때까지 [Rva+Base] 칼럼의아랫부분을 확인

1. 0x39010F6이 0x3901099 Crash 주소보다 크므로“?MapDLLHappyFunc@@YAPADPAD@Z”

2. 라인 번호 찾기 계산 : (Crash addr) – (preferred load addr) – 0x1000 0x03901099 – 0x03900000 – 0x1000 = 0x99

3. MAPDLL.CPP 에서 38 0001:00000096 (Line 38)

Page 66: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

66

Crash 주소로 소스와 라인을…

0x03901099 – 0x03900000 – 0x1000 = 0x99즉 0x99는 0x96과 0x9c 사이의크래시이므로MAPDLL.CPP 에서 38번째라인이문제가됨을알수있게된다.

MAPDLL.MAP 파일

Page 67: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

67

강력한 도구와 기술들

1. Crash 주소로 소스와 라인 정보 찾기2. Crash Handler3. 다중 머신과 다중 프로세스4. 다중 스레드로 된 Deadlock5. 자동화된 테스트6. OutputDebugString 호출하기

Page 68: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

68

Crash Handler

• Exception Handler– C++ 의 한정

• Unhandled Exception Filter– Microsoft Windows OS에 제한

• Register

• Call Stack

Page 69: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

69

Crash Handler

• 구조화된 예외 핸들링 vs C++ 예외 핸들링

(Structured Exception Handling vs C++ Exception Handling)

• 각각의 다른 접근 방법이 있다.

• 예외 핸들링을 빠르게 하는 것은 C++ 가 두 개의메인 타입의 예외 핸들링을 사용하기 때문에부분적으로 힘들다.

Page 70: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

70

Crash Handler

• 구조화된 예외 핸들링– 언어에 종속적

– C/C++ __try/__except & __try/__finally

– __try/__except• 코드는 __try안에, __except 블록 안에 예외 처리 방법 정의

• EXCEPTION_EXECUTE_HANDLER 라는 예외 필터 값 존재

– __try/__finally : __try 블록에서 코드가 완벽히종료되지 않더라도 함수에서 나올 때 항상 함수의 부분을실행

Page 71: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

71

Crash Handlersample code (SEH)void Foo(void){

__try {__try {

//우리의 코드} __except (EXCEPTION_EXECUTE_HANDLER) {

//이 블록은 블록에 있는 코드가 access violation이나//다른 클래시를 일으킨 경우에 실행될 것이다.//여기에 있는 코드가 예외 핸들러라고 불린다.

}} __finally {

//이 블록은 함수가 크래시를 일으키는 것과 상관없이 실행된다.//소멸 코드가 여기에 온다.

}}

Page 72: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

72

Crash Handler• 예외 핸들러를 찾고 실행하는 프로세스 : ‘unwinding the exception’• 예외 핸들러는 내부 스택에 저장됨

sample code (예외 필터 프로세싱이 있는 예제 SHE)long IntegerDivide(long x, long y){

long lRet;_try {

lRet = x/y;} __except(EXCEPTION_INT_DIVIDE_BY_ZERO ==

GetExceptionCode() ? EXCEPTION_EXECUTE_HANDLER: EXCEPTION_CONTINUE_SEARCH ) {lRet = NaN; //NaN(숫자가 아님)

}return (lRet);

}

Page 73: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

73

Crash Handler

• C++ 예외 핸들링 : 키워드 try, catch

• 예외 unwinding의 초기화 키워드 : Throw

Page 74: 어플리케이션디버깅pds.devpia.com/MAEUL/top_pds/18000/17708... ·  · 2004-06-30• Windows 80386 Debugger : WDEB386 • Kernel Debugger : i386KD • SoftICE, WinDBG. 23

74

Crash Handlersample code (C++ 예외 핸들러)BOOL ReadFileHeader(CFile *pFile, LPHEADERINFO pHeader){

ASSERT(FALSE == IsBadReadPtr(pFile, sizeof(cFile *)));ASSERT(FALSE == IsBadReadPtr(pHeader, sizeof(LPHEADERINFO)));if((TRUE == IsBadReadPtr(pFile, sizeof(Cfile *))) ||

(TRUE == IsBadReadPtr(pHeader, sizeof(LPHEADERINFO)))) {return FALSE;

}BOOL bRet;try {

pFile->Read(pHeader, sizeof(HEADERINFO))/bRet;

} catch (CFileException *e) {//파일이 잘려서 헤더가 읽혀질 수 없다면 그것을 핸들링 해야 한다.//그렇지 않으면, unwinding을 계속한다.if(CFileException::endOfFile == e->m_cause) {

e->Delete();bRet=false;

} else {//throw 키워드는 이 catch블록에 들어오는 동일한 예외를 던진다.throw;

}}return bRet;

}