私の理解では、Cソースコードをコンパイルすると、GCC/LDはコンパイル時にアドレスバインディングを実行します。通常、このアドレスはゼロから始まります。共有ライブラリから関数を呼び出すと、コンパイラは共有ライブラリのアドレスを事前に知る方法を教えてください。共有ライブラリはロード時にアドレスを取得することを知っています。私が間違っている場合は私を訂正してください。
あなたはあなた自身がこれを理解するのを助けるためにいくつかのことをすることができます。
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.1
とlibc.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つの異なる動作する実装を持つことができます。