ターン:FPICオブジェクトのLinuxの共有コンパイラパラメータ

 
最近、より興味深い知識のいくつかは、いくつかの要約ノートを行うためのもの、Linuxのプログラミングの基礎を見て、紙はFPICは、参照テキストの終わりを見ることを学ぶ、展開焦点を当てています。
  Linuxシステムでは、ダイナミックリンクファイルは動的共有オブジェクト(DSO、動的共有オブジェクト)と呼ばれる、共有オブジェクトと呼ばれ、通常の.soファイル拡張子です。Windowsシステムでは、それは.dll拡張子を持つ多く、ダイナミックリンクライブラリ(ダイナミックリンクライブラリ)と呼ばれています。ここだけメモLinuxの共有オブジェクト。
    共有オブジェクトを実装する場合、最も一般的なコマンドラインをコンパイルし、リンクされています 
 G ++ -fPIC -shared -o test.cc lib.so
    または:
    G ++ -fPIC TEST.CPP -c -o test.o 
    LD -shared test.o -o lib.so
    上記のコマンドラインは、共有ライブラリを産生することが示さ-shared、及び-fPICは位置独立コードを使用することを示しています。PIC:位置独立コード。    
    Linuxの共有ライブラリの下でコンパイルするときは、そうでない場合(AMD64マシンは、この間違っていることになる情報を持っているが、私はまた、インテルのマシンに現れた)エラーメッセージ内のリンクがあるだろう、-fPICパラメータを追加する必要があります。
/ usr / binに/ LD:test.o:共有オブジェクトを作成する際`ローカルシンボル」に対して再配置R_X86_64_32を使用することができません。-fPICで再コンパイル
test.o:シンボルを読み取ることができませんでした:不正な値の
collect2はを:ldは1つの終了ステータスを返しました
   共有オブジェクトを確認するために、どのようにPICはありますか?
readelfが-d foo.so | grepをTEXTREL 
シェルの上に任意の出力がある場合、これはfoo.so PICではありません。TEXTRELコードセグメントアドレス再配置テーブルを表し、PICは、コード再配置テーブルが含まれていないオブジェクトを共有しました。
     何FPIC目的ですか 共有オブジェクトは、共有オブジェクト命令が絶対アドレス、外部モジュールのアドレスを使用する場合、我々は、共有オブジェクトに関連したモジュールのローディング位置に応じて、このアドレスに調整を行う必要があり、異なる位置に異なるプロセスをロードすることができるロードされ、つまり、これらのアドレスを変更するために、それは、各プロセス内の物理メモリのコピーを持っている必要があり、共有物理メモリマルチプロセスを達成することができないセグメントに変更され、対応するプロセス、右にアクセスすることができます。FPIC命令が絶対アドレスに関連するそれらの場所の背後に限り、物理メモリを共有することができ、外部モジュールにアクセスするためのアドレスは、コードスニペットの内容ができることを確実にするために引き出されている複数のプロセスが同じ共有オブジェクトを使用できるようにすることです同じマルチプロセス、共有。
    データセグメントに配置されるGOT(グローバルオフセットテーブル)と呼ばれる場所に、アドレスの後に、特別な命令のこの部分から引き出され、各プロセスは、コンテンツの独自のコピーは、内部変数のアドレスであってもよい有します、関数のアドレス、異なるプロセスコンテンツの内容が異なる可能性があり、この部分は、「関連するアドレス」から分離されます。モジュールがロードされると、コンテンツのテーブルは、(遅延バインディングの非存在下で)取り込まGOTう。対応する項目のコール/ポップ/サブ得られた命令アドレスの同様の窓によって、GOTコードセグメントにアクセスするようになりました。
    アクセスモジュールのグローバル変数、同じモジュールで実行可能ファイルを解決するために、あなたはグローバル変数に問題がある可能性があり(この場合には、モジュール内のグローバル変数は、実行可能ファイル内のグローバル変数としてカバーされる)、グローバルモジュール用GOT間接的な変数のアクセスも介してアクセスできます。
    このように、各アクセスグローバル変数、外部関数がGOTで位置を計算するために必要とされ、その後、変数項に対応する値にアクセスし、呼び出し元の関数。走行性能から、比率はほとんど再配置をロードします。FPICパラメータをロードするときに再配置は、コードセグメントを使用していないロード時に、すべての補正特別なアドレスを再配置テーブルを必要とし、将来の実行にGOTと間接アクセスの位置を計算する必要はありません。(ただし、私はコンパイルとリンクされた共有ライブラリを、FPICパラメータを使用しないことができないとき、システムはFPICを持っている必要があり過半数を必要とするかもしれない、私のマシン上でそれをテストしました)
    あなたはGOTの内容に行けばロード時に計算され、それはそうそこに、読み込み速度に影響する 遅延バインディング だけGOTでいっぱいにするために、(レイジーバインディング)。それがために使用される PLT(プロシージャのリンクテーブル) 参照するモジュールの現在の動作の機能に対応するショートコードであり、その各々は:。関数が呼び出されると、まずここで、その後、GOTへ。関数が呼び出された最初の時間は、その後、PLTスキップローダー、ローダー、実際のアドレス計算機能、およびにGOTのPLTの記録位置から直接通話ジャンプ機能した後、項目GOTを対応するアドレスを書き込みます。これはまた、GOT位置を実行している多くの時間を計算するために複数の呼び出しを削減します。
    PIC共有オブジェクトは、データセグメントGOT、データ参照の絶対アドレスを再配置テーブルを持つことになり、これらは、再配置のために必要です。
  readelfが-r Lib.so
  再配置テーブルは、共有オブジェクト、.rel.dyn参照データが補正されるが、.rel.plt補正関数が参照されていることがわかります。
    
 
教材:「プログラマの自己栽培 - リンクがライブラリがロードされています。」

おすすめ

転載: www.cnblogs.com/timmgao/p/11012110.html