Read a Process's Memory Map with /proc/pid/maps
A segfault log gives you a bare address, and /proc/<pid>/maps is what turns that number into a named region and a file. The commands below are read-only: no debugger, no pause, no memory changes. This guide follows the installed proc_pid_maps(5) manpage from Linux man-pages 6.7, packaged here as manpages 6.7-2.
The route
Jump straight to the step you need, or tick off Done means at the end.
Allow about ten minutes. You need a shell and a running Linux process. Root is not a normal prerequisite, although the kernel's ptrace access check can deny access to another user's process. Start with your own shell so the first result is predictable.
1. Read the map for your current shell
Save the shell's process ID, then print its map:
pid=$$
printf 'Inspecting PID %s\n' "$pid"
sed -n '1,12p' "/proc/$pid/maps"
Expect several lines resembling this, although addresses, libraries and the number of regions will vary:
Inspecting PID 18420
55c8c4b1c000-55c8c4b1d000 r--p 00000000 08:02 131234 /usr/bin/bash
55c8c4b1d000-55c8c4c04000 r-xp 00001000 08:02 131234 /usr/bin/bash
55c8c4c04000-55c8c4c3c000 r--p 000e8000 08:02 131234 /usr/bin/bash
55c8c4c3c000-55c8c4c40000 r--p 0011f000 08:02 131234 /usr/bin/bash
55c8c4c40000-55c8c4c49000 rw-p 00123000 08:02 131234 /usr/bin/bash
55c8e2d9d000-55c8e2dbe000 rw-p 00000000 00:00 0 [heap]
Checkpoint
The file should open without sudo for your own shell. The final field is optional, so do not split a line on whitespace and assume it always has six fields; a blank pathname is a real result for an anonymous mapping.
2. Decode one mapping line
Each record has an address range, four permission characters, a file offset, device number, inode and an optional pathname:
address range perms offset dev inode pathname
55c8c4c40000-55c8c4c49000 rw-p 00123000 08:02 131234 /usr/bin/bash
- Address range is virtual address space, not a physical RAM location.
- Permission characters mean read, write, execute, and either shared (
s) or private copy-on-write (p). Sorw-pis writable private memory, andr-xpis executable private memory. - Offset is where the mapping begins in its backing file or object.
- Device and inode identify a file-backed object. An inode of
0means there is no associated inode, common for the heap and other anonymous regions. - Pathname usually names the backing file, but that is not a promise every byte currently comes from it: a private mapping can acquire anonymous copy-on-write pages after a write.
Do not treat r-xp as proof that code is currently executing, or rw-p as proof a region is safe to inspect as text. These are virtual memory permissions, and reading a live process repeatedly can produce different answers as mappings are created and removed.
3. Find the process regions people usually mean
Filter the complete map for the named pseudo-paths and file names:
pid=$$
grep -E '\[(heap|stack|vdso)\]|/usr/bin/bash' "/proc/$pid/maps"
Typical special entries: [heap] is the main process's heap, [stack] is the initial thread's stack, and [vdso] is the virtual dynamically linked shared object the kernel supplies. A blank pathname is also normal for anonymous mappings, so a filter that only prints lines ending in a file name is incomplete.
Modern kernels can show named anonymous mappings as [anon: name] from Linux 5.17, and named shared anonymous mappings as [anon_shmem: name] from Linux 6.2. The older [stack:tid] labels were removed in Linux 4.5. If you are writing tooling, accept these version-dependent labels rather than assuming every bracketed name is one of the three familiar regions.
4. Inspect a different PID carefully
Use an explicit numeric PID and quote the path:
target_pid=12345
if test -r "/proc/$target_pid/maps"; then
sed -n '1,20p' "/proc/$target_pid/maps"
else
status=$?
printf 'Cannot read /proc/%s/maps; check that the process exists and that access is permitted.\n' "$target_pid" >&2
exit "$status"
fi
Replace 12345 with a real process ID. The read permission test is only a first check: the process may exit between the test and the read, and the kernel applies the PTRACE_MODE_READ_FSCREDS access check described by the manpage. You may need elevated privilege for a process owned by another user:
$ sudo sed -n '1,20p' /proc/12345/maps
Use sudo only when the access policy requires it. It does not make a vanished PID reappear, and it does not freeze the target while you inspect it. For repeatable diagnostics, record the PID, command name and time of collection alongside the map.
5. Relate a file mapping to ELF program headers
For an executable or shared library named in the pathname column, compare the map's offset with the file's loadable segments:
$ readelf -l /usr/bin/bash | sed -n '/Program Headers:/,/Section to Segment mapping:/p'
Look for LOAD entries and their Offset values. A mapping whose offset starts at 00000000 commonly corresponds to the first loadable portion of an ELF file, while later read-only, executable or writable mappings begin at other file offsets. Addresses are relocated at run time, so compare the offset and permissions, not a hard-coded virtual address from another machine.
Tip
This is a correlation aid, not a complete memory dump. A pathname ending in (deleted) means the file was unlinked while still mapped: useful evidence, but the manpage warns that pathname text can be ambiguous, since newlines are escaped as an octal sequence and a literal backslash sequence cannot always be distinguished from the original pathname.
Common traps
- Do not assume a fixed field count. The pathname can contain spaces or be absent; read the first five whitespace-separated fields, then treat the remainder as pathname text.
- Do not confuse maps with memory usage. It describes virtual regions and access permissions. Use
/proc/$pid/smapsfor per-region accounting such as resident and proportional set size. - Do not infer a thread's stack from a [stack:tid] entry on a current kernel. Inspect
/proc/$pid/task/$tid/when you need thread-specific information. - Do not build security decisions from a single pathname or permission character. Mappings can change while a process runs, and the map does not tell you whether data is sensitive or code is trustworthy.
If a process exits during collection, rerun the command with a fresh PID. If access is denied even with the expected privilege, check the process ownership, the system's ptrace restrictions, and whether the target is inside another container or PID namespace.
Done means
- Read your shell's /proc/$pid/maps without changing system state.
- Explained each field: address, permissions, offset, device, inode and optional pathname.
- Recognised the special regions:
[heap],[stack],[vdso], anonymous mappings and version-dependent names. - Handled a missing or inaccessible PID in your script instead of silently producing an empty report.
- Used ELF offsets for correlation without mistaking the map for a stable memory dump.