Code Yarns ‍👨‍💻
Tech BlogPersonal Blog

Memory layout of a process in Linux

📅 2015-Apr-27 ⬩ ✍️ Ashwin Nanjappa ⬩ 📚 Archive

After reading The Art of Debugging, I was curious to see the memory layout of a process in Linux. In modern operating systems, this is essentially the virtual memory layout and I tried this with a 64-bit Linux.

I wrote a simple C++ program which had these components:

I compiled and ran the a.out program, made it wait for user input, found its PID and tried:

$ cat /proc/PID/maps

That output, with some annotations, is shown below:

Address                   Perm Offset   Dev   Inode     Path
00400000-00401000         r-xp 00000000 08:06 55325003  /home/joe/bin/a.out
00600000-00601000         r--p 00000000 08:06 55325003  /home/joe/bin/a.out
00601000-00602000         rw-p 00001000 08:06 55325003  /home/joe/bin/a.out
01b5f000-01b91000         rw-p 00000000 00:00 0         [heap]
7f180c4d2000-7f180c68d000 r-xp 00000000 08:06 13238492  /lib/x86_64-linux-gnu/libc-2.19.so
7f180c68d000-7f180c88c000 ---p 001bb000 08:06 13238492  /lib/x86_64-linux-gnu/libc-2.19.so
7f180c88c000-7f180c890000 r--p 001ba000 08:06 13238492  /lib/x86_64-linux-gnu/libc-2.19.so
7f180c890000-7f180c892000 rw-p 001be000 08:06 13238492  /lib/x86_64-linux-gnu/libc-2.19.so
7f180c892000-7f180c897000 rw-p 00000000 00:00 0 
7f180c897000-7f180ca04000 r-xp 00000000 08:06 45088807  /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21
7f180ca04000-7f180cc03000 ---p 0016d000 08:06 45088807  /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21
7f180cc03000-7f180cc0d000 r--p 0016c000 08:06 45088807  /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21
7f180cc0d000-7f180cc0f000 rw-p 00176000 08:06 45088807  /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21
7f180cc0f000-7f180cc13000 rw-p 00000000 00:00 0 
7f180cc13000-7f180cc36000 r-xp 00000000 08:06 13238486  /lib/x86_64-linux-gnu/ld-2.19.so
7f180ce06000-7f180ce0b000 rw-p 00000000 00:00 0 
7f180ce31000-7f180ce35000 rw-p 00000000 00:00 0 
7f180ce35000-7f180ce36000 r--p 00022000 08:06 13238486  /lib/x86_64-linux-gnu/ld-2.19.so
7f180ce36000-7f180ce37000 rw-p 00023000 08:06 13238486  /lib/x86_64-linux-gnu/ld-2.19.so
7f180ce37000-7f180ce38000 rw-p 00000000 00:00 0 
7fff9b79a000-7fff9b7bb000 rw-p 00000000 00:00 0         [stack]
7fff9b7fe000-7fff9b800000 r-xp 00000000 00:00 0         [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]

By observing the memory ranges in this output, we can build the classic memory layout of a process by ourselves:

0x00                                  0xFF
Text Data Heap ---> DLLs <--- Stack Kernel

I always found the vertical layout used in textbooks confusing, so I like to lay it out horizontally like this. Left to right, you go from low to high memory addresses.

A few notes by observing the output of proc and the layout:

Reference: Proc.txt from Linux kernel source code

Tried with: Linux 3.13.0-45 and Ubuntu 14.04