소스 모드에서 디버깅
디스어셈블된 이진 파일 대신 코드의 소스를 분석할 수 있는 경우 애플리케이션 디버깅이 더 쉽습니다.
원본 언어가 C, C++또는 어셈블리인 경우 WinDbg, CDB 및 KD는 디버깅에서 소스 코드를 사용할 수 있습니다.
컴파일 요구 사항
원본 디버깅을 사용하려면 이진 파일이 빌드되면 컴파일러 또는 링커에서 기호 파일(.pdb 파일)을 만들어야 합니다. 이러한 기호 파일은 이진 명령이 소스 줄에 해당하는 방법을 디버거에 보여 줍니다.
또한 기호 파일에 실제 원본 텍스트가 포함되어 있지 않으므로 디버거는 실제 원본 파일에 액세스할 수 있어야 합니다.
가능한 경우 컴파일러와 링커는 코드를 최적화하지 않아야 합니다. 코드가 최적화된 경우 소스 디버깅 및 지역 변수에 대한 액세스가 더 어렵고 때로는 거의 불가능합니다. Build 유틸리티를 컴파일러 및 링커로 사용하는 경우 최적화를 방지하려면 MSC_OPTIMIZATION 매크로를 /Od /Oi 로 설정합니다.
기호 파일 및 원본 파일 찾기
소스 모드에서 디버그하려면 디버거가 원본 파일 및 기호 파일을 찾을 수 있어야 합니다. 자세한 내용은 원본 경로를 참조하세요.
원본 디버깅 시작
디버거는 현재 디버그 중인 스레드에 대한 적절한 기호 및 원본 파일이 있을 때마다 원본 정보를 표시할 수 있습니다.
디버거를 사용하여 새 사용자 모드 애플리케이션을 시작하는 경우 Ntdll.dll 애플리케이션을 로드할 때 초기 중단이 발생합니다. 디버거는 Ntdll.dll 원본 파일에 액세스할 수 없으므로 이 시점에서 애플리케이션의 원본 정보에 액세스할 수 없습니다.
프로그램 카운터를 애플리케이션의 시작 부분으로 이동하려면 진입점에 중단점을 이진 파일에 추가합니다. 디버거 명령 창에서 다음 명령을 입력합니다.
bp main
g
그러면 애플리케이션이 로드되고 기본 함수가 입력되면 중지됩니다. (물론 기본 뿐만 아니라 모든 진입점을 사용할 수 있습니다.)
애플리케이션이 예외를 throw하면 디버거로 나뉩니다. 원본 정보는 이 시점에서 사용할 수 있습니다. 그러나 Ctrl+C, Ctrl+BREAK 또는 디버그 | 를 사용하여 중단을 실행하면 Break 명령을 실행하면 디버거가 새 스레드를 만들므로 소스 코드를 볼 수 없습니다.
원본 파일이 있는 스레드에 도달하면 디버거 명령 창을 사용하여 원본 디버깅 명령을 실행할 수 있습니다. WinDbg를 사용하는 경우 원본 창 이 나타납니다. 파일 메뉴에서 소스 파일 열기를 클릭하여 원본 창을 이미 연 경우 WinDbg는 일반적으로 원본에 대한 새 창을 만듭니다. 디버깅 프로세스에 영향을 주지 않고 이전 창을 닫을 수 있습니다.
WinDbg GUI의 원본 디버깅
WinDbg를 사용하는 경우 프로그램 카운터가 디버거에 원본 정보가 있는 코드에 있는 즉시 원본 창이 나타납니다.
WinDbg는 사용자 또는 WinDbg가 연 각 원본 파일에 대해 하나의 원본 창을 표시합니다. 이 창의 텍스트 속성에 대한 자세한 내용은 원본 Windows를 참조하세요.
그런 다음 애플리케이션을 단계별로 실행하거나 중단점 또는 커서로 실행할 수 있습니다. 단계별 실행 및 추적 명령에 대한 자세한 내용은 대상 제어를 참조하세요.
원본 모드인 경우 애플리케이션을 단계별로 실행할 때 적절한 원본 창이 포그라운드로 이동합니다. 애플리케이션을 실행하는 동안 호출되는 Microsoft Windows 루틴도 있기 때문에 디버거는 이러한 종류의 호출이 발생할 때 디스어셈블리 창을 포그라운드로 이동할 수 있습니다(디버거가 이러한 함수의 원본에 액세스할 수 없기 때문). 프로그램 카운터가 알려진 소스 파일로 돌아오면 적절한 원본 창이 활성화됩니다.
애플리케이션을 이동할 때 WinDbg는 원본 창과 디스어셈블리 창에서 사용자의 위치를 강조 표시합니다. 중단점이 설정된 줄도 강조 표시됩니다. 소스 코드는 언어 구문 분석에 따라 색이 지정됩니다. 원본 창을 선택한 경우 마우스로 기호를 마우스로 가리켜 평가할 수 있습니다. 이러한 기능 및 제어 방법에 대한 자세한 내용은 원본 Windows를 참조하세요.
WinDbg에서 소스 모드를 활성화하려면 l+t 명령을 사용하거나 디버그 메뉴에서 소스 모드를 클릭하거나 단추에서 소스 모드를 클릭합니다. 소스 모드가 활성화되면 상태 표시줄에서 ASM 표시기를 사용할 수 없는 것으로 표시됩니다.
소스 모드에서 함수를 단계별로 실행할 때 모든 지역 변수의 값을 보거나 변경할 수 있습니다. 자세한 내용은 읽기 및 쓰기 메모리를 참조하세요.
디버거 명령 창의 원본 디버깅
CDB를 사용하는 경우 별도의 원본 창이 없습니다. 그러나 원본을 단계별로 진행하면서 진행 상황을 계속 볼 수 있습니다.
CDB에서 소스 디버깅을 수행하려면 먼저 .lines(소스 줄 지원 토글) 명령을 실행하거나 -lines 명령줄 옵션을 사용하여 디버거를 시작하여 소스 줄 기호를 로드해야 합니다.
l+t 명령을 실행하면 모든 프로그램 단계별 실행이 한 번에 하나의 소스 줄로 수행됩니다. l-t를 사용하여 한 번에 하나의 어셈블리 명령을 단계별로 실행합니다. WinDbg를 사용하는 경우 이 명령은 디버그 메뉴에서 소스 모드를 선택하거나 선택 취소하거나 도구 모음 단추를 사용하는 것과 동일한 효과를 줍니다.
l+s 명령은 프롬프트에 현재 소스 줄과 줄 번호를 표시합니다. 줄 번호만 표시하려면 l+l 을 대신 사용합니다.
l+o 및 l+s를 사용하는 경우 프로그램을 단계별로 진행하는 동안 원본 줄만 표시됩니다. 프로그램 카운터, 디스어셈블리 코드 및 등록 정보가 숨겨집니다. 이러한 종류의 디스플레이를 사용하면 코드를 신속하게 단계별로 실행하고 원본만 볼 수 있습니다.
lsp(원본 줄 수 설정) 명령을 사용하여 애플리케이션을 단계별로 실행하거나 실행할 때 표시되는 원본 줄 수를 정확히 지정할 수 있습니다.
다음 명령 시퀀스는 원본 파일을 단계별로 실행할 수 있는 효과적인 방법입니다.
.lines enable source line information
bp main set initial breakpoint
l+t stepping will be done by source line
l+s source lines will be displayed at prompt
g run program until "main" is entered
pr execute one source line, and toggle register display off
p execute one source line
ENTER는 마지막 명령을 반복하므로 이제 ENTER 키를 사용하여 애플리케이션을 단계별로 실행할 수 있습니다. 각 단계에서는 소스 줄, 메모리 오프셋 및 어셈블리 코드가 표시됩니다.
디스어셈블리 표시를 해석하는 방법에 대한 자세한 내용은 어셈블리 모드에서 디버깅을 참조하세요.
어셈블리 코드가 표시되면 액세스 중인 모든 메모리 위치가 줄의 오른쪽 끝에 표시됩니다. d*(메모리 표시) 및 e*(값 입력) 명령을 사용하여 이러한 위치의 값을 보거나 변경할 수 있습니다.
오프셋 또는 메모리 정보를 확인하기 위해 각 어셈블리 명령을 확인해야 하는 경우 l-t 를 사용하여 소스 줄 대신 어셈블리 지침을 단계별로 실행합니다. 원본 줄 정보는 계속 표시될 수 있습니다. 각 소스 줄은 하나 이상의 어셈블리 지침에 해당합니다.
이러한 모든 명령은 WinDbg 및 CDB에서 사용할 수 있습니다. 명령을 사용하여 원본 창 대신 WinDbg의 디버거 명령 창 에서 원본 줄 정보를 볼 수 있습니다.
원본 선 및 오프셋
식 계산기를 사용하여 특정 소스 줄에 해당하는 오프셋을 확인하여 소스 디버깅을 수행할 수도 있습니다.
다음 명령은 메모리 오프셋을 표시합니다.
? `[[module!]filename][:linenumber]`
파일 이름을 생략하면 디버거는 현재 프로그램 카운터에 해당하는 원본 파일을 검색합니다.
디버거는 현재 기본 radix에 관계없이 앞에 0x를 추가하지 않는 한 린넘버를 10진수로 읽습니다. linenumber를 생략하면 식은 소스 파일에 해당하는 실행 파일의 초기 주소로 계산됩니다.
이 구문은 .lines 명령 또는 - lines 명령줄 옵션에 소스 줄 기호가 로드된 경우에만 CDB에서 이해됩니다.
이 기술은 프로그램 카운터가 가리키는 위치에 관계없이 사용할 수 있으므로 매우 다양합니다. 예를 들어 이 기술을 사용하면 다음과 같은 명령을 사용하여 중단점을 미리 설정할 수 있습니다.
bp `source.c:31`
자세한 내용은 소스 줄 구문 및 중단점 사용을 참조하세요.
소스 모드에서 단계별 실행 및 추적
원본 모드에서 디버깅하는 경우 단일 소스 줄에 여러 함수 호출이 있을 수 있습니다. p 및 t 명령을 사용하여 이러한 함수 호출을 구분할 수 없습니다.
예를 들어 다음 명령에서 t 명령은 GetTickCount 와 printf 둘 다로 단계가 있고 p 명령은 두 함수 호출을 모두 단계로 실행합니다.
printf( "%x\n", GetTickCount() );
다른 호출을 추적하는 동안 특정 호출을 단계별로 실행하려면 .step_filter(단계 필터 설정) 을 사용하여 스텝오버할 호출을 나타냅니다.
_step_filter 사용하여 프레임워크 함수(예: MFC(Microsoft Foundation Classes) 또는 ATL(Active Template Library) 호출)을 필터링할 수 있습니다.