私が書いた main.c
Linuxの場合:
int main()
{
while (1){}
}
コンパイルして起動すると、pmap
できます。
# pmap 28578
28578: ./a.out
0000000000400000 4K r-x-- /root/a.out
0000000000600000 4K r---- /root/a.out
0000000000601000 4K rw--- /root/a.out
00007f87c16c2000 1524K r-x-- /lib/libc-2.11.1.so
00007f87c183f000 2044K ----- /lib/libc-2.11.1.so
00007f87c1a3e000 16K r---- /lib/libc-2.11.1.so
00007f87c1a42000 4K rw--- /lib/libc-2.11.1.so
00007f87c1a43000 20K rw--- [ anon ]
00007f87c1a48000 128K r-x-- /lib/ld-2.11.1.so
00007f87c1c55000 12K rw--- [ anon ]
00007f87c1c65000 8K rw--- [ anon ]
00007f87c1c67000 4K r---- /lib/ld-2.11.1.so
00007f87c1c68000 4K rw--- /lib/ld-2.11.1.so
00007f87c1c69000 4K rw--- [ anon ]
00007fff19b82000 84K rw--- [ stack ]
00007fff19bfe000 8K r-x-- [ anon ]
ffffffffff600000 4K r-x-- [ anon ]
total 3876K
合計(3876)をKで除算すると、VIRT
の出力のtop
列に等しくなります。では、テキストセグメントはどこにありますか? 400000、600000、601000ですね。どこに何があるか説明はどこで読めますか? man pmap
は役に立たなかった。
テキストセグメントは0x400000でのマッピングです。読み取り可能および実行可能であるために「r-x」とマークされています。 0x600000でのマッピングは読み取り専用であるため、これはほぼ確実に実行可能ファイルの「.rodata」セクションです。 GCCはC文字列リテラルを読み取り専用セクションに配置します。 0x601000でのマッピングは「rw-」であるため、おそらくそれは有名なヒープです。実行可能ファイルmalloc()
1024バイトを用意し、アドレスを出力して確認します。
プロセスのPIDを見つけて次のようにすると、もう少し情報が得られる場合があります。cat /proc/$PID/maps
-私のArchラップトップでは、追加の情報が表示されます。それは3.12カーネルを実行しているので、/proc/$PID/numa_maps
もあり、小さな洞察を与えるかもしれないcattingも持っています。
実行可能ファイルで実行するその他のこと:nm
およびobjdump -x
。前者は、メモリマップ内のさまざまなものがどこにあるのかを知ることができるため、0x4000000セクションと他のセクションの内容を確認できます。 objdump -x
は、ELFファイルのヘッダーを他の多くのものの中で表示するため、すべてのセクションを表示できます。セクション名と、それらがランタイムにマップされているかどうかを確認できます。
「どこにあるのか」について書かれた説明を見つける限り、「ELFファイルのメモリレイアウト」については、googleなどのことを行う必要があります。 ELFファイル形式は、一般的に使用されるよりもエキゾチックなメモリレイアウトをサポートできることに注意してください。 GCCとGnu ldとglibcはすべて、実行可能ファイルがどのようにレイアウトされ、実行時にメモリにマップされるかについて、単純化した仮定を行います。これを文書化することを意図した多くのWebページが存在しますが、古いバージョンのLinux、古いバージョンのGCCまたはglibcにのみ適用されるか、x86実行可能ファイルにのみ適用されます。お持ちでない場合は、readelf
コマンドを入手してください。 Cプログラムを記述できる場合は、独自のバージョンのobjdump -x
またはreadelf
を作成して、実行可能ファイルがどのように機能するか、およびそれらの内容を理解してください。