Linux が共有ライブラリをアドレス空間にロードするタイミングと方法は?



私の質問は次のとおりです:


プログラムで共有オブジェクトのアドレスを指定するのはいつですか?リンク中?読み込んでいますか? system のメモリアドレスを見つけたい場合 libc 内のコマンド プログラム内で gdb で簡単に見つけることができました 、しかし、プログラムをデバッガーに持ち込みたくない場合はどうすればよいですか?


このアドレスは実行ごとに変わる可能性がありますか?実行時にライブラリまたは関数がこのプログラムのメモリ空間にロードされる場所を表示できる静的解析ツールは他にありますか?


編集:この情報はプログラム外で必要です (つまり、objdump のようなユーティリティを使用します) 情報収集のため)


答え:


ライブラリは ld.so によってロードされます (ダイナミック リンカまたはランタイム リンカ、別名 rtld、ld-linux.so.2 または ld-linux.so.* Linuxの場合; glibc の一部)。 「インタープリター」として宣言されています (INTERP; .interp 動的にリンクされたすべての ELF バイナリのセクション)。したがって、プログラムを開始すると、Linux は ld.so を開始します。 (メモリにロードし、そのエントリ ポイントにジャンプ)、次に ld.so プログラムをメモリにロードし、準備してから実行します。で動的プログラムを開始することもできます


 /lib/ld-linux.so.2 ./your_program your_prog_params

ld.so 実際の open を行います と mmap 必要なすべての ELF ファイルのうち、プログラムの ELF ファイルと必要なすべてのライブラリの ELF ファイルの両方。また、GOT および PLT テーブルに入力し、再配置の解決を行います (多くの場合、間接呼び出しを使用して、ライブラリから呼び出しサイトに関数のアドレスを書き込みます)。


ldd で取得できる一部のライブラリの典型的なロード アドレス 効用。実際には、ld.so のデバッグ環境変数を設定する bash スクリプトです (実際には LD_TRACE_LOADED_OBJECTS=1 glibc の rtld の場合)、プログラムを起動します。スクリプトを必要とせずに自分で行うこともできます。 bash を使用して、単一実行の環境変数を簡単に変更:


 LD_TRACE_LOADED_OBJECTS=1 /bin/echo

ld.so はこの変数を見て、必要なすべてのライブラリを解決し、それらのロード アドレスを出力します。しかし、この変数セットでは ld.so 実際にはプログラムを開始しません(プログラムまたはライブラリの静的コンストラクターについてはわかりません)。 ASLR 機能が無効になっている場合、ロード アドレスはほとんど同じになります。最新の Linux では ASLR が有効になっていることが多いため、無効にするには echo 0 | sudo tee /proc/sys/kernel/randomize_va_space を使用します .


system のオフセットを見つけることができます libc.so 内の関数 nm で binutils のユーティリティ。 nm -D /lib/libc.so を使うべきだと思います または objdump -T /lib/libc.so そしてgrep出力。