# 機能設計書 53-ildasm

## 概要

本ドキュメントは、.NETランタイムにおけるildasm（IL逆アセンブラ）の機能設計を記述する。ildasmは、.NETアセンブリ（DLLまたはEXE）を逆アセンブルし、CIL（Common Intermediate Language）ソースコードを出力するコマンドラインツールである。

### 本機能の処理概要

ildasmは、PE（Portable Executable）ファイル内のCLRメタデータとILバイトコードを解析し、人間が読めるテキスト形式のILソースコード（.ilファイル）を生成する機能である。

**業務上の目的・背景**：.NETアプリケーションの開発・デバッグ・リバースエンジニアリングにおいて、コンパイルされたアセンブリの内部構造を理解する必要がある場面が存在する。ildasmは、アセンブリの検査、デバッグ、学習目的でのIL解析に使用される。

**機能の利用シーン**：
- アセンブリ内部構造の検査・分析
- コンパイラが生成したILコードの確認
- 問題のあるアセンブリのデバッグ
- ilasmによる再アセンブルのためのソース生成
- メタデータ情報の詳細表示

**主要な処理内容**：
1. PEファイルのロードとCORヘッダの解析
2. CLRメタデータテーブルの読み取り（IMDInternalImport使用）
3. 型、メソッド、フィールド等の列挙
4. ILバイトコードのデコードと命令テキスト変換
5. デバッグ情報（PDB）との関連付け（オプション）
6. テキスト形式またはHTML/RTFでの出力

**関連システム・外部連携**：
- PEローダー（CEELoad）によるPEファイル解析
- IMDInternalImportによるメタデータ読み取り
- ISymUnmanagedReaderによるデバッグシンボル読み取り

**権限による制御**：特別な権限制御は行わない。入力ファイルの読み取り権限が必要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | ildasmはCLIツールのため、直接的なUI関連はない |

## 機能種別

開発ツール / 逆アセンブラ

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| inputFile | string | Yes | 入力アセンブリファイルパス | 存在するPE/DLL/EXEファイル |
| /output | string | No | 出力ファイルパス | 書き込み可能なパス |
| /text | flag | No | コンソールへのテキスト出力 | - |
| /html | flag | No | HTML形式で出力 | - |
| /rtf | flag | No | RTF形式で出力 | - |
| /bytes | flag | No | ILバイト列も表示 | - |
| /source | flag | No | ソースコード行を表示 | - |
| /tokens | flag | No | メタデータトークンを表示 | - |
| /header | flag | No | PEヘッダ情報を表示 | - |
| /stats | flag | No | 統計情報を表示 | - |
| /item | string | No | 特定の型・メソッドのみ出力 | 有効な型/メソッド名 |
| /pubonly | flag | No | public要素のみ出力 | - |
| /noil | flag | No | ILコード出力を抑制 | - |
| /project | flag | No | WinMDを.NET形式に変換 | - |

### 入力データソース

- .NETアセンブリファイル（.dll, .exe）
- デバッグシンボルファイル（.pdb）（オプション）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| ilSource | text file | 逆アセンブルされたILソースコード |
| metadata | text | メタデータ情報（オプション） |
| statistics | text | アセンブリ統計情報（オプション） |

### 出力形式（ILソース例）

```
.assembly extern mscorlib
{
  .publickeytoken = (B7 7A 5C 56 19 34 E0 89)
  .ver 4:0:0:0
}
.assembly MyAssembly
{
  .ver 1:0:0:0
}
.module MyModule.dll

.class public auto ansi MyClass
       extends [mscorlib]System.Object
{
  .method public hidebysig static void Main() cil managed
  {
    .entrypoint
    .maxstack 1
    IL_0000: ldstr      "Hello, World!"
    IL_0005: call       void [mscorlib]System.Console::WriteLine(string)
    IL_000a: ret
  }
}
```

## 処理フロー

### 処理シーケンス

```
1. PEファイルロード
   └─ PELoader::open() でファイルをメモリマップ
   └─ CORヘッダの取得

2. メタデータ読み取り
   └─ IMDInternalImportの取得
   └─ IMetaDataImport2の取得

3. アセンブリ情報出力
   └─ DumpManifest() でアセンブリ参照・モジュール情報

4. 型列挙と出力
   └─ 全TypeDef/TypeRefの列挙
   └─ DumpClass() で各型の詳細を出力

5. メソッドの逆アセンブル
   └─ DumpMethod() でメソッド定義
   └─ Disassemble() でILコード変換
   └─ DecodeOpcode() で各命令をデコード

6. 追加情報出力
   └─ カスタム属性
   └─ 例外ハンドラ情報
   └─ デバッグ情報（利用可能な場合）
```

### フローチャート

```mermaid
flowchart TD
    A[PEファイル入力] --> B[PELoader.open]
    B --> C[CORヘッダ解析]
    C --> D[IMDInternalImport取得]
    D --> E[アセンブリ情報出力]
    E --> F[TypeDef列挙]
    F --> G{次のTypeDefあり?}
    G -->|Yes| H[DumpClass]
    H --> I[メソッド列挙]
    I --> J{次のMethodあり?}
    J -->|Yes| K[DumpMethod]
    K --> L[Disassemble]
    L --> J
    J -->|No| G
    G -->|No| M[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-53-1 | ラウンドトリップ互換性 | 出力されたILはilasmで再アセンブル可能であること | 標準出力時 |
| BR-53-2 | トークン表示 | /tokensオプション時、各参照にメタデータトークンを付加 | /tokens指定時 |
| BR-53-3 | 可視性フィルタ | /pubonlyオプション時、public要素のみ出力 | /pubonly指定時 |
| BR-53-4 | WinMD変換 | /projectオプション時、WinRT型を.NET型に変換表示 | /project指定、.winmdファイル時 |

### IL命令デコード

IL命令は以下の形式でデコードされる：
- `IL_XXXX:` - オフセットラベル
- `opcode` - 命令名（小文字）
- `operand` - オペランド（トークン、定数等）

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

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

ildasmはデータベース操作を行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| Invalid PE | 不正なPE形式 | 入力ファイルがPE形式でない | 正しいアセンブリを指定 |
| No CLR Header | CLRヘッダなし | マネージドアセンブリでない | .NETアセンブリを指定 |
| Metadata Error | メタデータ読取エラー | 破損したメタデータ | アセンブリを再ビルド |
| Symbol Load Error | シンボル読込エラー | PDBファイルが見つからないまたは破損 | PDBを再生成または無視 |

### グローバル変数による状態管理

ildasmは多数のグローバル変数を使用してオプションと状態を管理する（dasm.cpp参照）：
- `g_fDumpIL` - ILコードを出力するか
- `g_fDumpHeader` - ヘッダを出力するか
- `g_fShowBytes` - バイト列を表示するか
- `g_fShowSource` - ソース行を表示するか

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

ildasmはトランザクション処理を行わない。読み取り専用の操作のみ。

## パフォーマンス要件

- 一般的なアセンブリ（数MB）は数秒以内に処理完了
- 大規模アセンブリでもメモリ使用量は入力サイズの数倍程度

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

- 悪意のあるアセンブリの解析時にバッファオーバーフローに注意
- 極端に大きい型パラメータや深いネストへの対策（SZSTRING_SIZE制限）

## 備考

本実装はC++で記述されたレガシーツールである。コード内には多数のグローバル変数と固定サイズバッファが使用されており、極端な入力に対してはバッファオーバーランのリスクがある。将来的にはマネージド実装への移行が検討されている。

---

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

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

### 推奨読解順序

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

まず、ildasmで使用される主要なデータ構造とグローバル変数を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | dis.h | `src/coreclr/ildasm/dis.h` | 主要関数宣言、定数定義、構造体 |
| 1-2 | ceeload.h | `src/coreclr/ildasm/ceeload.h` | PEローダークラス定義 |
| 1-3 | dynamicarray.h | `src/coreclr/ildasm/dynamicarray.h` | 動的配列テンプレート |
| 1-4 | dasm_sz.h | `src/coreclr/ildasm/dasm_sz.h` | サイズ計算ユーティリティ |

**読解のコツ**:
- **6-12行目(dis.h)**: MAX_CLASSNAME_LENGTH等の定数がバッファサイズを規定
- **14-18行目(dis.h)**: MODE_*定数がダンプモードを定義
- **23-31行目(dis.h)**: LineCodeDescrがデバッグ行情報を表現

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

ファイル処理の開始点を特定する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | dasm.cpp | `src/coreclr/ildasm/dasm.cpp` | メイン処理、グローバル変数定義 |
| 2-2 | windasm.cpp | `src/coreclr/ildasm/windasm.cpp` | Windows固有エントリポイント |

**主要処理フロー**:
- **50-72行目(dasm.cpp)**: グローバル変数の定義（g_pImport, g_pPELoader等）
- **73-102行目(dasm.cpp)**: オプションフラグの定義
- **150行目以降(dasm.cpp)**: `DisplayFile`関数が主要処理

#### Step 3: メタデータ読み取りを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | ceeload.cpp | `src/coreclr/ildasm/ceeload.cpp` | PEファイルのロードと解析 |
| 3-2 | dman.cpp | `src/coreclr/ildasm/dman.cpp` | マニフェスト・アセンブリ情報 |

**主要処理フロー**:
- PELoader::open() でファイルをオープン
- getCORHeader() でCLRヘッダを取得
- IMDInternalImportを取得してメタデータにアクセス

#### Step 4: IL命令デコードを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | dis.cpp | `src/coreclr/ildasm/dis.cpp` | IL命令のデコード処理 |
| 4-2 | dasm_mi.cpp | `src/coreclr/ildasm/dasm_mi.cpp` | メソッド実装情報 |

**主要処理フロー**:
- **Disassemble()**: メソッドILの逆アセンブル
- **DecodeOpcode()**: 各オペコードのデコード
- **dumpEHInfo()**: 例外ハンドラ情報の出力

#### Step 5: 型フォーマットを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | dasm_formattype.cpp | `src/coreclr/ildasm/dasm_formattype.cpp` | 型シグネチャのフォーマット |
| 5-2 | formattype.h | `src/coreclr/inc/formattype.h` | 型フォーマットユーティリティ |

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

```
main() / WinMain()
    │
    ├─ ParseCommandLine()
    │
    ├─ DumpFile()
    │      │
    │      ├─ PELoader::open()
    │      │      └─ メモリマップ
    │      │
    │      ├─ GetImport() → IMDInternalImport
    │      │
    │      ├─ DumpManifest()
    │      │      ├─ DumpAssembly()
    │      │      ├─ DumpAssemblyRefs()
    │      │      └─ DumpModuleRefs()
    │      │
    │      ├─ EnumTypeDefs()
    │      │
    │      └─ DumpClass() [各TypeDef]
    │             │
    │             ├─ DumpCustomAttributes()
    │             │
    │             ├─ DumpField() [各フィールド]
    │             │
    │             ├─ DumpMethod() [各メソッド]
    │             │      │
    │             │      ├─ DumpMethodSignature()
    │             │      │
    │             │      └─ Disassemble()
    │             │             │
    │             │             ├─ DecodeOpcode()
    │             │             │
    │             │             └─ PrettyPrintToken()
    │             │
    │             ├─ DumpEvent() [各イベント]
    │             │
    │             └─ DumpProp() [各プロパティ]
    │
    └─ Cleanup()
```

### データフロー図

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

PEファイル           ───▶ PELoader              ───▶ メモリマップ
  (.dll/.exe)              (ファイルロード)

メモリマップ         ───▶ IMDInternalImport     ───▶ メタデータテーブル
                          (メタデータ解析)

メタデータテーブル   ───▶ DumpClass             ───▶ 型定義テキスト
                          (型出力)

ILバイトコード       ───▶ Disassemble           ───▶ IL命令テキスト
                          (命令デコード)

PDBファイル          ───▶ ISymUnmanagedReader   ───▶ ソース行情報
  (オプション)            (シンボル読取)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| dasm.cpp | `src/coreclr/ildasm/dasm.cpp` | ソース | メイン処理、グローバル変数 |
| dis.cpp | `src/coreclr/ildasm/dis.cpp` | ソース | IL命令デコード |
| dis.h | `src/coreclr/ildasm/dis.h` | ヘッダ | 関数宣言、定数定義 |
| ceeload.cpp | `src/coreclr/ildasm/ceeload.cpp` | ソース | PEファイルローダー |
| ceeload.h | `src/coreclr/ildasm/ceeload.h` | ヘッダ | PELoaderクラス定義 |
| dman.cpp | `src/coreclr/ildasm/dman.cpp` | ソース | マニフェスト処理 |
| dasm_formattype.cpp | `src/coreclr/ildasm/dasm_formattype.cpp` | ソース | 型フォーマット |
| dasm_mi.cpp | `src/coreclr/ildasm/dasm_mi.cpp` | ソース | メソッド実装情報 |
| dasm_sz.cpp | `src/coreclr/ildasm/dasm_sz.cpp` | ソース | サイズ計算 |
| dasm_sz.h | `src/coreclr/ildasm/dasm_sz.h` | ヘッダ | サイズ計算宣言 |
| dres.cpp | `src/coreclr/ildasm/dres.cpp` | ソース | リソース処理 |
| dynamicarray.h | `src/coreclr/ildasm/dynamicarray.h` | ヘッダ | 動的配列テンプレート |
| windasm.cpp | `src/coreclr/ildasm/windasm.cpp` | ソース | Windowsエントリポイント |
| ildasmpch.h | `src/coreclr/ildasm/ildasmpch.h` | ヘッダ | プリコンパイルヘッダ |
| ildasmpch.cpp | `src/coreclr/ildasm/ildasmpch.cpp` | ソース | プリコンパイルヘッダ |
| resource.h | `src/coreclr/ildasm/resource.h` | ヘッダ | リソースID定義 |
| dasmenum.hpp | `src/coreclr/ildasm/dasmenum.hpp` | ヘッダ | 列挙型定義 |
