最終更新:2009-07-20 (月) 01:12:46 (5557d)
参考図書/ふつうのコンパイラを作ろう
- 『ふつうのコンパイラを作ろう』目次
- 第 1 章 コンパイラ作りを始めよう 1
- 1.2 コンパイルの過程 ---- 11
- 1.3 C♭コンパイラによるコンパイル ---- 16
- 第 2 章 C♭とcbc 19
- 第1 部 ソースコードの解析
- 第 3 章 構文解析の概要 35
- 第 4 章 字句解析 55
- 第 5 章 JavaCC によるパーサの記述 79
- 第 6 章 構文解析 97
- 第2 部 抽象構文木と中間表現
- 第 7 章 JavaCC のアクションと抽象構文木 131
- 第 8 章 抽象構文木の作成 157
- 第 9 章 意味解析(1)参照の解決 189
- 9.1 意味解析の概要 ---- 190
- 第 10 章 意味解析(2)静的型チェック 221
- 第 11 章 中間表現への変換 249
- 第3 部 アセンブリコードの生成
- 第 12 章 x86 アーキテクチャの概要 301
- 第 13 章 x86 アセンブラプログラミング 335
- 第 14 章 関数呼び出しと変数 377
- 第 15 章 式と文のコンパイル 395
- 第 16 章 スタックフレームの割り当て 437
- 第 17 章 最適化の手法 471
- 第4 部 リンクとロード
- 第 18 章 オブジェクトファイルの生成 487
- 第 19 章 リンクとライブラリ 521
- 第 20 章 プログラムのロード 547
- 第 21 章 位置独立コードの生成 579
- 第 22 章 本書を読み終えたあとに 615
- 付録 625
- 参考
『ふつうのコンパイラを作ろう』目次
第 1 章 コンパイラ作りを始めよう 1
1.1 本書の概要 ---- 2
1.2 コンパイルの過程 ---- 11
- コンパイルの4 つの段階 ---- 11
- 構文解析 ---- 11
- 意味解析 ---- 12
- 中間表現?の生成 ---- 13
- コード生成? ---- 14
- 最適化 ---- 14
- まとめ ---- 15
1.3 C♭コンパイラによるコンパイル ---- 16
- C♭コンパイラの必要環境 ---- 16
- C♭コンパイラのインストール ---- 17
- C♭によるHello, World! ---- 17
第 2 章 C♭とcbc 19
2.1 C♭言語の概要 ---- 20
- C♭でのHello, World! ---- 20
- C♭で削除された機能 ---- 21
- import 宣言の仕様 ---- 22
- インポートファイルの仕様 ---- 23
2.2 C♭コンパイラcbc の構成 ---- 25
- cbc のソースツリー? ---- 25
- cbc のパッケージ ---- 26
- compiler パッケージのクラス群 ---- 27
- main メソッド?の実装 ---- 27
- commandMain メソッドの実装 ---- 28
- Java 5 のgenerics ---- 29
- build メソッドの実装 ---- 29
- Java 5 のforeach 文 ---- 30
- compile メソッドの実装 ---- 31
第1 部 ソースコードの解析
第 3 章 構文解析の概要 35
3.1 構文解析の手法 ---- 36
- ソースコード解析の問題点 ---- 36
- ソースコード解析の定石 ---- 36
- 字句解析、構文解析、意味解析 ---- 37
- スキャナの働き ---- 38
- 単語の種類と意味値 ---- 39
- トークン? ---- 40
- 抽象構文木?とノード? ---- 41
3.2 パーサジェネレータ ---- 43
3.3 JavaCC? の概要 ---- 47
- JavaCC? とは ---- 47
- 文法記述ファイル? ---- 47
- 文法記述ファイルの例 ---- 48
- JavaCC? の実行 ---- 50
- JavaCC? で生成したパーサの起動 ---- 51
- 日本語の処理 ---- 53
第 4 章 字句解析 55
4.1 JavaCC によるスキャナの記述 ---- 56
- この章の目的 ---- 56
- JavaCC? の正規表現 ---- 56
- 固定文字列? ---- 57
- 連接? ---- 57
- 文字クラス? ---- 58
- 否定文字クラス? ---- 58
- 1 回以上の繰り返し ---- 59
- 0 回以上の繰り返し ---- 59
- n 回からm 回の繰り返し ---- 60
- ちょうどn 回の繰り返し ---- 60
- 省略可能 ---- 61
- 選択 ---- 61
4.2 構造のない単語のスキャン ---- 63
4.3 トークン?を生成しない単語のスキャン ---- 68
- SKIP 命令とSPECIAL_TOKEN 命令 ---- 68
- 空白の読み捨て ---- 69
- 行コメントの読み捨て ---- 69
4.4 構造を持つ単語のスキャン ---- 71
- 最長一致の原則とその問題 ---- 71
- 状態遷移?を使ったスキャン ---- 72
- MORE 命令 ---- 73
- ブロックコメント?の読み捨て ---- 75
- 文字列リテラル?のスキャン ---- 76
- 文字リテラル?のスキャン ---- 76
第 5 章 JavaCC? によるパーサの記述 79
5.1 EBNF? による文法の記述 ---- 80
- この章の目的 ---- 80
- JavaCC? での文法の記述 ---- 81
- 終端記号?と非終端記号? ---- 82
- JavaCC? のEBNF? 記法 ---- 83
- 連接? ---- 84
- 0 回以上の繰り返し ---- 84
- 1 回以上の繰り返し ---- 85
- 選択 ---- 86
- 省略可能 ---- 86
5.2 曖昧な文法とトークン?の先読み ---- 87
- 曖昧な文法 ---- 87
- JavaCC? の制限 ---- 89
- 左端共通部分のくくり出し ---- 89
- トークンの先読み ---- 90
- 省略可能な規則と衝突 ---- 92
- 繰り返しと衝突 ---- 93
- より柔軟なトークンの先読み ---- 94
- 先読みに関する注意 ---- 95
第 6 章 構文解析 97
6.1 定義の解析 ---- 98
- プログラム全体を表す記号 ---- 98
- 構文?の単位 ---- 99
- import 宣言の構文 ---- 100
- さまざまな定義の構文 ---- 101
- 変数定義の構文 ---- 103
- 関数定義の構文 ---- 104
- 構造体定義と共用体?定義の構文 ---- 106
- 構造体メンバと共用体メンバの構文 ---- 107
- typedef 文の構文 ---- 108
- 型の構文 ---- 108
- C言語とC♭の変数定義の違い ---- 109
- 基本型の構文 ---- 110
6.2 文の解析 ---- 113
- 文の構文 ---- 113
- if 文の構文 ---- 114
- if 文と中括弧の省略 ---- 115
- while 文の構文 ---- 116
- for 文の構文 ---- 116
- さまざまなジャンプ文の構文 ---- 117
6.3 式の解析 ---- 118
- 式の全体構造 ---- 118
- expr の規則 ---- 119
- 条件式 ---- 120
- 二項演算子? ---- 121
6.4 項の解析 ---- 125
第2 部 抽象構文木?と中間表現?
第 7 章 JavaCC? のアクションと抽象構文木? 131
7.1 JavaCC? のアクション ---- 132
- この章の目的 ---- 132
- 簡単なアクション ---- 132
- アクションの実行されるタイミング ---- 133
- 意味値?を返すアクション ---- 135
- 終端記号?の意味値?の取り出し ---- 136
- Token クラスのフィールド ---- 137
- 非終端記号?の意味値?の取り出し ---- 139
- 構文木?の構築 ---- 140
- 選択とアクション ---- 141
- 繰り返しとアクション ---- 143
- この節のまとめ ---- 145
7.2 抽象構文木?とノード? ---- 147
- Node クラス群 ---- 147
- Node クラスの定義 ---- 149
- 抽象構文木?の表示 ---- 150
- ノードによる式の表現の例 ---- 152
第 8 章 抽象構文木?の作成 157
8.1 式の抽象構文木? ---- 158
- リテラルの抽象構文木? ---- 158
- 型の表現 ---- 160
- TypeRef? クラスが必要な理由 ---- 161
- 単項演算の抽象構文木? ---- 162
- 二項演算の抽象構文木? ---- 164
- 条件式?の抽象構文木? ---- 166
- 代入式の抽象構文木? ---- 167
8.2 文の抽象構文木? ---- 171
8.3 宣言の抽象構文木? ---- 176
- 変数宣言リストの抽象構文木? ---- 176
- 関数定義の抽象構文木? ---- 178
- 宣言リストを表す抽象構文木? ---- 179
- プログラム全体を表す抽象構文木? ---- 180
- 外部シンボルのインポート ---- 181
- まとめ ---- 182
8.4 cbc パーサの起動 ---- 185
- Parser オブジェクトの生成 ---- 185
- ファイルのパース ---- 186
- パーサの起動 ---- 188
第 9 章 意味解析(1)参照の解決 189
9.1 意味解析の概要 ---- 190
- この章の目的 ---- 190
- 抽象構文木?のトラバース ---- 191
- Visitor パターンを使わない抽象構文木?の処理 ---- 192
- Visitor パターンによる抽象構文木?の処理 ---- 194
- Visitor パターンの一般化 ---- 196
- cbc におけるVisitor パターンの実装 ---- 198
- 意味解析に関わるcbc のクラス ---- 199
9.2 変数参照?の解決 ---- 201
- 問題の概要 ---- 201
- 実装の概要 ---- 201
- Scope ツリーの構造 ---- 203
- LocalResolver? クラスのフィールド ---- 204
- LocalResolver? クラスの起動 ---- 205
- 変数定義の登録 ---- 206
- 関数定義の処理 ---- 207
- pushScope メソッド ---- 208
- currentScope メソッド ---- 209
- popScope メソッド ---- 209
- ローカルスコープの追加 ---- 210
- VariableNode? と変数定義の対応付け ---- 211
- スコープツリーからの変数定義の取得 ---- 212
9.3 型名の解決 ---- 214
- 問題の概要 ---- 214
- 実装の概要 ---- 214
- TypeResolver? クラスのフィールド ---- 214
- TypeResolver? クラスの起動 ---- 215
- 型の宣言 ---- 216
- 型と抽象構文木?のトラバース ---- 217
- 変数定義の型の解決 ---- 218
- 関数定義の型の解決 ---- 219
第 10 章 意味解析(2)静的型チェック 221
10.1 型定義のチェック ---- 222
- 問題の概要 ---- 222
- 実装の概要 ---- 223
- 有向グラフのループを検出するアルゴリズム ---- 225
- 構造体・共用体の循環定義チェック ---- 226
10.2 式の妥当性のチェック ---- 229
- 問題の概要 ---- 229
- 実装の概要 ---- 230
- DereferenceChecker? クラスの起動 ---- 231
- 例外SemanticError? の捕捉 ---- 232
- 左辺値でない式のアドレス取得のチェック ---- 233
- ポインタでない値のデリファレンスのチェック ---- 234
- 暗黙のポインタ生成 ---- 235
10.3 静的型チェック ---- 237
- 問題の概要 ---- 237
- 実装の概要 ---- 238
- C♭における演算の型 ---- 238
- 暗黙の型変換 ---- 240
- TypeChecker? クラスの起動 ---- 241
- 二項演算式の型チェック ---- 242
- 暗黙の型変換の実装 ---- 244
第 11 章 中間表現?への変換 249
11.1 cbc の中間表現? ---- 250
- 中間表現?の表示 ---- 250
- 中間表現?を構成するクラス ---- 252
- 中間表現?ノードのフィールド ---- 253
- 中間表現?の演算子と型 ---- 254
- さまざまな中間表現? ---- 255
- 中間表現?の目的 ---- 256
11.2 IRGenerator クラスの概要 ---- 258
- 抽象構文木?のトラバースと返り値 ---- 258
- IRGenerator クラスの起動 ---- 258
- 関数本体の変換 ---- 259
- 文である式の判別 ---- 260
11.3 制御構造の変換 ---- 263
- if 文の変換(1)概要 ---- 263
- if 文の変換(2)else 節がない場合 ---- 264
- if 文の変換(3)else 節がある場合 ---- 265
- while 文の変換 ---- 266
- break 文の変換(1)問題の定義 ---- 268
- break 文の変換(2)実装の方針 ---- 269
- break 文の変換(3)実装 ---- 270
11.4 副作用のない式の変換 ---- 273
11.5 左辺値の変換 ---- 279
- 左辺と右辺 ---- 279
- 左辺値と右辺値 ---- 279
- cbc での左辺値の表現 ---- 280
- 構造体メンバのオフセット ---- 282
- メンバ参照(expr.memb)の変換 ---- 283
- 左辺値変換の例外:配列と関数 ---- 285
- メンバ参照式(ptr->memb)の変換 ---- 286
11.6 副作用を持つ式の変換 ---- 288
- 式の副作用とは ---- 288
- 副作用を持つ式の変換方針 ---- 289
- 単純な代入式の変換(1)文である場合 ---- 290
- テンポラリ変数の導入 ---- 291
- 単純な代入式の変換(2)式である場合 ---- 293
- 後置インクリメントの変換 ---- 295
第3 部 アセンブリコード?の生成
第 12 章 x86 アーキテクチャの概要 301
12.1 コンピュータの仕組み ---- 302
- CPU とメモリ ---- 302
- レジスタ ---- 303
- アドレス ---- 303
- 物理アドレスと仮想アドレス ---- 304
- さまざまなデバイス ---- 306
- キャッシュメモリ? ---- 308
12.2 x86 系CPU の歴史 ---- 311
- x86 系CPU とは ---- 311
- 32 ビットCPU とは ---- 312
- インストラクションセット?とは ---- 313
- IA-32 の変遷 ---- 314
- IA-32 の64 ビット拡張 ~ AMD64 ~ ---- 315
12.3 IA-32 の概要 ---- 317
- IA-32 のレジスタ ---- 317
- 汎用レジスタ ---- 319
- マシンスタック?とは ---- 320
- マシンスタック?の操作 ---- 321
- マシンスタック?の用途 ---- 323
- スタックフレーム?とは ---- 324
- インストラクションポインタ? ---- 325
- フラグレジスタ? ---- 326
12.4 データの表現と配置 ---- 328
- 符号なし整数の表現 ---- 328
- 符号付き整数の表現 ---- 328
- 負の整数の表現と2の補数 ---- 329
- エンディアン ---- 330
- アラインメント? ---- 331
- 構造体の表現 ---- 332
第 13 章 x86 アセンブラプログラミング 335
13.1 GNU アセンブラ?によるプログラミング ---- 336
13.2 GNU アセンブラの文法 ---- 340
- アセンブリ版Hello, World! ---- 340
- インストラクション ---- 341
- ディレクティブ ---- 341
- ラベル ---- 342
- コメント ---- 343
- ニモニックサフィックス ---- 343
- さまざまなオペランド ---- 344
- 間接メモリ参照 ---- 345
- x86 インストラクションセットの概要 ---- 348
13.3 転送命令 ---- 350
- mov? 命令 ---- 350
- push? 命令とpop? 命令 ---- 352
- lea? 命令 ---- 353
- movsx? 命令とmovzx? 命令 ---- 354
- 符号拡張とゼロ拡張 ---- 355
13.4 算術演算?命令 ---- 357
- add? 命令 ---- 357
- キャリーフラグ ---- 358
- sub 命令 ---- 358
- imul? 命令 ---- 359
- idiv? 命令とdiv 命令 ---- 360
- inc? 命令 ---- 362
- dec? 命令 ---- 362
- neg? 命令 ---- 362
13.5 ビット演算?命令 ---- 364
- and? 命令 ---- 364
- or? 命令 ---- 365
- xor? 命令 ---- 365
- not? 命令 ---- 366
- sal? 命令 ---- 366
- sar 命令 ---- 367
- shr? 命令 ---- 367
13.6 演算の制御 ---- 369
- jmp? 命令 ---- 369
- 条件付きジャンプ命令(jz?、jnz?、je?、jne?、……) ---- 370
- cmp 命令 ---- 372
- test 命令 ---- 372
- フラグを取り出す命令(SETcc) ---- 373
- call? 命令 ---- 374
- ret? 命令 ---- 375
第 14 章 関数呼び出しと変数 377
14.1 手続き呼び出し規約 ---- 378
14.2 Linux/x86 での関数呼び出し ---- 381
- 呼び出し完了まで ---- 381
- 関数本体の実行開始まで ---- 382
- 呼び出し元への復帰まで ---- 384
- 後始末完了まで ---- 385
- 関数呼び出しのまとめ ---- 385
14.3 Linux/x86 での関数呼び出しの詳細 ---- 389
- レジスタの保存と復帰 ---- 389
- caller-save レジスタとcallee-save レジスタ ---- 390
- caller-save レジスタとcallee-save レジスタの活用 ---- 391
- 大きな値と浮動小数点数の返しかた ---- 392
- 他のプラットフォームでの手続き呼び出し規約 ---- 394
第 15 章 式と文のコンパイル 395
15.1 コンパイル結果の調査 ---- 396
- cbc での調査方法 ---- 396
- gcc での調査方法 ---- 398
15.2 x86 アセンブリのオブジェクト表現とDSL ---- 399
- アセンブリを表現するクラス ---- 399
- アセンブリオブジェクトの表示 ---- 401
15.3 cbc のx86 アセンブリDSL ---- 403
- DSL によるアセンブリオブジェクトの生成 ---- 403
- レジスタの表現 ---- 404
- 即値?とメモリ参照?の表現 ---- 406
- インストラクションの表現 ---- 406
- ディレクティブ、ラベル、コメントの表現 ---- 407
15.4 CodeGenerator? クラスの概要 ---- 409
- CodeGenerator? クラスのフィールド ---- 409
- CodeGenerator? クラスの処理の概要 ---- 410
- compileStmts メソッドの実装 ---- 411
- cbc のコンパイル戦略 ---- 412
15.5 単純な式のコンパイル ---- 415
- Int ノードのコンパイル ---- 415
- Str ノードのコンパイル ---- 415
- Uni ノードのコンパイル(1)ビット否定 ---- 417
- Uni ノードのコンパイル(2)論理否定 ---- 419
15.6 二項演算のコンパイル ---- 421
- Bin ノードのコンパイル ---- 421
- compileBinaryOp? メソッドの実装 ---- 422
- 除算と剰余の実装 ---- 423
- 比較演算の実装 ---- 424
15.7 変数の参照と代入 ---- 426
- Var ノードのコンパイル ---- 426
- Addr ノードのコンパイル ---- 428
- Mem ノードのコンパイル ---- 429
- Assign ノードのコンパイル ---- 429
15.8 ジャンプ文のコンパイル ---- 432
- LabelStmt? ノードのコンパイル ---- 432
- Jump ノードのコンパイル ---- 432
- CJump ノードのコンパイル ---- 433
- Call ノードのコンパイル ---- 434
- Return ノードのコンパイル ---- 435
第 16 章 スタックフレームの割り当て 437
16.1 マシンスタック?の操作 ---- 438
- cbc のスタックフレーム ---- 438
- スタックポインタ?操作の方針 ---- 439
- 関数本体のコンパイル手順 ---- 440
16.2 引数とローカル変数へのメモリ参照割り当て ---- 442
- この節の概要 ---- 442
- 引数へのメモリ参照割り当て ---- 442
- ローカル変数へのメモリ参照割り当て:方針 ---- 444
- ローカル変数へのメモリ参照割り当て ---- 446
- スコープ内のローカル変数の処理 ---- 447
- アラインメントの計算 ---- 448
- 子スコープの変数への割り当て ---- 449
16.3 仮想スタックによるテンポラリ変数の割り当て ---- 451
- 仮想スタックの目的 ---- 451
- 仮想スタックのインターフェイス ---- 452
- 仮想スタックの構造 ---- 453
- virtulPush メソッドの実装 ---- 454
- VirtualStack?#extend メソッドの実装 ---- 454
- VirtualStack?#top メソッドの実装 ---- 455
- virtulPop メソッドの実装 ---- 455
- VirtualStack?#rewind メソッドの実装 ---- 456
- 仮想スタックの動作 ---- 456
16.4 マシンスタック?アクセスのオフセット調整 ---- 457
- この節の概要 ---- 457
- StackFrameInfo? クラス ---- 458
- 使われているcallee-save レジスタの算出 ---- 459
- テンポラリ変数領域のサイズの算出 ---- 460
- ローカル変数のオフセット調整 ---- 460
- テンポラリ変数のオフセット調整 ---- 461
16.5 プロローグ・エピローグの生成 ---- 462
- この節の概要 ---- 462
- プロローグの生成 ---- 463
- エピローグの生成 ---- 464
16.6 alloca の実装 ---- 466
- alloca 関数とは ---- 466
- 実装の方針 ---- 467
- alloca 関数の影響 ---- 467
- alloca 関数の実装 ---- 468
第 17 章 最適化の手法 471
17.1 最適化とは ---- 472
- いろいろな最適化 ---- 472
- 最適化の例 ---- 472
- 定数の畳み込み ---- 473
- 式の単純化 ---- 473
- 演算強度の低減 ---- 473
- 共通部分式の削除 ---- 474
- 不要命令の削除 ---- 474
- 関数インライン展開 ---- 475
17.2 最適化の分類 ---- 476
- 手法による最適化の分類 ---- 476
- 対象範囲による最適化の分類 ---- 477
- 適用段階による最適化の分類 ---- 478
17.3 cbc での最適化 ---- 479
- cbc における最適化の方針 ---- 479
- cbc で実装した最適化 ---- 479
- cbc での最適化の実装 ---- 480
17.4 より強力な最適化 ---- 481
- パターンマッチによる命令選択 ---- 481
- レジスタ割り当て ---- 482
- コントロールフロー解析 ---- 483
- 大規模なデータフロー解析とSSA 形式 ---- 483
- まとめ ---- 484
第4 部 リンクとロード?
第 18 章 オブジェクトファイルの生成 487
18.1 ELF ファイルの構造 ---- 488
- ELF の目的 ---- 488
- ELF のセクションとセグメント ---- 489
- オブジェクトファイルの主要なELF セクション ---- 491
- readelf コマンドによるセクションヘッダの表示 ---- 492
- readelf コマンドによるプログラムヘッダの表示 ---- 493
- readelf コマンドによるシンボルテーブルの表示 ---- 495
- readelf コマンドのオプション ---- 496
- DWARF フォーマットとは ---- 497
18.2 グローバル変数のELF ファイルでの表現 ---- 498
- 任意のELF セクションへの割り当て ---- 498
- 一般的なELF セクションへの割り当て ---- 499
- .bss セクションの確保 ---- 499
- コモンシンボル ---- 500
- グローバル変数に対応するシンボルの登録 ---- 502
- シンボルの付帯情報の登録 ---- 503
- コモンシンボルの付帯情報の登録 ---- 504
- まとめ ---- 505
18.3 グローバル変数のコンパイル ---- 507
- generate メソッドの実装 ---- 507
- generateAssemblyCode? メソッドの実装 ---- 507
- グローバル変数のコンパイル ---- 509
- 即値のコンパイル ---- 510
- コモンシンボルのコンパイル ---- 512
- 文字列リテラルのコンパイル ---- 513
- 関数ヘッダの生成 ---- 514
- 関数のコードサイズの計算 ---- 515
- まとめ ---- 516
18.4 オブジェクトファイルの生成 ---- 517
- as コマンド呼び出しの概要 ---- 517
- GNUAssembler クラスの呼び出し ---- 517
- as コマンドの呼び出し ---- 518
第 19 章 リンクとライブラリ 521
19.1 リンクの概要 ---- 522
19.2 リンクとは ---- 530
- リンクで行われる処理 ---- 530
- セクションのマージとは ---- 530
- 再配置とは ---- 531
- シンボルの解決とは ---- 533
19.3 ダイナミックリンクとスタティックリンク ---- 535
- 2 つのリンク手法 ---- 535
- ダイナミックリンクの利点 ---- 536
- ダイナミックリンクの欠点 ---- 536
- ダイナミックリンクの実行例 ---- 537
- スタティックリンクの実行例 ---- 538
- ライブラリの検索規則 ---- 539
19.4 ライブラリの作成 ---- 541
第 20 章 プログラムのロード 547
20.1 ELF セグメントのロード ---- 548
- mmap システムコールによるファイルのマップ ---- 548
- プロセスのメモリイメージ ---- 549
- メモリ領域の属性 ---- 551
- ELF セグメントとメモリ領域の対応 ---- 551
- ELF ファイルと対応しないメモリ領域 ---- 554
- ELF ファイルのロードの実装 ---- 555
20.2 ダイナミックリンクの過程 ---- 557
- ダイナミックリンカローダとは ---- 557
- プログラムの起動から終了までの概要 ---- 558
- ld.so の起動 ---- 559
- カーネルから渡される情報 ---- 560
- AUX ベクタ ---- 561
- 共有ライブラリの読み込み ---- 562
- シンボルの解決と再配置 ---- 564
- 初期化コードの実行 ---- 565
- メインプログラムの開始 ---- 566
- 終了処理の実行 ---- 567
- ld.so が解釈する環境変数 ---- 568
20.3 動的ロード ---- 570
- 動的ロードとは ---- 570
- Linux での動的ロード ---- 570
- 動的ロードの仕組み ---- 571
20.4 GNU ld によるリンク ---- 573
- cbc 用ld オプションの構築 ---- 573
- C ランタイム ---- 574
- 実行可能ファイルの作成 ---- 575
- 共有ライブラリの生成 ---- 576
第 21 章 位置独立コードの生成 579
21.1 位置独立コードとは ---- 580
- 位置独立コードとは ---- 580
- グローバルオフセットテーブル?(GOT?) ---- 582
- GOT のアドレス取得 ---- 582
- GOT を使ったグローバル変数アクセス ---- 584
- GOT を使ったファイル内グローバル変数へのアクセス ---- 585
- 手続きリンクテーブル(PLT) ---- 585
- PLT エントリの呼び出し ---- 588
- 位置独立な実行可能ファイル:PIE ---- 588
21.2 グローバル変数参照の実装 ---- 591
- GOT アドレスの取得 ---- 591
- PICThunk メソッドの実装 ---- 592
- 重複した関数の削除と非可視属性 ---- 593
- GOT アドレスのロード ---- 594
- locateSymbols メソッドの実装 ---- 595
- グローバル変数の参照 ---- 596
- グローバル変数へのアクセス:位置独立コードの場合 ---- 597
- 関数のシンボル ---- 598
- 文字列定数の参照 ---- 600
21.3 リンカ呼び出しの実装 ---- 602
- 実行可能ファイルの生成 ---- 602
- generateSharedLibrary? メソッド ---- 604
21.4 プログラムの解析から実行まで ---- 606
- ビルドとロードの過程 ---- 606
- 字句解析 ---- 607
- 構文解析 ---- 608
- 中間表現?の生成 ---- 609
- コード生成 ---- 610
- アセンブル ---- 611
- 共有ライブラリの生成 ---- 612
- 実行可能ファイルの生成 ---- 613
- ロード ---- 613
第 22 章 本書を読み終えたあとに 615
22.1 書籍紹介 ---- 616
22.2 リンク・ロード?について ---- 619
22.3 さまざまな言語機能? ---- 620
- 例外の実装に関する書籍 ---- 620
- ガベージコレクションとは ---- 621
- ガベージコレクションに関する書籍 ---- 621
- オブジェクト指向言語の実装 ---- 622
- 関数型言語 ---- 623
付録 625
- A.1 参考文献 ---- 626
- A.2 オンラインドキュメント ---- 629
- A.3 ソースコード ---- 630
- 索引 ---- 631