다음을 통해 공유


Windows 드라이버 디버그 단계별 랩(에코 커널 모드)

이 랩에서는 WinDbg 커널 디버거를 소개합니다. WinDbg를 사용하여 에코 커널 모드 샘플 드라이버 코드를 디버그합니다.

랩 목표

이 랩에는 디버깅 도구를 소개하고, 일반적인 디버깅 명령을 가르치고, 중단점 사용을 설명하고, 디버깅 확장을 사용하는 방법을 보여 주는 연습이 포함되어 있습니다.

이 랩에서는 라이브 커널 디버그 연결을 사용하여 다음 작업을 탐색합니다.

  • Windows 디버거 명령 사용
  • 표준 명령 사용(호출 스택, 변수, 스레드, IRQL)
  • 고급 드라이버 디버깅 명령 사용(!명령)
  • 기호 사용
  • 라이브 디버깅에서 중단점 설정
  • 호출 스택 보기
  • 플러그 앤 플레이 디바이스 트리 표시
  • 스레드 및 프로세스 컨텍스트 작업

사용자 및 커널 모드 디버깅

Windows 디버거를 사용하는 경우 두 가지 유형의 디버깅을 수행할 수 있습니다.

사용자 모드 - 애플리케이션 및 하위 시스템은 사용자 모드에서 컴퓨터에서 실행됩니다. 사용자 모드에서 실행되는 프로세스는 자체 가상 주소 공간 내에서 실행됩니다. 시스템 하드웨어, 사용을 위해 할당되지 않은 메모리 및 시스템 무결성을 손상시킬 수 있는 시스템의 다른 부분을 포함하여 시스템의 많은 부분에 직접 액세스할 수 없습니다. 사용자 모드에서 실행되는 프로세스는 시스템 및 기타 사용자 모드 프로세스와 효과적으로 격리되므로 이러한 리소스를 방해할 수 없습니다.

커널 모드 - 운영 체제 및 권한 있는 프로그램은 커널 모드에서 실행됩니다. 커널 모드 코드에는 시스템의 모든 부분에 액세스할 수 있는 권한이 있습니다. 사용자 모드 코드처럼 제한되지 않습니다. 사용자 모드 또는 커널 모드에서 실행되는 다른 프로세스의 모든 부분에 액세스할 수 있습니다. 대부분의 핵심 OS 기능과 많은 하드웨어 디바이스 드라이버는 커널 모드에서 실행됩니다.

이 연습에서는 사용자 모드 및 커널 모드 디버깅 중에 자주 사용되는 디버그 명령에 대해 설명합니다. 또한 이 연습에서는 커널 모드 디버깅에 사용되는 디버그 확장("bang" !commands라고도 함)을 다룹니다.

랩 설정

랩을 완료하려면 다음 하드웨어가 필요합니다.

  • Windows 10을 실행하는 랩톱 또는 데스크톱 컴퓨터(호스트)
  • Windows 10을 실행하는 두 번째 랩톱 또는 데스크톱 컴퓨터(대상)
  • 두 컴퓨터를 연결하는 네트워크 허브 또는 라우터 및 네트워크 케이블
  • 기호 파일을 다운로드하기 위한 인터넷 액세스

랩을 완료하려면 다음 소프트웨어가 필요합니다.

  • Visual Studio
  • Windows 10용 Windows SDK(소프트웨어 개발 키트)
  • Windows 10용 WDK(Windows 드라이버 키트)
  • Windows 10용 샘플 에코 드라이버

랩에는 다음 섹션이 있습니다.

커널 모드 WinDbg 세션에 연결

이 섹션에서는 호스트 및 대상 시스템에서 네트워크 디버깅을 구성합니다.

이 랩의 컴퓨터는 커널 디버깅에 이더넷 네트워크 연결을 사용하도록 구성해야 합니다.

이 랩에서는 두 대의 컴퓨터를 사용합니다. Windows 디버거는 호스트 시스템에서 실행되고 KMDF(커널 모드 드라이버 프레임워크) 에코 드라이버는 대상 시스템에서 실행됩니다.

네트워크 허브 또는 라우터 및 네트워크 케이블을 사용하여 두 컴퓨터를 연결합니다.

네트워크 허브 또는 라우터를 통해 연결된 두 컴퓨터를 보여 주는 다이어그램

커널 모드 애플리케이션을 사용하고 WinDbg를 사용하려면 이더넷 전송을 통해 KDNET을 사용하는 것이 좋습니다. 이더넷 전송 프로토콜을 사용하는 방법에 대한 자세한 내용은 WinDbg 시작(커널 모드)을 참조하세요. 대상 컴퓨터 설정에 대한 자세한 내용은 수동 드라이버 배포 를 위해 컴퓨터 준비 및 KDNET 네트워크 커널 디버깅 자동 설정을 참조하세요.

이더넷을 사용하여 커널 모드 디버깅 구성

대상 시스템에서 커널 모드 디버깅을 사용하도록 설정하려면 다음을 수행합니다.

  1. 호스트 시스템에서 명령 프롬프트 창을 열고 ipconfig를 입력하여 IPv4 주소를 확인합니다.

    Windows IP Configuration
    Ethernet adapter Ethernet:
       Connection-specific DNS Suffix  . :
       Link-local IPv6 Address . . . . . : fe80::c8b6:db13:d1e8:b13b%3
       Autoconfiguration IPv4 Address. . : 169.182.1.1
       Subnet Mask . . . . . . . . . . . : 255.255.0.0
       Default Gateway . . . . . . . . . :
    
  2. 호스트 시스템의 IP 주소를 기록합니다. ______________________________________

  3. 대상 시스템에서 명령 프롬프트 창을 열고 명령을 사용하여 ping 두 시스템 간의 네트워크 연결을 확인합니다.

    ping 169.182.1.1
    

    샘플 출력에 표시된 169.182.1.1 대신 기록한 호스트 시스템의 실제 IP 주소를 사용합니다.

    Pinging 169.182.1.1 with 32 bytes of data:
    Reply from 169.182.1.1: bytes=32 time=1ms TTL=255
    Reply from 169.182.1.1: bytes=32 time<1ms TTL=255
    Reply from 169.182.1.1: bytes=32 time<1ms TTL=255
    Reply from 169.182.1.1: bytes=32 time<1ms TTL=255
    
    Ping statistics for 169.182.1.1:
        Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
    Approximate round trip times in milli-seconds:
        Minimum = 0ms, Maximum = 1ms, Average = 0ms
    

다음 단계를 완료하여 대상 시스템에서 커널 모드 디버깅을 사용하도록 설정합니다.

Important

BCDEdit을 사용하여 부팅 정보를 변경하기 전에 테스트 컴퓨터에서 BitLocker 및 보안 부팅과 같은 Windows 보안 기능을 일시적으로 일시 중단해야 할 수 있습니다. 테스트가 완료되면 이러한 보안 기능을 다시 사용하도록 설정합니다. 보안 기능을 사용하지 않도록 설정하면 테스트 컴퓨터를 적절하게 관리합니다. 보안 부팅은 일반적으로 UEFI에서 사용하지 않도록 설정됩니다. UEFI 설정에 액세스하려면 시스템, 복구, 고급 시작을 사용합니다. 다시 시작할 때 문제 해결, 고급 옵션, UEFI 펌웨어 설정을 선택합니다. UEFI 옵션을 잘못 설정하거나 BitLocker를 사용하지 않도록 설정하면 시스템이 작동하지 않을 수 있으므로 주의해야 합니다.

  1. 대상 컴퓨터에서 관리자 권한으로 명령 프롬프트 창을 엽니다. 디버깅을 사용하도록 설정하려면 다음 명령을 입력합니다.

    bcdedit /set {default} DEBUG YES
    
  2. 테스트 서명을 사용하도록 설정하려면 다음 명령을 입력합니다.

    bcdedit /set TESTSIGNING ON 
    
  3. 호스트 시스템의 IP 주소를 설정하려면 이 명령을 입력합니다. 표시된 IP 주소가 아니라 이전에 기록한 호스트 시스템의 IP 주소를 사용합니다.

    bcdedit /dbgsettings net hostip:192.168.1.1 port:50000 key:2steg4fzbj2sz.23418vzkd4ko3.1g34ou07z4pev.1sp3yo9yz874p
    

    Warning

    연결의 보안을 강화하고 임의 클라이언트 디버거 연결 요청의 위험을 줄이려면 자동 생성된 임의 키를 사용합니다. 자세한 내용은 자동으로 KDNET 네트워크 커널 디버깅 설정을 참조 하세요.

  4. 다음 명령을 입력하여 값 dbgsettings 이 올바르게 설정되는지 확인합니다.

    bcdedit /dbgsettings
    
    key                     2steg4fzbj2sz.23418vzkd4ko3.1g34ou07z4pev.1sp3yo9yz874p
    debugtype               NET
    hostip                  169.168.1.1
    port                    50000
    dhcp                    Yes
    The operation completed successfully.
    

    참고 항목

    방화벽에서 메시지를 받고 디버거를 사용하려는 경우 세 개의 상자를 모두 선택합니다.

    Windows 방화벽이 앱의 일부 기능을 차단했음을 나타내는 Windows 보안 경고 대화 상자의 스크린샷

  5. 호스트 컴퓨터에서 관리자 권한으로 명령 프롬프트 창을 엽니다. 이 랩에서는 Windows 키트 설치의 일부로 설치된 WDK(Windows 드라이버 키트)의 x64 버전의 WinDbg.exe 사용합니다. 기본 WinDbg 디렉터리로 변경합니다. 기본 위치는 다음과 같습니다.

    cd C:\Program Files(x86)\Windows Kits\10\Debuggers\x64 
    

    이 랩에서는 두 컴퓨터가 모두 대상과 호스트 모두에서 64비트 버전의 Windows를 실행한다고 가정합니다. 그렇지 않은 경우 가장 좋은 방법은 대상이 실행되는 호스트에서 동일한 비트 의 도구를 실행하는 것입니다. 예를 들어 대상이 32비트 Windows를 실행하는 경우 호스트에서 32비트 버전의 디버거를 실행합니다. 자세한 내용은 32비트 또는 64비트 디버깅 도구 선택을 참조 하세요.

  6. 다음 명령을 사용하여 원격 사용자 디버그로 WinDbg를 엽니다. 키 및 포트의 값은 대상 컴퓨터에서 BCDEdit을 사용하여 이전에 설정한 값과 일치합니다.

    WinDbg –k net:port=50000,key=2steg4fzbj2sz.23418vzkd4ko3.1g34ou07z4pev.1sp3yo9yz874p
    
  7. 대상 시스템을 다시 시작합니다.

  8. 1~2분 후에 디버그 출력이 호스트 시스템에 표시되어야 합니다.

    Microsoft (R) Windows Debugger Version 10.0.17074.1002 AMD64
    Copyright (c) Microsoft Corporation. All rights reserved.
    
    Using NET for debugging
    Opened WinSock 2.0
    Waiting to reconnect...
    Connected to target 169.182.1.1 on port 50005 on local IP 169.182.1.2
    You can get the target MAC address by running .kdtargetmac command.
    Connected to Windows 10 16299 x64 target at (Wed Feb 28 17:16:23.051 2018 (UTC - 8:00)), ptr64 TRUE
    Kernel Debugger connection established.  (Initial Breakpoint requested)
    Symbol search path is: srv*
    Executable search path is: 
    Windows 10 Kernel Version 16299 MP (4 procs) Free x64
    Product: WinNt, suite: TerminalServer SingleUserTS
    Built by: 16299.15.amd64fre.rs3_release.170928-1534
    Machine Name:
    Kernel base = 0xfffff800`9540d000 PsLoadedModuleList = 0xfffff800`95774110
    Debug session time: Wed Feb 28 17:16:23.816 2018 (UTC - 8:00)
    System Uptime: 0 days 0:00:20.534
    

디버거 명령 창은 WinDbg의 기본 디버깅 정보 창입니다. 디버거 명령을 입력하고 이 창에서 명령 출력을 볼 수 있습니다.

디버거 명령 창은 두 개의 창으로 분할됩니다. 창 아래쪽에 있는 명령 항목 창인 더 작은 창에 명령을 입력하고 창 맨 위에 있는 더 큰 창에서 명령 출력을 봅니다.

명령 항목 창에서 위쪽 화살표 및 아래쪽 화살표 키를 사용하여 명령 기록을 스크롤합니다. 명령이 나타나면 명령을 편집하거나 Enter 키를 눌러 명령을 실행할 수 있습니다.

커널 모드 디버깅 명령 및 기술

이 섹션에서는 디버그 명령을 사용하여 대상 시스템에 대한 정보를 표시합니다.

일부 디버그 명령은 더 많은 정보를 빠르게 수집하도록 선택할 수 있는 DML(디버거 태그 언어)을 사용하여 텍스트를 표시합니다.

  1. 호스트 시스템에서 WinDBg의 Ctrl+스크롤 잠금을 사용하여 대상 시스템에서 실행되는 코드를 중단합니다. 대상 시스템이 응답하는 데 다소 시간이 걸릴 수 있습니다.

    라이브 커널 연결의 명령 창 출력을 보여 주는 디버거의 기본 화면입니다.

  2. 디버거 명령 창에서 DML을 사용하도록 설정하려면 다음 명령을 입력합니다.

    0: kd> .prefer_dml 1
    DML versions of commands on by default
    
  3. 명령을 사용하여 참조 명령 도움말에 .hh 액세스할 수 있습니다. 다음 명령을 입력하여 다음에 대한 명령 참조 도움말을 봅니다 .prefer_dml.

    0: kd> .hh .prefer_dml
    

    디버거 도움말 파일에는 명령에 대한 도움말이 .prefer_dml 표시됩니다.

    .prefer-dml 명령에 대한 도움말을 표시하는 디버거 도움말 애플리케이션의 스크린샷

  4. 대상 시스템에 자세한 버전 정보를 표시하려면 WinDbg 창에 꼭짓점(대상 컴퓨터 버전 표시) 명령을 입력합니다.

    0: kd> vertarget
    Windows 10 Kernel Version 9926 MP (4 procs) Free x64
    Product: WinNt, suite: TerminalServer SingleUserTS
    Built by: 9926.0.amd64fre.fbl_awesome1501.150119-1648
    Machine Name: ""
    Kernel base = 0xfffff801`8d283000 PsLoadedModuleList = 0xfffff801`8d58aef0
    Debug session time: Fri Feb 20 10:15:17.807 2015 (UTC - 8:00)
    System Uptime: 0 days 01:31:58.931
    
  5. 올바른 커널 모드 프로세스를 사용 중인지 확인하려면 WinDbg 창에 lm(로드된 모듈 나열) 명령을 입력하여 로드된 모듈을 표시합니다.

    0: Kd> lm
    start             end                 module name
    fffff801`09200000 fffff801`0925f000   volmgrx    (no symbols)
    fffff801`09261000 fffff801`092de000   mcupdate_GenuineIntel   (no symbols)
    fffff801`092de000 fffff801`092ec000   werkernel   (export symbols)       werkernel.sys
    fffff801`092ec000 fffff801`0934d000   CLFS       (export symbols)       CLFS.SYS
    fffff801`0934d000 fffff801`0936f000   tm         (export symbols)       tm.sys
    fffff801`0936f000 fffff801`09384000   PSHED      (export symbols)       PSHED.dll
    fffff801`09384000 fffff801`0938e000   BOOTVID    (export symbols)       BOOTVID.dll
    fffff801`0938e000 fffff801`093f7000   spaceport   (no symbols)
    fffff801`09400000 fffff801`094cf000   Wdf01000   (no symbols)
    fffff801`094d9000 fffff801`09561000   CI         (export symbols)       CI.dll
    ...
    

    생략된 출력은 "..."로 표시됩니다. 이 랩에서

  6. 특정 모듈에 대한 자세한 정보를 요청하려면 (자세한 정보 표시) 옵션을 사용합니다 v .

    0: Kd> lm v m tcpip
    Browse full module list
    start             end                 module name
    fffff801`09eeb000 fffff801`0a157000   tcpip      (no symbols)           
        Loaded symbol image file: tcpip.sys
        Image path: \SystemRoot\System32\drivers\tcpip.sys
        Image name: tcpip.sys
        Browse all global symbols  functions  data
        Timestamp:        Sun Nov 09 18:59:03 2014 (546029F7)
        CheckSum:         00263DB1
        ImageSize:        0026C000
        Translations:     0000.04b0 0000.04e4 0409.04b0 0409.04e4
    
    Unable to enumerate user-mode unloaded modules, Win32 error 0n30
    

    설정된 기호 경로와 로드된 기호가 없으므로 디버거에서 제한된 정보를 사용할 수 있습니다.

KMDF 에코 드라이버 다운로드 및 빌드

이 섹션에서는 KMDF 에코 드라이버를 다운로드하고 빌드합니다.

일반적으로 WinDbg를 사용할 때 사용자 고유의 드라이버 코드를 사용합니다. WinDbg 작업에 익숙해지려면 이 랩에서는 KMDF 템플릿 "Echo" 샘플 드라이버를 사용합니다. 소스 코드는 WinDbg에 표시되는 정보를 이해하는 데 도움이 됩니다. 이 샘플은 네이티브 커널 모드 코드를 한 단계씩 실행할 수 있는 방법을 설명하는 데도 사용됩니다. 이 기술은 복잡한 커널 모드 코드 문제를 디버깅하는 데 유용할 수 있습니다.

Echo 샘플 오디오 드라이버를 다운로드하고 빌드하려면 다음을 수행합니다.

  1. GitHub에서 KMDF Echo 샘플을 다운로드하고 추출합니다.

    KMDF Echo 샘플은 일반 폴더에 있습니다.

    일반 폴더 및 다운로드 zip 단추를 강조 표시하는 GitHub windows-driver-samples 페이지의 스크린샷.

    1. 하나의 zip 파일에서 드라이버 샘플 다운로드: 드라이버 샘플

    2. 로컬 하드 드라이브에 zip 파일을 다운로드합니다.

    3. zip 파일을 선택하고 길게 누르거나 마우스 오른쪽 단추로 클릭하고 모두 추출을 선택합니다. 새 폴더를 지정하거나 기존 폴더로 이동하여 추출된 파일을 저장합니다. 예를 들어 C:\DriverSamples\를 파일을 추출할 새 폴더로 지정할 수 있습니다.

    4. 파일을 추출한 후 다음 하위 폴더 로 이동합니다. C:\DriverSamples\general\echo\kmdf

  2. Microsoft Visual Studio에서 파일>열기>프로젝트/솔루션을 선택하고 추출된 파일이 포함된 폴더(예: C:\DriverSamples\general\echo\kmdf)로 이동합니다. kmdfecho 솔루션 파일을 두 번 클릭하여 엽니다.

    Visual Studio에서 솔루션 탐색기 찾습니다. 이 창이 아직 열려 있지 않으면 보기 메뉴에서 솔루션 탐색기 선택합니다. 솔루션 탐색기 세 개의 프로젝트가 있는 하나의 솔루션을 볼 수 있습니다.

    kmdfecho 프로젝트에서 로드된 device.c 파일을 표시하는 Visual Studio의 스크린샷

  3. 샘플의 구성 및 플랫폼을 설정합니다. 솔루션 탐색기 솔루션 'kmdfecho'(프로젝트 3개)를 선택하고 길게 클릭하거나 마우스 오른쪽 단추로 클릭하고 Configuration Manager를 선택합니다. 구성 및 플랫폼 설정이 세 프로젝트에 대해 동일한지 확인합니다. 기본적으로 구성은 Win10 디버그설정되고 플랫폼은 모든 프로젝트에 대해 Win64설정됩니다. 한 프로젝트에 대해 구성 또는 플랫폼을 변경하는 경우 나머지 세 프로젝트에 대해 동일한 변경을 수행합니다.

  4. 기존 드라이버와 겹치지 않는 값을 사용하도록 드라이버 샘플을 수정해야 합니다. 샘플 코드에서 프로덕션 드라이버로 - Windows에 설치된 기존 실제 드라이버와 공존하는 고유한 드라이버 샘플을 만드는 방법에 대한 샘플의 변경 내용을 참조하세요.

  5. 런타임 라이브러리를 설정합니다. 에코 드라이버 속성 페이지를 열고 C/C++>코드 생성을 찾습니다. 런타임 라이브러리를 다중 스레드 디버그(/MTd)로 변경합니다. 빌드 옵션에 대한 자세한 내용은 /MD, /MT, /LD(런타임 라이브러리 사용)를 참조하세요.

    런타임 라이브러리 설정을 강조 표시하는 Visual Studio의 Echo 속성 페이지 스크린샷

  6. 드라이버 속성에서 드라이버 서명>서명 모드가 테스트 서명으로 설정되어 있는지 확인합니다.

    서명 모드 설정을 강조 표시하는 Visual Studio의 Echo 속성 페이지 스크린샷

  7. Visual Studio에서 빌드>솔루션 빌드를 선택합니다.

    빌드 창에는 세 프로젝트 모두에 대한 빌드가 성공했음을 나타내는 메시지가 표시됩니다.

빌드 오류 메시지가 표시되면 빌드 오류 번호를 사용하여 수정 사항을 확인합니다. 예를 들어 MSBuild 오류 MSB8040 스펙터 완화 라이브러리를 사용하는 방법을 설명합니다.

  1. 파일 탐색기 샘플에 대해 추출된 파일이 포함된 폴더로 이동합니다. 예를 들어 이전에 지정한 폴더인 경우 C:\DriverSamples\general\echo\kmdf로 이동합니다. 해당 폴더 내에서 컴파일된 드라이버 파일의 위치는 Configuration Manager에서 선택한 구성 및 플랫폼 설정에 따라 달라집니다. 기본 설정을 변경하지 않은 상태로 두면 컴파일된 드라이버 파일이 64비트 디버그 빌드의 \x64\Debug 폴더에 저장됩니다.

    Autosync 드라이버 에 대한 빌드된 파일이 포함된 폴더로 이동합니다. C:\DriverSamples\general\echo\kmdf\driver\AutoSync\x64\Debug.

    폴더에는 다음 파일이 포함되어야 합니다.

    파일 설명
    Echo.sys 드라이버 파일입니다.
    Echo.inf 드라이버를 설치하는 데 필요한 정보가 포함된 정보(INF) 파일입니다.

    또한 echoapp.exe 파일이 빌드되었으며 C:\DriverSamples\general\echo\kmdf\exe\x64\Debug있어야 합니다.

    파일 설명
    EchoApp.exe echo.sys 드라이버와 통신하는 명령 프롬프트 실행 파일 테스트 파일입니다.
  2. USB 썸 드라이브를 찾거나 네트워크 공유를 설정하여 빌드된 드라이버 파일과 테스트 EchoApp 을 호스트에서 대상 시스템으로 복사합니다.

다음 섹션에서는 코드를 대상 시스템에 복사하고 드라이버를 설치하고 테스트합니다.

대상 시스템에 KMDF 에코 드라이버 샘플 설치

이 섹션에서는 DevCon 도구를 사용하여 에코 샘플 드라이버를 설치합니다.

드라이버를 설치하는 컴퓨터를 대상 컴퓨터 또는 테스트 컴퓨터라고 합니다. 일반적으로 이 컴퓨터는 드라이버 패키지를 개발하고 빌드하는 컴퓨터와는 별개입니다. 드라이버를 개발하고 빌드하는 컴퓨터를 호스트 컴퓨터라고 합니다.

드라이버 패키지를 대상 컴퓨터로 이동하고 드라이버를 설치하는 프로세스를 드라이버 배포라고 합니다.

테스트 서명된 드라이버를 배포하기 전에 테스트 서명을 사용하도록 설정하여 대상 컴퓨터를 준비합니다. 또한 WDK 설치에서 DevCon 도구를 찾아 대상 시스템에 복사해야 합니다.

대상 시스템에 드라이버를 설치하려면 다음 단계를 수행합니다.

대상 시스템에서 테스트 서명된 드라이버를 사용하도록 설정합니다.

  1. Windows 설정을 엽니다.

  2. 업데이트 및 보안에서 복구를 선택합니다.

  3. 고급 시작에서 지금 다시 시작을 선택합니다.

  4. 컴퓨터가 다시 시작되면 시작 옵션을 선택합니다. Windows 10에서 고급 옵션>시작 설정 문제 해결>을 선택한 다음 다시 시작을 선택합니다.

  5. F7 키를 눌러 드라이버 서명 적용 사용 안 함을 선택합니다.

  6. 대상 컴퓨터를 다시 시작 합니다.

호스트 시스템에서 WDK 설치의 도구 폴더로 이동하여 DevCon 도구를 찾습니다. 예를 들어 C:\Program Files (x86)\Windows Kits\10\Tools\x64\devcon.exe 폴더를 살펴봅니다.

빌드된 드라이버 패키지(예 : C:\EchoDriver)의 대상에 폴더를 만듭니다. 대상 시스템에 devcon.exe 복사합니다. 호스트 시스템에서 .cer 인증서를 찾습니다. 빌드된 드라이버 파일이 포함된 폴더의 호스트 컴퓨터에서 동일한 폴더에 있습니다. 호스트 컴퓨터에서 앞에서 설명한 빌드된 드라이버의 모든 파일을 복사하고 대상 컴퓨터에서 만든 것과 동일한 폴더에 저장합니다.

대상 컴퓨터에서 인증서 파일을 길게 선택하거나 마우스 오른쪽 단추로 클릭하고 설치를 선택한 다음 프롬프트에 따라 테스트 인증서를 설치합니다.

대상 컴퓨터를 설정하기 위한 자세한 지침이 필요한 경우 수동 드라이버 배포를 위해 컴퓨터 준비를 참조하세요.

다음 지침에서는 샘플 드라이버를 설치하고 테스트하는 방법을 보여 줍니다. 다음은 드라이버를 설치하는 데 사용하는 devcon 도구의 일반 구문입니다.

devcon install <INF file> <hardware ID>

이 드라이버를 설치하는 데 필요한 INF 파일은 echo.inf입니다. inf 파일에는 echo.sys 설치하기 위한 하드웨어 ID가 포함되어 있습니다. 에코 샘플의 경우 하드웨어 ID는 root\ECHO입니다.

대상 컴퓨터에서 관리자 권한으로 명령 프롬프트 창을 엽니다. 드라이버 패키지 폴더로 이동하여 다음 명령을 입력합니다.

devcon install echo.inf root\ECHO

개발자가 인식되지 않는 것에 대한 오류 메시지가 표시되면 devcon 도구에 경로를 추가해 보세요. 예를 들어 C:\Tools라는 폴더에 복사한 경우 다음 명령을 사용해 보세요.

c:\tools\devcon install echo.inf root\ECHO

테스트 드라이버가 서명되지 않은 드라이버임을 나타내는 대화 상자가 나타납니다. 계속하려면 이 드라이버 설치를 선택합니다.

Windows에서 드라이버 소프트웨어의 게시자를 확인할 수 없다는 Windows 보안 경고 스크린샷

 설치에 문제가 있는 경우 다음 파일을 확인하여 자세한 내용을 확인하세요. %windir%\inf\setupapi.dev.log

샘플 드라이버를 성공적으로 설치한 후에는 테스트할 준비가 된 것입니다.

대상 컴퓨터의 명령 프롬프트 창에서 devmgmt를 입력하여 장치 관리자 엽니다. 장치 관리자 보기 메뉴에서 유형별로 디바이스를 선택합니다. 디바이스 트리의 샘플 디바이스 노드에서 샘플 WDF Echo Driver습니다.

샘플 WDF 에코 드라이버를 강조 표시하는 장치 관리자 트리의 스크린샷

echoapp을 입력하여 테스트 에코 앱을 시작하여 드라이버가 작동하고 있는지 확인합니다.

C:\Samples\KMDF_Echo_Sample> echoapp
DevicePath: \\?\root#sample#0005#{cdc35b6e-0be4-4936-bf5f-5537380a7c1a}
Opened device successfully
512 Pattern Bytes Written successfully
512 Pattern Bytes Read successfully
Pattern Verified successfully
30720 Pattern Bytes Written successfully
30720 Pattern Bytes Read successfully
Pattern Verified successfully

WinDbg를 사용하여 드라이버에 대한 정보 표시

이 섹션에서는 기호 경로를 설정하고 커널 디버거 명령을 사용하여 KMDF 에코 샘플 드라이버에 대한 정보를 표시합니다.

드라이버에 대한 정보를 보려면 다음을 수행합니다.

  1. 호스트 시스템에서 디버거를 닫은 경우 관리자 명령 프롬프트 창에서 다음 명령을 사용하여 다시 엽니다.

    WinDbg -k net:port=50000,key=2steg4fzbj2sz.23418vzkd4ko3.1g34ou07z4pev.1sp3yo9yz874p
    
  2. Ctrl+Break(스크롤 잠금)를 사용하여 대상 시스템에서 실행되는 코드를 중단합니다.

  3. WinDbg 환경에서 Microsoft 기호 서버에 대한 기호 경로를 설정하려면 이 .symfix 명령을 사용합니다.

    0: kd> .symfix
    
  4. 로컬 기호를 사용할 로컬 기호 위치를 추가하려면 다음을 사용하여 .sympath+ .reload /f경로를 추가합니다.

    0: kd> .sympath+ C:\DriverSamples\general\echo\kmdf
    0: kd> .reload /f
    

    .reload force 옵션이 있는 /f 명령은 지정된 모듈에 대한 모든 기호 정보를 삭제하고 기호를 다시 로드합니다. 경우에 따라 이 명령은 모듈 자체를 다시 로드하거나 언로드합니다.

WinDbg에서 제공하는 고급 기능을 사용하려면 적절한 기호를 로드해야 합니다. 기호가 제대로 구성되지 않은 경우 기호에 종속된 기능을 사용하려고 하면 기호를 사용할 수 없음을 나타내는 메시지가 표시됩니다.

0:000> dv
Unable to enumerate locals, HRESULT 0x80004005
Private symbols (symbols.pri) are required for locals.
Type “.hh dbgerr005” for details.

기호를 사용하는 데 사용할 수 있는 여러 가지 방법이 있습니다. 대부분의 경우 필요한 경우 Microsoft에서 제공하는 기호 서버에서 기호에 액세스하도록 컴퓨터를 구성할 수 있습니다. 이 랩에서는 이 방법을 사용합니다. 환경의 기호가 다른 위치에 있는 경우 해당 위치를 사용하도록 단계를 수정합니다. 자세한 내용은 Windows 디버거의 기호 경로를 참조 하세요.

원본 디버깅을 수행하려면 확인된(디버그) 버전의 이진 파일을 빌드해야 합니다. 컴파일러는 기호 파일(.pdb 파일)을 만듭니다. 이러한 기호 파일은 이진 명령이 소스 줄에 해당하는 방법을 디버거에 보여 줍니다. 실제 원본 파일 자체도 디버거에서 액세스할 수 있어야 합니다.

기호 파일에는 소스 코드의 텍스트가 포함되어 있지 않습니다. 디버깅의 경우 링커가 코드를 최적화하지 않는 것이 가장 좋습니다. 코드가 최적화된 경우 소스 디버깅 및 지역 변수에 대한 액세스가 더 어렵고 거의 불가능할 수 있습니다. 지역 변수 또는 소스 줄을 보는 데 문제가 있는 경우 다음 빌드 옵션을 설정합니다.

set COMPILE_DEBUG=1
set ENABLE_OPTIMIZER=0
  1. 에코 드라이버에 대한 정보를 표시하려면 디버거의 명령 영역에 다음 명령을 입력합니다.

    0: kd> lm m echo* v
    Browse full module list
    start             end                 module name
    fffff801`4ae80000 fffff801`4ae89000   ECHO       (private pdb symbols)  C:\Samples\KMDF_ECHO_SAMPLE\echo.pdb
        Loaded symbol image file: ECHO.sys
        Image path: \SystemRoot\system32\DRIVERS\ECHO.sys
        Image name: ECHO.sys
    ...  
    

    자세한 내용은 lm을 참조 하세요.

  2. 이 랩은 이전에 설정 prefer_dml 되었기 때문에 출력의 일부 요소는 선택할 수 있는 핫 링크입니다. 디버그 출력에서 모든 전역 기호 찾아보기 링크를 선택하여 문자 "a"로 시작하는 항목 기호에 대한 정보를 표시합니다.

    0: kd> x /D Echo!a*
    
  3. 에코 샘플에는 문자 "a"로 시작하는 기호가 없으므로 "Echo"로 시작하는 에코 드라이버와 연결된 모든 기호에 대한 정보를 표시하도록 입력 x ECHO!Echo* 합니다.

    0: kd> x ECHO!Echo*
    fffff801`0bf95690 ECHO!EchoEvtIoQueueContextDestroy (void *)
    fffff801`0bf95000 ECHO!EchoEvtDeviceSelfManagedIoStart (struct WDFDEVICE__ *)
    fffff801`0bf95ac0 ECHO!EchoEvtTimerFunc (struct WDFTIMER__ *)
    fffff801`0bf9b120 ECHO!EchoEvtDeviceSelfManagedIoSuspend (struct WDFDEVICE__ *)
    ...
    

    자세한 내용은 x(기호 검사)를 참조하세요.

  4. 확장에는 !lmi 모듈에 대한 자세한 정보가 표시됩니다. !lmi echo를 입력합니다. 출력은 이 예제에 표시된 텍스트와 유사해야 합니다.

    0: kd> !lmi echo
    Loaded Module Info: [echo] 
             Module: ECHO
       Base Address: fffff8010bf94000
         Image Name: ECHO.sys
    … 
    
  5. 이 예제와 !dh 같이 확장을 사용하여 헤더 정보를 표시합니다.

    0: kd> !dh echo
    
    File Type: EXECUTABLE IMAGE
    FILE HEADER VALUES
         14C machine (i386)
           6 number of sections
    54AD8A42 time date stamp Wed Jan 07 11:34:26 2015
    ...
    
  6. 대상 시스템의 모든 디버그 메시지가 디버거에 표시되도록 기본 디버그 비트 마스크를 변경하려면 다음을 입력합니다.

    0: kd> ed nt!Kd_DEFAULT_MASK 0xFFFFFFFF
    

    일부 드라이버는 0xFFFFFFFF 마스크를 사용할 때 추가 정보를 표시합니다. 표시되는 정보의 양을 줄이려면 마스크를 0x00000000 설정합니다.

    0: kd> ed nt!Kd_DEFAULT_MASK 0x00000000
    

    dd 명령을 사용하여 마스크가 모든 디버거 메시지를 표시하도록 설정되어 있는지 확인합니다.

    0: kd> dd nt!kd_DEFAULT_MASK 
    fffff802`bb4057c0  ffffffff 00000000 00000000 00000000
    fffff802`bb4057d0  00000000 00000000 00000000 00000000
    fffff802`bb4057e0  00000001 00000000 00000000 00000000
    fffff802`bb4057f0  00000000 00000000 00000000 00000000
    fffff802`bb405800  00000000 00000000 00000000 00000000
    fffff802`bb405810  00000000 00000000 00000000 00000000
    fffff802`bb405820  00000000 00000000 00000000 00000000
    fffff802`bb405830  00000000 00000000 00000000 00000000
    

플러그 앤 플레이 디바이스 트리 정보 표시

이 섹션에서는 에코 샘플 디바이스 드라이버 및 해당 드라이버가 플러그 앤 플레이 디바이스 트리에 있는 위치에 대한 정보를 표시합니다.

플러그 앤 플레이 디바이스 트리의 디바이스 드라이버에 대한 정보는 문제 해결에 유용할 수 있습니다. 예를 들어 디바이스 드라이버가 디바이스 트리에 상주하지 않는 경우 디바이스 드라이버 설치에 문제가 있을 수 있습니다.

디바이스 노드 디버그 확장에 대한 자세한 내용은 !devnode를 참조하세요.

  1. 호스트 시스템에서 플러그 앤 플레이 디바이스 트리의 모든 디바이스 노드를 보려면 명령을 입력합니다!devnode 0 1.

    0: kd> !devnode 0 1
    Dumping IopRootDeviceNode (= 0xffffe0005a3a8d30)
    DevNode 0xffffe0005a3a8d30 for PDO 0xffffe0005a3a9e50
      InstancePath is "HTREE\ROOT\0"
      State = DeviceNodeStarted (0x308)
      Previous State = DeviceNodeEnumerateCompletion (0x30d)
      DevNode 0xffffe0005a3a3d30 for PDO 0xffffe0005a3a4e50
        InstancePath is "ROOT\volmgr\0000"
        ServiceName is "volmgr"
        State = DeviceNodeStarted (0x308)
        Previous State = DeviceNodeEnumerateCompletion (0x30d)
        DevNode 0xffffe0005a324560 for PDO 0xffffe0005bd95ca0…
    …
    
  2. Ctrl+F를 사용하여 생성된 출력을 검색하여 디바이스 드라이버의 이름인 에코를 찾습니다.

    'echo'라는 용어를 검색하는 WinDbg의 찾기 대화 상자 스크린샷

  3. 에코 디바이스 드라이버를 로드해야 합니다. !devnode 0 1 echo 이 예제와 같이 명령을 사용하여 에코 디바이스 드라이버와 연결된 플러그 앤 플레이 정보를 표시합니다.

    0: Kd> !devnode 0 1 echo
    Dumping IopRootDeviceNode (= 0xffffe0007b725d30)
    DevNode 0xffffe0007b71a630 for PDO 0xffffe0007b71a960
      InstancePath is "ROOT\SAMPLE\0000"
      ServiceName is "ECHO"
      State = DeviceNodeStarted (0x308)
      Previous State = DeviceNodeEnumerateCompletion (0x30d)
    …
    
  4. 이전 명령에 표시된 출력에는 드라이버의 실행 중인 인스턴스와 연결된 PDO(이 예제에서는 0xffffe0007b71a960)가 포함됩니다. !devobj <PDO address> 명령을 입력하여 에코 디바이스 드라이버와 연결된 플러그 앤 플레이 정보를 표시합니다. 여기에 표시된 주소가 !devnode 아니라 컴퓨터에 표시되는 PDO 주소를 사용합니다.

    0: kd> !devobj 0xffffe0007b71a960
    Device object (ffffe0007b71a960) is for:
     0000000e \Driver\PnpManager DriverObject ffffe0007b727e60
    Current Irp 00000000 RefCount 0 Type 00000004 Flags 00001040
    Dacl ffffc102c9b36031 DevExt 00000000 DevObjExt ffffe0007b71aab0 DevNode ffffe0007b71a630 
    ExtensionFlags (0x00000800)  DOE_DEFAULT_SD_PRESENT
    Characteristics (0x00000180)  FILE_AUTOGENERATED_DEVICE_NAME, FILE_DEVICE_SECURE_OPEN
    AttachedDevice (Upper) ffffe000801fee20 \Driver\ECHO
    Device queue is not busy.
    
  5. 명령에 표시되는 !devnode 0 1 출력에는 드라이버의 실행 중인 인스턴스와 연결된 PDO 주소가 포함되어 있으며, 이 예제 에서는 0xffffe0007b71a960. !devstack <PDO address> 디바이스 드라이버와 연결된 플러그 앤 플레이 정보를 표시하는 명령을 입력합니다. 이 예제에 표시된 주소가 !devnode 아니라 컴퓨터에 표시되는 PDO 주소를 사용합니다.

    0: kd> !devstack 0xffffe0007b71a960
      !DevObj           !DrvObj            !DevExt           ObjectName
      ffffe000801fee20  \Driver\ECHO       ffffe0007f72eff0  
    > ffffe0007b71a960  \Driver\PnpManager 00000000  0000000e
    !DevNode ffffe0007b71a630 :
      DeviceInst is "ROOT\SAMPLE\0000"
      ServiceName is "ECHO"
    

출력은 매우 간단한 디바이스 드라이버 스택이 있음을 보여줍니다. 에코 드라이버는 PnPManager 노드의 자식입니다. PnPManager 는 루트 노드입니다.

\Driver\ECHO
\Driver\PnpManager

이 다이어그램은 더 복잡한 디바이스 노드 트리를 보여줍니다.

약 20개의 노드로 구성된 디바이스 노드 트리를 보여 주는 다이어그램

더 복잡한 드라이버 스택에 대한 자세한 내용은 드라이버 스택 및 디바이스 노드 및 디바이스 스택을 참조하세요.

중단점 및 소스 코드 작업

이 섹션에서는 중단점을 설정하고 커널 모드 소스 코드를 한 단계씩 실행합니다.

코드를 단계별로 실행하고 변수 값을 실시간으로 확인하려면 중단점을 사용하도록 설정하고 소스 코드에 대한 경로를 설정합니다.

중단점은 특정 코드 줄에서 코드 실행을 중지합니다. 해당 지점에서 코드를 한 단계씩 실행하여 코드의 특정 섹션을 디버그합니다.

디버그 명령을 사용하여 중단점을 설정하려면 다음 b 명령 중 하나를 사용합니다.

명령 설명
bp 있는 모듈이 언로드될 때까지 활성 상태인 중단점을 설정합니다.
bu 모듈이 언로드될 때 확인되지 않는 중단점을 설정하고 모듈이 다시 로드될 때 다시 사용하도록 설정합니다.
bm 기호의 중단점을 설정합니다. 이 명령은 클래스의 모든 메서드와 같이 일치하는 모든 기호에 중단점을 설정하는 데 와일드카드(*)를 사용하거나 bp 적절하게 사용할 bu 수 있습니다.

자세한 내용은 WinDbg의 소스 코드 디버깅을 참조 하세요.

  1. 호스트 시스템에서 WinDbg UI를 사용하여 현재 WinDbg 세션에서 디버그>소스 모드가 사용하도록 설정되어 있는지 확인합니다.

  2. 다음 명령을 입력하여 소스 경로에 로컬 코드 위치를 추가합니다.

    .srcpath+ C:\DriverSamples\KMDF_Echo_Sample\driver\AutoSync
    
  3. 다음 명령을 입력하여 기호 경로에 로컬 기호 위치를 추가합니다.

    .sympath+ C:\DriverSamples\KMDF_Echo_Sample\driver\AutoSync
    
  4. x 명령을 사용하여 에코 드라이버와 연결된 기호를 검사하여 중단점에 사용할 함수 이름을 확인합니다. 와일드카드 또는 Ctrl+F를 사용하여 함수 이름을 찾을 DeviceAdd 수 있습니다.

    0: kd> x ECHO!EchoEvt*
    8b4c7490          ECHO!EchoEvtIoQueueContextDestroy (void *)
    8b4c7000          ECHO!EchoEvtDeviceSelfManagedIoStart (struct WDFDEVICE__ *)
    8b4c7820          ECHO!EchoEvtTimerFunc (struct WDFTIMER__ *)
    8b4cb0e0          ECHO!EchoEvtDeviceSelfManagedIoSuspend (struct WDFDEVICE__ *)
    8b4c75d0          ECHO!EchoEvtIoWrite (struct WDFQUEUE__ *, struct WDFREQUEST__ *, unsigned int)
    8b4cb170          ECHO!EchoEvtDeviceAdd (struct WDFDRIVER__ *, struct 
    …
    

    출력은 에코 드라이버에 대한 메서드가 DeviceAdd .임을 ECHO!EchoEvtDeviceAdd보여 줍니다.

    또는 소스 코드를 검토하여 중단점에 대한 함수 이름을 찾습니다.

  5. 드라이버 이름을 사용하여 명령으로 bm 중단점을 설정한 다음 함수 이름(예 AddDevice: 중단점을 설정하려는 위치)을 느낌표로 구분합니다. 이 랩은 로드되는 드라이버를 감시하는 데 사용합니다 AddDevice .

    0: kd> bm ECHO!EchoEvtDeviceAdd
      1: fffff801`0bf9b1c0 @!"ECHO!EchoEvtDeviceAdd"
    

    와 같은 <module>!<symbol><class>::<method>'<file.cpp>:<line number>'변수 설정과 함께 다른 구문을 사용하거나 여러 번 <condition> <#>건너뛸 수 있습니다. 자세한 내용은 WinDbg 및 기타 Windows 디버거의 조건부 중단점을 참조하세요.

  6. 현재 중단점을 나열하여 명령을 입력 bl 하여 중단점이 설정되었는지 확인합니다.

    0: kd> bl
    1 e fffff801`0bf9b1c0     0001 (0001) ECHO!EchoEvtDeviceAdd
    

    여기에 표시된 출력의 "e"는 중단점 번호 1이 실행되도록 설정되어 있음을 나타냅니다.

  7. (go) 명령을 입력 g 하여 대상 시스템에서 코드 실행을 다시 시작합니다.

  8. 대상 시스템의 Windows에서 아이콘을 사용하거나 mmc devmgmt.msc를 입력하여 장치 관리자 엽니다. 장치 관리자 샘플 노드를 확장합니다.

  9. KMDF 에코 드라이버 항목을 선택하고 길게 누르거나 마우스 오른쪽 단추로 클릭하고 메뉴에서 사용 안 함을 선택합니다.

  10. KMDF 에코 드라이버 항목을 다시 선택하고 길게 누르거나 마우스 오른쪽 단추로 클릭하고 메뉴에서 [사용]을 선택합니다.

  11. 호스트 시스템에서 드라이버를 사용하도록 설정 하면 AddDevice 디버그 중단점이 발생합니다. 대상 시스템에서 드라이버 코드의 실행이 중단되어야 합니다. 중단점이 적중되면 AddDevice 루틴이 시작될 때 실행을 중지해야 합니다. 디버그 명령 출력이 Breakpoint 1 hit표시됩니다.

    샘플 코드 로컬 및 명령 창을 표시하는 WinDbg의 스크린샷

  12. 명령을 입력 p 하거나 AddDevice 루틴의 다음 끝에 도달할 때까지 F10 키를 눌러 코드 줄을 한 줄씩 단계별로 실행합니다. 중괄호 문자(})가 표시된 것처럼 강조 표시됩니다.

    AddDevice 루틴의 시작 부분에 중괄호 문자가 강조 표시된 코드 창의 스크린샷

다음 섹션에서는 DeviceAdd 코드가 실행된 후 변수의 상태를 검사합니다.

다음 명령을 사용하여 기존 중단점을 수정할 수 있습니다.

명령 설명
bl 중단점을 나열합니다.
bc 목록에서 중단점을 지웁니다. 모든 중단점을 지우는 데 사용합니다 bc * .
bd 중단점을 사용하지 않도록 설정합니다. 모든 중단점을 사용하지 않도록 설정하는 데 사용합니다 bd * .
be 중단점을 사용하도록 설정합니다. 모든 중단점을 사용하도록 설정하는 데 사용합니다 be * .

또는 WinDbg UI에서 중단점을 수정할 수도 있습니다.

메모리 위치에 액세스할 때 발생하는 중단점을 설정할 수도 있습니다. ba 다음 구문과 함께 (액세스 시 중단) 명령을 사용합니다.

ba <access> <size> <address> {options}
옵션 설명
e execute: CPU가 주소에서 명령을 가져올 때
r 읽기/쓰기: CPU가 주소에 읽거나 쓰는 경우
w 쓰기: CPU가 주소에 쓰는 경우

지정된 시간에 4개의 데이터 중단점만 설정할 수 있습니다. 중단점을 트리거하기 위해 데이터를 올바르게 정렬해야 합니다. 단어는 2로 나눌 수 있는 주소로 끝나야 하고, dword는 4로, 쿼드 단어는 0 또는 8로 나눌 수 있어야 합니다.

예를 들어 특정 메모리 주소에 읽기/쓰기 중단점을 설정하려면 이 예제와 같은 명령을 사용할 수 있습니다.

ba r 4 0x0003f7bf0

다음 명령을 사용하여 괄호 안에 표시된 연결된 키보드 바로 가기를 사용하여 코드를 단계별로 실행할 수 있습니다.

  • 중단(Ctrl+Break). 이 명령은 시스템이 실행되고 WinDbg와 통신하는 동안 시스템을 중단합니다. 커널 디버거의 시퀀스는 Ctrl+C입니다.
  • 커서까지 실행합니다(F7 또는 Ctrl+F10). 실행을 중단하려는 원본 또는 디스어셈블리 창에 커서를 놓고 F7 키를 누릅니다. 코드 실행은 해당 지점까지 실행됩니다. 코드 실행 흐름이 커서가 나타내는 지점에 도달하지 않으면 WinDbg가 중단되지 않습니다. IF 문이 실행되지 않으면 이 상황이 발생할 수 있습니다.
  • 실행(F5). 중단점이 발견되거나 버그 검사와 같은 이벤트가 발생할 때까지 실행합니다.
  • 스텝오버(F10). 이 명령을 사용하면 코드 실행이 한 번에 하나의 문 또는 하나의 명령을 진행합니다. 호출이 발생하면 호출 루틴을 입력하지 않고 코드 실행이 호출을 통해 전달됩니다. 프로그래밍 언어가 C 또는 C++이고 WinDbg가 소스 모드인 경우 디버그>소스 모드를 사용하여 소스 모드설정하거나 해제할 수 있습니다.
  • 단계별 실행(F11). 이 명령은 호출 실행이 호출 루틴으로 이동한다는 점을 제외하고 스텝오버와 같습니다.
  • 나가기(Shift+F11). 이 명령을 사용하면 실행이 실행되고 호출 스택의 현재 루틴 또는 현재 위치에서 종료됩니다. 이 명령은 루틴을 충분히 본 경우에 유용합니다.

자세한 내용은 WinDbg의 소스 코드 디버깅을 참조 하세요.

변수 보기 및 호출 스택

이 섹션에서는 변수 및 호출 스택에 대한 정보를 표시합니다.

이 랩에서는 앞에서 설명한 프로세스를 사용하여 AddDevice 루틴에서 중지되었다고 가정합니다. 여기에 표시된 출력을 보려면 필요한 경우 앞에서 설명한 단계를 반복합니다.

호스트 시스템에서 변수를 표시하려면 로컬 메뉴 항목 보기를>사용하여 지역 변수를 표시합니다.

지역 변수 창을 표시하는 WinDbg의 스크린샷

전역 변수 주소의 위치를 찾으려면 .를 입력합니다 ? <variable name>.

  • 프로시저 나가기(Shift+F11) – 이 명령을 실행하면 현재 루틴(호출 스택의 현재 위치)에서 실행이 실행되고 종료됩니다. 이 기능은 루틴을 충분히 본 경우 유용합니다.

자세한 내용은 디버깅 참조 설명서의 WinDbg(클래식) 에서 소스 코드 디버깅을 참조하세요.

섹션 8: 변수 및 호출 스택 보기

섹션 8에서는 변수 및 호출 스택에 대한 정보를 표시합니다.

이 랩에서는 앞에서 설명한 프로세스를 사용하여 AddDevice 루틴에서 중지되었다고 가정합니다. 여기에서 출력 표시를 보려면 필요한 경우 앞에서 설명한 단계를 반복합니다.

<- 호스트 시스템에서

변수 표시

로컬 메뉴 항목 보기를>사용하여 지역 변수를 표시합니다.

지역 변수 창을 표시하는 WinDbg의 스크린샷

전역 변수

? < 을 입력하여 전역 변수 주소의 위치를 찾을 수 있습니다.변수 이름>입니다.

지역 변수

dv 명령을 입력하여 지정된 프레임에 대한 모든 지역 변수의 이름과 값을 표시할 수 있습니다. 특정 프레임에 대한 모든 지역 변수의 이름과 값을 표시하려면 다음 명령을 입력합니다 dv .

0: kd> dv
         Driver = 0x00001fff`7ff9c838
     DeviceInit = 0xffffd001`51978190
         status = 0n0

호출 스택은 프로그램 카운터의 현재 위치로 이어진 함수 호출 체인입니다. 호출 스택의 최상위 함수는 현재 함수이고, 다음 함수는 현재 함수를 호출하는 함수입니다.

호출 스택을 표시하려면 명령을 사용합니다 k* .

명령 설명
kb 스택과 처음 세 개의 매개 변수를 표시합니다.
kp 스택과 전체 매개 변수 목록을 표시합니다.
kn 옆에 프레임 정보가 있는 스택을 볼 수 있습니다.
  1. 호스트 시스템에서 호출 스택을 계속 사용할 수 있도록 하려면 호출 스택 보기를>선택하여 확인합니다. 창 맨 위에 있는 열을 선택하여 추가 정보 표시를 전환합니다.

    호출 스택 창을 표시하는 WinDbg의 스크린샷

  2. kn 이 명령을 사용하여 샘플 어댑터 코드를 중단 상태로 디버깅하는 동안 호출 스택을 표시합니다.

    3: kd> kn
    # Child-SP          RetAddr           Call Site
    00 ffffd001`51978110 fffff801`0942f55b ECHO!EchoEvtDeviceAdd+0x66 [c:\Samples\kmdf echo sample\c++\driver\autosync\driver.c @ 138]
    01 (Inline Function) --------`-------- Wdf01000!FxDriverDeviceAdd::Invoke+0x30 [d:\wbrtm\minkernel\wdf\framework\shared\inc\private\common\fxdrivercallbacks.hpp @ 61]
    02 ffffd001`51978150 fffff801`eed8097d Wdf01000!FxDriver::AddDevice+0xab [d:\wbrtm\minkernel\wdf\framework\shared\core\km\fxdriverkm.cpp @ 72]
    03 ffffd001`51978570 fffff801`ef129423 nt!PpvUtilCallAddDevice+0x35 [d:\9142\minkernel\ntos\io\pnpmgr\verifier.c @ 104]
    04 ffffd001`519785b0 fffff801`ef0c4112 nt!PnpCallAddDevice+0x63 [d:\9142\minkernel\ntos\io\pnpmgr\enum.c @ 7397]
    05 ffffd001`51978630 fffff801`ef0c344f nt!PipCallDriverAddDevice+0x6e2 [d:\9142\minkernel\ntos\io\pnpmgr\enum.c @ 3390]
    ...
    

호출 스택은 나중에 에코 드라이버 DeviceAdd 함수를 호출한 WDF(드라이버 프레임워크 코드)를 호출하는 PnP(플러그 앤 플레이 코드)로 호출된 커널(nt)을 보여 줍니다.

프로세스 및 스레드 표시

이 섹션에서는 커널 모드에서 실행되는 프로세스 및 스레드에 대한 정보를 표시합니다.

프로세스

!process 디버거 확장을 사용하여 프로세스 정보를 표시하거나 설정할 수 있습니다. 중단점을 설정하여 소리가 재생될 때 사용되는 프로세스를 검사합니다.

  1. 호스트 시스템에서 명령을 입력 dv 하여 루틴과 연결된 로캘 변수를 EchoEvtIo 검사합니다.

    0: kd> dv ECHO!EchoEvtIo*
    ECHO!EchoEvtIoQueueContextDestroy
    ECHO!EchoEvtIoWrite
    ECHO!EchoEvtIoRead         
    
  2. 다음을 사용하여 bc *이전 중단점을 지웁니다.

    0: kd> bc *  
    
  3. 다음 명령을 사용하여 루틴에 EchoEvtIo 기호 중단점을 설정합니다.

    0: kd> bm ECHO!EchoEvtIo*
      2: aade5490          @!”ECHO!EchoEvtIoQueueContextDestroy”
      3: aade55d0          @!”ECHO!EchoEvtIoWrite”
      4: aade54c0          @!”ECHO!EchoEvtIoRead”
    
  4. 중단점을 나열하여 중단점이 제대로 설정되어 있는지 확인합니다.

    0: kd> bl
    1 e aabf0490 [c:\Samples\kmdf echo sample\c++\driver\autosync\queue.c @ 197]    0001 (0001) ECHO!EchoEvtIoQueueContextDestroy
    ...
    
  5. 코드 실행을 다시 시작하려면 다음을 입력 g 합니다.

    0: kd> g
    
  6. 대상 시스템에서 대상 시스템에서 드라이버 테스트 프로그램을 실행 EchoApp.exe 합니다.

  7. 호스트 시스템에서 테스트 앱이 실행되면 드라이버의 I/O 루틴이 호출됩니다. 이 호출로 인해 중단점이 실행되고 대상 시스템에서 드라이버 코드 실행이 중지됩니다.

    Breakpoint 2 hit
    ECHO!EchoEvtIoWrite:
    fffff801`0bf95810 4c89442418      mov     qword ptr [rsp+18h],r8
    
  8. !process 명령을 사용하여 echoapp.exe 실행에 관련된 현재 프로세스를 표시합니다.

    0: kd> !process
    PROCESS ffffe0007e6a7780
        SessionId: 1  Cid: 03c4    Peb: 7ff7cfec4000  ParentCid: 0f34
        DirBase: 1efd1b000  ObjectTable: ffffc001d77978c0  HandleCount:  34.
        Image: echoapp.exe
        VadRoot ffffe000802c79f0 Vads 30 Clone 0 Private 135. Modified 5. Locked 0.
        DeviceMap ffffc001d83c6e80
        Token                             ffffc001cf270050
        ElapsedTime                       00:00:00.052
        UserTime                          00:00:00.000
        KernelTime                        00:00:00.000
        QuotaPoolUsage[PagedPool]         33824
        QuotaPoolUsage[NonPagedPool]      4464
        Working Set Sizes (now,min,max)  (682, 50, 345) (2728KB, 200KB, 1380KB)
        PeakWorkingSetSize                652
        VirtualSize                       16 Mb
        PeakVirtualSize                   16 Mb
        PageFaultCount                    688
        MemoryPriority                    BACKGROUND
        BasePriority                      8
        CommitCharge                      138
    
            THREAD ffffe00080e32080  Cid 03c4.0ec0  Teb: 00007ff7cfece000 Win32Thread: 0000000000000000 RUNNING on processor 1
    

    출력은 프로세스가 드라이버 쓰기 이벤트의 중단점이 적중되었을 때 실행되고 있던 echoapp.exe 스레드와 연결되어 있음을 보여 줍니다. 자세한 내용은 !process를 참조 하세요.

  9. !process 0 0 이 값을 사용하여 모든 프로세스에 대한 요약 정보를 표시합니다. 출력에서 Ctrl+F를 사용하여 echoapp.exe 이미지와 연결된 프로세스에 대해 동일한 프로세스 주소를 찾습니다. 예제에서 프로세스 주소는 .입니다 ffffe0007e6a7780.

    ...
    
    PROCESS ffffe0007e6a7780
        SessionId: 1  Cid: 0f68    Peb: 7ff7cfe7a000  ParentCid: 0f34
        DirBase: 1f7fb9000  ObjectTable: ffffc001cec82780  HandleCount:  34.
        Image: echoapp.exe
    
    ...
    
  10. 이 랩의 뒷부분에서 사용할 echoapp.exe 연결된 프로세스 ID를 기록합니다. Ctrl+C를 사용하여 나중에 사용할 수 있도록 주소를 복사 버퍼에 복사할 수도 있습니다.

    _____________________________________________________(echoapp.exe 프로세스 주소)

  11. 디버거에 필요에 따라 입력 g 하여 echoapp.exe 실행이 완료될 때까지 코드를 앞으로 실행합니다. 읽기 및 쓰기 이벤트의 중단점에 여러 번 도달합니다. echoapp.exe 완료되면 Ctrl+ScrLk(Ctrl+Break)를 눌러 디버거에 침입합니다.

  12. 명령을 !process 사용하여 다른 프로세스를 실행하고 있는지 확인합니다. 여기에 표시된 출력에서 시스템 이미지 값이 있는 프로세스는 Echo Image 값과 다릅니다.

    1: kd> !process
    PROCESS ffffe0007b65d900
        SessionId: none  Cid: 0004    Peb: 00000000  ParentCid: 0000
        DirBase: 001ab000  ObjectTable: ffffc001c9a03000  HandleCount: 786.
        Image: System
        VadRoot ffffe0007ce45930 Vads 14 Clone 0 Private 22. Modified 131605. Locked 64.
        DeviceMap ffffc001c9a0c220
        Token                             ffffc001c9a05530
        ElapsedTime                       21:31:02.516
    ...
    

    출력은 OS를 중지했을 때 시스템 프로세스 ffffe0007b65d900이 실행 중이었으면 표시됩니다.

  13. 명령을 !process 사용하여 이전에 기록한 echoapp.exe 연결된 프로세스 ID를 확인합니다. 이 예제에 표시된 예제 프로세스 주소 대신 이전에 기록한 echoapp.exe 프로세스 주소를 제공합니다.

    0: kd> !process ffffe0007e6a7780
    TYPE mismatch for process object at 82a9acc0
    

    echoapp.exe 프로세스가 더 이상 실행되지 않으므로 프로세스 개체를 더 이상 사용할 수 없습니다.

스레드

스레드를 보고 설정하는 명령은 프로세스에 대한 명령과 유사합니다. !thread 명령을 사용하여 스레드를 봅니다. .thread를 사용하여 현재 스레드를 설정합니다.

  1. 호스트 시스템에서 디버거를 입력 g 하여 대상 시스템에서 코드 실행을 다시 시작합니다.

  2. 대상 시스템에서 EchoApp.exe 드라이버 테스트 프로그램을 실행합니다.

  3. 호스트 시스템에서 중단점이 적중되고 코드 실행이 중지됩니다.

    Breakpoint 4 hit
    ECHO!EchoEvtIoRead:
    aade54c0 55              push    ebp
    
  4. 실행 중인 스레드를 보려면 !thread를 입력합니다. 다음 예제와 유사한 정보가 표시되어야 합니다.

    0: kd>  !thread
    THREAD ffffe000809a0880  Cid 0b28.1158  Teb: 00007ff7d00dd000 Win32Thread: 0000000000000000 RUNNING on processor 0
    IRP List:
        ffffe0007bc5be10: (0006,01f0) Flags: 00060a30  Mdl: 00000000
    Not impersonating
    DeviceMap                 ffffc001d83c6e80
    Owning Process            ffffe0008096c900       Image:         echoapp.exe
    ...
    

    echoapp.exe 이미지 이름을 확인합니다. 이는 테스트 앱과 연결된 스레드를 보고 있음을 나타냅니다.

  5. !process 명령을 사용하여 이 스레드가 echoapp.exe 연결된 프로세스에서 실행되는 유일한 스레드인지 확인합니다. 프로세스에서 실행 중인 스레드의 스레드 번호는 명령이 표시한 스레드 !thread 와 동일합니다.

    0: kd> !process
    PROCESS ffffe0008096c900
        SessionId: 1  Cid: 0b28    Peb: 7ff7d00df000  ParentCid: 0f34
        DirBase: 1fb746000  ObjectTable: ffffc001db6b52c0  HandleCount:  34.
        Image: echoapp.exe
        VadRoot ffffe000800cf920 Vads 30 Clone 0 Private 135. Modified 8. Locked 0.
        DeviceMap ffffc001d83c6e80
        Token                             ffffc001cf5dc050
        ElapsedTime                       00:00:00.048
        UserTime                          00:00:00.000
        KernelTime                        00:00:00.000
        QuotaPoolUsage[PagedPool]         33824
        QuotaPoolUsage[NonPagedPool]      4464
        Working Set Sizes (now,min,max)  (681, 50, 345) (2724KB, 200KB, 1380KB)
        PeakWorkingSetSize                651
        VirtualSize                       16 Mb
        PeakVirtualSize                   16 Mb
        PageFaultCount                    686
        MemoryPriority                    BACKGROUND
        BasePriority                      8
        CommitCharge                      138
    
            THREAD ffffe000809a0880  Cid 0b28.1158  Teb: 00007ff7d00dd000 Win32Thread: 0000000000000000 RUNNING on processor 0
    
  6. !process 0 0 명령을 사용하여 두 관련 프로세스의 프로세스 주소를 찾고 여기에 해당 프로세스 주소를 기록합니다.

    Cmd.exe: ____________________________________________________________

    EchoApp.exe: _______________________________________________________

    0: kd> !process 0 0 
    
    …
    
    PROCESS ffffe0007bbde900
        SessionId: 1  Cid: 0f34    Peb: 7ff72dfa7000  ParentCid: 0c64
        DirBase: 19c5fa000  ObjectTable: ffffc001d8c2f300  HandleCount:  31.
        Image: cmd.exe
    …
    PROCESS ffffe0008096c900
        SessionId: 1  Cid: 0b28    Peb: 7ff7d00df000  ParentCid: 0f34
        DirBase: 1fb746000  ObjectTable: ffffc001db6b52c0  HandleCount:  34.
        Image: echoapp.exe
    …
    

    또는 모든 프로세스에 대한 자세한 정보를 표시하는 데 사용할 !process 0 17 수 있습니다. 이 명령의 출력은 길 수 있습니다. 출력은 Ctrl+F를 사용하여 검색할 수 있습니다.

  7. 명령을 !process 사용하여 컴퓨터를 실행하는 두 프로세스에 대한 프로세스 정보를 나열합니다. 이 예제에 표시된 주소가 아니라 출력의 !process 0 0 프로세스 주소를 제공합니다.

    이 예제 출력은 이전에 기록된 cmd.exe 프로세스 ID에 대한 것입니다. 이 프로세스 ID 의 이미지 이름은 cmd.exe.

    0: kd>  !process ffffe0007bbde900
    PROCESS ffffe0007bbde900
        SessionId: 1  Cid: 0f34    Peb: 7ff72dfa7000  ParentCid: 0c64
        DirBase: 19c5fa000  ObjectTable: ffffc001d8c2f300  HandleCount:  31.
        Image: cmd.exe
        VadRoot ffffe0007bb8e7b0 Vads 25 Clone 0 Private 117. Modified 20. Locked 0.
        DeviceMap ffffc001d83c6e80
        Token                             ffffc001d8c48050
        ElapsedTime                       21:33:05.840
        UserTime                          00:00:00.000
        KernelTime                        00:00:00.000
        QuotaPoolUsage[PagedPool]         24656
        QuotaPoolUsage[NonPagedPool]      3184
        Working Set Sizes (now,min,max)  (261, 50, 345) (1044KB, 200KB, 1380KB)
        PeakWorkingSetSize                616
        VirtualSize                       2097164 Mb
        PeakVirtualSize                   2097165 Mb
        PageFaultCount                    823
        MemoryPriority                    FOREGROUND
        BasePriority                      8
        CommitCharge                      381
    
            THREAD ffffe0007cf34880  Cid 0f34.0f1c  Teb: 00007ff72dfae000 Win32Thread: 0000000000000000 WAIT: (UserRequest) UserMode Non-Alertable
                ffffe0008096c900  ProcessObject
            Not impersonating
    ...
    

    이 예제 출력은 이전에 기록된 echoapp.exe 프로세스 ID에 대한 것입니다.

    0: kd>  !process ffffe0008096c900
    PROCESS ffffe0008096c900
        SessionId: 1  Cid: 0b28    Peb: 7ff7d00df000  ParentCid: 0f34
        DirBase: 1fb746000  ObjectTable: ffffc001db6b52c0  HandleCount:  34.
        Image: echoapp.exe
        VadRoot ffffe000800cf920 Vads 30 Clone 0 Private 135. Modified 8. Locked 0.
        DeviceMap ffffc001d83c6e80
        Token                             ffffc001cf5dc050
        ElapsedTime                       00:00:00.048
        UserTime                          00:00:00.000
        KernelTime                        00:00:00.000
        QuotaPoolUsage[PagedPool]         33824
        QuotaPoolUsage[NonPagedPool]      4464
        Working Set Sizes (now,min,max)  (681, 50, 345) (2724KB, 200KB, 1380KB)
        PeakWorkingSetSize                651
        VirtualSize                       16 Mb
        PeakVirtualSize                   16 Mb
        PageFaultCount                    686
        MemoryPriority                    BACKGROUND
        BasePriority                      8
        CommitCharge                      138
    
            THREAD ffffe000809a0880  Cid 0b28.1158  Teb: 00007ff7d00dd000 Win32Thread: 0000000000000000 RUNNING on processor 0
            IRP List:
                ffffe0007bc5be10: (0006,01f0) Flags: 00060a30  Mdl: 00000000
            Not impersonating
    ...
    
  8. 여기에 두 프로세스와 연결된 첫 번째 스레드 주소를 기록합니다.

    Cmd.exe: ____________________________________________________

    EchoApp.exe: _________________________________________________

  9. 명령을 !Thread 사용하여 현재 스레드에 대한 정보를 표시합니다.

    0: kd>  !Thread
    THREAD ffffe000809a0880  Cid 0b28.1158  Teb: 00007ff7d00dd000 Win32Thread: 0000000000000000 RUNNING on processor 0
    IRP List:
        ffffe0007bc5be10: (0006,01f0) Flags: 00060a30  Mdl: 00000000
    Not impersonating
    DeviceMap                 ffffc001d83c6e80
    Owning Process            ffffe0008096c900       Image:         echoapp.exe
    Attached Process          N/A            Image:         N/A
    ...
    

    예상대로 현재 스레드는 echoapp.exe 연결된 스레드이며 실행 중 상태입니다.

  10. 명령을 !Thread 사용하여 cmd.exe 프로세스와 연결된 스레드에 대한 정보를 표시합니다. 이전에 기록한 스레드 주소를 제공합니다.

    0: kd> !Thread ffffe0007cf34880
    THREAD ffffe0007cf34880  Cid 0f34.0f1c  Teb: 00007ff72dfae000 Win32Thread: 0000000000000000 WAIT: (UserRequest) UserMode Non-Alertable
        ffffe0008096c900  ProcessObject
    Not impersonating
    DeviceMap                 ffffc001d83c6e80
    Owning Process            ffffe0007bbde900       Image:         cmd.exe
    Attached Process          N/A            Image:         N/A
    Wait Start TickCount      4134621        Ticks: 0
    Context Switch Count      4056           IdealProcessor: 0             
    UserTime                  00:00:00.000
    KernelTime                00:00:01.421
    Win32 Start Address 0x00007ff72e9d6e20
    Stack Init ffffd0015551dc90 Current ffffd0015551d760
    Base ffffd0015551e000 Limit ffffd00155518000 Call 0
    Priority 14 BasePriority 8 UnusualBoost 3 ForegroundBoost 2 IoPriority 2 PagePriority 5
    Child-SP          RetAddr           : Args to Child                                                           : Call Site
    ffffd001`5551d7a0 fffff801`eed184fe : fffff801`eef81180 ffffe000`7cf34880 00000000`fffffffe 00000000`fffffffe : nt!KiSwapContext+0x76 [d:\9142\minkernel\ntos\ke\amd64\ctxswap.asm @ 109]
    ffffd001`5551d8e0 fffff801`eed17f79 : ffff03a5`ca56a3c8 000000de`b6a6e990 000000de`b6a6e990 00007ff7`d00df000 : nt!KiSwapThread+0x14e [d:\9142\minkernel\ntos\ke\thredsup.c @ 6347]
    ffffd001`5551d980 fffff801`eecea340 : ffffd001`5551da18 00000000`00000000 00000000`00000000 00000000`00000388 : nt!KiCommitThreadWait+0x129 [d:\9142\minkernel\ntos\ke\waitsup.c @ 619]
    ...
    

    이 스레드는 cmd.exe 연결되며 대기 상태입니다.

  11. 대기 중인 CMD.exe 스레드의 스레드 주소를 제공하여 컨텍스트를 대기 중인 스레드로 변경합니다.

    0: kd> .Thread ffffe0007cf34880
    Implicit thread is now ffffe000`7cf34880
    
  12. 명령을 k 사용하여 대기 중인 스레드와 연결된 호출 스택을 볼 수 있습니다.

    0: kd> k
      *** Stack trace for last set context - .thread/.cxr resets it
    # Child-SP          RetAddr           Call Site
    00 ffffd001`5551d7a0 fffff801`eed184fe nt!KiSwapContext+0x76 [d:\9142\minkernel\ntos\ke\amd64\ctxswap.asm @ 109]
    01 ffffd001`5551d8e0 fffff801`eed17f79 nt!KiSwapThread+0x14e [d:\9142\minkernel\ntos\ke\thredsup.c @ 6347]
    02 ffffd001`5551d980 fffff801`eecea340 nt!KiCommitThreadWait+0x129 [d:\9142\minkernel\ntos\ke\waitsup.c @ 619]
    03 ffffd001`5551da00 fffff801`ef02e642 nt!KeWaitForSingleObject+0x2c0 [d:\9142\minkernel\ntos\ke\wait.c @ 683]
    ...
    

    호출 스택 요소는 KiCommitThreadWait 이 스레드가 예상대로 실행되고 있지 않음을 나타냅니다.

스레드 및 프로세스에 대한 자세한 내용은 다음 참조를 참조하세요.

IRQL, 등록 및 WinDbg 세션 종료

이 섹션에서는 IRQL(인터럽트 요청 수준) 및 레지스터의 내용을 표시합니다.

저장된 IRQL 보기

IRQL은 인터럽트 서비스의 우선 순위를 관리하는 데 사용됩니다. 각 프로세서에는 스레드가 발생하거나 낮을 수 있는 IRQL 설정이 있습니다. 프로세서의 IRQL 설정 또는 그 아래에서 발생하는 인터럽트는 마스킹되며 현재 작업을 방해하지 않습니다. 프로세서의 IRQL 설정 위에서 발생하는 인터럽트는 현재 작업보다 우선합니다.

호스트 시스템에서 !irql 확장은 디버거 중단이 발생하기 전에 대상 컴퓨터의 현재 프로세서에 IRQL을 표시합니다. 대상 컴퓨터가 디버거에 침입하면 IRQL이 변경되지만 디버거 중단 직전에 유효했던 IRQL이 저장되고 표시됩니다 !irql.

0: kd> !irql
Debugger saved IRQL for processor 0x0 -- 2 (DISPATCH_LEVEL)

레지스터 보기

호스트 시스템에서 r(Registers) 명령을 사용하여 현재 프로세서의 현재 스레드에 대한 레지스터의 내용을 표시합니다.

0: kd> r
rax=000000000000c301 rbx=ffffe00173eed880 rcx=0000000000000001
rdx=000000d800000000 rsi=ffffe00173eed8e0 rdi=ffffe00173eed8f0
rip=fffff803bb757020 rsp=ffffd001f01f8988 rbp=ffffe00173f0b620
 r8=000000000000003e  r9=ffffe00167a4a000 r10=000000000000001e
r11=ffffd001f01f88f8 r12=0000000000000000 r13=ffffd001f01efdc0
r14=0000000000000001 r15=0000000000000000
iopl=0         nv up ei pl nz na pe nc
cs=0010  ss=0018  ds=002b  es=002b  fs=0053  gs=002b             efl=00000202
nt!DbgBreakPointWithStatus:
fffff803`bb757020 cc              int     3

또는 레지스터 보기를>선택하여 레지스터의 내용을 표시할 수 있습니다. 자세한 내용은 r(레지스터)을 참조하세요.

어셈블리 언어 코드 실행을 단계별로 실행하고 다른 시나리오에서 레지스터의 내용을 보는 것이 유용할 수 있습니다. 어셈블리 언어 디스어셈블리 에 대한 자세한 내용은 주석이 추가된 x86 디스어셈블리주석이 추가된 x64 디스어셈블리를 참조하세요.

레지스터의 내용에 대한 자세한 내용은 x86 아키텍처x64 아키텍처를 참조하세요.

WinDbg 세션 종료

디버거를 연결된 상태로 유지하지만 대상에서 작업하려면 대상 컴퓨터가 호스트 컴퓨터 디버거에 연결하지 않도록 중단점을 bc *지웁니다. 그런 다음, g 명령을 사용하여 대상 컴퓨터가 다시 실행되도록 합니다.

디버깅 세션을 종료하려면 호스트 시스템에서 디버거에 침입하여 (종료 및 분리) 명령을 입력 qd 하거나 메뉴에서 디버깅 중지를 선택합니다.

0: kd> qd

자세한 내용은 WinDbg에서 디버깅 세션 종료를 참조하세요.

Windows 디버깅 리소스

자세한 내용은 Windows 디버깅에서 확인할 수 있습니다. 이러한 책 중 일부는 예제에서 Windows Vista와 같은 이전 버전의 Windows를 사용하지만 설명된 개념은 대부분의 Windows 버전에 적용할 수 있습니다.

참고 항목