C ++仮想アドレス空間とコンパイラリンクの原理

1.仮想アドレス空間

悪意のあるプログラムが他のプログラムのメモリデータを変更しないように、プロセスアドレス空間を分離する必要があるため、仮想アドレス空間がコンピューターに導入されます。

仮想アドレス空間のレイアウト
ここに画像の説明を挿入

.text(コードセグメント) 実行可能コード、読み取り専用変数、文字列定数
.data(データセグメント) 初期化され、初期値が0ではないグローバル変数と静的変数(グローバルおよびローカル)
.bss 初期化されていないか、初期値が0のグローバル変数と静的変数。変数が初期化されると、bssセグメントがクリアされます
ヒープ 動的に割り当てられたメモリ
共有ライブラリ プログラムは、実行時に動的にメモリに読み込まれます(Linuxでは.soファイル、未亡人では.DLLファイル)。
スタック プログラムの実行中、ここでデータ操作を実行し、一時データ(ローカル変数、ローカル読み取り専用変数、関数パラメーター、戻りアドレスなど)を格納し、関数スタックを開くなどする必要があります。Linuxでは、スタックは上位アドレスから下位アドレスに開かれます。関数スタックの場合、関数が完了するとメモリが解放されます。
コマンドラインパラメーター ps -eLfと同様に、-eLfはコマンドラインパラメータであり、psは実行可能プログラムです。
環境変数 LinuxでのPATHやHOMEなどの環境変数(子プロセスは親プロセスの環境変数を継承します)
ZONE_DMA 直接アクセスエリア、16M
ZONE_NORMAL 共通領域、マッピングページディレクトリテーブル、892M
ハイメモリ領域 1Gより大きいファイルのマッピング

2.コンパイルとリンクの原則
コンパイルとリンク:

1)プリコンパイル(* .iファイルを生成)
1>すべての「#define」を削除してすべてのマクロを展開します;
2>「#if」、「#ifdef」、「」などのすべての条件付きプリコンパイル命令を破棄します#elif "、" #else "、" #endif ";
3>再帰的なプロセスである" #include "命令を処理する;
4>すべてのコメントを削除する" // "と" / * * / ";
5>追加する行番号とファイル名の識別;
6> #pragmaコンパイラーのすべての命令をコンパイラーで使用するために予約します。

2)コンパイル(* .sファイルの生成)
前処理されたファイルは、一連の字句解析、構文解析、意味解析、および最適化の対象となり、対応するアセンブリコードファイルが生成されます。

3)アセンブリ(* .oファイルの生成、オブジェクトファイルとも呼ばれます)
アセンブラは、アセンブリコードをマシンが実行できる命令に変換します各アセンブリステートメントは、ほぼマシン命令に対応しています。

4)リンク(* .exeファイルを生成、実行可能ファイルとも呼ばれます)
1>アドレスとスペースの割り当て;
2>シンボル分析;
3>シンボルの再配置;

.oファイルの単純なファイル形式のレイアウト
ここに画像の説明を挿入
ここに画像の説明を挿入
。Bssはターゲットファイルのスペースを占有しません。ELF
ここに画像の説明を挿入
ヘッダーにセクションヘッダーと呼ばれるセクションがあることがわかります。このセクションには、セクションのサイズなど、ターゲットファイルの各セクションの詳細情報が保存されます。オフセットとその他の情報を開始します。コンパイラは、このセクションにアクセスしている限り、各セクションの詳細情報を知ることができます。.bssはスペースを占有しませんが、.bssセクションの詳細情報はセクションヘッダーに格納され
ここに画像の説明を挿入
ます。gdata3は.bssセクションに格納されていないことがわかります。このデータは、C言語の強いシンボルと弱いシンボルに関連するCOMブロックに格納されます。

ストロングシンボル:グローバル初期化シンボルウィークシンボル:グローバル未初期化シンボルストロングシンボルとウィークシンボルの選択規則:
1. 2つのストロングシンボルのコンパイルエラー
2. 1つのストロングシンボルと1つのウィークシンボルがストロングシンボルを選択します
3. 2つのウィークシンボルコンパイラごとに異なる処理方法

プロジェクトには複数のソースファイルがある場合があります。コンパイル段階では、各ファイルが個別にコンパイルされます。他のファイルには強いシンボルが含まれている可能性があるため、コンパイル中に特定のシンボルを特定する方法はありません。したがって、このファイルのウィークシンボルは、.bssセクションではなくCOMブロックに格納されます

シンボルの解決とシンボルの再配置

シンボルの解決
各ファイルシンボルリファレンス(外部シンボルへの参照)でシンボルの定義を見つけます。これはシンボル解決です

シンボルの再配置
まず、リンクする前に生成されたアセンブリコードを確認します。
ここに画像の説明を挿入
これらの2つの場所はそれぞれ0000です。0000は、リンクする前にコンパイラによってgdataに与えられるアドレスを表します。FFFF FF FCは、リンクする前にコンパイラによってSum関数に与えられる関数のエントリアドレスを表します。 。どちらのアドレスも無効です。リンク後にこれら2つのアドレスを確認してください。これら2つの
ここに画像の説明を挿入
アドレスは、gdataの特定の仮想アドレスとSum関数の相対変位オフセットになります。シンボルのリダイレクトは、特定の仮想アドレスまたは相対変位オフセットを.oファイルの.textセクション命令の無効なアドレスに与えることです。
実行可能ファイルのヘッダー情報を見てみましょう
ここに画像の説明を挿入
この時点で、このプログラムのエントリアドレスには080480A4が割り当てられています。これは、メイン関数のエントリアドレスです。これでプログラムを実行できます。

おすすめ

転載: blog.csdn.net/Gunanhuai/article/details/102846904