web-dev-qa-db-ja.com

いつ/どのようにLinuxは共有ライブラリをアドレス空間にロードしますか?

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

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

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

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

39
Ryan

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

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

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

lddユーティリティで取得できるいくつかのライブラリの一般的なロードアドレス。これは実際にはbashスクリプトであり、ld.so(glibcのrtldの場合は実際にはLD_TRACE_LOADED_OBJECTS=1)のデバッグ環境変数を設定してプログラムを起動します。スクリプトを使用せずに自分で行うこともできます。 bashを使用すると、1回の実行で環境変数を簡単に変更できます。

 LD_TRACE_LOADED_OBJECTS=1 /bin/echo

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

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

66
osgx

「ソースに直接行き、馬に尋ねなさい...」

Drepper-共有ライブラリの書き方

Linuxライブラリライターの必読ドキュメント。ロードのメカニズムについて少し詳しく説明します。

13
Dipstick

nmコマンドは、libc.soで使用され、libc.so内のsystemシンボルの場所を示します。ただし、ASLRが有効になっている場合、アドレスlibc.soが読み込まれるため、systemの最終アドレスは、プログラムが実行されるたびにランダムに変化します。 ASLRがなくても、libc.soが読み込まれるアドレスを特定し、その量だけsystemのアドレスをオフセットする必要があります。

名前をハードコーディングせずに関数のアドレスだけが必要な場合は、メインプログラムをdlopen()することができます。

void *self = dlopen(NULL, RTLD_NOW);
dlsym(self, "system"); // returns the pointer to the system() function

コンパイル時に名前がわかっている関数のアドレスだけが必要な場合は、void *addr = &system;を使用します。

7
ThiefMaster

お使いの環境にLD_LIBRARY_PATHパスを設定することをお勧めします。これは、共有ライブラリの場所を定義します。 /etc/ld.so.confを調べる必要がある場合もあります。この投稿を見てください http://www.google.com/url?sa=t&source=web&cd=3&ved=0CCQQFjAC&url=http%3A%2F%2Fubuntuforums .org%2Fshowthread.php%3Ft%3D324660&ei = KqJpTey7JofEsAPE9_imBA&usg = AFQjCNEIbGGrTHp4fufRuj4Yfc58RTHcag&sig2 = _9tdlyadMbPc-FcOdCko-w

0
mozillanerd