# 機能設計書 94-libelf

## 概要

本ドキュメントは、FreeBSDのlibelfライブラリの機能設計を記述する。libelfはELF（Executable and Linkable Format）バイナリの解析・操作を行うライブラリであり、リンカ、デバッガ、オブジェクトファイル操作ツール等の基盤となる。

### 本機能の処理概要

libelfは、ELF形式のオブジェクトファイル、実行ファイル、共有ライブラリの読み取り・書き込み・解析を行うためのCライブラリである。ELFヘッダ、セクションヘッダ、プログラムヘッダ、シンボルテーブル等のELF構造体へのアクセスAPIを提供する。

**業務上の目的・背景**：FreeBSDのツールチェーン（リンカ、コンパイラ出力の解析、デバッグ情報の読み取り等）において、ELFバイナリの構造的な操作が必要である。libelfはこれらの要求に対し、プラットフォーム非依存のELFアクセスAPIを提供する。

**機能の利用シーン**：readelf/objdumpによるバイナリ解析、リンカ（ld）によるオブジェクト結合、strip/nmによるシンボル操作、elfdumpによるELFダンプ、カーネルモジュールのロード時のELF解析などで使用される。

**主要な処理内容**：
1. ELFファイルのオープン・クローズ（elf_begin/elf_end）
2. ELFヘッダの読み書き（gelf_getehdr/gelf_update_ehdr）
3. セクションの列挙・操作（elf_getscn/elf_newscn）
4. セクションデータの読み書き（elf_getdata/elf_newdata）
5. プログラムヘッダの読み書き（gelf_getphdr/gelf_update_phdr）
6. ar(1)アーカイブメンバーの操作
7. ELFバイトオーダー変換
8. 32bit/64bitクラスの透過的処理（GElf API）

**関連システム・外部連携**：elftoolchainプロジェクト、LLVM/Clangツールチェーン

**権限による制御**：ELFファイルへのアクセスはファイルシステムのパーミッションに依存する。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 画面機能マッピングに直接の関連画面なし |

## 機能種別

データ操作（バイナリ解析ライブラリ）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| Elf * | Elf * | Yes | ELFハンドル（elf_begin()で作成） | NULLチェック |
| Elf_Cmd | Elf_Cmd | Yes | 操作コマンド（ELF_C_READ, ELF_C_WRITE等） | 有効な列挙値 |
| int fd | int | Yes | ファイルデスクリプタ | 有効なfd |
| Elf_Scn * | Elf_Scn * | Yes（セクション操作時） | セクション記述子 | NULLチェック |

### 入力データソース

- ファイルデスクリプタ経由のELFファイル
- メモリマップ経由のELFデータ（elf_memory()）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| Elf * | Elf * | ELFハンドル |
| GElf_Ehdr | GElf_Ehdr | ELFヘッダ（クラス非依存） |
| GElf_Phdr | GElf_Phdr | プログラムヘッダ |
| GElf_Shdr | GElf_Shdr | セクションヘッダ |
| Elf_Data * | Elf_Data * | セクションデータ |
| Elf_Kind | Elf_Kind | ファイル種別（ELF_K_ELF, ELF_K_AR等） |

### 出力先

- 呼び出し元アプリケーションへの構造体返却
- elf_update()によるファイルへの書き戻し

## 処理フロー

### 処理シーケンス

```
1. バージョン設定（elf_version）
   └─ ライブラリバージョンの設定・確認
2. ELFハンドル作成（elf_begin / elf_memory）
   └─ ファイル/メモリからELF構造の読み取り
3. ヘッダ・セクション操作
   └─ gelf_getehdr, elf_getscn, elf_getdata等によるデータアクセス
4. データ変更（書き込みモード時）
   └─ gelf_update_*, elf_newscn, elf_newdata等によるデータ変更
5. ファイル更新（elf_update）
   └─ 変更内容のファイルへの書き戻し
6. ハンドル解放（elf_end）
   └─ リソース解放
```

### フローチャート

```mermaid
flowchart TD
    A[elf_version: バージョン設定] --> B[elf_begin: ハンドル作成]
    B --> C{elf_kind: 種別判定}
    C -->|ELF_K_ELF| D[gelf_getehdr: ヘッダ読み取り]
    C -->|ELF_K_AR| E[ar メンバー列挙]
    D --> F[elf_getscn: セクション列挙]
    F --> G[elf_getdata: データ読み取り]
    G --> H{変更あり?}
    H -->|Yes| I[elf_update: ファイル更新]
    H -->|No| J[elf_end: 解放]
    I --> J
    E --> J
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-94-1 | バージョン確認必須 | elf_begin()の前にelf_version(EV_CURRENT)を呼ぶ必要がある | 全API使用時 |
| BR-94-2 | GElf透過性 | GElf APIは32bit/64bit ELFを透過的に扱う | GElf_*関数使用時 |
| BR-94-3 | 参照カウント | elf_begin()で開いたハンドルはelf_end()で参照カウントをデクリメント | 常時 |
| BR-94-4 | arアーカイブ対応 | ar(1)アーカイブファイル内の個別ELFメンバーにアクセス可能 | ELF_K_ARの場合 |

### 計算ロジック

ELFハッシュ値の計算（elf_hash関数）: シンボル名からハッシュテーブルインデックスを計算するELF標準のハッシュアルゴリズム。

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

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| ELF_E_* | ライブラリエラー | 不正なELFファイル、APIの誤使用等 | elf_errmsg(elf_errno())でメッセージ取得 |
| NULL返却 | 操作失敗 | elf_begin失敗、elf_getscn該当なし等 | elf_errno()でエラー番号確認 |

### リトライ仕様

リトライ機構は組み込まれていない。

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

ELF書き込みは、elf_update(elf, ELF_C_WRITE)呼び出し時にまとめてファイルに書き出される。書き込み途中でエラーが発生した場合、ファイルが不完全な状態になる可能性がある。

## パフォーマンス要件

- 大容量ELFファイル（デバッグ情報を含むバイナリ等）の効率的な処理
- mmapによるファイルマッピングのサポート（LIBELF_F_RAWFILE_MMAP）

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

- 不正なELFファイルの読み込み時のバッファオーバーフロー対策
- ELFヘッダのフィールド値の範囲チェック
- setuid/setgidバイナリの解析時のセキュリティ

## 備考

- libelfはelftoolchainプロジェクト由来で、contrib/elftoolchain/libelf/以下にソースが配置
- FreeBSDのELFツール群（readelf, elfcopy, nm, size, strings等）はこのライブラリに依存

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | _libelf.h | `contrib/elftoolchain/libelf/_libelf.h` | struct _Elf（87-98行目）: ELFハンドルの内部構造。e_activations（参照カウント）、e_byteorder、e_class、e_cmd、e_fd、e_flags、e_kind等のフィールド。LIBELF_F_*フラグ（75-82行目） |
| 1-2 | _libelf_config.h | `contrib/elftoolchain/libelf/_libelf_config.h` | プラットフォーム固有の設定 |

**読解のコツ**: struct _Elfのe_flagsフィールドは、API定義のフラグ（下位16bit）とライブラリ内部フラグ（上位16bit）を共有する。LIBELF_PRIVATE(N)マクロはグローバル状態へのアクセサ。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | elf_begin.c | `contrib/elftoolchain/libelf/elf_begin.c` | elf_begin(): ファイルデスクリプタからELFハンドルを作成する主要関数 |
| 2-2 | elf_end.c | `contrib/elftoolchain/libelf/elf_end.c` | elf_end(): 参照カウントのデクリメントとリソース解放 |

#### Step 3: セクション操作を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | elf_getscn.c | `contrib/elftoolchain/libelf/elf_getscn.c` | セクション記述子の取得 |
| 3-2 | elf_data.c | `contrib/elftoolchain/libelf/elf_data.c` | セクションデータの読み取り |

#### Step 4: エラー処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | elf_errmsg.c | `contrib/elftoolchain/libelf/elf_errmsg.c` | エラーメッセージ文字列の取得 |
| 4-2 | elf_errno.c | `contrib/elftoolchain/libelf/elf_errno.c` | エラー番号の取得・リセット |

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

```
elf_version(EV_CURRENT)              [バージョン設定]
    │
elf_begin(fd, cmd, NULL)             [ハンドル作成]
    │
    ├─ elf_kind(elf)                 [種別判定: ELF_K_ELF/AR/NONE]
    │
    ├─ gelf_getehdr(elf, &ehdr)      [ELFヘッダ取得]
    │
    ├─ elf_getscn(elf, index)        [セクション取得]
    │      └─ gelf_getshdr(scn, &shdr) [セクションヘッダ取得]
    │             └─ elf_getdata(scn, NULL) [セクションデータ取得]
    │
    ├─ gelf_getphdr(elf, index, &phdr) [プログラムヘッダ取得]
    │
    └─ elf_end(elf)                  [解放]
```

### データフロー図

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

ELFファイル(fd)   ───▶ elf_begin()              ───▶ Elf * ハンドル
                         │
Elf *             ───▶ gelf_getehdr()           ───▶ GElf_Ehdr (ヘッダ)
                         │
Elf *             ───▶ elf_getscn(index)        ───▶ Elf_Scn * (セクション)
                         │
Elf_Scn *         ───▶ elf_getdata()            ───▶ Elf_Data * (データ)
                         │
変更データ         ───▶ elf_update(ELF_C_WRITE)  ───▶ ファイル書き戻し
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| _libelf.h | `contrib/elftoolchain/libelf/_libelf.h` | ヘッダ | 内部構造体・マクロ定義 |
| _libelf_config.h | `contrib/elftoolchain/libelf/_libelf_config.h` | ヘッダ | プラットフォーム設定 |
| elf_begin.c | `contrib/elftoolchain/libelf/elf_begin.c` | ソース | ハンドル作成 |
| elf_end.c | `contrib/elftoolchain/libelf/elf_end.c` | ソース | ハンドル解放 |
| elf_data.c | `contrib/elftoolchain/libelf/elf_data.c` | ソース | データアクセス |
| elf_getscn.c | `contrib/elftoolchain/libelf/elf_getscn.c` | ソース | セクション取得 |
| elf_errmsg.c | `contrib/elftoolchain/libelf/elf_errmsg.c` | ソース | エラーメッセージ |
| elf_hash.c | `contrib/elftoolchain/libelf/elf_hash.c` | ソース | ハッシュ計算 |
| elf_kind.c | `contrib/elftoolchain/libelf/elf_kind.c` | ソース | 種別判定 |
| elf_memory.c | `contrib/elftoolchain/libelf/elf_memory.c` | ソース | メモリからのELF読み込み |
| elf_fill.c | `contrib/elftoolchain/libelf/elf_fill.c` | ソース | パディング文字設定 |
| Makefile | `lib/libelf/Makefile` | ビルド | ライブラリビルド設定 |
