2011-08-20 17 views
4

私は共有ライブラリの再配置を調査中で、何か不思議に思っていました。このコードを考えてみましょう:共有ライブラリの再配置エントリ

int myglob; 

int ml_util_func(int p) 
{ 
    return p + 2; 
} 

int ml_func2(int a, int b) 
{ 
    int c = ml_util_func(a); 
    return c + b + myglob; 
} 

私はgcc -shared非PIC共有ライブラリにそれをコンパイルします。私はx86上で動作する32ビットのUbuntuでこれを行います。

結果の.soは、ml_util_funcへのコールの再配置エントリがml_func2にあります。

0000050d <ml_func2>: 
50d: 55      push ebp 
50e: 89 e5     mov ebp,esp 
510: 83 ec 14    sub esp,0x14 
513: 8b 45 08    mov eax,DWORD PTR [ebp+0x8] 
516: 89 04 24    mov DWORD PTR [esp],eax 
519: e8 fc ff ff ff   call 51a <ml_func2+0xd> 
         51a: R_386_PC32 ml_util_func 
51e: 89 45 fc    mov DWORD PTR [ebp-0x4],eax 
521: 8b 45 0c    mov eax,DWORD PTR [ebp+0xc] 
524: 8b 55 fc    mov edx,DWORD PTR [ebp-0x4] 
527: 01 c2     add edx,eax 
529: a1 00 00 00 00   mov eax,ds:0x0 
         52a: R_386_32 myglob 
52e: 8d 04 02    lea eax,[edx+eax*1] 
531: c9      leave 
532: c3      ret  
533: 90      nop 

call命令にR_386_PC32移転:ここml_func2objdump -dR -Mintelの出力です。

今、私の質問はです。この移転はなぜ必要ですe8はx86では "call relative ..."で、同じオブジェクトにml_util_funcが定義されているので、リンカは動的ローダに残さずに、呼び出しと呼び出しの間の相対的なオフセットを計算できますか?

興味深いことに、ml_util_funcstaticと宣言された場合、再配置は消え、リンカーは正しくオフセットを計算して挿入します。それについては、ml_util_funcについてもそれは何か、それについてリンカを怠惰にする輸出されている?

P .:私は、PIC以外のコードで意図的に遊んでいます。ロード時の移転を理解しています。

+0

-fPICなしで '.so'をコンパイルする理由 – osgx

+0

@ osgx:私の質問が最初の文章で述べているように、私は具体的にはロード時の移転に興味があります。私は現在、P.S.を追加しました。明確にする –

+0

あるライブラリのグローバルシンボルを別のライブラリ(LD_PRELOAD)でオーバーロードすることはできますか? – osgx

答えて

4

はなぜ見つけることができませんが、これは、この程度のbinutilsからのコメントです:

のbinutils-2.11.90-20010705-src.tar.gz/BFD/ELF32-i386.c:679

 /* If we are creating a shared library, and this is a reloc 
     against a global symbol, or a non PC relative reloc 
     against a local symbol, then we need to copy the reloc 
     into the shared library. However, if we are linking with 
     -Bsymbolic, we do not need to copy a reloc against a 
     global symbol which is defined in an object we are 

私はこの再配置を作成して、ユーザーがライブラリ内のグローバルシンボルをオーバーロードできると考えています。そして、-Bsymbolicはこの能力を無効にし、ライブラリ自体からのシンボルの再配置を生成しないようです。

http://www.rocketaware.com/man/man1/ld.1.htm

-Bsymbolic このオプションは、リンク編集セッションで を解決するために、出力内のすべてのシンボル参照が発生します。実行時に唯一残っている実行時間は、ベースアドレスの再配置、すなわちロードアドレスに対する の変換です。 のシンボリックリファレンスを解決できないと、エラーが報告されます。

種々-Bモードおよび制限の説明(C++)ここで長く:

http://developers.sun.com/sunstudio/documentation/ss12/mr/man1/CC.1.html

-B 結合

  Specifies whether a library binding for linking is 
      symbolic, dynamic (shared), or static (nonshared). 

      -Bdynamic is the default. You can use the -B 
      option several times on a command line. 

      For more information on the -Bbinding option, see 
      the ld(1) man page and the Solaris documentation. 


      -Bdynamic directs the link editor to look for 
      liblib.so files. Use this option if you want 
      shared library bindings for linking. If the 
      liblib.so files are not found, it looks for 
      liblib.a files. 

      -Bstatic directs the link editor to look only for 
      liblib.a files. The .a suffix indicates that the 
      file is static, that is, nonshared. Use this 
      option if you want nonshared library bindings for 
      linking. 

      -Bsymbolic forces symbols to be resolved within a 
      shared library if possible, even when a symbol is 
      already defined elsewhere. For an explanation of 
      -Bsymbolic, see the ld(1) man page. 

      This option and its arguments are passed to the 
      linker, ld. If you compile and link in separate 
      steps and are using the -Bbinding option, you must 
      include the option in the link step. 

      Warning: 

      Never use -Bsymbolic with programs containing C++ 
      code, use linker scoping instead. See the C++ 
      User's Guide for more information on linker scop- 
      ing. See also the -xldscope option. 

      With -Bsymbolic, references in different modules 
      can bind to different copies of what is supposed 
      to be one global object. 

      The exception mechanism relies on comparing 
      addresses. If you have two copies of something, 
      their addresses won't compare equal, and the 
      exception mechanism can fail because the exception 
      mechanism relies on comparing what are supposed to 
      be unique addresses. 
+1

興味深いことに、Bsymbolicについて説明しているこのページもあります:http://www.technovelty.org/code/c/bsymbolic.html私はこれを勉強しますポインタのおかげで –

+0

Bsymbolicはちょうど関連するフラグだと思うのですが、実際のところはシンボルの検索順です - 実行可能ファイル、共有ライブラリ、そしてこれを使ってグローバルシンボルを上書きする機能検索順序。 LD_PRELOADは別の方法です。 –

0

注オブジェクトその必ずしもそのブロックにリンクされているブロックではありません全体。コードによって参照されるかどうかに応じて、最後の.exeに配置できるシンボルを別々のセクションに配置する方法があります。 (-gc-sectionリンカーオプションと関連するセクション生成gccオプションの検索)

セクションを使用しない場合は、これを単純にマイクロオプティマイザーではないかもしれません。

関連する問題