5

Itanium C++ ABIにおける「GP/関数アドレス ペア」とは何を意味しますか? GPは何の略ですか?

4

2 に答える 2

7

簡単な説明:gpは、実際には、Itanium ABI に準拠するすべての関数に対する隠しパラメーターです。これは、関数が使用するグローバル変数への一種のthisポインターです。私の知る限り、これを行う主流の OS はもうありません。

GP は「グローバル ポインタ」の略です。これは、実行可能ファイルによって静的に割り当てられるデータのベース アドレスであり、Itanium アーキテクチャにはそのためのレジスタがあります。

たとえば、プログラムにこれらのグローバル変数とこの関数があるとします。

int foo;
int bar;
int baz;

int func()
{
    foo++;
    bar += foo;
    baz *= bar / foo;
    return foo + bar + baz;
}

gp/関数のペアは、概念的には&foo, &func. 生成されたコードは、グローバルが配置されている場所を見つけるためにfuncを参照します。gpコンパイラは、 、 、 、でfoo見つかることを認識しています。gpbargp + 4bazgp + 8

func が外部ライブラリで定義されていると仮定すると、プログラムから呼び出すと、コンパイラは次のような一連の命令を使用します。

  • 現在の gp 値をスタックに保存します。
  • のペアからfunc何らかのレジスタにコード アドレスをロードします。
  • 同じペアから GP に gp 値をロードします。
  • コードアドレスを格納したレジスタへの間接呼び出しを実行します。
  • 以前にスタックに保存した古い gp 値を復元し、関数の呼び出しを再開します。

これにより、実行可能ファイルは絶対アドレスをデータ シンボルに保存しないため、完全に位置に依存しなくなります。したがって、実行可能ファイルを使用するプロセスの数に関係なく、実行可能ファイルのインスタンスを 1 つだけメモリに保持することができます (単一のプロセス内で同じ実行可能ファイルを複数回実行しても、システム全体で実行可能コードのコピーが 1 つしかない)、関数ポインターを少し奇妙にするという犠牲を払って。Itanium ABI では、関数ポインターはコード アドレスではありません (「通常の」x86 ABI の場合と同様): gp 値およびコード アドレスへのアドレスです。メソッドがthisポインタを持たない場合、メソッドが多くのことを実行できないのと同じように、そのグローバル変数にアクセスすることはできません。

私が知っているこの概念を使用する唯一の ABI は、Mac OS Classic PowerPC ABI です。彼らはそれらのペアを「遷移ベクトル」と呼んだ。

x86_64 は RIP 相対アドレス指定をサポートしているため (x86 には同等の EIP 相対アドレス指定がありませんでした)、追加のレジスタを使用したり、「拡張」関数ポインターを使用したりすることなく、位置に依存しないコードを非常に簡単に作成できるようになりました。コードとデータを一定のオフセットに保つ必要があります。したがって、Itanium ABI のこの部分は、おそらく Intel プラットフォームでは完全になくなっています。

Itanium Register Conventionsから:

8.2 gp レジスタ

静的に割り当てられたデータを参照したり、別のプロシージャを呼び出したりするすべてのプロシージャは、その静的データとそのリンケージ テーブルにアクセスできるように、gp レジスタ内のデータ セグメントへのポインタを必要とします。各ロード モジュールには独自のデータ セグメントがあり、そのロード モジュール内のエントリ ポイントを呼び出す前に、gp レジスタを正しく設定する必要があります。

リンケージ規則では、各ロード モジュールがその短いデータ セグメント内の場所を参照するために、正確に 1 つの gp 値を定義する必要があります。この場所は、スカラーおよびリンケージ テーブル エントリをアドレス指定するための短い変位の即時命令の有用性を最大化するために選択されることが期待されます。DLL ローダーは、データ セグメントをメモリにロードした後、各ロード モジュールの gp レジスタの絶対値を決定します。

ロード モジュール内の呼び出しの場合、gp レジスタは変更されないため、ローカルであることがわかっている呼び出しはそれに応じて最適化できます。

ロード モジュール間の呼び出しの場合、gp レジスタは新しいロード モジュールの正しい gp 値で​​初期化する必要があり、呼び出し元の関数はそれ自体の gp 値が保存および復元されることを確認する必要があります。

于 2013-09-20T02:42:02.760 に答える