# 機能設計書 29-llvm-nm

## 概要

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

### 本機能の処理概要

llvm-nmは、ビットコードファイルやオブジェクトファイルからシンボル名とその情報（アドレス、型、サイズ等）を抽出して表示するツールである。GNU nmの多くの機能をサポートし、複数の出力フォーマットを提供する。

**業務上の目的・背景**：シンボルテーブルの調査は、リンクエラーの診断、ライブラリの内容確認、シンボル競合の検出などで必要となる。llvm-nmはGNU nmとの互換性を持ちながら、LLVMツールチェーンに統合された形でこの機能を提供する。

**機能の利用シーン**：
- オブジェクトファイル内のシンボル一覧表示
- 未定義シンボルの検出
- エクスポートシンボルの確認
- アーカイブ内のシンボルマップ表示
- シンボルサイズの確認

**主要な処理内容**：
1. オブジェクトファイル/アーカイブの読み込み
2. シンボルテーブルの抽出
3. シンボル情報のフィルタリング/ソート
4. 指定フォーマットでの出力（bsd/sysv/posix/darwin）

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

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

## 関連画面

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

## 機能種別

バイナリ解析ツール / シンボルテーブル表示

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| input files | string[] | No | 入力ファイル（デフォルト: a.out） | ファイル存在確認 |
| -a/--debug-syms | flag | No | デバッグシンボルを含める | - |
| -g/--extern-only | flag | No | 外部シンボルのみ | - |
| -u/--undefined-only | flag | No | 未定義シンボルのみ | - |
| -U/--defined-only | flag | No | 定義済みシンボルのみ | - |
| -p/--no-sort | flag | No | ソートしない | - |
| -n/--numeric-sort | flag | No | アドレス順ソート | - |
| -S/--print-size | flag | No | シンボルサイズを表示 | - |
| -r/--reverse-sort | flag | No | 逆順ソート | - |
| --size-sort | flag | No | サイズ順ソート | - |
| --demangle | flag | No | シンボル名をデマングル | - |
| -f/--format | enum | No | 出力形式（bsd/sysv/posix/darwin） | - |
| -A/--print-file-name | flag | No | ファイル名を各行に表示 | - |
| --radix | enum | No | アドレス基数（d/o/x） | - |

### 入力データソース

- オブジェクトファイル（ELF、COFF、MachO、Wasm、XCOFF）
- ビットコードファイル（.bc）
- アーカイブファイル（.a）
- ユニバーサルバイナリ（MachO）
- TAPIファイル

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| アドレス | hex/oct/dec | シンボルのアドレス |
| サイズ | hex/oct/dec | シンボルのサイズ（オプション） |
| タイプ | char | シンボルタイプ（T/U/D/B等） |
| 名前 | string | シンボル名 |

### 出力先

- 標準出力

## 処理フロー

### 処理シーケンス

```
1. 初期化
   └─ コマンドライン引数解析（OptTable使用）
   └─ ターゲット初期化

2. 各入力ファイルの処理
   └─ createBinary()でバイナリ読み込み
   └─ フォーマット判定

3. シンボル抽出
   └─ SymbolicFile::symbols()からシンボル取得
   └─ フラグに応じたフィルタリング

4. シンボル処理
   └─ NMSymbol構造体に変換
   └─ アドレス/サイズ/タイプ取得
   └─ デマングル（オプション）

5. ソートと出力
   └─ 指定順序でソート
   └─ 指定フォーマットで出力
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[コマンドライン解析]
    B --> C{入力ファイル指定?}
    C -->|No| D[a.outをデフォルト]
    C -->|Yes| E[入力ファイルループ]
    D --> E
    E --> F[createBinary]
    F --> G{ファイルタイプ?}
    G -->|Archive| H[アーカイブ処理]
    G -->|MachOUniversal| I[アーキテクチャ選択]
    G -->|ObjectFile| J[オブジェクト処理]
    G -->|IRObject| K[IR処理]
    H --> L[シンボル抽出]
    I --> L
    J --> L
    K --> L
    L --> M[フィルタリング]
    M --> N[ソート]
    N --> O{出力形式?}
    O -->|bsd| P[BSD形式出力]
    O -->|sysv| Q[SYSV形式出力]
    O -->|posix| R[POSIX形式出力]
    O -->|darwin| S[darwin形式出力]
    P --> T[次のファイル]
    Q --> T
    R --> T
    S --> T
    T --> E
    E -->|完了| U[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | GNU nm互換 | GNU nmのフラグと類似動作 | 常時 |
| BR-002 | デフォルトファイル | 入力未指定時はa.out | 入力なし時 |
| BR-003 | シンボルタイプ文字 | T/U/D/B等の標準文字を使用 | 常時 |

### 計算ロジック

シンボルタイプは以下のルールで決定：
- T: テキスト（コード）セクション
- U: 未定義
- D: データセクション
- B: BSSセクション
- 小文字: ローカルシンボル

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 1 | File Error | ファイル読み込み失敗 | ファイル確認 |
| 1 | Format Error | 未サポートフォーマット | フォーマット確認 |
| 警告 | Warning | 軽微な問題 | 処理継続 |

### リトライ仕様

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

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

該当なし

## パフォーマンス要件

- 大規模バイナリでも効率的に処理
- シンボル数に応じたソート時間

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

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

## 備考

- MachO固有オプション（--add-dyldinfo等）
- XCOFF固有オプション（--no-rsrc）
- 行番号表示（-l）はllvm-symbolizerと連携

---

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

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

### 推奨読解順序

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

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

**主要処理フロー**:
- **60-93行目**: NmOptTable - オプションテーブル定義
- **95-135行目**: グローバル設定変数
- **218-289行目**: NMSymbol構造体 - シンボル情報保持
- **293-行目以降**: シンボル処理関数群

**読解のコツ**: NMSymbol構造体がシンボル情報のコアデータ構造。shouldPrint()メソッドでフィルタリングロジックを理解できる。

#### Step 2: NMSymbol構造体を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | llvm-nm.cpp | `llvm/tools/llvm-nm/llvm-nm.cpp` | NMSymbol構造体 |

**主要処理フロー**:
- **218-228行目**: メンバ変数定義（Address、Size、TypeChar、Name等）
- **240-245行目**: isDefined()メソッド
- **247-256行目**: initializeFlags()メソッド
- **258-268行目**: shouldPrint()メソッド - フィルタリングロジック
- **271-288行目**: 比較演算子 - ソート順序の定義

#### Step 3: シンボル出力形式を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | llvm-nm.cpp | `llvm/tools/llvm-nm/llvm-nm.cpp` | 出力関数群 |

**主要処理フロー**:
- darwinPrintSymbol() - darwin形式出力
- その他のprintXXX関数 - bsd/sysv/posix形式

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

```
llvm_nm_main()
    │
    ├─ NmOptTable.parseArgs()
    │
    └─ for each InputFilename
           │
           ├─ createBinary()
           │
           └─ switch(BinaryType)
                  │
                  ├─ Archive
                  │      └─ dumpArchive()
                  │
                  ├─ MachOUniversalBinary
                  │      └─ dumpMachOUniversal()
                  │
                  ├─ TapiUniversal
                  │      └─ dumpTapiUniversal()
                  │
                  └─ SymbolicFile
                         └─ dumpSymbolicFile()
                                │
                                └─ dumpSymbolNamesFromObject()
                                       │
                                       ├─ symbols()
                                       ├─ NMSymbol作成
                                       ├─ フィルタリング
                                       ├─ ソート
                                       └─ 出力
```

### データフロー図

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

オブジェクト/アーカイブ ────────▶ createBinary()
                                   │
                                   ▼
                           SymbolicFile::symbols()
                                   │
                                   ▼
                           NMSymbol作成
                                   │
                                   ▼
                           shouldPrint()でフィルタリング
                                   │
                                   ▼
                           std::sort()でソート
                                   │
                ┌──────────────────┼──────────────────┐
                ▼                  ▼                  ▼
          BSD形式          SYSV形式          POSIX形式
                │                  │                  │
                └──────────────────┼──────────────────┘
                                   ▼
                           stdout ──────────────────▶ シンボル一覧
```

### 関連ファイル一覧

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