# 機能設計書 30-llvm-size

## 概要

本ドキュメントは、LLVM llvm-sizeの機能設計について記述する。llvm-sizeは、オブジェクトファイルの各セクションのサイズと合計サイズを表示するツールであり、Unix sizeコマンドと互換性のある機能を提供する。

### 本機能の処理概要

llvm-sizeは、オブジェクトファイルやアーカイブファイルからセクションサイズ情報を抽出し、berkeley/sysv/darwin形式で表示するツールである。GNU sizeおよびdarwin sizeと互換性のある出力を提供する。

**業務上の目的・背景**：バイナリサイズの分析は、組み込みシステム開発やコードサイズ最適化において重要である。llvm-sizeは、text/data/bssセクションのサイズを素早く確認し、バイナリサイズの内訳を把握するために使用される。

**機能の利用シーン**：
- オブジェクトファイルのセクションサイズ確認
- バイナリサイズの最適化分析
- コンパイル結果のサイズ比較
- アーカイブ内の各メンバーのサイズ確認
- MachO ユニバーサルバイナリのアーキテクチャ別サイズ表示

**主要な処理内容**：
1. オブジェクトファイル/アーカイブの読み込み
2. セクション情報の抽出
3. サイズ計算（berkeley: text/data/bss、sysv: 各セクション）
4. 指定フォーマットでの出力

**関連システム・外部連携**：llvm-objdump、llvm-nm、llvm-readobj

**権限による制御**：特になし。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 本機能はコマンドラインツールであり、画面は存在しない |

## 機能種別

バイナリ解析ツール / セクションサイズ表示

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| input files | string[] | No | 入力ファイル（デフォルト: a.out） | ファイル存在確認 |
| --format | enum | No | 出力形式（berkeley/sysv/darwin） | - |
| --radix | enum | No | サイズ表示の基数（8/10/16） | - |
| -A | flag | No | --format=sysvのエイリアス | - |
| -B | flag | No | --format=berkeleyのエイリアス | - |
| -m | flag | No | --format=darwinのエイリアス | - |
| -d | flag | No | --radix=10のエイリアス | - |
| -o | flag | No | --radix=8のエイリアス | - |
| -x | flag | No | --radix=16のエイリアス | - |
| -t/--totals | flag | No | 合計を表示（berkeley形式のみ） | - |
| --common | flag | No | ELFコモンシンボルを含める | - |
| --arch | string | No | MachOアーキテクチャ指定 | MachO専用 |
| -l | flag | No | darwin形式で詳細表示（アドレス/オフセット） | MachO専用 |
| --exclude-pagezero | flag | No | __PAGEZEROを合計から除外 | MachO専用 |

### 入力データソース

- オブジェクトファイル（ELF、COFF、MachO）
- アーカイブファイル（.a）
- MachOユニバーサルバイナリ

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| text | integer | テキストセクションサイズ |
| data | integer | データセクションサイズ |
| bss | integer | BSSセクションサイズ |
| dec/oct | integer | 合計サイズ（10進/8進） |
| hex | integer | 合計サイズ（16進） |
| filename | string | ファイル名 |

### 出力先

- 標準出力

### 出力形式

**Berkeley形式（デフォルト）**：
```
   text	   data	    bss	    dec	    hex	filename
  12345	    678	     90	  13113	   3339	a.out
```

**SysV形式**：
```
section              size       addr
.text                12345      0x1000
.data                  678      0x4000
Total                13023
```

**Darwin形式（MachO）**：
```
Segment __TEXT: 12345 (vmaddr 0x1000 fileoff 0)
	Section __text: 10000 (addr 0x1000 offset 0)
total 12345
```

## 処理フロー

### 処理シーケンス

```
1. 初期化
   └─ コマンドライン引数解析（SizeOptTable使用）
   └─ 出力形式/基数の設定

2. 各入力ファイルの処理
   └─ createBinary()でバイナリ読み込み
   └─ ファイルタイプ判定

3. ファイルタイプ別処理
   └─ Archive: メンバーをイテレート
   └─ MachOUniversal: アーキテクチャ選択
   └─ ObjectFile: 直接処理

4. セクションサイズ計算
   └─ sysv: 各セクション個別表示
   └─ berkeley: text/data/bssに集約
   └─ darwin: MachOセグメント/セクション表示

5. 出力と集計
   └─ フォーマットに応じた出力
   └─ --totalsオプション時は合計表示
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[コマンドライン解析]
    B --> C{出力形式?}
    C -->|berkeley| D[Radix設定]
    C -->|sysv| D
    C -->|darwin| D
    D --> E[入力ファイルループ]
    E --> F[createBinary]
    F --> G{ファイルタイプ?}
    G -->|Archive| H[アーカイブ処理]
    G -->|MachOUniversal| I[ユニバーサルバイナリ処理]
    G -->|ObjectFile| J[オブジェクト処理]
    H --> K[printObjectSectionSizes]
    I --> K
    J --> K
    K --> L{出力形式?}
    L -->|sysv| M[セクション個別表示]
    L -->|berkeley| N[text/data/bss集約]
    L -->|darwin| O[セグメント/セクション表示]
    M --> P[次のファイル]
    N --> P
    O --> P
    P --> E
    E -->|完了| Q{--totals?}
    Q -->|Yes| R[printBerkeleyTotals]
    Q -->|No| S[終了]
    R --> S
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | デフォルトファイル | 入力未指定時はa.out | 入力なし時 |
| BR-002 | デフォルト形式 | 出力形式未指定時はberkeley | 常時 |
| BR-003 | デフォルト基数 | 基数未指定時は10（decimal） | 常時 |
| BR-004 | MachOセグメント分類 | __TEXT/__DATA/__OBJC/othersに分類 | MachO+berkeley時 |
| BR-005 | ELFセクション除外 | SHT_NULL/SHT_SYMTABは除外 | ELF+sysv時 |

### 計算ロジック

**Berkeley形式のセクション分類**：
- text: isBerkeleyText()がtrueのセクション
- data: isBerkeleyData()がtrueのセクション
- bss: isBSS()がtrueのセクション

**MachO Berkeley形式**：
- __TEXT: __TEXTセグメントのvmsize
- __DATA: __DATAセグメントのvmsize
- __OBJC: __OBJCセグメントのvmsize
- others: その他のセグメント（--exclude-pagezero時は__PAGEZERO除外）

**ELFコモンシンボル（--common）**：
- SF_Commonフラグを持つシンボルのサイズを集計
- Berkeley形式ではbssに加算

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

本機能はデータベースを使用しない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 1 | File Error | ファイル読み込み失敗 | ファイル確認 |
| 1 | Format Error | 未サポートフォーマット | フォーマット確認 |
| 1 | Arch Error | 指定アーキテクチャが存在しない | --arch確認 |

### リトライ仕様

エラー時はHadError=trueを設定して継続。最終的にリターンコード1。

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

該当なし

## パフォーマンス要件

- 大規模バイナリでも効率的に処理
- セクションヘッダのみ読み込み

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

- 入力ファイルの妥当性検証

## 備考

- MachO固有のセグメント分類（__TEXT/__DATA/__OBJC/others）
- ELFコモンシンボルの明示的な表示（--common）
- 複数ファイルの合計表示（--totals）

---

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

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

### 推奨読解順序

#### Step 1: メインソースを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | llvm-size.cpp | `llvm/tools/llvm-size/llvm-size.cpp` | ツール全体の実装 |

**主要処理フロー**:
- **39-72行目**: オプション定義（SizeOptTable、OutputFormatTy、RadixTy）
- **74-99行目**: グローバル設定変数（OutputFormat、Radix、TotalSizes等）
- **101-152行目**: エラー処理関数群
- **368-523行目**: printObjectSectionSizes() - コア処理
- **889-965行目**: llvm_size_main() - メイン関数

**読解のコツ**: OutputFormatTy（berkeley/sysv/darwin）とRadixTy（octal/decimal/hexadecimal）の組み合わせで出力形式が決まる。

#### Step 2: 出力形式別の処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | llvm-size.cpp | `llvm/tools/llvm-size/llvm-size.cpp` | 出力形式処理 |

**主要処理フロー**:
- **206-279行目**: printDarwinSectionSizes() - darwin形式出力
- **281-363行目**: printDarwinSegmentSizes() - MachO berkeley形式
- **384-461行目**: sysv形式出力処理
- **462-522行目**: 標準berkeley形式出力処理

#### Step 3: ファイルタイプ別処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | llvm-size.cpp | `llvm/tools/llvm-size/llvm-size.cpp` | ファイル処理 |

**主要処理フロー**:
- **553-862行目**: printFileSectionSizes() - ファイルタイプ分岐
- **565-595行目**: アーカイブ処理
- **596-842行目**: MachOユニバーサルバイナリ処理
- **843-861行目**: 通常オブジェクトファイル処理

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

```
llvm_size_main()
    │
    ├─ SizeOptTable.parseArgs()
    │
    └─ for each InputFilename
           │
           └─ printFileSectionSizes()
                  │
                  ├─ createBinary()
                  │
                  └─ switch(BinaryType)
                         │
                         ├─ Archive
                         │      └─ for each child
                         │             └─ printObjectSectionSizes()
                         │
                         ├─ MachOUniversalBinary
                         │      └─ for each architecture
                         │             └─ printObjectSectionSizes()
                         │
                         └─ ObjectFile
                                └─ printObjectSectionSizes()
                                       │
                                       ├─ darwin形式
                                       │      └─ printDarwinSectionSizes()
                                       │
                                       ├─ MachO + berkeley形式
                                       │      └─ printDarwinSegmentSizes()
                                       │
                                       ├─ sysv形式
                                       │      └─ セクション個別出力
                                       │
                                       └─ berkeley形式
                                              └─ text/data/bss集約出力
```

### データフロー図

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

オブジェクト/アーカイブ ────────▶ createBinary()
                                   │
                                   ▼
                           ファイルタイプ判定
                                   │
                 ┌─────────────────┼─────────────────┐
                 ▼                 ▼                 ▼
              Archive      MachOUniversal      ObjectFile
                 │                 │                 │
                 └─────────────────┼─────────────────┘
                                   ▼
                           printObjectSectionSizes()
                                   │
                 ┌─────────────────┼─────────────────┐
                 ▼                 ▼                 ▼
           sysv形式          berkeley形式       darwin形式
           (各セクション)    (text/data/bss)   (セグメント)
                 │                 │                 │
                 └─────────────────┼─────────────────┘
                                   ▼
                           stdout ──────────────────▶ サイズ情報
                                   │
                                   ▼
                           TotalSizes集計
                                   │
                                   ▼ (--totals時)
                           printBerkeleyTotals()
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| llvm-size.cpp | `llvm/tools/llvm-size/llvm-size.cpp` | ソース | メイン実装 |
| CMakeLists.txt | `llvm/tools/llvm-size/CMakeLists.txt` | ビルド設定 | ビルドスクリプト |
| Opts.td | `llvm/tools/llvm-size/Opts.td` | 定義 | オプション定義 |
| ObjectFile.h | `llvm/include/llvm/Object/ObjectFile.h` | ヘッダ | オブジェクトファイル抽象 |
| MachO.h | `llvm/include/llvm/Object/MachO.h` | ヘッダ | MachO処理 |
| MachOUniversal.h | `llvm/include/llvm/Object/MachOUniversal.h` | ヘッダ | ユニバーサルバイナリ |
| Archive.h | `llvm/include/llvm/Object/Archive.h` | ヘッダ | アーカイブ処理 |
| ELFObjectFile.h | `llvm/include/llvm/Object/ELFObjectFile.h` | ヘッダ | ELF処理 |
