# 機能設計書 23-バイナリローダ

## 概要

本ドキュメントは、mrubyランタイムにおけるバイナリローダ機能の設計を記述する。コンパイル済みmrubyバイナリ（.mrb）ファイルの読み込みとirepへの変換を行う。

### 本機能の処理概要

バイナリローダは、mrbcコマンドやコンパイラで生成されたRite Binary Format（.mrbファイル）を読み込み、mrubyランタイムで実行可能なirep（命令列表現）に変換する機能である。セクション構造に基づいてIREPデータ、デバッグ情報、ローカル変数情報を順次パースする。

**業務上の目的・背景**：mrubyはコンパイル済みバイナリを読み込んで実行する方式をサポートしており、事前コンパイルによる起動時間の短縮やソースコード秘匿を実現する。組み込みシステムではROMに配置したバイナリを直接実行するユースケースもある。

**機能の利用シーン**：mrubyコマンドでの.mrbファイル実行、C APIからのirep読み込み（mrb_load_irep）、静的データとしてリンクされたバイナリの読み込み、ファイルからのバイナリ読み込み。

**主要な処理内容**：
1. バイナリヘッダの検証（マジックナンバー、バージョン確認）
2. IREPセクションの読み込み（命令列、プール、シンボル）
3. デバッグセクションの読み込み（ファイル名テーブル、行番号情報）
4. ローカル変数セクションの読み込み
5. メモリバッファ/ファイルからの読み込み
6. 読み込んだirepの実行

**関連システム・外部連携**：コンパイラ（mruby-compiler gem）やmrbcコマンドで生成されたバイナリを読み込む。仮想マシン（VM）のmrb_top_runで実行する。

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 本機能はC APIおよびCLIツール経由で使用され、画面は関連しない |

## 機能種別

データ連携（バイナリファイルの読み込みとデシリアライズ）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| mrb | mrb_state* | Yes | mrubyインタプリタ状態 | NULLでないこと |
| bin | const uint8_t* | Yes（メモリ読み込み時） | バイナリデータへのポインタ | RITE_BINARY_IDENT確認 |
| buf | const void* | Yes（バッファ読み込み時） | バッファへのポインタ | - |
| bufsize | size_t | Yes（バッファ読み込み時） | バッファサイズ | ヘッダサイズ以上 |
| fp | FILE* | Yes（ファイル読み込み時） | ファイルポインタ | NULLでないこと |
| c | mrb_ccontext* | No | コンパイラコンテキスト | - |

### 入力データソース

- .mrbバイナリファイル（ファイルシステム）
- メモリ上のバイナリデータ（静的データ、ROMなど）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| irep | mrb_irep* | 読み込んだ命令列表現 |
| result | mrb_value | 実行結果（mrb_load_irep系） |
| proc | struct RProc* | 生成されたProcオブジェクト（mrb_load_proc） |

### 出力先

呼び出し元への戻り値

## 処理フロー

### 処理シーケンス

```
1. バイナリヘッダ読み込み（read_binary_header）
   └─ マジックナンバー "RITE" 確認
   └─ メジャーバージョン一致確認
   └─ バイナリサイズ取得
2. セクション順次読み込み（read_irep）
   ├─ IREPセクション "IREP"
   │     └─ read_section_irep → read_irep_record
   │           ├─ nlocals, nregs, rlen読み込み
   │           ├─ ISEQ（命令列）読み込み
   │           ├─ POOLブロック読み込み
   │           ├─ SYMSブロック読み込み
   │           └─ 子irep再帰読み込み
   ├─ デバッグセクション "DBG\0"
   │     └─ read_section_debug
   └─ ローカル変数セクション "LVAR"
         └─ read_section_lv
3. 実行（load_irep）
   └─ mrb_top_run
```

### フローチャート

```mermaid
flowchart TD
    A[バイナリデータ入力] --> B[read_binary_header]
    B --> C{ヘッダ検証OK?}
    C -->|No| D[NULL返却]
    C -->|Yes| E[セクションループ]
    E --> F{セクション識別}
    F -->|IREP| G[read_section_irep]
    F -->|DBG| H[read_section_debug]
    F -->|LVAR| I[read_section_lv]
    F -->|END| J[完了]
    G --> E
    H --> E
    I --> E
    J --> K[load_irep/mrb_top_run]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | バージョン互換 | メジャーバージョンは完全一致、マイナーバージョンは下位互換 | read_binary_header |
| BR-02 | 静的データ最適化 | ROデータの場合iseqコピーを省略（MRB_ISEQ_NO_FREE） | FLAG_SRC_STATIC |
| BR-03 | シンボルインターン | 静的データはmrb_intern_static、mallocデータはmrb_intern | FLAG_SRC_MALLOC |

### 計算ロジック

- バイナリサイズはビッグエンディアンの4バイト整数
- POOLブロックの型識別: IREP_TT_INT32, IREP_TT_INT64, IREP_TT_FLOAT, IREP_TT_STR, IREP_TT_BIGINT

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| MRB_DUMP_INVALID_FILE_HEADER | ヘッダ不正 | マジックナンバー不一致/バージョン不一致 | 正しいバイナリを使用 |
| MRB_DUMP_READ_FAULT | 読み込み不足 | bufsize不足/fread失敗 | 十分なデータを提供 |
| MRB_DUMP_GENERAL_FAILURE | 一般エラー | データ破損等 | バイナリを再生成 |
| E_SCRIPT_ERROR | スクリプトエラー | irep load error | バイナリファイルの整合性を確認 |

### リトライ仕様

リトライは不要。

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

GCアリーナの保存・復帰（mrb_gc_arena_save/restore）により、読み込み途中のエラー時にメモリリークを防止する。

## パフォーマンス要件

- 静的データ（ROM）からの読み込み時はメモリコピーを最小化
- GCアリーナの保存・復帰で読み込み中のGC負荷を軽減

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

- バイナリデータのサイズ検証によりバッファオーバーフローを防止
- SIZE_ERROR_MULマクロによる乗算オーバーフローチェック

## 備考

- Rite Binary Format Version: "0400"
- セクション識別子: "IREP", "DBG\0", "LVAR", "END\0"
- MRB_NO_STDIOが定義されている場合、ファイル読み込み関数は無効化される

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | dump.h | `include/mruby/dump.h` | rite_binary_header構造体（72-79行目）、セクションヘッダ、エラーコード定義 |
| 1-2 | irep.h | `include/mruby/irep.h` | mrb_irep構造体の定義 |

**読解のコツ**: dump.hにはバイナリフォーマットの全定数が定義されている。bin_to_uint32等のインラインヘルパーも重要。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | load.c | `src/load.c` | mrb_load_irep（691-695行目）: 最も単純な公開API |
| 2-2 | load.c | `src/load.c` | mrb_load_irep_cxt（677-683行目）: コンテキスト付きロード |
| 2-3 | load.c | `src/load.c` | load_irep（664-675行目）: 実行まで行うコア関数 |

**主要処理フロー**:
1. **691-695行目**: mrb_load_irep → mrb_load_irep_cxt(cxt=NULL)
2. **677-683行目**: mrb_proc_read_irep → load_irep
3. **664-675行目**: load_irep → mrb_top_run

#### Step 3: バイナリ解析処理

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | load.c | `src/load.c` | read_binary_header（550-579行目）: ヘッダ検証 |
| 3-2 | load.c | `src/load.c` | read_irep（581-632行目）: セクションループ |
| 3-3 | load.c | `src/load.c` | read_irep_record_1（62-251行目）: 単一irep読み込み |
| 3-4 | load.c | `src/load.c` | read_irep_record（253-283行目）: 再帰的irep読み込み |

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

```
mrb_load_irep (公開API)
    │
    └─ mrb_load_irep_cxt
           │
           ├─ mrb_proc_read_irep
           │     └─ read_irep
           │           ├─ read_binary_header (ヘッダ検証)
           │           ├─ read_section_irep
           │           │     └─ read_irep_record (再帰)
           │           │           └─ read_irep_record_1
           │           ├─ read_section_debug
           │           │     └─ read_debug_record (再帰)
           │           └─ read_section_lv
           │                 └─ read_lv_record (再帰)
           │
           └─ load_irep
                  └─ mrb_top_run (VM実行)
```

### データフロー図

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

uint8_t[] (バイナリ) ───▶ read_binary_header   ───▶ バイナリサイズ
                           │
                      ───▶ read_section_irep    ───▶ mrb_irep*
                           │
                      ───▶ read_section_debug   ───▶ debug_info
                           │
                      ───▶ read_section_lv      ───▶ lv (ローカル変数名)
                           │
mrb_irep*            ───▶ load_irep             ───▶ mrb_value (実行結果)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| load.c | `src/load.c` | ソース | バイナリローダの実装本体 |
| dump.h | `include/mruby/dump.h` | ヘッダ | バイナリフォーマット定義・ヘルパー関数 |
| irep.h | `include/mruby/irep.h` | ヘッダ | irep構造体定義 |
| debug.h | `include/mruby/debug.h` | ヘッダ | デバッグ情報構造体定義 |
| endian.h | `include/mruby/endian.h` | ヘッダ | エンディアン判定 |
| dump.c | `src/dump.c` | ソース | バイナリダンパ（対となる出力機能） |
| vm.c | `src/vm.c` | ソース | mrb_top_run（読み込んだirepの実行） |
