Windows 上の DTrace
DTrace (DTrace.exe) は、システム情報とイベントを表示するコマンドライン ツールです。 DTrace は、Windows に移植されたオープンソースのトレース プラットフォームです。 DtraceはもともとSolarisオペレーティングシステム用に開発されました。 ユーザー/カーネル関数、D 言語を使用してスクリプトを作成する機能、および投機的トレースの両方の動的インストルメンテーションを提供します。 さらに、DTrace には、ETW インストルメンテーション、ETW イベント生成、システム呼び出しプローブ、ライブ ダンプ キャプチャ機能などの Windows OS 固有の拡張機能があります。
Note
DTraceは、バージョン18980およびWindows Server Build 18975以降のInsiderのビルドでサポートされています。
Windows GitHubサイトのDTraceは次の場所にあります。
https://github.com/microsoft/DTrace-on-Windows
DTrace情報を開く
DTraceの詳細については、ケンブリッジ大学のOpenDTrace Specification version 1.0を参照してください。
主要なGitHubサイトはhttps://github.com/opendtrace/にあります。
有用なスクリプトのセットは、https://github.com/opendtrace/toolkitで入手できます。
次のようなDTraceの書籍が多数用意されています。
DTrace:Brendan GreggとJim MauroによるOracle Solaris、Mac OS XおよびFreeBSDにおける動的トレース
Solaris のパフォーマンスとツール: Solaris 10 と OpenSolaris の DTrace と MDB の手法 リチャード・マクドゥーガル、ジム・マウロ、ブレンダン・グレッグ
Windows DTraceに関するフィードバックの提供
フィードバック ハブを使用して、新しい機能を要求したり、Windows DTrace で問題やバグを報告したりできます。
- Windows でフィードバック ハブを起動するには、検索に移動し、 feedback という単語を入力し、 Feedback Hub を選択します。
- 機能の提案または問題の報告を選択します。
- 問題または提案の詳細な具体的な説明を提供します。
DTrace Windows拡張機能
Windows で使用できる Dtrace プロバイダーの一部と、そのインストルメント化された機能を次に示します。
syscall – NTOS システム呼び出し。
fbt (関数境界トレース) – カーネル関数のエントリと戻り値。
pid(プロセスID) – ユーザーモードプロセスのトレース。 カーネル モード FBT と同様ですが、任意の関数オフセットのインストルメンテーションも可能です。
etw (Windows のイベント トレース) – ETW に対してプローブを定義できるようにします。 このプロバイダーは、DTrace の既存のオペレーティング システム インストルメンテーションを活用するのに役立ちます。
SYSCALL – NTOS システム呼び出し
SYSCALLは、システムコールが入力される前に起動するエントリプローブと、システムコールが完了した後で制御がユーザーレベルに戻る前に起動するリターンプローブのペアをシステムコールごとに提供します。 すべてのSYSCALLプローブで、関数名は計装システム コールの名前に設定され、モジュール名は関数が存在するモジュールです。 SYSCALLプロバイダが提供するシステムコールの名前は、コマンドdtrace.exe -l -P syscall
プロンプトからコマンドを入力することによって確認できます。 プローブ名は小文字のsyscallであることに注意してください。 このコマンドは、システムコールdtrace -ln 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
...
これらの例では、すべての画面出力が表示されるわけではないことに注意してください。 「..」は、切り捨てられた出力を表すために使用されます。
出力をスクロールするには、次のように「moreもっと」コマンドにパイプアウトします。
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:::
プロバイダから利用可能なすべてのプローブとそのパラメータの一覧を表示します。
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
...
Note
nt内で使用可能なコールは数千あるため、データをログに記録するDTraceコマンドを実行する場合は、関数名を空のままにしておくことはお勧めできません。 パフォーマンスへの影響を回避するために推奨される方法は、fbt:nt:*Timer*:entry
などの機能名の少なくとも一部を指定することです。
PID
Dtrace PIDプロバイダでは、ウェブブラウザやデータベースなどのユーザーモードプロセスの内部実行をトレースできます。 プロセス起動時にDTraceを接続して、プロセス起動の問題をデバッグすることもできます。 PID定義の一部として、プロセスで定義された関数と、関数内の特定のオフセット(またはすべてワイルドカード*を使用したオフセット)を指定します。 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
Note
C++で記述された関数をトレースする場合、関数名が長すぎたり、完全な形式でプローブとして指定できないことがあります。 一般的な解決策は、ターゲット関数に一意に一致する式を使用することです。 例えば、「String::Copy()」に一致させるにはプローブ名の「probefunc」部分に「String??Copy」を、「String::GetPinnableReference()」に一致させるには「*GetPinnableReference」を使用します。
Dtrace Windowsアーキテクチャ
ユーザーはDTraceコマンドを使用してDTraceと対話し、DTraceエンジンのフロントエンドとして機能します。 Dスクリプトはユーザ空間で中間フォーマット(DIF)にコンパイルされ、実行のためにDTraceカーネルコンポーネントに送信されます。DIF仮想機械と呼ばれることもあります。 これはdtrace.sysドライバで実行されます。
Traceext.sys(トレースエクステンション)は、Windowsカーネル拡張ドライバであり、DTraceがトレースを提供するために依存する機能をWindowsで公開できます。 Windowsカーネルは、スタックウォークまたはメモリアクセス中にコールアウトを提供し、トレース拡張によって実装されます。
WindowsでのDTraceのインストール
サポートされているバージョンのWindowsを実行していることを確認します。 DTraceの現在のダウンロードは、バージョン18980とWindows Server Build 18975以降の20H1 WindowsのInsiderビルドでサポートされています。 このバージョンのDTraceを旧バージョンのWindowsにインストールすると、システムが不安定になる可能性があり、推奨しません。 (19H1用のDTraceのアーカイブバージョンは使用できなくなり、サポートされなくなりました。)
MicrosoftダウンロードセンターからMSIインストールファイル(WindowsのDtraceダウンロード)をダウンロードします。
「インストールの完了」を選択します。
重要
bcdeditを使用してブート情報を変更する前に、テストPCのPatchguard、BitLocker、Secure BootなどのWindowsセキュリティ機能を一時的に停止する必要があります。 テストが完了したら、これらのセキュリティ機能を再度有効にし、セキュリティ機能が無効になっている場合は、テストPCを適切に管理します。
PATH 環境変数を更新して C:\Program Files\DTraceを含めます
set PATH=%PATH%;"C:\Program Files\DTrace"
- bcditコマンドを使用して、機械上でDTraceを有効にします。
bcdedit /set dtrace ON
新しいWindows Insiderビルドにアップデートするときは、dtrace bceditオプションを再度設定する必要があります。
Note
BitLockerを使用している場合は、ブート値を変更するときに無効にします。 これを行わないと、BitLockerの回復キーの入力を求めるプロンプトが表示される場合があります。 この状況から回復する1つの方法は、回復コンソールを起動してbcdit値、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 Addコマンドを使用します。
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デバッガのシンボルパスを参照してください。
仮想機械内でのDTraceの使用
VMでDTraceを実行している場合は、次のPowerShellコマンドを使用して、VMをサポートする機械でネストされた仮想化をオンにします。 DTraceを実行しているVMに<VMName>
を提供します。 管理者としてPowerShell Windowsを開きます。
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
...
これら3つのプローブだけがリストされている場合は、DTrace.sysドライバがロードされている問題があります。
C:\> dtrace -l
ID PROVIDER MODULE FUNCTION NAME
1 dtrace BEGIN
2 dtrace END
3 dtrace ERROR
DTraceを使用する前に - 1行のコマンド
管理者コマンドプロンプトからこれらのコマンドを実行して開始します。
このコマンドは、プログラムごとに5秒間syscallサマリーを表示します。 tick-5secパラメータは、期間を指定します。 exit(0);を指定すると、コマンドが完了すると終了してコマンドプロンプトに戻ります。 出力は、 [pid,execname] = count();
を使用して指定します。プロセス ID (PID)、実行可能ファイル名、および過去 5 秒間のカウントが表示されます。
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
...
シンボルを使用する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