# 機能設計書 8-DTrace動的トレーシング

## 概要

本ドキュメントは、FreeBSDにおけるDTrace動的トレーシング機能の設計を記述する。カーネルおよびユーザ空間の動的トレーシング・プロファイリング機構を対象とする。

### 本機能の処理概要

**業務上の目的・背景**：DTraceはSun Microsystems（現Oracle）が開発した動的トレーシングフレームワークであり、本番環境で稼働中のシステムに対して安全にトレーシングを実行できる。パフォーマンス問題の診断、システム動作の可視化、セキュリティ監視などに使用される。FreeBSDはDTraceをCDDLライセンスの下で採用している。

**機能の利用シーン**：本番システムのパフォーマンスボトルネック分析、システムコール呼び出しパターンの解析、I/O遅延の測定、メモリ割り当てパターンの追跡、セキュリティインシデントの調査、カーネル開発時のデバッグで利用される。

**主要な処理内容**：
1. **DTraceフックインフラ（kern_dtrace.c）**: カーネル内のDTraceフック機構。トラップハンドラ、システムコールエントリ/リターン、プロセスライフサイクルイベントにフックポイントを提供する。
2. **systraceプロバイダ**: システムコールのエントリ・リターンをトレースするプロバイダ。systrace_probe_func関数ポインタ経由で呼び出される。
3. **fasttrapプロバイダ**: ユーザ空間プロセスの任意の関数エントリ・リターンをトレースする。dtrace_pid_probe_ptr/dtrace_return_probe_ptrフック経由。
4. **DTraceコアエンジン**: cddl/ディレクトリ内のDTrace本体実装。D言語スクリプトのコンパイル・実行、プローブの管理、データ集約を行う。
5. **SDT（Statically Defined Tracing）**: カーネルソースコードに静的に埋め込まれたトレースポイント。SDT_PROBE_DEFINEマクロで定義される。

**関連システム・外部連携**：プロセス管理（proc:::createプローブ等）、ファイルシステム、ネットワーク、スケジューラ、各種カーネルサブシステムとの連携。dtrace(1)コマンドラインツール。

**権限による制御**：DTrace使用にはroot権限が必要。DTrace破壊モード（destructive actions）はデフォルトで無効であり、securelevelおよびloader.conf設定で制御される。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 26 | セキュリティ強化設定画面 | 補助機能 | DTrace破壊モード無効化のloader.conf設定 |

## 機能種別

カーネル基盤機能（動的トレーシング・プロファイリング）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| D言語スクリプト | char * | Yes | トレーシングスクリプト | D言語文法に準拠 |
| プローブ指定 | provider:module:function:name | Yes | トレースするプローブの指定 | 有効なプローブパターン |
| -n オプション | char * | No | プローブ名指定 | - |
| -s オプション | char * | No | スクリプトファイル指定 | ファイル存在チェック |
| -p オプション | pid_t | No | トレース対象プロセスID | 有効なPID |

### 入力データソース

dtrace(1)コマンドのCLI引数・スクリプトファイル、DTraceカーネルモジュール経由の/dev/dtraceデバイスインタフェース。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| トレースデータ | 可変 | プローブ発火時のコンテキスト情報（タイムスタンプ、PID、CPU等） |
| 集約データ | 集約関数結果 | @agg[key] = count()/sum()/avg()等の集約結果 |
| プロファイルデータ | スタックトレース | ustack()/stack()によるスタックサンプリング |

### 出力先

標準出力（dtrace(1)コマンド）、DTraceバッファ。

## 処理フロー

### 処理シーケンス

```
1. DTraceフック初期化
   ├─ kern_dtrace.c: フック関数ポインタの初期化
   │    ├─ dtrace_trap_func: トラップフック
   │    ├─ dtrace_pid_probe_ptr: PIDプロバイダフック
   │    ├─ systrace_probe_func: systraceフック
   │    └─ KDTRACE_HOOKS有効時のフック登録

2. プローブ有効化
   ├─ dtrace(1) → /dev/dtrace ioctl
   │    ├─ プローブの検索・マッチング
   │    ├─ プローブの有効化（ブレークポイント挿入等）
   │    └─ D言語スクリプトのコンパイル

3. プローブ発火・データ収集
   ├─ カーネルイベント発生
   │    ├─ SDT_PROBE_*マクロによるフック呼び出し
   │    ├─ DTraceエンジンがプローブアクションを実行
   │    └─ バッファへのデータ記録

4. データ出力
   └─ dtrace(1)がバッファからデータを読み出して表示
```

### フローチャート

```mermaid
flowchart TD
    A[dtrace -n 'probe{action}'] --> B[/dev/dtrace ioctl]
    B --> C[D言語コンパイル]
    C --> D[プローブ有効化]
    D --> E[カーネルイベント待機]
    E --> F{プローブ発火}
    F -->|Yes| G[アクション実行]
    G --> H[バッファ記録]
    H --> E
    F -->|終了| I[データ出力]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | root権限必須 | DTrace使用にはroot権限が必要 | 全DTrace操作時 |
| BR-02 | 安全性保証 | DTraceスクリプトはカーネルパニックを引き起こさないことが保証される | 通常モード時 |
| BR-03 | 破壊モード制限 | destructive actions（system(), chill()等）はデフォルト無効 | 明示的有効化が必要 |
| BR-04 | CDDLライセンス | DTraceコードはCDDLライセンス下で提供 | cddl/ディレクトリ |
| BR-05 | SDTプローブ | カーネルソースに埋め込まれた静的プローブはオーバーヘッドなし（無効時） | KDTRACE_HOOKS有効時 |

### 計算ロジック

KDTRACE_PROC_SIZE（43行目）は64バイト、KDTRACE_THREAD_SIZE（44行目）は256バイトのプロセス・スレッド毎DTraceデータ領域を定義する。DTraceが無効の場合、SDTプローブはNOP命令となりオーバーヘッドはほぼゼロ。

## データベース操作仕様

### 操作別データベース影響一覧

本機能はトレーシング専用であり、永続的なデータベース操作は行わない。

| 操作 | 対象データ構造 | 操作種別 | 概要 |
|-----|-------------|---------|------|
| プローブ登録 | dtrace_provider | INSERT | プロバイダ・プローブの登録 |
| トレースデータ | dtrace_buffer | INSERT | プローブ発火時のデータ記録 |

### テーブル別操作詳細

該当なし（トレーシング専用、永続ストレージへの書き込みなし）。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| EPERM | 権限不足 | 非rootでのDTrace使用 | root権限で実行 |
| EINVAL | スクリプト不正 | D言語コンパイルエラー | スクリプトの修正 |
| ENOMEM | メモリ不足 | バッファ割り当て失敗 | バッファサイズ削減 |
| EBUSY | リソース競合 | プローブの重複有効化 | 既存のDTraceセッション終了 |

### リトライ仕様

DTraceはリアルタイムトレーシングであり、バッファ溢れ時はドロップカウントを増加させ、データロスを報告する。

## トランザクション仕様

DTraceバッファはCPU毎に独立して管理され、ロックフリーのリングバッファ構造を持つ。プローブ発火時のデータ記録はアトミックに行われる。

## パフォーマンス要件

- 無効プローブ: オーバーヘッドほぼゼロ（NOP命令）
- 有効プローブ: プローブ発火毎に数百ナノ秒〜数マイクロ秒
- バッファ読み出し: ポーリング間隔に依存

## セキュリティ考慮事項

- DTrace破壊モードの無効化によるシステム保護
- securelevelによる制限
- 画面No.26のセキュリティ強化設定でloader.conf設定が提供される
- DTraceによるカーネルメモリ内容の読み取りが可能なため、root権限を厳格に管理

## 備考

- kern_dtrace.cの43-44行目でKDTRACE_PROC_SIZE=64、KDTRACE_THREAD_SIZE=256が定義
- 46-47行目でFEATURE(kdtrace_hooks)が宣言され、DTraceカーネルモジュールのロードに必要なフック
- 49行目でM_KDTRACEメモリ割り当てタグが定義
- 52-55行目でdtrace_trap_func、dtrace_doubletrap_func、dtrace_pid_probe_ptr、dtrace_return_probe_ptrのフック変数が宣言
- 57-58行目でsystrace_enabled（読み頻度最適化）とsystrace_probe_funcが宣言

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | dtrace_bsd.h | `sys/sys/dtrace_bsd.h` | DTraceフック関数ポインタ型の定義 |
| 1-2 | sdt.h | `sys/sys/sdt.h` | SDT_PROBE_DEFINEマクロ群の定義。静的プローブの宣言方法 |

**読解のコツ**: DTraceのFreeBSD統合は「フック」アーキテクチャで実現されている。カーネル本体はBSDライセンスのフック変数（関数ポインタ）を定義し、CDDLライセンスのDTraceモジュールがロード時にこれらのフック変数に実装を設定する。

#### Step 2: カーネルフックインフラを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | kern_dtrace.c | `sys/kern/kern_dtrace.c` | DTraceフック変数の定義と初期化。プロセス・スレッド毎のDTraceデータ管理 |

**主要処理フロー**:
1. **43-44行目**: KDTRACE_PROC_SIZE=64、KDTRACE_THREAD_SIZE=256の定義
2. **46-47行目**: FEATURE(kdtrace_hooks)の宣言
3. **49行目**: M_KDTRACEメモリタグ定義
4. **52-55行目**: トラップ/PIDプローブ/リターンプローブのフック変数宣言
5. **57-58行目**: systraceフック変数（__read_frequently最適化付き）

#### Step 3: DTraceコアエンジンを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | dtrace.c | `sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c` | DTraceコアエンジン |
| 3-2 | fasttrap.c | `sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c` | fasttrapプロバイダ |

### プログラム呼び出し階層図

```
dtrace(1) コマンド
    |
    +-- /dev/dtrace ioctl
            |
            +-- dtrace_open/ioctl/close [DTraceコアエンジン]
                    |
                    +-- dtrace_probe_create() [プローブ作成]
                    +-- dtrace_probe_enable() [プローブ有効化]
                    +-- dtrace_dof_create() [D言語コンパイル]

カーネルイベント発生時:
    |
    +-- SDT_PROBE_*() マクロ [静的プローブ]
    +-- systrace_probe_func() [syscallプローブ]
    +-- dtrace_pid_probe_ptr() [PIDプローブ]
            |
            +-- dtrace_probe() [プローブアクション実行]
                    +-- dtrace_buffer_store() [バッファ記録]
```

### データフロー図

```
[入力]                  [処理]                         [出力]

D言語スクリプト ───> DTraceコンパイラ ─────────────> バイトコード

カーネルイベント ──> プローブ発火 ─────────────────> バッファ記録
                    アクション実行

バッファデータ ───> dtrace(1)ポーリング ────────────> 標準出力
                                                       集約結果
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| kern_dtrace.c | `sys/kern/kern_dtrace.c` | ソース | DTraceカーネルフックインフラ |
| dtrace.c | `sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c` | ソース | DTraceコアエンジン |
| fasttrap.c | `sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c` | ソース | fasttrapプロバイダ |
| dtrace_bsd.h | `sys/sys/dtrace_bsd.h` | ヘッダ | フック関数ポインタ型定義 |
| sdt.h | `sys/sys/sdt.h` | ヘッダ | SDTプローブマクロ定義 |
