# 機能設計書 31-llvm-objcopy

## 概要

本ドキュメントは、LLVM llvm-objcopyツールの機能設計を記述する。llvm-objcopyは、オブジェクトファイルのコピーと変換を行うユーティリティであり、GNU objcopyの互換ツールとして機能する。

### 本機能の処理概要

llvm-objcopyは、オブジェクトファイルを読み込み、様々な変換操作を適用した後、新しいオブジェクトファイルまたはバイナリ形式で出力するツールである。

**業務上の目的・背景**：ソフトウェア開発において、オブジェクトファイルの加工は頻繁に必要となる作業である。デバッグシンボルの削除によるバイナリサイズの削減、セクションの追加・削除・変更、シンボル操作、フォーマット変換など、ビルドプロセスやリリースパイプラインで必要とされる様々なバイナリ操作を一元的に提供する。特にクロスプラットフォーム開発やCI/CDパイプラインにおいて、GNU binutilsに依存せずLLVMツールチェインのみで完結できる利点がある。

**機能の利用シーン**：リリースビルドでのシンボル削除、組み込み開発でのバイナリフォーマット変換（ELF to Binary/IHex/SREC）、デバッグ情報の分離（split-dwarf）、オブジェクトファイルへのカスタムセクション追加、セクションフラグやアライメントの変更などで利用される。

**主要な処理内容**：
1. コマンドライン引数の解析とツール種別の判定（objcopy/strip/install-name-tool/bitcode-strip）
2. 入力ファイルの読み込み（Binary/IHex/ELF/COFF/MachO/Wasm形式対応）
3. 設定に基づくオブジェクト変換処理の実行
4. 出力ファイルの生成（各種フォーマット対応）
5. パーミッション・タイムスタンプの保持処理

**関連システム・外部連携**：LLVM ObjCopyライブラリ（llvm/lib/ObjCopy/）を使用。ELF/COFF/MachO/Wasm各形式のオブジェクトコピー機能を利用する。

**権限による制御**：ファイルシステムの読み書き権限に依存。--preserve-datesオプションでオリジナルファイルのタイムスタンプを保持可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | CLI | 主画面 | コマンドライン実行による全機能の制御 |

## 機能種別

バイナリ変換処理 / ファイル操作

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| input | string | Yes | 入力ファイル名 | ファイル存在チェック |
| output | string | No | 出力ファイル名 | 省略時は入力ファイルと同じ |
| --input-target/-I | string | No | 入力フォーマット指定 | binary/ihex/elf32-*/elf64-* |
| --output-target/-O | string | No | 出力フォーマット指定 | binary/ihex/srec/elf32-*/elf64-* |
| --strip-debug/-g | flag | No | デバッグセクション削除 | - |
| --strip-all/-S | flag | No | 非必須シンボル全削除 | - |
| --strip-unneeded | flag | No | 未使用シンボル削除 | - |
| --add-section | string | No | セクション追加 | section=file形式 |
| --remove-section/-R | string | No | セクション削除 | セクション名パターン |
| --keep-section | string | No | セクション保持 | セクション名パターン |
| --rename-section | string | No | セクション名変更 | old=new形式 |
| --add-symbol | string | No | シンボル追加 | name=[section:]value[,flags] |
| --strip-symbol/-N | string | No | シンボル削除 | シンボル名パターン |
| --keep-symbol/-K | string | No | シンボル保持 | シンボル名パターン |
| --redefine-sym | string | No | シンボル名変更 | old=new形式 |
| --split-dwo | string | No | DWO分割出力先 | ファイルパス |
| --add-gnu-debuglink | string | No | デバッグリンク追加 | デバッグファイルパス |
| --compress-debug-sections | string | No | デバッグセクション圧縮 | zlib/zstd |
| --decompress-debug-sections | flag | No | デバッグセクション展開 | - |
| --preserve-dates/-p | flag | No | タイムスタンプ保持 | - |
| --regex | flag | No | 正規表現マッチング有効化 | - |
| --wildcard/-w | flag | No | ワイルドカードマッチング有効化 | - |

### 入力データソース

- 入力オブジェクトファイル（ELF/COFF/MachO/Wasm形式）
- 入力バイナリファイル（--input-target=binary指定時）
- 入力Intel HEXファイル（--input-target=ihex指定時）
- アーカイブファイル（.a）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 出力オブジェクトファイル | binary | 変換後のオブジェクトファイル |
| DWOファイル | binary | --split-dwo指定時の分離デバッグ情報 |
| ダンプセクション | binary | --dump-section指定時のセクションデータ |

### 出力先

- 出力オブジェクトファイル（指定パスまたは標準出力）
- 分離DWOファイル（--split-dwo指定時）
- 抽出セクションファイル（--dump-section指定時）

## 処理フロー

### 処理シーケンス

```
1. コマンドライン引数の展開
   └─ レスポンスファイル（@file）の展開処理
2. ツール種別の判定
   └─ 実行ファイル名からobjcopy/strip/install-name-tool/bitcode-stripを判定
3. オプション解析
   └─ 各ツール専用のオプションパーサーで解析
4. 入力ファイルの読み込み
   └─ フォーマット自動検出またはユーザー指定フォーマットで読み込み
5. 各ConfigManagerに対して変換処理を実行
   └─ executeObjcopy()でオブジェクト変換を実行
6. 出力ファイルの生成
   └─ 指定フォーマットでファイル出力
7. パーミッション・タイムスタンプの処理
   └─ --preserve-dates指定時にオリジナルの日時を復元
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[引数展開]
    B --> C{ツール種別判定}
    C -->|objcopy| D[parseObjcopyOptions]
    C -->|strip| E[parseStripOptions]
    C -->|install-name-tool| F[parseInstallNameToolOptions]
    C -->|bitcode-strip| G[parseBitcodeStripOptions]
    D --> H[ConfigManager生成]
    E --> H
    F --> H
    G --> H
    H --> I{入力フォーマット}
    I -->|Binary| J[executeObjcopyOnRawBinary]
    I -->|IHex| K[executeObjcopyOnIHex]
    I -->|Archive| L[executeObjcopyOnArchive]
    I -->|Object| M[executeObjcopyOnBinary]
    J --> N[出力生成]
    K --> N
    L --> N
    M --> N
    N --> O[パーミッション適用]
    O --> P[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | フォーマット自動検出 | 入力フォーマット未指定時はマジックナンバーから自動判定 | --input-target未指定時 |
| BR-02 | 出力フォーマット継承 | 出力フォーマット未指定時は入力と同じフォーマット使用 | --output-target未指定時 |
| BR-03 | シンボルマッチング | --regex指定時は正規表現、--wildcard指定時はワイルドカード、未指定時はリテラルマッチ | シンボル操作オプション使用時 |
| BR-04 | セクションマッチング | セクション名指定は常にワイルドカードまたは正規表現パターン | セクション操作オプション使用時 |
| BR-05 | DWO分割 | --split-dwo指定時は.dwoセクションを別ファイルに出力し、元ファイルからは削除 | --split-dwo指定時 |

### 計算ロジック

- CRC32計算: --add-gnu-debuglink使用時にデバッグファイルのCRC32を計算してリンク情報に埋め込む

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

該当なし（ファイル操作のみ）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 1 | 引数エラー | 不正なオプション指定 | エラーメッセージ出力して終了 |
| 1 | ファイルエラー | 入力ファイルが存在しない | ファイル名とエラーを出力して終了 |
| 1 | フォーマットエラー | サポートされていないファイル形式 | エラーメッセージ出力して終了 |
| 1 | 変換エラー | オブジェクト変換中のエラー | エラーメッセージ出力して終了 |

### リトライ仕様

リトライ処理なし（即時終了）

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

該当なし（単一ファイル操作）

## パフォーマンス要件

特に規定なし。入力ファイルサイズに比例した処理時間。

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

- 入力ファイルの検証（マジックナンバー確認）
- 出力ファイルパスの正規化
- シンボリックリンク追従時の注意

## 備考

- GNU objcopyとの互換性を重視した実装
- 複数の実行名（llvm-objcopy/llvm-strip/llvm-install-name-tool/llvm-bitcode-strip）で異なる動作

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | ObjcopyOptions.h | `llvm/tools/llvm-objcopy/ObjcopyOptions.h` | DriverConfig, ConfigManager構造体の定義 |
| 1-2 | CommonConfig.h | `llvm/include/llvm/ObjCopy/CommonConfig.h` | CommonConfig構造体の定義と各設定項目 |

**読解のコツ**: ConfigManagerがCommonConfig, ELFConfig, COFFConfig, MachOConfigを集約している点を理解する。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | llvm-objcopy.cpp | `llvm/tools/llvm-objcopy/llvm-objcopy.cpp` | llvm_objcopy_main関数がエントリーポイント |

**主要処理フロー**:
1. **214-228行目**: main関数開始、引数展開処理
2. **230-237行目**: getDriverConfig()でツール種別判定とオプション解析
3. **239-247行目**: 各ConfigManagerに対してexecuteObjcopy()を実行

#### Step 3: オプション解析を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | ObjcopyOptions.cpp | `llvm/tools/llvm-objcopy/ObjcopyOptions.cpp` | 各ツール向けのオプション解析処理 |

**主要処理フロー**:
- **60-84行目**: getDriverConfig()でツール名からパーサーを選択
- **698-1304行目**: parseObjcopyOptions()でobjcopy用オプション解析
- **1309-1451行目**: parseInstallNameToolOptions()
- **1453-1520行目**: parseBitcodeStripOptions()
- **1522-1672行目**: parseStripOptions()

#### Step 4: 変換処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | llvm-objcopy.cpp | `llvm/tools/llvm-objcopy/llvm-objcopy.cpp` | executeObjcopy関数の処理フロー |

**主要処理フロー**:
- **126-212行目**: executeObjcopy()で入力フォーマットに応じた処理分岐
- **88-97行目**: executeObjcopyOnIHex()でIntel HEX処理
- **101-121行目**: executeObjcopyOnRawBinary()でバイナリ処理
- **165-175行目**: アーカイブ/バイナリの処理分岐

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

```
llvm_objcopy_main()
    │
    ├─ getDriverConfig()
    │      ├─ parseObjcopyOptions()
    │      ├─ parseStripOptions()
    │      ├─ parseInstallNameToolOptions()
    │      └─ parseBitcodeStripOptions()
    │
    └─ executeObjcopy()
           ├─ FilePermissionsApplier::create()
           ├─ executeObjcopyOnRawBinary()
           │      └─ elf::executeObjcopyOnRawBinary()
           ├─ executeObjcopyOnIHex()
           │      └─ elf::executeObjcopyOnIHex()
           ├─ executeObjcopyOnArchive()
           └─ executeObjcopyOnBinary()
                  ├─ elf::executeObjcopyOnBinary()
                  ├─ coff::executeObjcopyOnBinary()
                  ├─ macho::executeObjcopyOnBinary()
                  └─ wasm::executeObjcopyOnBinary()
```

### データフロー図

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

入力ファイル ──────▶ MemoryBuffer読込 ──────▶ Binary生成
     │                     │
     │                     ▼
オプション ──────▶ ConfigManager ──────▶ 変換処理
     │                     │
     │                     ▼
     └────────────▶ writeToOutput() ──────▶ 出力ファイル
                           │
                           ▼
                   FilePermissionsApplier ──────▶ パーミッション設定
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| llvm-objcopy.cpp | `llvm/tools/llvm-objcopy/llvm-objcopy.cpp` | ソース | メイン処理、エントリーポイント |
| ObjcopyOptions.cpp | `llvm/tools/llvm-objcopy/ObjcopyOptions.cpp` | ソース | オプション解析処理 |
| ObjcopyOptions.h | `llvm/tools/llvm-objcopy/ObjcopyOptions.h` | ヘッダ | オプション関連の型定義 |
| ObjcopyOpts.td | `llvm/tools/llvm-objcopy/ObjcopyOpts.td` | TableGen | objcopyオプション定義 |
| StripOpts.td | `llvm/tools/llvm-objcopy/StripOpts.td` | TableGen | stripオプション定義 |
| InstallNameToolOpts.td | `llvm/tools/llvm-objcopy/InstallNameToolOpts.td` | TableGen | install-name-toolオプション定義 |
| BitcodeStripOpts.td | `llvm/tools/llvm-objcopy/BitcodeStripOpts.td` | TableGen | bitcode-stripオプション定義 |
| ObjCopy.h | `llvm/include/llvm/ObjCopy/ObjCopy.h` | ヘッダ | ObjCopyライブラリAPI |
| CommonConfig.h | `llvm/include/llvm/ObjCopy/CommonConfig.h` | ヘッダ | 共通設定構造体定義 |
| ELFObjcopy.h | `llvm/include/llvm/ObjCopy/ELF/ELFObjcopy.h` | ヘッダ | ELF用ObjCopy API |
| COFFObjcopy.h | `llvm/include/llvm/ObjCopy/COFF/COFFObjcopy.h` | ヘッダ | COFF用ObjCopy API |
| MachOObjcopy.h | `llvm/include/llvm/ObjCopy/MachO/MachOObjcopy.h` | ヘッダ | MachO用ObjCopy API |
| WasmObjcopy.h | `llvm/include/llvm/ObjCopy/wasm/WasmObjcopy.h` | ヘッダ | Wasm用ObjCopy API |
