C++ 소프트웨어 디버깅 기술: Windbg를 사용하여 소프트웨어 예외 분석 시의 다양한 세부 사항과 기술 요약

1. 덤프 파일

덤프 파일은 소프트웨어가 예외 상황에 처했을 때 생성되는 프로세스 컨텍스트 정보를 포함하는 파일로, 예외가 발생한 어셈블리 명령어와 해당 시점의 레지스터 값, 스레드 정보 및 함수 호출 스택, 심지어 메모리 내 변수 값까지 확인할 수 있습니다.

덤프 파일은 소프트웨어 예외 분석의 핵심 자료로, 대부분의 경우 사후에 Windbg를 사용하여 정적 분석을 수행합니다.

1.1. 덤프 파일 생성 방식

덤프 파일은 주로 MiniDumpWriteDump 시스템 API 함수를 호출하여 생성됩니다. 주요 생성 방식은 세 가지입니다:

  • 프로그램 내 설치된 예외 처리 모듈을 통한 자동 생성: 가장 일반적이고 효율적인 방식으로, 소프트웨어에 내장된 예외 처리 모듈이 예외를 감지하면 자동으로 덤프 파일을 생성합니다. 예외 처리 모듈은 CrashRpt, CrashPad, BreakPad와 같은 오픈소스를 활용하여 구현할 수 있습니다.
  • 작업 관리자를 통한 덤프 파일 추출: 프로그램이 데드락이나 무한 루프 상태에 빠졌거나 오류 메시지가 표시될 때(프로세스가 여전히 실행 중인 경우), 작업 관리자에서 대상 프로세스를 찾아 우클릭 후 "덤프 파일 생성"을 선택하여 추출합니다.
  • Windbg에서 .dump 명령 사용: 예외 처리 모듈이 일부 예외를 감지하지 못하거나 덤프 생성 과정에서二次崩溃이 발생하는 경우, Windbg를 대상 프로세스에 연결하여 동적 디버깅을 수행하고 .dump 명령을 사용하여 덤프 파일을 생성합니다.

또한, 예외 처리 모듈이 모든 예외를 포착하지 못하는 경우 Windows 응용 프로그램 로그에서 시스템이 자동으로 생성한 덤프 파일을 확인할 수 있습니다. 이는 재현이 어려운 문제 해결에 매우 중요합니다.

1.2. 덤프 파일 크기

덤프 파일은 작은 미니 덤프와 큰 풀 덤프로 구분됩니다. MiniDumpWriteDump 함수의 매개변수를 설정하여 크기를 제어할 수 있습니다. 예외 처리 모듈을 통해 자동 생성된 덤프 파일은 보통 수백 KB에서 몇 MB 정도로 유지하는 것이 좋습니다.

HANDLE dumpFile;
dumpFile = CreateFile(filePath, GENERIC_READ|GENERIC_WRITE, 
FILE_SHARE_WRITE|FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

MINIDUMP_EXCEPTION_INFORMATION exceptionInfo;
exceptionInfo.ThreadId = GetCurrentThreadId();
exceptionInfo.ExceptionPointers = exceptionPointers;
exceptionInfo.ClientPointers = TRUE;

MINIDUMP_TYPE dumpType = (MINIDUMP_TYPE)(MiniDumpNormal 
    | MiniDumpWithHandleData 
    | MiniDumpWithUnloadedModules 
    | MiniDumpWithIndirectlyReferencedMemory 
    | MiniDumpScanMemory 
    | MiniDumpWithProcessThreadData 
    | MiniDumpWithThreadInfo);

BOOL success = MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), 
dumpFile, dumpType, &exceptionInfo, NULL, NULL);

작업 관리자나 Windbg 동적 디버깅에서 생성된 풀 덤프는 프로세스의 모든 메모리 정보를 포함하며, 가상 메모리 크기와 유사합니다. 변수 값을 확인하려면 해당 모듈의 PDB 파일이 필요하며, 풀 덤프는 모든 변수 값을 확인할 수 있습니다.

2. PDB 기호 파일

PDB(Program Database File)는 이진 파일의 모든 함수 및 변수 기호와 디버깅 정보를 저장합니다. 함수 호출 정보와 변수 값을 확인하려면 PDB 파일이 필수적입니다.

2.1. PDB 파일 경로 설정

Windbg에서 PDB 파일을 로드하려면 경로를 설정해야 합니다. 비즈니스 모듈 PDB와 시스템 라이브러리 PDB 두 가지 유형을 고려해야 합니다.

Windbg 메뉴에서 "File -> Symbol File Path..."를 열고 다음 형식으로 경로를 설정합니다:

C:\\pdb\\local; srv*f:\\symbols*http://msdl.microsoft.com/download/symbols

첫 번째 경로는 비즈니스 모듈 PDB의 로컬 경로이며, 두 번째는 마이크로소프트 시스템 PDB 서버 주소입니다.

2.2. PDB 파일의 타임스탬프 및 이름 문제

PDB 파일 로딩은 타임스탬프를 엄격히 검증합니다. 컴파일 시간이 다르면 로딩이 실패하며, 파일 이름도 원본 프로젝트 이름과 일치해야 합니다.

2.3. 어떤 PDB 파일을 찾아야 하는가?

함수 호출 스택에 표시된 모듈 이름을 기준으로 해당 PDB 파일을 찾습니다. 가장 최근의 몇 개 모듈만 찾으면 충분하며, lm 명령으로 모듈의 타임스탬프를 확인할 수 있습니다.

lm vm

PDB 파일 로딩이 실패할 경우 .reload 명령을 사용하여 강제 로딩할 수 있습니다:

.reload /f businessModule.dll

3. Windbg를 사용한 덤프 파일 정적 분석 및 동적 디버깅 절차

Windbg를 사용한 소프트웨어 예외 분석은 정적 분석(덤프 파일 분석)과 동적 디버깅(프로세스 연결) 두 가지 방식이 있습니다. 각 방식의 절차는 다음과 같습니다:

3.1. 정적 분석 절차

  1. Windbg 실행 및 덤프 파일 로드
  2. PDB 경로 설정
  3. 기본 명령어 입력 (kn, kv, kp 등)
  4. 스택 분석 및 문제 위치 확인
  5. 변수 값 확인 및 추가 분석

3.2. 동적 디버깅 절차

  1. Windbg 실행
  2. 대상 프로세스 연결 (.attach 명령)
  3. 실행 중단 설정 (bp 명령)
  4. 실행 및 문제 재현
  5. 스택 및 변수 분석

4. 예외 발생 비즈니스 모듈 식별 및 문제 해결

예외가 발생한 어셈블리 명령어와 함수 호출 스택을 통해 문제 모듈을 식별합니다. 비즈니스 모듈에서 발생한 경우 해당 모듈의 함수를 직접 분석하며, 시스템 라이브러리에서 발생한 경우 상위 비즈니스 모듈에서 문제를 찾아야 합니다.

5. 32/64비트 컨텍스트 전환

64비트 OS에서 32비트 프로그램의 덤프 파일을 분석할 때, 함수 호출 스택이 이상하게 표시될 수 있습니다. 이 경우 .effmach 명령을 사용하여 32비트 컨텍스트로 전환해야 합니다:

.effmach X86

6. IsBadWritePtr/IsBadReadPtr 관련 예외 처리

이 두 함수는 더 이상 권장되지 않지만, 일부 라이브러리에서 여전히 사용될 수 있습니다. 이 함수 호출로 인한 예외는 치명적이지 않으므로 g 명령으로 건너뛸 수 있습니다.

7. 정적 분석 vs 동적 디버깅 사용 시점

다음과 같은 경우 동적 디버깅을 사용해야 합니다:

  • 데드락 또는 데드락 문제 발생 시
  • 예외 처리 모듈이 예외를 포착하지 못한 경우
  • 덤프 생성 과정에서二次崩溃 발생 시
  • abort() 함수 호출로 인한 프로세스 종료 시
  • IDE 디버깅 시 유효한 스택 정보가 없는 경우
  • 프로그램 시작 시 충돌 발생 시
  • 오류 메시지 팝업 표시 시

8. IDA 디스어셈블러 보조 도구

어셈블리 코드 컨텍스트를 확인해야 할 경우 IDA를 사용하여 C++ 소스 코드와 상호 참조하여 문제를 정확히 파악할 수 있습니다. 특히 릴리스 빌드에서 컴파일러 최적화로 인해 소스 코드와 어셈블리 코드의 직접적인 매핑이 어려울 때 유용합니다.

9. Windbg 명령어 숙지

다음과 같은 주요 명령어를 숙지해야 합니다:

  • .excr: 예외 정보 확인
  • kn/kv/kp: 스택 정보 확인
  • lm: 모듈 정보 확인
  • .reload: PDB 강제 로딩
  • .dump: 덤프 파일 생성

자세한 명령어 정보는 Windbg 도움말(Help -> Index)에서 확인할 수 있습니다.

태그: Windbg C++ 디버깅 소프트웨어 예외 PDB

7월 19일 22:21에 게시됨