私はコンパイラの初心者ですが、プログラムがどのように構造化されているか (バイナリ)、プログラムがどのように読み取られ、実行のためにメモリにロードされるかについて学ぶことに非常に興味があります。すぐに始められるように、どの電子ブック/書籍/チュートリアルを読むことをお勧めしますか?
2 に答える
ELF ファイルのレイアウト
ELF ファイルには 2 つのビューがあります。
- プログラム ヘッダーには、実行時に使用されるセグメントが表示されます
- セクション ヘッダーには、バイナリのセクションのセットが一覧表示されます
各 ELF ファイルは、1 つの ELF ヘッダーとそれに続くファイル データで構成されます。
ファイル データには、次のものを含めることができます。
- 0 個以上のセグメントを記述するプログラム ヘッダー テーブル
- 0 個以上のセクションを記述するセクション ヘッダー テーブル
- プログラム ヘッダー テーブルまたはセクション ヘッダー テーブルのエントリによって参照されるデータ
セグメントにはファイルのランタイム実行に必要な情報が含まれ、セクションにはリンクと再配置のための重要なデータが含まれます。ファイル全体の任意のバイトは、最大で 1 つのセクションによって所有される可能性があり、どのセクションによっても所有されない孤立したバイトが存在する可能性があります。
プログラムをメモリにロードする
コンピューティングでは、ローダーはプログラムのロードを担当するオペレーティング システムの一部です。
これは、プログラムをメモリに配置して実行の準備を整えるため、プログラムの開始プロセスにおける重要な段階の 1 つです。
プログラムのロードには以下が含まれます。
- 実行可能ファイル (プログラム テキストを含むファイル) の内容をメモリに読み込む
- 実行可能ファイルの実行を準備するために必要なその他の準備タスクを実行します。
読み込みが完了すると、オペレーティング システムは、読み込まれたプログラム コードに制御を渡すことによって、プログラムを開始します。
*NIX 方式
Unix では、ローダーはシステム コールのハンドラです
execve()
。Unix ローダーのタスクは次のとおりです。
- 検証(権限、メモリ要件など)
- プログラム イメージをディスクからメインメモリにコピーする
- コマンドライン引数をスタックにコピーする
- レジスタの初期化 (スタック ポインタなど)
- プログラムのエントリポイントにジャンプ (
_start
)
コンパイラと実行可能バイナリはリモートで関連付けられています。ld
(実際の実行可能ファイルは、コンパイラではなく、リンカーによってビルドされます)。
Linux システムでは、Linux カーネルはコピー オン ライトおよびデマンド ページング技術を使用して、 ELF実行可能ファイルのプログラム ページを遅延ロードします。共有ライブラリは動的にロードでき、できれば位置に依存しないコードを含むことができます。
コンパイラの構築、リンカーとローダーに関する Levine の本、Linux Assembly Howto、Program Library Howto、ldd (1)、execve(2)、intro(2)、fork(2)、mmap( 2)、dlopen(3)、elf(5)、proc(5)、signal(7)のマニュアル ページ。
また、何が表示されているかを理解するようにしcat /proc/self/maps
てください (それを実行しているプロセスのメモリ マップcat
)。で遊ぶこともできますobjdump
。