gccで共有ライブラリをコンパイルする場合、-fPICオプションはコードを位置に依存しないものとしてコンパイルします。すべてのコード位置に依存しないコンパイルを行わない理由(パフォーマンスまたはその他)はありますか?
gccで共有ライブラリをコンパイルする場合、-fPICオプションはコードを位置に依存しないものとしてコンパイルします。すべてのコード位置に依存しないコンパイルを行わない理由(パフォーマンスまたはその他)はありますか?
回答:
はい、パフォーマンス上の理由があります。一部のアクセスは、メモリ内の絶対位置を取得するために、事実上別の間接層の下にあります。
グローバル変数のオフセットを格納するGOT(グローバルオフセットテーブル)もあります。私には、これはIAT修正テーブルのように見えます。これは、ウィキペディアやその他のいくつかのソースによって位置に依存するものとして分類されています。
受け入れられた答えに加えて。PICコードのパフォーマンスを大きく損なうものの1つは、x86に「IP相対アドレス指定」がないことです。「IP相対アドレス指定」を使用すると、現在の命令ポインタからXバイトのデータを要求できます。これにより、PICコードがはるかに簡単になります。
ジャンプと呼び出しは通常EIPに関連しているため、実際には問題にはなりません。ただし、データにアクセスするには、少し手間がかかります。レジスタは、コードが必要とするデータへの「ベースポインタ」として一時的に予約される場合があります。たとえば、一般的な手法は、x86での呼び出しの動作方法を悪用することです。
call label_1
.dd 0xdeadbeef
.dd 0xfeedf00d
.dd 0x11223344
label_1:
pop ebp ; now ebp holds the address of the first dataword
; this works because the call pushes the **next**
; instructions address
; real code follows
mov eax, [ebp + 4] ; for example i'm accessing the '0xfeedf00d' in a PIC way
この手法やその他の手法により、データアクセスに間接層が追加されます。たとえば、gccコンパイラで使用されるGOT(グローバルオフセットテーブル)。
x86-64は、物事をはるかに簡単にする「RIP相対」モードを追加しました。
完全に位置に依存しないコードを実装すると、コードジェネレーターに制約が追加され、より高速な操作の使用が妨げられたり、その制約を維持するための手順が追加されたりするためです。
これは、仮想メモリシステムなしでマルチプロセッシングを取得するための許容可能なトレードオフである可能性があります。この場合、プロセスが互いのメモリに侵入しないことを信頼し、特定のアプリケーションを任意のベースアドレスにロードする必要があります。
最近の多くのシステムでは、パフォーマンスのトレードオフが異なり、ローダーの再配置は、オプティマイザーが自由に統治できる場合にできる最善の方法よりも安価であることがよくあります(コードが最初にロードされるたびにコストがかかります)。また、仮想アドレス空間の可用性は、そもそも位置独立の動機のほとんどを隠します。
現在、オペレーティングシステムとコンパイラは、デフォルトですべてのコードを位置に依存しないコードとして作成します。-fPICフラグなしでコンパイルしてみてください。コードは正常にコンパイルされますが、警告が表示されます。WindowsのようなOSは、これを実現するためにメモリマッピングと呼ばれる手法を使用します。
質問の日付は2009年です。10年が経過し、現在、すべてのコードは実際には位置に依存していません。これは現在、オペレーティングシステムとコンパイラによって実施されています。オプトアウトする方法はありません。すべてのコードはPIEで強制コンパイルされ、このASLRの言い訳の一部として、-no-pic / -no-pieフラグは無視されます。その理由は、セキュリティの強化を装って、以前は高速だったアプリの速度を落とし、新しいハードウェアを販売するためです。これは完全に不合理です。メモリサイズが大きくなると、動的リンクの地獄を完全に取り除き、すべてのアプリを静的にコンパイルできるようになるからです。
人々がリアルモードや他の自由を奪うことを黙って受け入れたとき、同じことが以前に起こりました。また、コンテキストスイッチとアドレス変換の遅延により、MMUの速度が大幅に低下します。科学者が物理実験をサンプリングするために使用するような、パフォーマンスが重要なシステムにはMMUはありません。
コードがこれらすべての補助輪によってハンディキャップされていることすら知らないので、文句を言うことはありません。何と言えばいい?今すぐPICで2倍遅いソフトウェアをお楽しみください!さらに、LLVMの登場により、すぐにJIT(マネージコード)が適用され、x86インラインアセンブリにアクセスできなくなり、C / C ++コードの速度がさらに低下します。「安全のために自由を犠牲にする人はどちらにも値しない。」