Windows의 DTrace

DTrace(DTrace.exe)는 시스템 정보 및 이벤트를 표시하는 명령줄 도구입니다. DTrace는 windows로 포팅된 오픈 소스 추적 플랫폼입니다. DTrace는 원래 Solaris 운영 체제용으로 개발되었습니다. 사용자/커널 함수의 동적 계측, D-언어, 추측 추적을 사용하여 스크립팅하는 기능을 제공합니다. 또한 DTrace에는 ETW 계측, ETW 이벤트 생성, 시스템 호출 프로브 및 라이브 덤프 캡처 기능과 같은 Windows OS 관련 확장이 있습니다.

참고 항목

DTrace는 버전 18980 및 Windows Server 빌드 18975 이후의 Windows 참가자 빌드에서 지원됩니다.

Windows GitHub 사이트의 DTrace는 다음과 같습니다.

https://github.com/microsoft/DTrace-on-Windows

DTrace 정보 열기

DTrace에 대한 자세한 내용은 케임브리지 대학의 OpenDTrace 사양 버전 1.0을 참조하세요.

기본 GitHub 사이트는 .에 https://github.com/opendtrace/있습니다.

유용한 스크립트 집합은 .에서 https://github.com/opendtrace/toolkit사용할 수 있습니다.

다음과 같은 여러 DTrace 책을 사용할 수 있습니다.

DTrace: 브렌던 그레그와 짐 마우로의 Oracle Solaris, Mac OS X 및 FreeBSD 의 동적 추적

Solaris 성능 및 도구: DTrace 및 MDB Techniques for Solaris 10 and OpenSolaris by Richard McDougall, Jim Mauro, Brendan Gregg

Windows DTrace에 대한 피드백 제공

피드백 허브를 사용하여 새 기능을 요청하거나 Windows DTrace의 문제 또는 버그를 보고할 수 있습니다.

  1. 피드백 허브를 시작합니다. 검색으로 이동하여 피드백이라는 단어를 입력한 다음 피드백 허브를 선택합니다.
  2. 기능 제안 또는 문제 보고 중 하나를 선택합니다.
  3. 문제 또는 제안에 대한 상세하고 구체적인 설명을 제공합니다.

DTrace Windows 확장

다음은 Windows에서 사용할 수 있는 공급자 중 일부와 계측하는 항목입니다.

  • syscall – NTOS 시스템 호출

  • fbt(함수 경계 추적) – 커널 함수 항목 및 반환

  • pid(프로세스 ID) – 사용자 모드 프로세스 추적 커널 모드 FBT와 마찬가지로 임의 함수 오프셋의 계측도 허용합니다.

  • etw(Windows용 이벤트 추적) – ETW에 대해 프로브를 정의할 수 있습니다. 이 공급자는 DTrace에서 기존 운영 체제 계측을 활용하는 데 도움이 됩니다.

SYSCALL

SYSCALL은 각 시스템 호출에 대해 한 쌍의 프로브를 제공합니다. 즉, 시스템 호출을 입력하기 전에 발생하는 항목 프로브와 시스템 호출이 완료된 후 제어가 사용자 수준으로 다시 전송되기 전에 발생하는 반환 프로브를 제공합니다. 모든 SYSCALL 프로브의 경우 함수 이름은 계측된 시스템 호출의 이름으로 설정되고 모듈 이름은 함수가 존재하는 모듈입니다. SYSCALL 공급자가 제공한 시스템 호출의 이름은 명령 프롬프트에서 명령을 dtrace.exe -l -P syscall 입력하여 찾을 수 있습니다. 프로브 이름은 소문자 syscall입니다. 또한 명령은 dtrace -ln syscall::: syscall 공급자에서 사용할 수 있는 모든 프로브 및 해당 매개 변수를 나열합니다.

C:\> dtrace -ln syscall:::
  ID   PROVIDER            MODULE                          FUNCTION NAME
    6    syscall                                 NtWaitHighEventPair entry
    7    syscall                                 NtWaitHighEventPair return
    8    syscall                       NtRegisterThreadTerminatePort entry
    9    syscall                       NtRegisterThreadTerminatePort return
...

이러한 예제에서는 모든 화면 출력이 표시되지 않습니다. "..." 는 잘린 출력을 나타내는 데 사용됩니다.

출력을 스크롤하려면 다음과 같이 더 많은 명령으로 파이프합니다.

dtrace -ln syscall:::|more

v 옵션을 추가하여 사용 가능한 syscall 프로브에 대한 자세한 정보를 표시합니다.

C:\> dtrace -lvn syscall:::
...

  942    syscall                                    NtSaveMergedKeys entry

        Probe Description Attributes
                Identifier Names: Private
                Data Semantics:   Private
                Dependency Class: ISA

        Argument Attributes
                Identifier Names: Private
                Data Semantics:   Private
                Dependency Class: ISA

        Argument Types
                args[0]: HANDLE
                args[1]: HANDLE
                args[2]: HANDLE
...

ETW

DTrace에는 기존 매니페스트/추적 로그된 ETW 프로브에 대한 지원이 포함됩니다. 이벤트가 발생할 때 ETW 이벤트를 동기적으로 계측, 필터링 및 구문 분석할 수 있습니다. 또한 DTrace를 사용하여 다양한 이벤트/시스템 상태를 결합하여 복잡한 오류 상황을 디버그하는 데 도움이 되는 통합 출력 스트림을 제공할 수 있습니다.

명령은 dtrace -ln etw::: syscall 공급자에서 사용할 수 있는 모든 프로브 및 해당 매개 변수를 나열합니다.

  C:\> dtrace -ln etw:::
  ID   PROVIDER            MODULE                          FUNCTION NAME
  944        etw 048dc470-37c1-52a8-565a-54cb27be37ec           0xff_0xffffffffffffffff generic_event
  945        etw aab97afe-deaf-5882-1e3b-d7210f059dc1           0xff_0xffffffffffffffff generic_event
  946        etw b0f40491-9ea6-5fd5-ccb1-0ec63be8b674           0xff_0xffffffffffffffff generic_event
  947        etw 4ee869fa-9954-4b90-9a62-308c74f99d32           0xff_0xffffffffffffffff generic_event
  ...

자세한 내용은 DTrace ETW를 참조 하세요.

함수 경계 추적(FBT)

FBT(함수 경계 추적) 공급자는 Windows 커널의 대부분의 함수에 대한 항목 및 반환과 관련된 프로브를 제공합니다. 이 함수는 프로그램 텍스트의 기본 단위입니다. 다른 DTrace 공급자와 마찬가지로 FBT는 명시적으로 사용하도록 설정되지 않은 경우 프로브 효과가 없습니다. 사용하도록 설정하면 FBT는 프로브된 함수에서만 프로브 효과를 유도합니다. FBT는 x86 및 x64 플랫폼에서 구현되었습니다.

각 명령 집합에는 다른 함수를 호출하지 않고 FBT에서 계측할 수 없는 컴파일러(소위 리프 함수)에 의해 고도로 최적화된 함수 수가 적습니다. 이러한 함수에 대한 프로브는 DTrace에 없습니다.

이 명령은 dtrace -ln fbt:nt:: nt 모듈에 사용할 수 있는 모든 프로브 및 해당 매개 변수를 나열합니다. 디버거 lm(로드된 모듈 나열) 명령을 사용하여 사용 가능한 모든 모듈을 나열합니다.

C:\>dtrace -ln "fbt:nt::"
   ID   PROVIDER            MODULE                          FUNCTION NAME
 3336        fbt                nt                PiDqActionDataFree entry
 3337        fbt                nt                PiDqActionDataFree return
 3338        fbt                nt PiDqActionDataGetRequestedProperties entry
 3339        fbt                nt PiDqActionDataGetRequestedProperties return
 3340        fbt                nt _CmGetMatchingFilteredDeviceInterfaceList entry
...

참고 항목

nt에서 사용할 수 있는 수천 개의 호출이 있으므로 데이터를 기록하는 DTrace 명령을 실행할 때 함수 이름을 비워 두는 것은 좋지 않습니다. 성능에 영향을 주지 않도록 하는 권장 방법은 함수 이름의 적어도 일부를 지정하는 것입니다(예: fbt:nt:*Timer*:entry.).

PID

DTrace PID 공급자를 사용하면 웹 브라우저 또는 데이터베이스와 같은 사용자 모드 프로세스의 내부 실행을 추적할 수 있습니다. 프로세스 시작 시 DTrace를 연결하여 프로세스 시작 문제를 디버그할 수도 있습니다. PID 정의의 일부로 프로세스에 정의된 함수와 함수 내에서 특정 오프셋(또는 wild카드 *를 사용하는 모든 오프셋)을 지정합니다. PID 공급자는 스크립트 실행 시 이진 파일을 시작하거나 실행해야 합니다.

이 예제 명령은 notepad.exe 연결된 PID의 특정 호출에 대한 정보를 표시합니다. 디버거 lm(로드된 모듈 나열) 명령을 사용하여 사용 가능한 모든 모듈을 나열합니다.

C:\Windows\system32>dtrace -ln "pid$target:ntdll:RtlAllocateHeap:entry" -c notepad.exe
   ID   PROVIDER            MODULE                          FUNCTION NAME
 5102    pid6100             ntdll                   RtlAllocateHeap entry

참고 항목

C++로 작성된 추적 함수의 경우 함수 이름이 너무 길거나 데코레이팅되어 전체 형식의 프로브로 지정될 수 있습니다. 일반적인 해결 방법은 대상 함수와 고유하게 일치하는 식을 사용하는 것입니다. 예를 들어 'String??을 사용하시겠습니까? 'String::Copy()'와 일치하도록 프로브 이름의 'probefunc' 부분으로 복사하거나 '*GetPinnableReference'를 'String::GetPinnableReference()'와 일치하도록 복사합니다.

DTrace Windows 아키텍처

사용자는 DTrace 엔진의 프런트 엔드 역할을 하는 DTrace 명령을 통해 DTrace와 상호 작용합니다. D 스크립트는 사용자 공간에서 DIF(중간 형식)로 컴파일되고 실행을 위해 DTrace 커널 구성 요소로 전송되며, DIF Virtual Machine이라고도 합니다. dtrace.sys 드라이버에서 실행됩니다.

Traceext.sys(추적 확장명)는 Windows 커널 확장 드라이버로, Windows에서 DTrace가 추적을 제공하기 위해 사용하는 기능을 노출할 수 있습니다. Windows 커널은 스택 워크 또는 메모리 액세스 중에 설명선을 제공하며 추적 확장에 의해 구현됩니다.

DTrace.sys 통신하고 Traceext.sys 호출하는 libtrace에 연결된 dtrace.exe 있는 DTrace Windows 아키텍처를 보여 주는 다이어그램

Windows에서 DTrace 설치

  1. 지원되는 버전의 Windows를 실행하고 있는지 확인합니다. DTrace의 현재 다운로드는 버전 18980 및 Windows Server 빌드 18975 이후의 20H1 Windows 참가자 빌드에서 지원됩니다. 이전 버전의 Windows에 이 버전의 DTrace를 설치하면 시스템 불안정이 발생할 수 있으며 권장되지 않습니다. (보관된 19H1용 DTrace 버전은 더 이상 사용할 수 없으며 더 이상 지원되지 않습니다.)

  2. Microsoft 다운로드 센터에서 MSI 설치 파일(Windows에서 DTrace 다운로드)을 다운로드합니다.

  3. 설치 완료를 선택합니다.

    Important

    bcdedit를 사용하여 부팅 정보를 변경하기 전에 테스트 PC에서 Patchguard, BitLocker 및 보안 부팅과 같은 Windows 보안 기능을 일시적으로 일시 중단해야 할 수 있습니다. 테스트가 완료되면 이러한 보안 기능을 다시 사용하도록 설정하고 보안 기능이 비활성화된 경우 테스트 PC를 적절하게 관리합니다.

  4. C:\Program Files\DTrace를 포함하도록 PATH 환경 변수 업데이트

set PATH=%PATH%;"C:\Program Files\DTrace"
  1. bcdedit 명령을 사용하여 컴퓨터에서 DTrace를 사용하도록 설정합니다.
bcdedit /set dtrace ON

새 Windows 참가자 빌드로 업데이트하는 경우 dtrace bcdedit 옵션을 다시 설정해야 합니다.

참고 항목

BitLocker를 사용하는 경우 부팅 값을 변경할 때 사용하지 않도록 설정합니다. 이렇게 하지 않으면 BitLocker 복구 키를 입력하라는 메시지가 표시될 수 있습니다. 이 상황에서 복구하는 한 가지 방법은 복구 콘솔로 부팅하고 bcdedit 값을 bcdedit /set {default} dtrace on복원하는 것입니다. OS 업데이트에서 값을 제거하고 추가한 경우 OS를 복구하려면 bcdedit를 사용하여 값을 bcdedit /deletevalue {default} dtrace제거합니다. 그런 다음 BitLocker를 사용하지 않도록 설정하고 dtrace bcdedit /set dtrace ON를 다시 사용하도록 설정합니다.

VSM 및 보안 커널을 사용하도록 설정하려면 "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\DeviceGuard\EnableVirtualizationBasedSecurity"를 1로 설정하여 컴퓨터에서 FBT(커널 함수 경계 추적)를 사용하도록 컴퓨터에서 VSM(가상 보안 모드)을 구성합니다.

이렇게 하려면 다음과 같이 REG 추가 명령을 사용합니다.

REG ADD HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\DeviceGuard\ /v EnableVirtualizationBasedSecurity /t REG_DWORD /d 1

일부 DTrace 명령은 Windows 기호를 사용합니다. Windows 기호를 사용하려면 기호 디렉터리를 만들고 기호 경로를 설정합니다.

mkdir c:\symbols
set _NT_SYMBOL_PATH=srv*C:\symbols*https://msdl.microsoft.com/download/symbols

기호 경로에 대한 자세한 내용은 Windows 디버거의 기호 경로를 참조 하세요.

Virtual Machine 내에서 DTrace 사용

VM에서 DTrace를 실행하는 경우 다음 PowerShell 명령을 사용하여 VM이 중지될 때 VM을 지원하는 컴퓨터에서 중첩된 가상화를 켭니다. <VMName> DTrace를 실행 중인 VM에 대해 제공합니다. PowerShell Windows를 관리istrator로 엽니다.

Set-VMProcessor -VMName <VMName> -ExposeVirtualizationExtensions $true

VM을 지원하는 PC를 다시 부팅합니다.

DTrace 설치 유효성 검사

-l 옵션을 사용하여 활성 프로브를 나열합니다. DTrace가 활성화된 경우 etw 및 시스템 이벤트에 대한 많은 프로브가 나열되어야 합니다.

관리자 권한으로 Windows 명령 프롬프트를 열어 DTrace 명령을 입력합니다.

C:\> dtrace -l

...

  179    syscall                                 NtLockVirtualMemory return
  180    syscall                               NtDeviceIoControlFile entry
  181    syscall                               NtDeviceIoControlFile return
  182    syscall                                 NtCreateUserProcess entry
  183    syscall                                 NtCreateUserProcess return
  184    syscall                                      NtQuerySection entry
  185    syscall                                      NtQuerySection return

...

 3161        etw 222962ab-6180-4b88-a825-346b75f2a24a           0xff_0xffffffffffffffff generic_event
 3162        etw 3ac66736-cc59-4cff-8115-8df50e39816b           0xff_0xffffffffffffffff generic_event
 3163        etw 42695762-ea50-497a-9068-5cbbb35e0b95           0xff_0xffffffffffffffff generic_event
 3164        etw 3beef58a-6e0f-445d-b2a4-37ab737bd47e           0xff_0xffffffffffffffff generic_event

...

이러한 세 프로브만 나열되면 로드되는 DTrace.sys 드라이버에 문제가 있습니다.

C:\>  dtrace -l
   ID   PROVIDER            MODULE                          FUNCTION NAME
    1     dtrace                                                     BEGIN
    2     dtrace                                                     END
    3     dtrace                                                     ERROR

DTrace 시작 - 한 줄 명령

관리자 명령 프롬프트에서 이러한 명령을 실행하여 시작합니다.

이 명령은 5초 동안 프로그램별 syscall 요약을 표시합니다. tick-5sec 매개 변수는 기간을 지정합니다. exit(0); 을 선택하면 명령 프롬프트가 완료될 때 명령이 종료됩니다. 출력은 PID(프로세스 ID), 실행 파일 이름 및 지난 5초 동안의 개수를 표시하여 지정 [pid,execname] = count(); 됩니다.

C:\> dtrace -Fn "tick-5sec {exit(0);} syscall:::entry{ @num[pid,execname] = count();} "  
dtrace: description 'tick-5sec ' matched 471 probes
CPU FUNCTION
  0 | :tick-5sec

     1792  svchost.exe                                                       4
     4684  explorer.exe                                                      4
     4916  dllhost.exe                                                       4
     6192  svchost.exe                                                       4
     6644  SecurityHealth                                                    4
       92  TrustedInstall                                                    5
      504  csrss.exe                                                         5
      696  svchost.exe                                                       6
...

이 명령은 3초 동안의 타이머 집합/취소 호출을 요약합니다.

C:\> dtrace -Fn "tick-3sec {exit(0);} syscall::Nt*Timer*:entry { @[probefunc, execname, pid] = count();}"
dtrace: description 'tick-3sec ' matched 14 probes
CPU FUNCTION
  0 | :tick-3sec

  NtCreateTimer                                       WmiPrvSE.exe                                            948                1
  NtCreateTimer                                       svchost.exe                                             564                1
  NtCreateTimer                                       svchost.exe                                            1276                1
  NtSetTimer2                                         svchost.exe                                            1076                1
  NtSetTimer2                                         svchost.exe                                            7080                1
  NtSetTimerEx                                        WmiPrvSE.exe                                            948                1
...  

기호를 사용하는 한 줄 명령

이러한 명령은 Windows 기호를 활용하며 설치 섹션에서 설명한 대로 기호 경로를 설정해야 합니다. 설치 앞부분에서 멘션 디렉터리를 만들고 이러한 명령을 사용하여 기호 경로를 설정합니다.

C:\> mkdir c:\symbols
C:\> set _NT_SYMBOL_PATH=srv*C:\symbols*https://msdl.microsoft.com/download/symbols

이 예제 명령은 상위 NT 함수를 표시합니다.

C:\> dtrace -n "fbt:nt:*Timer*:entry { @k[probefunc] = count(); } tick-5s { trunc(@k, 10);printa(@k); exit(0); }"
dtrace: description 'fbt:nt:*Timer*:entry ' matched 340 probes
CPU     ID                    FUNCTION:NAME
  0  22362                         :tick-5s
  KeCancelTimer                                                   712
  KeSetTimer2                                                     714
  HalpTimerClearProblem                                           908
  ExpSetTimerObject                                               935
  NtSetTimerEx                                                    935
  KeSetTimer                                                     1139
  KeSetCoalescableTimer                                          3159
  KeResumeClockTimerFromIdle                                    11767
  xHalTimerOnlyClockInterruptPending                            22819
  xHalTimerQueryAndResetRtcErrors                               22819

이 명령은 SystemProcess 커널 구조를 덤프합니다.

C:\> dtrace -n "BEGIN {print(*(struct nt`_EPROCESS *) nt`PsInitialSystemProcess);exit(0);}"

...

   uint64_t ParentSecurityDomain = 0
    void *CoverageSamplerContext = 0
    void *MmHotPatchContext = 0
    union _PS_PROCESS_CONCURRENCY_COUNT ExpectedConcurrencyCount = {
         Fraction :20 = 0
         Count :12 = 0
        uint32_t AllFields = 0
    }
    struct _KAFFINITY_EX IdealProcessorSets = {
        uint16_t Count = 0x1
        uint16_t Size = 0x20
        uint32_t Reserved = 0
        uint64_t [32] Bitmap = [ 0x1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
    }
}

이 명령은 지난 10초 동안의 위쪽 커널 스택을 표시합니다.

C:\> dtrace -qn "profile-997hz { @[stack()] = count(); } tick-10sec { trunc(@,5); printa(@); exit(0);}"

              nt`KiDispatchInterruptContinue
              nt`KiDpcInterrupt+0x318
              nt`KiSwapThread+0x1054
              nt`KiCommitThreadWait+0x153
              nt`KeRemoveQueueEx+0x263
              nt`IoRemoveIoCompletion+0x54
              nt`NtWaitForWorkViaWorkerFactory+0x284
              nt`KiSystemServiceCopyEnd+0x35
               14

              nt`KiDispatchInterruptContinue
              nt`KiDpcInterrupt+0x318
...

이 명령은 시작하는 동안 notepad.exe 호출한 상위 모듈을 표시합니다. -c 옵션은 지정된 명령(notepad.exe)을 실행하고 완료되면 종료됩니다.

C:\> dtrace -qn "pid$target:::entry { @k[probemod] = count();} tick-10s{printa(@k); exit(0);}" -c notepad.exe

  gdi32full                                                         5
  msvcp_win                                                         6
  combase                                                           7
  notepad                                                           9
  ADVAPI32                                                         10
  GDI32                                                            11
  SHELL32                                                          11
  USER32                                                           21
  win32u                                                          345
  KERNELBASE                                                     3727
  msvcrt                                                         7749
  KERNEL32                                                       9883
  RPCRT4                                                        11710
  ntdll                                                        383445

참고 항목

DTrace Windows 프로그래밍

DTrace ETW

DTrace 라이브 덤프

DTrace Windows 코드 샘플