私は共有ライブラリの再配置を調査中で、何か不思議に思っていました。このコードを考えてみましょう:共有ライブラリの再配置エントリ
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_func2
上objdump -dR -Mintel
の出力です。
今、私の質問はです。この移転はなぜ必要です? e8
はx86では "call relative ..."で、同じオブジェクトにml_util_func
が定義されているので、リンカは動的ローダに残さずに、呼び出しと呼び出しの間の相対的なオフセットを計算できますか?
興味深いことに、ml_util_func
がstatic
と宣言された場合、再配置は消え、リンカーは正しくオフセットを計算して挿入します。それについては、ml_util_func
についてもそれは何か、それについてリンカを怠惰にする輸出されている?
P .:私は、PIC以外のコードで意図的に遊んでいます。ロード時の移転を理解しています。
-fPICなしで '.so'をコンパイルする理由 – osgx
@ osgx:私の質問が最初の文章で述べているように、私は具体的にはロード時の移転に興味があります。私は現在、P.S.を追加しました。明確にする –
あるライブラリのグローバルシンボルを別のライブラリ(LD_PRELOAD)でオーバーロードすることはできますか? – osgx