web-dev-qa-db-ja.com

動的にロード/リンクされたライブラリのメモリレイアウト

linuxシステムで共有ライブラリをロードするとき、共有ライブラリのメモリレイアウトはどうなりますか?

たとえば、元のメモリレイアウトは次のとおりです。

+-----------+
|heap(ori)  |
+-----------+
|stack(ori) |
+-----------+
|.data(ori) |
+-----------+
|.text(ori) |
+-----------+

Dlopen foo.so、メモリレイアウトはAまたはBですか?

A
+-----------+
|heap(ori)  |
+-----------+
|stack(ori) |
+-----------+
|.data(ori) |
+-----------+
|.text(ori) |
+-----------+
|heap(foo)  |
+-----------+
|stack(foo) |
+-----------+
|.data(foo) |
+-----------+
|.text(foo) |
+-----------+

または

B
+-----------+
|heap(ori)  |
+-----------+
|heap(foo)  |
+-----------+
|stack(foo) |
+-----------+
|stack(ori) |
+-----------+
|.data(foo) |
+-----------+
|.data(ori) |
+-----------+
|.text(foo) |
+-----------+
|.text(ori) |
+-----------+

またはAとB以外...?

6
Richard

答えは「その他」です。 _cat /proc/self/maps_を使用すると、メモリレイアウトを垣間見ることができます。私の64ビットArchラップトップ::

_00400000-0040c000 r-xp 00000000 08:02 1186758                            /usr/bin/cat
0060b000-0060c000 r--p 0000b000 08:02 1186758                            /usr/bin/cat
0060c000-0060d000 rw-p 0000c000 08:02 1186758                            /usr/bin/cat
02598000-025b9000 rw-p 00000000 00:00 0                                  [heap]
7fe4b805c000-7fe4b81f5000 r-xp 00000000 08:02 1182914                    /usr/lib/libc-2.21.so
7fe4b81f5000-7fe4b83f5000 ---p 00199000 08:02 1182914                    /usr/lib/libc-2.21.so
7fe4b83f5000-7fe4b83f9000 r--p 00199000 08:02 1182914                    /usr/lib/libc-2.21.so
7fe4b83f9000-7fe4b83fb000 rw-p 0019d000 08:02 1182914                    /usr/lib/libc-2.21.so
7fe4b83fb000-7fe4b83ff000 rw-p 00000000 00:00 0
7fe4b83ff000-7fe4b8421000 r-xp 00000000 08:02 1183072                    /usr/lib/ld-2.21.so
7fe4b85f9000-7fe4b85fc000 rw-p 00000000 00:00 0
7fe4b85fe000-7fe4b8620000 rw-p 00000000 00:00 0
7fe4b8620000-7fe4b8621000 r--p 00021000 08:02 1183072                    /usr/lib/ld-2.21.so
7fe4b8621000-7fe4b8622000 rw-p 00022000 08:02 1183072                    /usr/lib/ld-2.21.so
7fe4b8622000-7fe4b8623000 rw-p 00000000 00:00 0
7ffe430c4000-7ffe430e5000 rw-p 00000000 00:00 0                          [stack]
7ffe431ed000-7ffe431ef000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]
_

実行可能ファイルが低メモリにロードされていることがわかります。明らかに.textセグメント、読み取り専用データ、.bssです。それはまさに「ヒープ」です。より高いメモリでは、Cライブラリと「ELFファイルインタープリター」、「ld-so」がロードされます。次にスタックが来る。ロードされた共有ライブラリの数に関係なく、特定のアドレス空間には1つのスタックと1つのヒープしかありません。 catはCライブラリがロードされているようです。

_cat /proc/$$/maps_を実行すると、catを呼び出したシェルのメモリマッピングが得られます。どのシェルにも多数の動的に読み込まれるライブラリがありますが、zshbashは大量に読み込まれます。 「[ヒープ]」が1つ、「[スタック]」が1つあることがわかります。

dlopen()を呼び出すと、共有オブジェクトファイルは_/usr/lib/libc-2.21.so_よりも高いアドレスのアドレス空間にマッピングされます。 「実装に依存する」メモリマッピングセグメントがあり、mmap()によって返されたすべてのアドレスが表示されます。素敵なグラフィックについては、 メモリ内のプログラムの分析 を参照してください。

_/usr/lib/ld-2.21.so_のソースは少しトリッキーですが、内部の多くはdlopen()と共有しています。 dlopen()は二級市民ではありません。

「vdso」と「vsyscall」はいくぶん不可解ですが、 このStackoverflowの質問 は、ウィキペディアと同様に、適切な説明があります。

6
Bruce Ediger