크래쉬 덤프 분석 패턴 (Part 1)

CDA (Crash Dump Analysis)

출처(source) - https://www.dumpanalysis.org/blog/index.php/2006/10/30/crash-dump-analysis-patterns-part-1/

번역(translation) – 김희준( https://insidekernel.net , drost@naver.com )


크래쉬 덤프 분석 패턴 (Part 1)

크래쉬 덤프 분석만을 3년 넘게 해오다가, 제 지식을 패턴의 형태로 정리하기로 했습니다.

패턴이란 무엇일까요 특정한 상황(컨텍스트)에서 반복하여 발생하는 문제에 대하여 적용할 수 있는 일반적인 해결책이라고 할 수 있습니다.

수많은 패턴들과 패턴 랭귀지들이 소프트웨어 엔지니어링에 존재합니다. 참고로 다음 +700 패턴들의 리스트를 살펴보세요:

The Pattern Almanac 2000.

그리고 다음 링크도 꽤 유용한 내용을 담고 있습니다:

Patterns Library

 

오늘 제가 처음으로 설명해드리고 싶은 패턴은 다중 예외(Multiple Exceptions) 입니다. 이 패턴은 하나의 프로세스에서 여러 개의 스레드 수만큼 여러 예외(“크래쉬”)들이 일어날 수 있다는 사실을 설명하는 패턴입니다. 아래의 UML 다이어그램은 프로세스, 스레드, 예외들 간의 관계에 대해서 보여주고 있습니다.

윈도우에서 모든 프로세스들은 최소 하나의 실행 스레드를 가지고 있기 때문에 오류가 발생하면스레드당 최소 하나의 예외(잘못된 메모리 참조같은)가 발생할 수 있습니다. 그 스레드에서 만약 예외 처리 코드가 또 다른 예외를 발생시키거나 첫 번째 예외가 처리되었지만 다른 예외가 또 발생한다면 두 번째 예외가 발생할 수 있을 것입니다.

그렇다면 어플리케이션이나 서비스가 크래쉬되고 고객사(특정한 상황)로부터 받은 크래쉬 덤프 파일(반복하여 발생하는 문제)을 가지고 있다면 이러한 문제에 대한 일반적인 해결책이 무엇일까요? 일반적인 해결책으로는 모든 스레드와 스레드의 스택을 살펴보고 툴에 의존하지 않는 것입니다.

 

여기 확실한 예제가 될 수 있는 오늘 받은 하나의 덤프가 있습니다:

Internet Explorer가 크래쉬되어서 WinDbg로 덤프를 열고 ‘ !analyze –v’ 명령을 실행했습니다. 다음은 WinDbg 출력 내용입니다.

ExceptionAddress: 7c822583 (ntdll!DbgBreakPoint)
   ExceptionCode: 80000003 (Break instruction exception)
  ExceptionFlags: 00000000
NumberParameters: 3
   Parameter[0]: 00000000
   Parameter[1]: 8fb834b8
   Parameter[2]: 00000003

Break Instruction이란 예외를 보고 여러분들께서는 고객이 잘못된 덤프를 보내줬거나 instruction 의미를 모르고 있고 이 덤프는 크래쉬로 생성된 것이 아니라 프로그램을 실행하다가 manual하게 생성한 것이라고 생각할지도 모르겠습니다. 그러나 저는 모든 스레드를 살펴보다가 스레드 15와 16에서 다음 두 스택의 내용을 발견하였습니다:

0:016>~*kL...

  15  Id: 1734.8f4 Suspend: 1 Teb: 7ffab000 Unfrozen
ntdll!KiFastSystemCallRet
ntdll!NtRaiseHardError+0xc
kernel32!UnhandledExceptionFilter+0x54b
kernel32!BaseThreadStart+0x4a
kernel32!_except_handler3+0x61
ntdll!ExecuteHandler2+0x26
ntdll!ExecuteHandler+0x24
ntdll!KiUserExceptionDispatcher+0xe
componentA!xxx
componentB!xxx
mshtml!xxx
kernel32!BaseThreadStart+0x34

 

# 16  Id: 1734.11a4 Suspend: 1 Teb: 7ffaa000 Unfrozen
ntdll!DbgBreakPoint
ntdll!DbgUiRemoteBreakin+0x36

 

여기에서 우린 componentA.dll과 componentB.dll에서 오류가 발생했거나 mshtml.dll에서 두 모듈에 영향을 끼쳐 실제 크래쉬가 발생했다고 확인할 수 있습니다. 왜 이런 일이 발생했을까요? 고객이 Internet Explorer가 예외 메시지 박스를 보여줄 때 manual하게 덤프 했을 것입니다. 아래의 레퍼런스에서는 ZwRaiseHardError가 에러 메시지 박스를 보여준다고 설명하고 있습니다.

Windows NT/2000 Native API Reference

또는 다른 일이 발생했을 수도 있겠죠. 하나의 프로세스 덤프에서 여러 스레드들의 예외들을 볼 수 있는 것은 크래쉬된 스레드가 Visual C++ 디버그 메시지 박스 같은 메시지 박스를 보여주고 프로세스가 종료되지 않도록 하기 때문입니다. 우리가 살펴보았던 WinDbg의 자동 분석 명령어는 오직 마지막 브레이크 포인트 예외(#16에서 보여주는 것)만을 인식합니다. 정리하자면 “자동 분석automatic analysis” 기능을 맹신하지 말고 가능하면 여러 다양한 예외의 목록을 보여주는 우리만의 확장기능을 작성해보도록 합시다.

- Dmitry Vostokov -