# 機能設計書 94-sancov

## 概要

本ドキュメントは、LLVMプロジェクトにおけるsancov（サニタイザカバレッジツール）の機能設計書である。sancovは、サニタイザ（AddressSanitizer、UBSan等）によって収集されたコードカバレッジデータを処理・分析するツールである。

### 本機能の処理概要

sancovは、サニタイザ機能で計装されたバイナリの実行時に生成される.sancovファイル（バイナリカバレッジデータ）を読み込み、シンボル化、マージ、統計出力などの処理を行うツールである。

**業務上の目的・背景**：セキュリティテスト（ファジング）やコードカバレッジ分析において、どのコードパスが実行されたかを把握することは重要である。Clangの-fsanitize-coverageオプションで生成されるカバレッジデータを分析可能な形式に変換し、テスト網羅性の評価やファジングの効率化を支援する。

**機能の利用シーン**：
- ファジングテストでのカバレッジフィードバック
- テストスイートの網羅性評価
- カバレッジデータの可視化・レポート生成
- 複数テスト実行結果のマージ

**主要な処理内容**：
1. .sancovファイルの読み込み・解析
2. カバレッジポイントのシンボル化（ファイル名:行番号への変換）
3. 複数カバレッジデータのマージ
4. カバレッジ差分の計算
5. カバレッジ統計の出力
6. カバレッジ/未カバレッジ関数のリスト出力

**関連システム・外部連携**：Clangの-fsanitize-coverage、LLVMシンボライザ、オブジェクトファイル解析と連携する。

**権限による制御**：特になし（スタンドアロンツール）

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| N/A | コマンドライン | 主画面 | コマンドライン引数による操作 |

## 機能種別

データ処理 / カバレッジ分析

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| input files | string[] | Yes | .sancovファイル、バイナリ、.symcovファイル | - |
| -print | flag | No | 生カバレッジアドレスを出力 | - |
| -print-coverage-pcs | flag | No | カバレッジポイントのアドレスを出力 | - |
| -covered-functions | flag | No | カバーされた関数を出力 | - |
| -not-covered-functions | flag | No | カバーされていない関数を出力 | - |
| -print-coverage-stats | flag | No | カバレッジ統計を出力 | - |
| -symbolize | flag | No | シンボル化してJSON出力 | - |
| -merge | flag | No | 複数.symcovをマージ | - |
| -diff | flag | No | 2つの.sancovの差分を計算 | - |
| -union | flag | No | 複数.sancovを結合 | - |

### 入力データソース

- .sancovファイル（バイナリカバレッジデータ）
- 計装済みバイナリファイル
- .symcovファイル（シンボル化済みカバレッジ、JSON形式）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| アドレスリスト | text | 16進アドレスのリスト |
| 関数リスト | text | ファイル:行番号 関数名 形式 |
| カバレッジ統計 | text | ポイント数/関数数の統計 |
| シンボル化データ | JSON | .symcov形式のカバレッジ情報 |
| 差分/結合データ | binary | .sancov形式 |

### 出力先

標準出力または-oオプションで指定したファイル

## 処理フロー

### 処理シーケンス

```
1. コマンドライン解析
   └─ アクション種別と入力ファイルの特定
2. 入力ファイル分類
   └─ .sancov、バイナリ、.symcovの判別
3. アクションに応じた処理
   └─ print: 生アドレス出力
   └─ symbolize: シンボル化とJSON出力
   └─ diff/union: ファイル間演算
   └─ covered/not-covered: 関数リスト生成
4. 結果出力
   └─ 標準出力またはファイルへ
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[コマンドライン解析]
    B --> C{アクション判定}
    C -->|print| D[readAndPrintRawCoverage]
    C -->|diff| E[diffRawCoverage]
    C -->|union| F[unionRawCoverage]
    C -->|print-coverage-pcs| G[printCovPoints]
    C -->|その他| H[readSymbolizeAndMergeCmdArguments]
    D --> I[結果出力]
    E --> J[出力ファイル書き込み]
    F --> J
    G --> I
    H --> K{アクション}
    K -->|covered-functions| L[printCoveredFunctions]
    K -->|not-covered-functions| M[printNotCoveredFunctions]
    K -->|stats| N[computeStats]
    K -->|symbolize/merge| O[JSON出力]
    L --> I
    M --> I
    N --> I
    O --> I
    I --> P[終了]
    J --> P
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-94-01 | ファイル形式判定 | .sancovはマジックナンバー0xC0BFFFFFで識別 | ファイル読込時 |
| BR-94-02 | ビット幅 | 32bit/64bitをヘッダで判定 | .sancov解析時 |
| BR-94-03 | ゼロアドレス除外 | アドレス0は無効として除外 | カバレッジ読込時 |
| BR-94-04 | 無視リスト | -ignorelist指定でシンボルをフィルタ | シンボル化時 |

### 計算ロジック

- カバレッジ率 = CoveredIds.size() / Points.size()
- 差分(diff): A - B = Aにあり Bにないアドレス
- 結合(union): 全ファイルのアドレス和集合

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

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

本ツールはデータベースを使用しない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 1 | ファイルエラー | .sancov読込失敗 | ファイルパス確認 |
| 1 | フォーマットエラー | 不正なマジックナンバー | 有効な.sancovを使用 |
| 1 | マッチエラー | バイナリと.sancovの不一致 | 対応するバイナリを指定 |
| 1 | シンボル化エラー | __sanitizer_cov*関数が見つからない | 計装済みバイナリを使用 |

### リトライ仕様

リトライは実装されていない。

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

該当なし

## パフォーマンス要件

- 大量のカバレッジポイントを処理するため、メモリ使用量はファイルサイズに比例
- シンボル化処理はディスアセンブルを伴うため時間がかかる

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

- 入力ファイルの基本的な形式検証を実施
- デフォルト無視リストでサニタイザ内部関数をフィルタ

## 備考

.sancovファイル形式：8バイトヘッダ（4バイトビット幅 + 4バイトマジック）+ アドレス配列

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | sancov.cpp | `llvm/tools/sancov/sancov.cpp` | FileHeader、RawCoverage、SymbolizedCoverage構造体 |

**読解のコツ**: FileHeaderが.sancovファイルのヘッダ形式を定義し、RawCoverageが生カバレッジ、SymbolizedCoverageがシンボル化済みデータを表す。

#### Step 2: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | sancov.cpp | `llvm/tools/sancov/sancov.cpp` | sancov_main関数 |

**主要処理フロー**:
1. **1342-1347行目**: ターゲット初期化とオプション解析
2. **1350-1353行目**: PrintActionの場合の生データ出力
3. **1354-1363行目**: DiffActionの差分計算
4. **1364-1373行目**: UnionActionの結合処理
5. **1374-1380行目**: PrintCovPointsActionのカバレッジポイント出力
6. **1382行目**: readSymbolizeAndMergeCmdArgumentsでシンボル化処理

#### Step 3: カバレッジファイルI/Oを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | sancov.cpp | `llvm/tools/sancov/sancov.cpp` | RawCoverage::read()、RawCoverage::write() |

**主要処理フロー**:
- **236-276行目**: RawCoverage::read()で.sancovファイル読込
- **289-314行目**: RawCoverage::write()で.sancovファイル書込
- **250-253行目**: マジックナンバー検証
- **257-269行目**: 32bit/64bit判定とアドレス読込

#### Step 4: シンボル化処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | sancov.cpp | `llvm/tools/sancov/sancov.cpp` | getCoveragePoints()、symbolize() |

**主要処理フロー**:
- **551-622行目**: getCoveragePoints()でカバレッジポイント情報取得
- **906-938行目**: symbolize()でシンボル化処理
- **494-499行目**: createSymbolizer()でシンボライザ作成

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

```
sancov_main() [sancov.cpp:1342]
    │
    ├─ parseArgs() [1252-1340行目]
    │
    ├─ [PrintAction]
    │      └─ readAndPrintRawCoverage() [1044-1052行目]
    │             └─ RawCoverage::read()
    │
    ├─ [DiffAction]
    │      └─ diffRawCoverage() [1086-1107行目]
    │             └─ RawCoverage::read() x2
    │             └─ std::set_difference()
    │             └─ RawCoverage::write()
    │
    ├─ [UnionAction]
    │      └─ unionRawCoverage() [1109-1134行目]
    │             └─ RawCoverage::read() x N
    │             └─ RawCoverage::write()
    │
    ├─ [PrintCovPointsAction]
    │      └─ printCovPoints() [871-877行目]
    │             └─ findCoveragePointAddrs()
    │                    └─ getObjectCoveragePoints()
    │
    └─ [その他]
           └─ readSymbolizeAndMergeCmdArguments() [1169-1248行目]
                  │
                  ├─ SymbolizedCoverage::read() [.symcovの場合]
                  │
                  ├─ RawCoverage::read() + symbolize()
                  │      └─ getCoveragePoints()
                  │             └─ createSymbolizer()
                  │
                  └─ merge()
```

### データフロー図

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

.sancovファイル ───────▶ RawCoverage::read() ───▶ std::set<uint64_t>
                              │
                              ▼
バイナリファイル ───────▶ findCoveragePointAddrs() ───▶ 全カバレッジポイント
                              │
                              ▼
                        getCoveragePoints() ───▶ CoveragePoint[]
                              │
                              ▼
                        LLVMSymbolizer ───────▶ DILineInfo
                              │
                              ▼
                        symbolize() ──────────▶ SymbolizedCoverage
                              │
                              ▼
                        JSON出力/統計計算 ────▶ 標準出力/.symcov
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| sancov.cpp | `llvm/tools/sancov/sancov.cpp` | ソース | 全機能の実装 |
| Opts.inc | `llvm/tools/sancov/Opts.inc` | 生成ファイル | コマンドラインオプション定義 |
