目的
仮想メモリ空間のアドレス等のメモリマップを調べる。
なお、ちゃんと調べたわけではないので誤りがあるかもしれない。
環境
- OS: Oracle Enterprise Linux 5.8
- Kernel: 2.6.32-300.10.1.el5uek x86_64
仮想メモリ空間のメモリマップ
Unix/Linux における仮想メモリ空間のメモリマップは一般には以下のようになっている。
+------------------------------+ 0x0000000000000000
: :
+------------------------------+
| |
| text | 機械命令
| |
+------------------------------+
| |
| data | 初期化された static 変数
| |
+------------------------------+
| |
| BSS | 初期化されていない static 変数
| |
+------------------------------+
| |
| heap | malloc() で動的に確保される領域(上位アドレスに伸びる)
| |
+------------------------------+
| |||| |
| VVVV |
: :
: :
| |
+------------------------------+
| |
| shared memory | 共有メモリ領域
| |
+------------------------------+
| |
: :
: :
| ^^^^ |
| |||| |
+------------------------------+
| |
| stack | 関数呼び出しやローカル変数等で使用されるスタック領域(下位アドレスに伸びる)
| |
+------------------------------+
| |
| arguments / environments | 引数と環境変数
| |
+------------------------------+
: :
: :
+------------------------------+ 0xffffffffffffffff = 2^64 (64bit の場合)
実例
以下のプログラムでメモリマップを確認する。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
|
実行結果は以下。
$ gcc -o hello hello.c
$ ./hello ARGworld
hello, ARGworld: 0x00007ffff7269cb5
hello, not initialized global world: 0x0000000000600ec0
hello, initialized global world: 0x0000000000600de0
hello, not initialized static world: 0x0000000000600e80
hello, initialized static world: 0x0000000000600e20
hello, malloc world: 0x0000000001f61010
hello, shared memory world: 0x00007f2eeea0e000
hello, big malloc world: 0x00007f2eee9b0010
hello, medium malloc world 1: 0x00007f2eee98f010
hello, medium malloc world 2: 0x0000000001f61060
hello, local world: 0x00007ffff7269680
メモリマップは pmap
や cat /proc/<PID>/maps
や cat /proc/<PID>/smaps
で確認できる。
$ pmap -x 19671
19671: ./hello ARGworld
Address Kbytes RSS Dirty Mode Mapping
0000000000400000 4 4 0 r-x-- hello
0000000000600000 4 4 4 rw--- hello
0000000001f61000 132 8 8 rw--- [ anon ]
00000037be000000 112 96 0 r-x-- ld-2.5.so
00000037be21c000 4 4 4 r---- ld-2.5.so
00000037be21d000 4 4 4 rw--- ld-2.5.so
00000037be400000 1340 248 0 r-x-- libc-2.5.so
00000037be54f000 2044 0 0 ----- libc-2.5.so
00000037be74e000 16 12 8 r---- libc-2.5.so
00000037be752000 4 4 4 rw--- libc-2.5.so
00000037be753000 20 16 16 rw--- [ anon ]
00007f2eee98d000 408 20 20 rw--- [ anon ]
00007f2eeea0e000 4 4 4 rw-s- [ shmid=0x578006 ]
00007f2eeea0f000 8 8 8 rw--- [ anon ]
00007ffff7255000 84 8 8 rw--- [ stack ]
00007ffff730e000 4 4 0 r-x-- [ anon ]
ffffffffff600000 4 0 0 r-x-- [ anon ]
---------------- ------ ------ ------
total kB 4196 444 88
$ cat /proc/19671/maps
00400000-00401000 r-xp 00000000 fd:00 5101878 /tmp/hello
00600000-00601000 rw-p 00000000 fd:00 5101878 /tmp/hello
01f61000-01f82000 rw-p 00000000 00:00 0 [heap]
37be000000-37be01c000 r-xp 00000000 fd:00 1871272 /lib64/ld-2.5.so
37be21c000-37be21d000 r--p 0001c000 fd:00 1871272 /lib64/ld-2.5.so
37be21d000-37be21e000 rw-p 0001d000 fd:00 1871272 /lib64/ld-2.5.so
37be400000-37be54f000 r-xp 00000000 fd:00 1871273 /lib64/libc-2.5.so
37be54f000-37be74e000 ---p 0014f000 fd:00 1871273 /lib64/libc-2.5.so
37be74e000-37be752000 r--p 0014e000 fd:00 1871273 /lib64/libc-2.5.so
37be752000-37be753000 rw-p 00152000 fd:00 1871273 /lib64/libc-2.5.so
37be753000-37be758000 rw-p 00000000 00:00 0
7f2eee98d000-7f2eee9f3000 rw-p 00000000 00:00 0
7f2eeea0e000-7f2eeea0f000 rw-s 00000000 00:04 5734406 /SYSV00000000 (deleted)
7f2eeea0f000-7f2eeea11000 rw-p 00000000 00:00 0
7ffff7255000-7ffff726a000 rw-p 00000000 00:00 0 [stack]
7ffff730e000-7ffff730f000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
size
コマンドで text や BSS のサイズを確認できる。
$ size hello
text data bss dec hex filename
2414 704 160 3278 cce hello
$ size --format=SysV -x hello
hello :
section size addr
.interp 0x1c 0x400200
.note.ABI-tag 0x20 0x40021c
.gnu.hash 0x1c 0x400240
.dynsym 0x108 0x400260
.dynstr 0x6d 0x400368
.gnu.version 0x16 0x4003d6
.gnu.version_r 0x20 0x4003f0
.rela.dyn 0x18 0x400410
.rela.plt 0xd8 0x400428
.init 0x18 0x400500
.plt 0xa0 0x400518
.text 0x488 0x4005c0
.fini 0xe 0x400a48
.rodata 0x25 0x400a58
.eh_frame_hdr 0x34 0x400a80
.eh_frame 0xd4 0x400ab8
.ctors 0x10 0x600b90
.dtors 0x10 0x600ba0
.jcr 0x8 0x600bb0
.dynamic 0x190 0x600bb8
.got 0x8 0x600d48
.got.plt 0x60 0x600d50
.data 0xa0 0x600dc0
.bss 0xa0 0x600e60
.comment 0x114 0x0
Total 0xde2
これらから次のようなメモリマップとなっていると考えられる。
+------------------------------+ 0x0000000000000000
: :
+------------------------------+ 0x0000000000400000
|text | 機械命令
| |
+------------------------------+ 0x0000000000401000
: :
+------------------------------+ 0x0000000000600000
| | 0x0000000000600dc0
|data | 初期化された static 変数
| initialized global var | 0x0000000000600de0
| initialized static var | 0x0000000000600e20
| |
+------------------------------+ 0x0000000000600e60
|BSS | 初期化されていない static 変数
| not initialized static var | 0x0000000000600e80
| not initialized global var | 0x0000000000600ec0
| |
+------------------------------+ 0x0000000000601000
: :
+------------------------------+ 0x0000000001f61000
|heap | malloc() で動的に確保される領域(上位アドレスに伸びる)
| malloc var | 0x0000000001f61010
| malloc var | 0x0000000001f61060
| |
+------------------------------+ 0x0000000001f82000
| |||| |
| VVVV |
: :
: :
| |
+------------------------------+ 0x00000037be000000
| |
| 共有ライブラリ |
| (ld-2.5.so, libc-2.5.so) |
+------------------------------+ 0x00000037be753000
| ??? |
+------------------------------+ 0x00000037be758000
| |
: :
: :
| ^^^^ ?? |
| |||| ?? |
+------------------------------+ 0x00007f2eee98d000
|heap?? |
| malloc var | 0x00007f2eee98f010
| big malloc var | 0x00007f2eee9b0010
| |
+------------------------------+ 0x00007f2eee9f3000
: :
+------------------------------+ 0x00007f2eeea0e000
|shared memory | 共有メモリ領域
| shared memory var | 0x00007f2eeea0e000
| |
+------------------------------+ 0x00007f2eeea0f000
|??? |
+------------------------------+ 0x00007f2eeea11000
| |
: :
: :
| ^^^^ |
| |||| |
+------------------------------+ 0x00007ffff7255000
|stack | 関数呼び出しやローカル変数等で使用されるスタック領域(下位アドレスに伸びる)
| local var | 0x00007ffff7269680
| arguments[1] | 0x00007ffff7269cb5
| |
+------------------------------+ 0x00007ffff726a000
: :
+------------------------------+ 0x00007ffff730e000
|??? |
+------------------------------+ 0x00007ffff730f000
| |
: :
: :
| |
+------------------------------+ 0xffffffffff600000
|arguments / environments?? |
| |
+------------------------------+ 0xffffffffff601000
: :
: :
+------------------------------+ 0xffffffffffffffff = 2^64 (64bit の場合)
heap としては 0x0000000001f61000 〜 0x0000000001f82000 の 132Kbytes が割り当てられているようだが、 約132Kbytes より大きく malloc() で動的にメモリを割り当てるとアドレスが飛んで 0x00007f2eee98d000 付近に メモリが割り当てられ、しかも下位にメモリが伸びているようだ。