WinDbg를 이용해서 Kenel debugging을 하려면 디버깅 대상이 되는 Target machine과 이를 디버깅 및 컨트롤 하는 Host machine, 그리고 이 두 컴퓨터를 연결하기 위한 COM, IEEE1394, USB 등의 케이블이 필요합니다. Target machine에서 발생하는 문제점을 파악하기 위해서는 이렇게 물리적으로 분리된 컴퓨터를 이용해서 Kernel debugging을 하는 것이 좋습니다만, 이렇게 PC를 2대 마련하는 것이 쉽지 않습니다.

만약 분석하려는 문제점이 물리적인 장비가 아니라 Virtual PC에서도 재현이 되는 것이라면 간단히 하나의 PC에서 Virtual PC를 이용해서 Target machine을 가상으로 실행해서 Kernel debugging 하는 것이 가능합니다. (다만, Virtual PC나 VMWare와 같은 가상 머신에서 하드웨어 관련 이슈는 확인이 불가능한 경우가 많습니다.)

오늘은 Virtual PC를 이용해서 Kernel debugging 하는 방법을 알아보도록 하겠습니다.

1. Virtual PC 2007 설치하기
http://www.microsoft.com/downloads/details.aspx?FamilyId=04D26402-3199-48A3-AFA2-2DC0B40A73B6&displaylang=en

2. Virtual PC 2007에 Target OS 설치하기
본 문서에서는 Windows XP를 Virtual PC에 설치한 것으로 가정합니다. 만약 기존에 만들어진 VPC 이미지가 있다면 해당 파일을 복사한 뒤에 등록해서 사용하면 됩니다.

3. 디버깅하려는 Target OS를 선택하고 ‘Settings’ 클릭. (단, 해당 VPC는 반드시 Power off 상태여야 합니다.)

image

4. ‘COM1’은 선택하고 'Named pipe’에 “\\.\pipe\debug”라고 입력합니다. 예로서 debug라는 이름을 사용했습니다만 이름은 임의로 정하시면 됩니다. 나중에 Host Machine의 WinDbg에서 여기서 지정한 이름으로 Named pipe로 연결을 시도할 것입니다.

image

5. ‘OK’를 클릭합니다.

6. Target VPC를 부팅한 후

- Windows XP 일 경우 : c:\boot.ini 파일을 열고 다음과 같이 /debug 옵션을 추가합니다.

multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Microsoft Windows XP Professional" /debug /debugport=COM1 /baudrate=115200 /fastdetect /NoExecute=OptIn

- Windows Vista 이상일 경우 : 관리자 권한으로 prompt 창을 열고 다음 명령을 수행한다.

bcdedit –debug on
bcdedit –dbgsettings serial debugport:1 baudrate:115200

이로써 Target machine으로 사용될 VPC 이미지에 대한 setting은 완료되었습니다.

이제 Host machine에서 WinDbg에서 kernel debugging을 위해 설정하는 방법을 알아보도록 하겠습니다.

1. WinDbg를 실행합니다.

2. File 메뉴에서 ‘Kernel Debugging…’를 선택하고, Port:에 “\\.\pipe\debug”라고 입력합니다.

image

3. ‘확인’을 누르면 다음과 같이 WinDbg는 지정한 named pipe를 이용해서 Target machine과 연결될 수 있도록 대기합니다.

image

4. VPC를 재부팅 한 후 부팅 옵션에서 ‘debug enabled’ 항목을 선택합니다.

image

5. WinDbg 화면에서 다음과 같이 Kernel debugger가 연결되었음을 확인할 수 있습니다.

image

이렇게 Target machine이 연결되었으면 Vitual PC를 이용한 Kernel debugging을 할 수 있도록 환경이 설정 되었음을 의미합니다.

'Programming' 카테고리의 다른 글

OS Kernel 함수들의 Prefix  (0) 2009.10.14
DriverEntry 함수  (0) 2009.09.11
Device Stack와 Driver loading 순서  (0) 2009.09.07
PnP device의 인식 과정  (0) 2009.09.07
Wow64 - Registry Redirection  (0) 2009.09.01
Posted by noenemy
,

디버깅을 할 때 가장 우선적으로 필요한 것이 디버깅 대상이 되는 모듈들의 심볼 파일입니다. 리버싱이나 어셈블리에 익숙하다면 굳이 심볼이 없어도 물론 분석이 가능하겠지만 많은 노력과 시간을 필요로 하겠죠. 오늘은 심볼 파일에 대해서 잠깐 살펴 볼까 합니다.

프로그램을 개발한 후의 그 결과물은 대부분 실행파일(.exe, .dll)이나 드라이버 파일(.sys)입니다. 저희가 작성한 로직들이 컴파일과 링크 과정을 거쳐서 이진수로 구성된 binary file 형태가 됩니다. 모듈을 빌드할 때 디버깅에 필요한 정보를 담은 파일을 생성하면 개발시나 또는 개발이 완료되어 릴리즈된 이후에도 문제가 발생했을 때 이를 분석하는데 도움이 됩니다. 빌드시 생성되는 .pdb 또는 .dbg 확장자를 가진 파일들 심볼 파일(symbol file)이라고 부릅니다.

심볼 파일에는 다음과 같은 내용 들이 저장됩니다.

- 전역변수의 이름과 주소
- 함수명과 함수의 시작주소
- FPO(Frame pointer omission) 데이터
- 지역 변수의 이름과 위치
- 이진코드에 해당하는 소스 파일의 경로와 라인 수
- 변수나 구조체의 타입 정보 등

위와 같은 내용은 프로그램의 실행에는 필요 없는 부분이기 때문에 실행 파일에는 포함되어 있지 않습니다. 하지만 저희가 작성한 소스 코드가 컴파일된 이후에 실행파일에는 이해할 수 없는 이진 코드 형태로만 저장됩니다. 디버깅 시에는 이진 코드의 특정 영역이 어느 함수인지, 어느 변수인지, 소스 코드의 어느 라인에 해당하는지에 대한 정보가 필요하게 되는데 심볼 파일이 그 역할을 담당합니다.

Public symbol과 Private symbol

심볼 파일 내에 저장되는 정보의 종류에 따라 public symbol과 private symbol로 구분할 수 있습니다. public symbol에는 전역 변수, 함수명과 시작 주소, FPO 정보 등이 포함됩니다. Private symbole에는 public symbol의 정보 외에도 지역 변수, 소스 경로, 소스 라인번호, 변수나 구조체의 선언도 포함됩니다.

주로 public symbol은 작성한 모듈을 외부에 SDK 형태로 배포할 때 외부 업체에게 문제 분석에 도움이 될 수 있도록 제공됩니다. 대신 private symbol에는 내부 코드에 대한 세부 사항이 모두 포함되어 있으므로 자사의 코드 디버깅 용으로 사용하고 대부분 외부로는 공개하지 않습니다.

심볼 파일의 관리

프로젝트를 진행하는 개발과정에서 그리고 제품이 릴리즈 된 이후에도 소스 코드는 계속해서 변경이 됩니다. 따라서 하나의 파일에 대해서 여러 가지 버전이 존재하게 됩니다. 특정 문제를 분석하기 위해서는 어느 버전의 파일에서 문제가 발생했는지를 알아야 하고 해당 버전에 대한 심볼 파일과 소스 코드가 있어야 정확한 분석이 가능합니다.

따라서 프로그램을 작성할 때에는 빌드된 모듈의 버전 관리와 이에 해당하는 심볼 파일, 소스 코드에 대한 버전 관리가 잘 되어야 제품에 대한 기술 지원이 가능해집니다. 이러한 버전 관리에 대한 개발 인프라를 잘 구축하고, 또한 모듈을 버전별로 심볼 파일을 모아둔 심볼서버를 구성하면 문제 발생시 보다 신속하고 정확한 유지 보수가 가능해집니다.

'Programming' 카테고리의 다른 글

Wow64 - Registry Redirection  (0) 2009.09.01
Wow64에 대해서  (0) 2009.09.01
JavaScript로 클래스 구현하기  (0) 2009.06.16
Windows Sidebar Gadget 만들기 #3 - Settings  (0) 2009.06.01
주요 System Process들  (0) 2009.05.28
Posted by noenemy
,

LiveKD

Programming 2009. 5. 15. 19:15

WinDbg tool을 이용해서 커널 디버깅을 하려면 target machine을 host machine과 1394나 COM port를 이용해서 연결을 해야 합니다. 최근에는 제약 사항이 있긴 하지만 USB 2.0을 이용해서 좀 더 빠른 속도로 커널 디버깅을 할 수 있고, VMWare나 VirtualPC와 같은 가상 머신을 로컬 컴퓨터에 실행시킨 상태에서도 디버깅이 가능하지만 특정 문제가 발생하는 장비를 분석하기 위해 다른 host machine을 매번 연결하는 것은 번거로운 작업임에는 틀림이 없습니다.

제 경우도 사실 WinDbg를 쓰기 이전에 Numega사의 SoftIce라는 디버깅 툴을 먼저 사용하였습니다. Windows XP 부터 더 이상 버전업이 되지 않고 단종된 제품입니다만, 기존 운영체제 환경에서는 커널모드 디버깅에 있어서 매우 독보적인 존재였습니다. 무엇보다 가장 편했던 기능은 디버깅이 필요한 장비에 바로 설치해서 해당 장비의 커널디버깅을 바로 할 수 있다는 점이었습니다. 언제든지 디버깅일 필요한 시점에서 SoftICE를 호출하고, 현재 장비의 특정 위치에 breakpoint를 걸고 tracing을 하는 작업이 가능했었습니다. 무엇보다도 매우 빠른 속도로 디버깅할 수 있어서 편리하였습니다. (현재 WinDbg가 1394를 지원하기 때문에 많이 빨라졌지만, 이 당시만 해도 serial cable을 이용해서 많은 양의 디버깅 데이터를 target machine과 host machine 간에 통신을 했어야 했기에 반응 속도가 매우 느렸습니다.)

하지만 SoftICE를 설치하면 해당 장비가 오동작하거나 BSOD가 수시로 발생하는 등의 문제가 많았는데, 그것은 local machine에 설치된 운영체제에 종속성이 강하였기 때문입니다. 운영체제가 핫픽스나 서비스팩 등의 설치에 따라서 이미지가 변경될 때마 이러한 일들이 일어났고, Numega 사는 새로운 변경사항에 대한 업데이트를 하고, 이러한 과정을 거듭하다가 아마도 사업 자체를 포기한 것 같습니다. 현재 Windows 7의 출시를 앞두고 있는 상황에서는 추억속의 디버거가 됐지만 WinDbg를 사용하면서 항상 SoftICE를 가끔 그리워 하게 됩니다.

서론이 길었는데 오늘 설명하고자 하는 내용은 WinDbg를 이용해서 로컬 장비의 kernel debugging을 하는 방법을 소개하고자 합니다. 현재는 마이크로소프트사로 입사한 Mark Russinovich(sysinternals 사이트 운영자)가 Sysinternals 사이트에 공개한 LiveKD 라는 툴을 이용하면 제약사항이 있긴하지만 SoftICE 처럼 원격 장비가 아닌 로컬 장비의 커널 디버깅이 가능합니다.

먼저 아래 사이트에서 livekd.zip 파일을 다운로드 받은 후에, WinDbg가 설치된 폴더에 압축을 풉니다.
http://technet.microsoft.com/en-us/sysinternals/bb897415.aspx

해당 폴더에 가보면 livekd.exe라는 실행 파일이 있는데 이를 command window에서 실행하면 됩니다. 다음은 실행 방법에 대한 설명입니다. 실행 옵션이 많지 않기 때문에 비교적 간단하게 사용할 수 있습니다.

Usage: livekd [-w] [-d] [-k ] [debugger options]

-w Runs windbg instead of Kd (Kd is the default).
-d Runs Dumpchk exam instead of Kd (Kd is the default).
-k Specifices complete path and filename of debugger image to execute.

간단히 command에서 livekd.exe를 실행시키면 다음과 같이 console mode로 kernel debugging이 가능합니다.

livekd -w 를 실행하면 다음과 같이 WInDbg가 실행되면서 GUI 모드에서 사용이 가능합니다.

하지만 LiveKD는 실행시점에 수집한 kernel 상태에 대한 snapshot 정보를 보여주는 것이기 때문에 덤프 파일의 내용을 분석하는 것과 같은 방법으로 접근이 가능합니다. 즉, breakpoint를 걸고 tracing과 같은 interactive debugging은 되지 않습니다. 제약사항이 있긴 하지만 여러모로 유용하게 사용할 수 있는 툴인 것 같습니다.

LiveKD는 실행 시점에 시스템 정보를 snapshot을 떠서 정보를 보여주므로 실행된 이후에 변경된 시스템 정보는 확인되지 않습니다. 이 경우엔 LiveKD를 재시작함으로써 새로운 정보를 확인할 수 있습니다. q 명령을 실행하면 다음과 같이 재시작하겠냐는 메시지가 뜨는데, 여기서 y를 실행하면 다시 현재 시점의 snapshot을 얻을 수 있습니다.

0: kd> q
quit:

Execute Kd again? (y/n) y

.... LiveKd 재시작됨....

다음에는 시간되면 WinDbg를 이용한 Local Live Debugging에 대해서 다뤄볼까 합니다.

'Programming' 카테고리의 다른 글

Remote Session인지 확인하는 방법  (0) 2009.05.22
Kernel Mode vs. User Mode  (0) 2009.05.21
TIB와 IsDebuggerPresent  (0) 2009.05.13
데이터 실행 방지(DEP)  (0) 2009.05.11
응답 없음(Not Responding)  (0) 2009.05.11
Posted by noenemy
,

thread별로 로컬 변수나 함수 호출간에 전달할 파라미터 정보를 저장하기 위한 임시 공간으로서 thread stack을 사용할 수 있는데, thread의 특정 시점에 사용 중이던 stack 정보를 역으로 추적해서 현재 실행 중인 함수의 위치까지 실행된 과정을 call stack으로 보여주고, 각 함수에 전달된 파라미터 정보를 확인하는 과정을 Stack backtracing이라고 합니다. 다음에 기회가 되면 이와 관련된 함수 호출 규약(function calling convention) stack 사용 및 해제하는 과정을 다루도록 하겠습니다.

 

어느 debugger를 이용하든지 thread stack backtracing 을 해서 stack frame 정보를 확인하는 것이 live debugging이나 post mortem debugging에 필수 과정이라고 할 수 있습니다. 특히 windbg의 경우 stack backtracing을 위해 k 명령어를 제공하고 있는데 파라미터에 따라서 그 사용법이 매우 다양하기 때문에 어떤 것을 사용해야 되는지 헷갈리는 경우가 많습니다. 제 경우에도 주로 사용하는 몇 개의 명령어만 쓰고 있는데 이번 기회에 세부 사용법을 정리해보도록 하겠습니다. 일단 이것 저것 많이 써보면서 몸으로 익히는 게 중요할 것 같습니다.

 

세부 내용은 WinDbg의 매뉴얼을 참고 했습니다.

 

구문

*유저모드에서

[~Thread] k[b|p|P|v] [n] [f] [L] [FrameCount]
[~Thread] k[b|p|P|v] [n] [f] [L] = BasePtr [FrameCount]
[~Thread] k[b|p|P|v] [n] [f] [L] = BasePtr StackPtr InstructionPtr 
[~Thread] kd [WordCount]

*커널모드에서

[Processor] k[b|p|P|v] [n] [f] [L] [FrameCount]
[Processor] k[b|p|P|v] [n] [f] [L] = BasePtr [FrameCount]
[Processor] k[b|p|P|v] [n] [f] [L] = BasePtr StackPtr InstructionPtr 
[Processor] kd [WordCount]

파라미터

 

b: 각 함수에 전달된 파라미터를 3개씩 보기

p: 함수에 전달된 모든 파라미터 보기

P: 함수에 전달된 모든 파라미터 보기. 줄바꿈을 이용해서 보여준다.

v: FPO(Frame Pointer Omission) 정보 보기

n: frame number 보기

f: frame 사이의 간격(실제 스택상에서 해당 frame bytes ) 보기

L: 소스 상에서의 라인 번호 숨기기

 

실제 예

동일한 thread에서 k 명령어의 사용에 따른 차이점을 아래 예를 통해서 확인할 수 있습니다.

 

1: kd> k

ChildEBP RetAddr 

83093868 8208fbf4 nt!MmAccessFault+0x106 [d:\vista_ldr\base\ntos\mm\mmfault.c @ 251]

83093868 82091f60 nt!_KiTrap0E+0xdc [d:\vista_ldr\base\ntos\ke\i386\trap.asm @ 5651]

830938f0 8fc9dbbb nt!Exfi386InterlockedExchangeUlong [d:\vista_ldr\base\ntos\ex\i386\intrlfst.asm @ 782]

83093904 8204b2e7 C7xUSBV3!powerWaitWakeCallback+0x1b [c:\projects\wibro\usb\xp\miniport.08.06.24_328\power.c @ 399]

8309392c 822cec69 nt!PopRequestCompletion+0x38 [d:\vista_ldr\base\ntos\po\pocall.c @ 349]

83093964 820acc1b nt!IovpLocalCompletionRoutine+0xcc [d:\vista_ldr\base\ntos\io\iomgr\ioverifier.c @ 1028]

8309399c 822ceb53 nt!IopfCompleteRequest+0x11d [d:\vista_ldr\base\ntos\io\iomgr\iosubs.c @ 3848]

83093a0c 8f7431f4 nt!IovCompleteRequest+0x11c [d:\vista_ldr\base\ntos\io\iomgr\ioverifier.c @ 946]

83093a20 8f74a7f6 usbhub!UsbhCompletePdoWakeIrp+0xaf [d:\vistartm\drivers\wdm\usb\hub\usbhub\pdopwr.c @ 1864]

83093a40 8f74a9e0 usbhub!UsbhPdoRemoveCleanup+0x3f [d:\vistartm\drivers\wdm\usb\hub\usbhub\pdo.c @ 1267]

83093a58 8f72e41e usbhub!UsbhPdoPnp_RemoveDevice+0x41 [d:\vistartm\drivers\wdm\usb\hub\usbhub\pdo.c @ 2152]

83093a74 8f726c92 usbhub!UsbhPdoPnp+0x78 [d:\vistartm\drivers\wdm\usb\hub\usbhub\pnp.c @ 1759]

83093a88 822ce681 usbhub!UsbhGenDispatch+0x4a [d:\vistartm\drivers\wdm\usb\hub\usbhub\hub.c @ 1116]

83093aac 82027f1c nt!IovCallDriver+0x252 [d:\vista_ldr\base\ntos\io\iomgr\ioverifier.c @ 574]

83093ac0 825cfce9 nt!IofCallDriver+0x1b [d:\vista_ldr\base\ntos\io\iomgr\iosubs.c @ 2370]

83093b08 822ce681 ndis!ndisPnPDispatch+0x4a4 [d:\vistartm\net\ndis\sys\ndispnp.c @ 1426]

83093b2c 82027f1c nt!IovCallDriver+0x252 [d:\vista_ldr\base\ntos\io\iomgr\ioverifier.c @ 574]

83093b40 821af73b nt!IofCallDriver+0x1b [d:\vista_ldr\base\ntos\io\iomgr\iosubs.c @ 2370]

83093b74 821af9a3 nt!IopSynchronousCall+0xce [d:\vista_ldr\base\ntos\io\pnpmgr\irp.c @ 215]

83093bd0 82006592 nt!IopRemoveDevice+0xd5 [d:\vista_ldr\base\ntos\io\pnpmgr\irp.c @ 663]

 

1: kd> kd 5

83093868  83093880

8309386c  8208fbf4 nt!_KiTrap0E+0xdc [d:\vista_ldr\base\ntos\ke\i386\trap.asm @ 5651]

83093870  00000001

83093874  9112ee50

83093878  00000000

 

1: kd> kbL

ChildEBP RetAddr  Args to Child             

83093868 8208fbf4 00000001 9112ee50 00000000 nt!MmAccessFault+0x106

83093868 82091f60 00000001 9112ee50 00000000 nt!_KiTrap0E+0xdc

830938f0 8fc9dbbb a78aae90 898b30b0 a78aaf00 nt!Exfi386InterlockedExchangeUlong

83093904 8204b2e7 89683700 898b3000 00000004 C7xUSBV3!powerWaitWakeCallback+0x1b

8309392c 822cec69 00000000 a78aae90 898b3000 nt!PopRequestCompletion+0x38

83093964 820acc1b 00000000 a78aae90 830939d4 nt!IovpLocalCompletionRoutine+0xcc

8309399c 822ceb53 a78aae90 896837b8 c0000120 nt!IopfCompleteRequest+0x11d

83093a0c 8f7431f4 c0000120 896837b8 89683700 nt!IovCompleteRequest+0x11c

83093a20 8f74a7f6 89522028 89683700 c0000120 usbhub!UsbhCompletePdoWakeIrp+0xaf

83093a40 8f74a9e0 89683700 a7834eb8 a7834fdc usbhub!UsbhPdoRemoveCleanup+0x3f

83093a58 8f72e41e 89683700 a7834eb8 a7834eb8 usbhub!UsbhPdoPnp_RemoveDevice+0x41

83093a74 8f726c92 89683700 a7834eb8 89683700 usbhub!UsbhPdoPnp+0x78

83093a88 822ce681 89683700 a7834eb8 a7834eb8 usbhub!UsbhGenDispatch+0x4a

83093aac 82027f1c 825cfce9 00000000 89683700 nt!IovCallDriver+0x252

83093ac0 825cfce9 a7834eb8 892f6030 875fce30 nt!IofCallDriver+0x1b

83093b08 822ce681 892f6030 00000002 a7835000 ndis!ndisPnPDispatch+0x4a4

83093b2c 82027f1c 821af73b 83093bcc 892f6030 nt!IovCallDriver+0x252

83093b40 821af73b 89683700 89301ea8 89683700 nt!IofCallDriver+0x1b

83093b74 821af9a3 89683700 83093ba8 00000000 nt!IopSynchronousCall+0xce

83093bd0 82006592 89683700 00000002 9f7d2510 nt!IopRemoveDevice+0xd5

 

1: kd> kvL

ChildEBP RetAddr  Args to Child             

83093868 8208fbf4 00000001 9112ee50 00000000 nt!MmAccessFault+0x106 (CONV: stdcall)

83093868 82091f60 00000001 9112ee50 00000000 nt!_KiTrap0E+0xdc (FPO: [0,0] TrapFrame @ 83093880) (CONV: cdecl)

830938f0 8fc9dbbb a78aae90 898b30b0 a78aaf00 nt!Exfi386InterlockedExchangeUlong (FPO: [0,0,0])

83093904 8204b2e7 89683700 898b3000 00000004 C7xUSBV3!powerWaitWakeCallback+0x1b (FPO: [Non-Fpo]) (CONV: stdcall)

8309392c 822cec69 00000000 a78aae90 898b3000 nt!PopRequestCompletion+0x38 (CONV: stdcall)

83093964 820acc1b 00000000 a78aae90 830939d4 nt!IovpLocalCompletionRoutine+0xcc (CONV: stdcall)

8309399c 822ceb53 a78aae90 896837b8 c0000120 nt!IopfCompleteRequest+0x11d (CONV: fastcall)

83093a0c 8f7431f4 c0000120 896837b8 89683700 nt!IovCompleteRequest+0x11c (CONV: fastcall)

83093a20 8f74a7f6 89522028 89683700 c0000120 usbhub!UsbhCompletePdoWakeIrp+0xaf (FPO: [Non-Fpo]) (CONV: stdcall)

83093a40 8f74a9e0 89683700 a7834eb8 a7834fdc usbhub!UsbhPdoRemoveCleanup+0x3f (FPO: [Non-Fpo]) (CONV: stdcall)

83093a58 8f72e41e 89683700 a7834eb8 a7834eb8 usbhub!UsbhPdoPnp_RemoveDevice+0x41 (FPO: [Non-Fpo]) (CONV: stdcall)

83093a74 8f726c92 89683700 a7834eb8 89683700 usbhub!UsbhPdoPnp+0x78 (FPO: [Non-Fpo]) (CONV: stdcall)

83093a88 822ce681 89683700 a7834eb8 a7834eb8 usbhub!UsbhGenDispatch+0x4a (FPO: [Non-Fpo]) (CONV: stdcall)

83093aac 82027f1c 825cfce9 00000000 89683700 nt!IovCallDriver+0x252 (CONV: fastcall)

83093ac0 825cfce9 a7834eb8 892f6030 875fce30 nt!IofCallDriver+0x1b (CONV: fastcall)

83093b08 822ce681 892f6030 00000002 a7835000 ndis!ndisPnPDispatch+0x4a4 (FPO: [Non-Fpo]) (CONV: stdcall)

83093b2c 82027f1c 821af73b 83093bcc 892f6030 nt!IovCallDriver+0x252 (CONV: fastcall)

83093b40 821af73b 89683700 89301ea8 89683700 nt!IofCallDriver+0x1b (CONV: fastcall)

83093b74 821af9a3 89683700 83093ba8 00000000 nt!IopSynchronousCall+0xce (CONV: stdcall)

83093bd0 82006592 89683700 00000002 9f7d2510 nt!IopRemoveDevice+0xd5 (CONV: stdcall)

 

1: kd> kpL

ChildEBP RetAddr 

83093868 8208fbf4 nt!MmAccessFault(unsigned long FaultStatus = 1, void * VirtualAddress = 0x9112ee50, char PreviousMode = 0 '', void * TrapInformation = 0x83093880)+0x106

83093868 82091f60 nt!_KiTrap0E(void)+0xdc

830938f0 8fc9dbbb nt!Exfi386InterlockedExchangeUlong(void)

83093904 8204b2e7 C7xUSBV3!powerWaitWakeCallback(struct _DEVICE_OBJECT * Object = 0x89683700, unsigned char MinorFunction = 0x00 '', union _POWER_STATE PowerState = union _POWER_STATE, struct _MINIPORT_ADAPTER * Adapter = 0x9112eb50, struct _IO_STATUS_BLOCK * IoStatus = 0xa78aaea8)+0x1b

8309392c 822cec69 nt!PopRequestCompletion(struct _DEVICE_OBJECT * DeviceObject = 0x00000000, struct _IRP * Irp = 0xa78aae90, void * Context = 0x898b3000)+0x38

83093964 820acc1b nt!IovpLocalCompletionRoutine(struct _DEVICE_OBJECT * DeviceObject = 0x00000000, struct _IRP * Irp = 0xa78aae90, void * Context = 0x830939d4)+0xcc

8309399c 822ceb53 nt!IopfCompleteRequest(struct _IRP * Irp = 0x9112ee50, char PriorityBoost = 0 '')+0x11d

83093a0c 8f7431f4 nt!IovCompleteRequest(struct _IRP * Irp = 0x9112ee50, char PriorityBoost = 0 '')+0x11c

83093a20 8f74a7f6 usbhub!UsbhCompletePdoWakeIrp(struct _DEVICE_OBJECT * HubFdo = 0x89522028, struct _DEVICE_OBJECT * Pdo = 0x89683700, long NtStatus = -1073741536)+0xaf

83093a40 8f74a9e0 usbhub!UsbhPdoRemoveCleanup(struct _DEVICE_OBJECT * Pdo = 0x89683700)+0x3f

83093a58 8f72e41e usbhub!UsbhPdoPnp_RemoveDevice(struct _DEVICE_OBJECT * Pdo = 0x89683700, struct _IRP * Irp = 0xa7834eb8)+0x41

83093a74 8f726c92 usbhub!UsbhPdoPnp(struct _DEVICE_OBJECT * HubPdo = 0x89683700, struct _IRP * Irp = 0xa7834eb8)+0x78

83093a88 822ce681 usbhub!UsbhGenDispatch(struct _DEVICE_OBJECT * DeviceObject = 0x89683700, struct _IRP * Irp = 0xa7834eb8)+0x4a

83093aac 82027f1c nt!IovCallDriver(struct _DEVICE_OBJECT * DeviceObject = 0x9112ee50, struct _IRP * Irp = 0x00000000, void * ReturnAddress = 0x825cfce9)+0x252

83093ac0 825cfce9 nt!IofCallDriver(struct _DEVICE_OBJECT * DeviceObject = 0x9112ee50, struct _IRP * Irp = 0x00000000)+0x1b

83093b08 822ce681 ndis!ndisPnPDispatch(struct _DEVICE_OBJECT * DeviceObject = 0x892f6030, struct _IRP * Irp = 0x00000002)+0x4a4

83093b2c 82027f1c nt!IovCallDriver(struct _DEVICE_OBJECT * DeviceObject = 0x9112ee50, struct _IRP * Irp = 0x00000000, void * ReturnAddress = 0x821af73b)+0x252

83093b40 821af73b nt!IofCallDriver(struct _DEVICE_OBJECT * DeviceObject = 0x9112ee50, struct _IRP * Irp = 0x00000000)+0x1b

83093b74 821af9a3 nt!IopSynchronousCall(struct _DEVICE_OBJECT * DeviceObject = 0x89683700, struct _IO_STACK_LOCATION * TopStackLocation = 0x83093ba8, long DefaultStatus = -1882596448, unsigned long DefaultInformation = 0x83093bd0, unsigned long * Information = 0x00000000)+0xce

83093bd0 82006592 nt!IopRemoveDevice(struct _DEVICE_OBJECT * TargetDevice = 0x89683700, unsigned long IrpMinorCode = 2)+0xd5

 

1: kd> kPL

ChildEBP RetAddr 

83093868 8208fbf4 nt!MmAccessFault(

                                unsigned long FaultStatus = 1,

                                void * VirtualAddress = 0x9112ee50,

                                char PreviousMode = 0 '',

                                void * TrapInformation = 0x83093880)+0x106

83093868 82091f60 nt!_KiTrap0E(void)+0xdc

830938f0 8fc9dbbb nt!Exfi386InterlockedExchangeUlong(void)

83093904 8204b2e7 C7xUSBV3!powerWaitWakeCallback(

                                struct _DEVICE_OBJECT * Object = 0x89683700,

                                unsigned char MinorFunction = 0x00 '',

                                union _POWER_STATE PowerState = union _POWER_STATE,

                                struct _MINIPORT_ADAPTER * Adapter = 0x9112eb50,

                                struct _IO_STATUS_BLOCK * IoStatus = 0xa78aaea8)+0x1b

8309392c 822cec69 nt!PopRequestCompletion(

                                struct _DEVICE_OBJECT * DeviceObject = 0x00000000,

                                struct _IRP * Irp = 0xa78aae90,

                                void * Context = 0x898b3000)+0x38

83093964 820acc1b nt!IovpLocalCompletionRoutine(

                                struct _DEVICE_OBJECT * DeviceObject = 0x00000000,

                                struct _IRP * Irp = 0xa78aae90,

                                void * Context = 0x830939d4)+0xcc

8309399c 822ceb53 nt!IopfCompleteRequest(

                                struct _IRP * Irp = 0x9112ee50,

                                char PriorityBoost = 0 '')+0x11d

83093a0c 8f7431f4 nt!IovCompleteRequest(

                                struct _IRP * Irp = 0x9112ee50,

                                char PriorityBoost = 0 '')+0x11c

83093a20 8f74a7f6 usbhub!UsbhCompletePdoWakeIrp(

                                struct _DEVICE_OBJECT * HubFdo = 0x89522028,

                                struct _DEVICE_OBJECT * Pdo = 0x89683700,

                                long NtStatus = -1073741536)+0xaf

83093a40 8f74a9e0 usbhub!UsbhPdoRemoveCleanup(

                                struct _DEVICE_OBJECT * Pdo = 0x89683700)+0x3f

83093a58 8f72e41e usbhub!UsbhPdoPnp_RemoveDevice(

                                struct _DEVICE_OBJECT * Pdo = 0x89683700,

                                struct _IRP * Irp = 0xa7834eb8)+0x41

83093a74 8f726c92 usbhub!UsbhPdoPnp(

                                struct _DEVICE_OBJECT * HubPdo = 0x89683700,

                                struct _IRP * Irp = 0xa7834eb8)+0x78

83093a88 822ce681 usbhub!UsbhGenDispatch(

                                struct _DEVICE_OBJECT * DeviceObject = 0x89683700,

                                struct _IRP * Irp = 0xa7834eb8)+0x4a

83093aac 82027f1c nt!IovCallDriver(

                                struct _DEVICE_OBJECT * DeviceObject = 0x9112ee50,

                                struct _IRP * Irp = 0x00000000,

                                void * ReturnAddress = 0x825cfce9)+0x252

83093ac0 825cfce9 nt!IofCallDriver(

                                struct _DEVICE_OBJECT * DeviceObject = 0x9112ee50,

                                struct _IRP * Irp = 0x00000000)+0x1b

83093b08 822ce681 ndis!ndisPnPDispatch(

                                struct _DEVICE_OBJECT * DeviceObject = 0x892f6030,

                                struct _IRP * Irp = 0x00000002)+0x4a4

83093b2c 82027f1c nt!IovCallDriver(

                                struct _DEVICE_OBJECT * DeviceObject = 0x9112ee50,

                                struct _IRP * Irp = 0x00000000,

                                void * ReturnAddress = 0x821af73b)+0x252

83093b40 821af73b nt!IofCallDriver(

                                struct _DEVICE_OBJECT * DeviceObject = 0x9112ee50,

                                struct _IRP * Irp = 0x00000000)+0x1b

83093b74 821af9a3 nt!IopSynchronousCall(

                                struct _DEVICE_OBJECT * DeviceObject = 0x89683700,

                                struct _IO_STACK_LOCATION * TopStackLocation = 0x83093ba8,

                                long DefaultStatus = -1882596448,

                                unsigned long DefaultInformation = 0x83093bd0,

                                unsigned long * Information = 0x00000000)+0xce

83093bd0 82006592 nt!IopRemoveDevice(

                                struct _DEVICE_OBJECT * TargetDevice = 0x89683700,

                                unsigned long IrpMinorCode = 2)+0xd5

 

1: kd> kfL

  Memory  ChildEBP RetAddr 

          83093868 8208fbf4 nt!MmAccessFault+0x106

        0 83093868 82091f60 nt!_KiTrap0E+0xdc

       88 830938f0 8fc9dbbb nt!Exfi386InterlockedExchangeUlong

       14 83093904 8204b2e7 C7xUSBV3!powerWaitWakeCallback+0x1b

       28 8309392c 822cec69 nt!PopRequestCompletion+0x38

       38 83093964 820acc1b nt!IovpLocalCompletionRoutine+0xcc

       38 8309399c 822ceb53 nt!IopfCompleteRequest+0x11d

       70 83093a0c 8f7431f4 nt!IovCompleteRequest+0x11c

       14 83093a20 8f74a7f6 usbhub!UsbhCompletePdoWakeIrp+0xaf

       20 83093a40 8f74a9e0 usbhub!UsbhPdoRemoveCleanup+0x3f

       18 83093a58 8f72e41e usbhub!UsbhPdoPnp_RemoveDevice+0x41

       1c 83093a74 8f726c92 usbhub!UsbhPdoPnp+0x78

       14 83093a88 822ce681 usbhub!UsbhGenDispatch+0x4a

       24 83093aac 82027f1c nt!IovCallDriver+0x252

       14 83093ac0 825cfce9 nt!IofCallDriver+0x1b

       48 83093b08 822ce681 ndis!ndisPnPDispatch+0x4a4

       24 83093b2c 82027f1c nt!IovCallDriver+0x252

       14 83093b40 821af73b nt!IofCallDriver+0x1b

       34 83093b74 821af9a3 nt!IopSynchronousCall+0xce

       5c 83093bd0 82006592 nt!IopRemoveDevice+0xd5

'Programming' 카테고리의 다른 글

On-demand 메모리 관리  (0) 2009.04.02
Thread States  (0) 2009.03.27
Intel CPU registers  (0) 2009.03.20
Windbg Remote debugging 설정 방법  (0) 2009.03.20
Windows Error Reporting(WER)이란  (0) 2009.02.25
Posted by noenemy
,

오늘은 WinDbg를 이용해서 remote debugging을 하는 방법을 알아보려 합니다.

 

원격지의 WinDbg 프로그램을 서로 Server, Client 처럼 TCP/IP나 named pipe를 이용해서 통신하게 함으로써 debugging을 하는 방법입니다. 이 방법은 실제 debugging을 진행할 사람과 재현 장비가 멀리 떨어져 있는 경우 네트웤을 통해 디버깅을 할 수 있게 해주므로 매우 유용하게 사용할 수 있습니다. 다만 이렇게 WinDbg 끼리 서로 통신하려면 상호간에 연결이 되어야 하므로 약간을 설정이 필요합니다.

 

여기서는 TCP/IP를 이용한 remote debugging 방법을 알아보도록 하지요.

 

다음과 같은 상황을 가정해 보았습니다.

 

 

우선 일반적으로 kernel debugging을 하기 위한 환경 설정을 먼저 진행합니다. Target machine과 Host machine을 1394를 이용해서 연결하는 과정입니다.
(
세부 내용은 http://msdn.microsoft.com/en-us/library/cc266332.aspx 참고)

 

1.     일반적으로 kernel debugging을 위해서 target machine host machine 1394 cable을 이용해서 연결한 뒤

2.     Target machine debug mode로 부팅하고 (boot.ini 수정이나 vista에서는 bcdedit.exe 설정 필요)

3.     Host machine에서는 WinDbg를 실행시킨 후 kernel debug를 시작한다.

4.     Target machine Host machine windbg가 연결되면 kernel debugging이 가능하다.

 

자..여기까지 진행되었다면 Host machine과 원격지에 있는 Remote machine을 연결하는 방법을 알아보도록 하겠습니다.
현재 상황에서는 Host machine의 WinDbg가 server의 역할을, 그리고 Remote machine의 WinDbg가 client의 역할을 하게 됩니다.

즉, Hostmachine WinDbg Remote machine WinDbg가 서로 연결되어 통신할 수 있다면, Remote machine에서 Host machine을 거쳐서 Target machine kernel debugging을 하는 것이 가능해집니다.

 

Host machine Remote machine TCP/IP named pipe로 연결이 가능한데, 여기서는 TCP/IP를 이용한 네트워크 연결법을 알아보도록 하겠습니다. 

 

5.     Host machine에서 windbg break한 상태에서 kernel debug mode에서 다음과 같이 입력합니다.

A.     Kd> .server tcp:Port=<port number>

B.      Host machine windbg에서 server start 되었다는 메시지가 보여집니다. , Host machine에서 지정한 port number remote machine이 연결하기를 기다리는 상태가 됩니다.

 

이제 원격지에서 실제로 debugging할 엔지니어에게 host machine에 접근할 수 있는 장비명(or IP 주소) Port 번호를 알려줍니다. 만약 중간에 방화벽 같은 게 있다면 접근이 허용될 수 있도록 설정을 해줘야 합니다.

 

이제 Remote machine에서 Host machine으로 접근해 보겠습니다.

 

6.     Remote machine WinDbg file 메뉴에서 ‘connect to remote session’을 선택하고 접근할 Host machine의 server name(or IP 주소)과 지정한 port 번호를 입력합니다.

 

 

          

 

7.     연결에 성공하였다면 Remote machine WinDbg에서 다음과 같은 메시지를 볼 수 있습니다.

 

Microsoft (R) Windows Debugger Version 6.11.0001.402 X86

Copyright (c) Microsoft Corporation. All rights reserved.

 

Server started.  Client can connect with any of these command lines

0: <debugger> -remote tcp:Port=10123,Server=SOONKKIM2

SOONKKIM1\soonkkim (tcp 157.60.9.124:43460) connected at Fri Mar 20 15:52:52 2009

 

8.     Remote machine WinDbg를 이용해서 debugging을 진행하면 됩니다.

 

'Programming' 카테고리의 다른 글

Windbg Stack Backtracing 명령어  (0) 2009.03.27
Intel CPU registers  (0) 2009.03.20
Windows Error Reporting(WER)이란  (0) 2009.02.25
강제로 덤프파일 수집하기  (0) 2009.02.19
Driver Verifier에 대해서  (0) 2009.02.09
Posted by noenemy
,

Kernel mode에서 처리할 수 없는 exception이 발생하는 경우 흔히 우리가 블루스크린이라고 말하는 BSOD(Blue Screen Of Death) 화면을 볼 수 있습니다. 이때 시스템에서 설정한 옵션에 따라 오류 발생 시점의 메모리 정보를 dump file에 저장함으로써 나중에 왜 블루스크린이 발생했는지에 대한 원인을 분석하는데 사용할 수 있습니다. 이러한 덤프 분석을 문제가 발생한 이후에 이를 조사한다는 의미에서 Post morterm analysis라는 용어를 쓰기도 합니다.

블루스크린이 발생하면 파란 배경화면에 발생한 오류에 대한 코드와 몇 가지 추가 정보가 파라미터로 보여지고 덤프 파일을 저장하는 과정이 보여집니다. 즉, 메모리 상태를 덤프해서 memory.dmp 파일(일반적으로 c:\Windows에 위치)에 저장을 하는 과정입니다. 일반 사용자에게는 컴퓨터를 사용 중에 갑자기 이 화면을 만나게 되면 작업이 중단되고 시스템이 재시작되어야 하므로 매우 곤욕스럽습니다. 하지만 원인을 분석하고 이를 해결함으로써 컴퓨터 사용환경이 보다 더 안정적으로 될 수 있는 기회가 되므로 엔지니어나 개발자에게는 이때 저장되는 덤프 파일 정보가 문제해결에 매우 중요한 단서가 됩니다.

명시적으로 오류가 발생해서 BSOD가 발생하고 덤프 파일이 수집이 가능한 경우가 대부분이지만, 특정 시점에 덤프 파일을 강제로 생성할 필요가 있는 경우도 있습니다. 예를 들어, 특정 시점에 컴퓨터의 반응이 불안정하거나 너무 느려진 경우(주로 hanging이라고 부름) 그 원인을 찾기 위해 덤프를 수집하고 이를 분석할 필요가 있는데, 이는 커널에서 특정 예외가 발생한 경우가 아니기 때문에 덤프가 생성이 되지를 않습니다. 그래서 강제로 특정 시점의 덤프를 수집할 필요가 있는데 다음과 같은 방법으로 수집이 가능합니다.

*키보드의 특수 키 조합으로 강제로 BSOD를 발생시키는 방법으로 사용중인 키보드에 따라서 이 방법을 사용하지 못할 수도 있습니다. 예를 들어 노트북의 경우 제조 모델에 따라 키패드의 조합이 다르고, 특히 오른쪽 Ctrl 키를 이용하므로 왼쪽 Ctrl 키만 있는 일부 키보드를 이용해서는 수집할 수 없습니다.

* How to get full dump file manually

1. 제어판 - 시스템 - 고급 - 시작 및 복구
2. 현재 서버의 물리적인 Memory 가 2GB 이하라면 “전체 메모리 덤프(Full Memory dump)” 로 설정합니다. 만약 2GB 이상이라면 “커널 메모리 덤프(Kernel Memory dump)” 로 설정하십시오.
3. 기존 파일에 덮어쓰기 : 옵션 선택 확인 (선택되어 있어야 합니다.)
4. %SystemRoot% 파티션에 Paging 파일이 존재해야 합니다.
5. Paging 파일(pagefile.sys)의 크기가 물리적인 메모리보다 최소한 같거나 커야 합니다.
6. 기본적으로 Memory Dump 는 C:\Windows 에 저장됩니다. C Drive 에 공간이 충분히 있는지 확인하십시오.
7. 레지스트리 편집기를 실행하여 아래 레지스트리 키를 추가한 후, 이를 적용하기 위하여 시스템을 재부팅 합니다.

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\i8042prt\Parameters
값 이름: CrashOnCtrlScroll
데이터 형식: REG_DWORD
값: 1

8. 오른쪽 Ctrl 키를 누른 상태에서 Scroll Lock 키를 두 번 누르면, BSOD가 발생하고 덤프가 수집됩니다.

*덤프 수집이 안된다면, 레지스트리 변경후 재부팅을 했는지 또는 오른쪽 Ctrl 키를 눌렀는지, Scroll Lock 키를 두 번 눌렀는지, 특수한 키보드를 사용중인지를 확인해보시기 바랍니다.

'Programming' 카테고리의 다른 글

Windbg Stack Backtracing 명령어  (0) 2009.03.27
Intel CPU registers  (0) 2009.03.20
Windbg Remote debugging 설정 방법  (0) 2009.03.20
Windows Error Reporting(WER)이란  (0) 2009.02.25
Driver Verifier에 대해서  (0) 2009.02.09
Posted by noenemy
,

WinDbg 관련 링크

MS MVP 2006. 6. 23. 14:07

'MS MVP' 카테고리의 다른 글

태권도 시범 in Seattle  (9) 2007.04.17
MS MVP 2006  (0) 2006.07.02
MS MVP 2005 선정  (0) 2005.07.02
날샜다.  (0) 2005.05.16
Posted by noenemy
,