On this page
Process Memory Layout
Coverage: Interpreting /proc/pid/maps → stack/heap/mmap/vDSO/vvar/vsyscall → segments (text/data/bss) → Memory layout and ASLR → mmap mapping types Applicable to: Linux x86-64/ARM64 user space
Overview
Each Linux process sees a 48-bit (or 57-bit) virtual address space. Understanding the layout of this space is crucial for debugging out-of-bounds memory access, analyzing core dumps, and optimizing memory usage. /proc/pid/maps is the "map" of this layout.
Typical 64-bit Layout
/proc/pid/maps Detailed Explanation
# Format: address perms offset dev inode pathname
# === Binary (PIE) ===
# === Heap ===
# === Shared libraries ===
# === Thread stack (anonymous mmap) ===
# === Stack ===
Permission Bits Explanation
r--p: read-only, private ← .rodata, read-only segments
r-xp: read+execute, private ← .text
rw-p: read+write, private ← .data, .bss, heap, stack
r--s: read-only, shared ← rarely used
rw-s: read+write, shared ← MAP_SHARED mappings
---p: no access, private ← guard pages (stack/heap guard)
Anonymous Mappings vs. File Mappings
[heap], [stack], [vdso]: Anonymous mappings (no filename, created by kernel)
/lib64/libc.so.6: File mappings (has filename, mmap from file)
7f1233e00000 (no [name]): Anonymous mapping (malloc, thread stack)
→ Not [heap]! malloc uses mmap
Detailed Explanation of Each Region
Stack: Automatic Stack Growth
// Stack is allocated using mmap or brk (depending on kernel config)
// VM_GROWSDOWN: push beyond current stack bottom → page fault → kernel automatically expands stack
// → Expansion is limited by RLIMIT_STACK (default 8MB)
// → There is a guard page (---p) below the stack top to prevent overflow
// Main thread stack: located at [stack]
// Child thread stacks: pthread_create → mmap (usually 8MB, located in the mmap region)
Heap: brk vs mmap
// Traditional brk/sbrk: expands the data segment (directly following .bss)
// → User space: brk(addr) → changes program break
// → Problem: Fragmentation, cannot be released independently
// malloc's current strategy:
// 1. Small allocations (< 128KB default): uses brk → placed in [heap] region
// 2. Large allocations (>= 128KB): uses mmap → independent anonymous mapping
// 3. mmap threshold: can be adjusted via mallopt(M_MMAP_THRESHOLD)
vDSO / vvar / vsyscall: Kernel Injection
[vdso]: .so injected by the kernel into each process address space
Provides: __vdso_clock_gettime, __vdso_getcpu, __vdso_time, __vdso_getrandom
→ Executed in user space, no syscall → Extremely fast
[vvar]: vDSO data page (kernel timekeeper structure, per-CPU data)
→ R/O for userland
[vsyscall]: Deprecated fast system call page (x86 only)
→ Fixed address: 0xffffffffff600000 (security risk)
→ Now default emulate (page fault → kernel simulation → return)
Tools
# Process memory layout
|
# Memory mapping summary
# Memory usage summary
|
# VmPeak: Historical maximum virtual memory
# VmSize: Current virtual memory
# VmRSS: Physical memory (Resident)
# VmData/VmStk/VmExe/VmLib: Data/Stack/Code/Libraries
# ASLR settings
References
- Kernel Documentation:
Documentation/filesystems/proc.rst(maps/smaps) - Source Code:
fs/proc/task_mmu.c(/proc/pid/maps implementation),arch/x86/entry/vdso/ - LWN: "The vDSO and vvar", "ASLR for 64-bit Linux"
Keywords: /proc/pid/maps, stack, heap, vDSO, vvar, ASLR, PIE, smaps, brk, mmap