誰もこの質問に回答していないので、私は試してみると思います。
実際の例を使って、これがどのように機能するかを見てみましょう。ここには、人為的だが意図的に外部のグローバル関数とデータ(再配置のパンとバター)が混在しているCコードがあります。
/* hello.c */
char* hello = "hello";
/* say.c */
#include "stdio.h"
extern char* hello;
void say(void){
printf(hello);
}
/* main.c */
extern void say(void);
void please_say(void){
say();
}
int main(void){
please_say();
return 0;
}
今すぐ共有オブジェクト/ライブラリを取得するための通常の方法は-fPICと各Cファイルをコンパイルすること、および-sharedで多くをリンクします。私たちがそれをした後、readelfを使って移転を調べることができます。このような何か:次のように
gcc -fPIC -c *.c
gcc -shared -o libtemp.so *.o
readelf -r libtemp.so
再配置データは次のとおりです。
Relocation section '.rel.dyn' at offset 0x34c contains 6 entries:
Offset Info Type Sym.Value Sym. Name
000016dc 00000008 R_386_RELATIVE
000016e0 00000008 R_386_RELATIVE
000016ac 00000106 R_386_GLOB_DAT 00000000 __gmon_start__
000016b0 00000206 R_386_GLOB_DAT 00000000 _Jv_RegisterClasses
000016b4 00000d06 R_386_GLOB_DAT 000016e0 hello
000016b8 00000406 R_386_GLOB_DAT 00000000 __cxa_finalize
Relocation section '.rel.plt' at offset 0x37c contains 5 entries:
Offset Info Type Sym.Value Sym. Name
000016c8 00000107 R_386_JUMP_SLOT 00000000 __gmon_start__
000016cc 00000507 R_386_JUMP_SLOT 000004fc please_say
000016d0 00000807 R_386_JUMP_SLOT 00000540 say
000016d4 00000307 R_386_JUMP_SLOT 00000000 printf
000016d8 00000407 R_386_JUMP_SLOT 00000000 __cxa_finalize
ハローのためのR_386_GLOB_DAT項目はGOTエントリです。同様に、R_386_JUMP_SLOTの項目、例えばplease_sayとprintfはPLTエントリです。それらは、位置独立コードの使用であり、私たちが共有オブジェクトを作成したという事実ではありません。
-fPICなしで同じビルドプロセスを実行すると、異なる再配置が発生します。だから、
gcc -c *.c
gcc -shared -o libtemp.so *.o
readelf -r libtemp.so
は私達に、すべての定義について
Relocation section '.rel.dyn' at offset 0x34c contains 9 entries:
Offset Info Type Sym.Value Sym. Name
00001674 00000008 R_386_RELATIVE
00001678 00000008 R_386_RELATIVE
000004d3 00000802 R_386_PC32 000004f0 say
000004e0 00000502 R_386_PC32 000004cc please_say
000004f7 00000d01 R_386_32 00001678 hello
000004ff 00000302 R_386_PC32 00000000 printf
00001654 00000106 R_386_GLOB_DAT 00000000 __gmon_start__
00001658 00000206 R_386_GLOB_DAT 00000000 _Jv_RegisterClasses
0000165c 00000406 R_386_GLOB_DAT 00000000 __cxa_finalize
Relocation section '.rel.plt' at offset 0x394 contains 2 entries:
Offset Info Type Sym.Value Sym. Name
0000166c 00000107 R_386_JUMP_SLOT 00000000 __gmon_start__
00001670 00000407 R_386_JUMP_SLOT 00000000 __cxa_finalize
今、共有オブジェクトが持っているおなじみの再配置を提供します。 helloの絶対的な再配置と、関数のPC相対再配置があります。
これはどういう意味ですか? GOTテーブルとPLTテーブルはまだそこにあります。注意すべき2つの重要なことがあります。 1つは、コンパイルされたコードのGOTまたはPLTエントリがないことです。 2番目は、GOTテーブルとPLTテーブルがまだ必要であるということです。それらは初期化とクリーンアップに使用されています(標準ライブラリの場合もあります)。カスタムELFローダーを使用しているので、メインアプリケーションが標準的な再配置を行う代わりに、GOTエントリとPLTエントリの基本的なサポートを実装することをお勧めします。
あなたのアプリケーションは、再配置の価格を支払うが、ポジションの独立性は支払わない。