2011-01-25 20 views
0

私はリロケータブル共有ライブラリを生成するカスタムツールチェーンを持っています。これは等しくカスタムのELFローダで動作し、これらをメモリにロードして修正します。私は今、gccとbinutilsにこのローダーと互換性のあるELFファイルを生成するよう説得しようとしています。binutilsでリロケータブル共有ライブラリを作成する

残念ながら、binutilsはの再配置可能な共有オブジェクトの生成を拒否しているようです。それはPIC共有オブジェクトを生成しますが、私はGOT/PLTの余分なオーバーヘッドのためにこれをしたくありません(また、カスタムELFローダーはそれをサポートしていません)。また、リロケータブルオブジェクトが生成されますが、動的オブジェクトではないため、ELFローダーがロードできる適切なセクションがありません。

GNU ldが同じコマンドラインで-relocatableと-sharedを指定することを拒否している理由についてはっきりしていません。誰でも私を啓発することはできますか?そして、誰も私が探しているオブジェクトファイルを生成するための呪文を知っていますか?

答えて

2

誰もこの質問に回答していないので、私は試してみると思います。

実際の例を使って、これがどのように機能するかを見てみましょう。ここには、人為的だが意図的に外部のグローバル関数とデータ(再配置のパンとバター)が混在している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エントリの基本的なサポートを実装することをお勧めします。

あなたのアプリケーションは、再配置の価格を支払うが、ポジションの独立性は支払わない。

関連する問題