web-dev-qa-db-ja.com

プロセスは共有ライブラリのアドレスをどのように知っていますか?

私の理解では、Cソースコードをコンパイルすると、GCC/LDはコンパイル時にアドレスバインディングを実行します。通常、このアドレスはゼロから始まります。共有ライブラリから関数を呼び出すと、コンパイラは共有ライブラリのアドレスを事前に知る方法を教えてください。共有ライブラリはロード時にアドレスを取得することを知っています。私が間違っている場合は私を訂正してください。

3
Saber

あなたはあなた自身がこれを理解するのを助けるためにいくつかのことをすることができます。

ldd /usr/bin/cat

私のラップトップでは、次の出力が得られます。

1771 % ldd /usr/bin/cat 
        linux-vdso.so.1 (0x00007ffc37fba000)
        libc.so.6 => /usr/lib/libc.so.6 (0x00007f1ea7018000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f1ea73bc000)

linux-vdso.so.1libc.so.6には完全修飾パスがなく、lddは、libc.so.6で動的にリンクするために使用される実際のパスを示しています。

少し変更を加えて、もう一度lddを実行することで、それを確認できます(そして少し学びます)。

1790 % export LD_LIBRARY_PATH=/lib
1791 % ldd /usr/bin/cat 
        linux-vdso.so.1 (0x00007fff0a5a0000)
        libc.so.6 => /lib/libc.so.6 (0x00007fa257535000)
        /lib64/ld-linux-x86-64.so.2 (0x00007fa2578d9000)

よく見ると、ダイナミックリンカー(この場合は/lib64/ld-linux-x86-64.so.2)がCライブラリとして/lib/libc.so.6を選択することがわかります。したがって、環境変数LD_LIBRARY_PATHは、動的リンクで実際に使用されるファイルを決定するために重要です。

あなたができる他のことはstraceです:

strace -o cat.trace /usr/bin/cat /etc/motd

ファイルcat.traceには、サブジェクトプロセスが実行するシステムコールの記録が含まれます。それらのいくつかは、動的にリンクされているとしてlddによって示されるファイルのmmap()になります。mmapをグーグルでフォローアップします。

さらに読む:man ld.so

readelfコマンドがインストールされているかどうか、インストールできるかどうか、またはコンパイルできるかどうかを確認してください。 readelf -a /usr/bin/catを実行します。実際の ELF仕様 は私の意見では浸透できませんが、 somegood ELF形式 information があります。それを見つけてみてください。

musl libc がインストールされているか、インストールできる場合は、musllibcでコンパイルされた単純な実行可能ファイルで上記と同じ実験を行うと非常に有益です。ダイナミックリンクのように複雑なものでも、同じオペレーティングシステム上に2つの異なる動作する実装を持つことができます。

2
Bruce Ediger