Fundamentals 9 min read

Understanding Linux Executable Files and Their Virtual Address Space

This article explains how Linux creates a new process with its own virtual address space, maps ELF executable segments to memory regions, describes the roles of code, data, and BSS sections, shows how to inspect mappings via /proc/pid/maps, and clarifies segment‑section relationships and loading details.

Liangxu Linux
Liangxu Linux
Liangxu Linux
Understanding Linux Executable Files and Their Virtual Address Space

Process Creation and Virtual Address Space

When an executable is run, Linux creates a new process and allocates a fresh virtual address space. The kernel reads the ELF file header, establishes a mapping between the file’s segments and the process’s address space, and sets the CPU instruction pointer to the entry point.

ELF File Layout

An ELF executable contains binary instructions and data that have already been translated into machine code. Inside the file, distinct segments (code, data, BSS, etc.) are defined. The code segment holds executable instructions, the data segment stores initialized variables, and the BSS segment reserves space for uninitialized variables.

32‑bit and 64‑bit Virtual Address Spaces

Inspecting the Process Layout via /proc

The virtual memory areas (VMAs) of a process can be examined with: cat /proc/pid/maps Each line of the output corresponds to a VMA described by the vm_area_struct structure, which includes vm_start and vm_end addresses and permission flags.

Segment Permissions

The first three VMAs usually correspond to the ELF file’s loadable segments. Their permissions differ:

Read‑execute (code segment)

Read‑write (data and BSS segments)

Read‑only (read‑only data)

Segments vs. Sections

ELF distinguishes between segments (used by the loader) and sections (used by the linker). The readelf -S name.elf command shows the section header table, while readelf -l name.elf displays the program header table containing segment information.

Loading Details and BSS Handling

Only two LOAD‑type segments need to be mapped; other segments like NOTE or GNU_STACK serve auxiliary purposes. The FileSiz field gives the size of the segment in the ELF file, while MemSiz shows the size in memory. The difference often accounts for the BSS area, which is zero‑filled at runtime and does not have a separate LOAD segment.

The BSS size can be observed as a 0x20 (32‑byte) increase in MemSiz compared to FileSiz. This extra space is automatically zero‑initialized, which explains why uninitialized global or static variables in C appear as zero.

Verification Example

A small program that prints the addresses of global and static variables confirms that the BSS region follows the data segment in memory.

Overall, ELF segments provide the execution view of a binary, while sections represent the linking view. The loader maps segments (and thus VMAs) based on their permissions, consolidating sections with similar attributes to reduce fragmentation and simplify memory management.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

ELFVirtual MemorySegmentsProcess Address Space
Liangxu Linux
Written by

Liangxu Linux

Liangxu, a self‑taught IT professional now working as a Linux development engineer at a Fortune 500 multinational, shares extensive Linux knowledge—fundamentals, applications, tools, plus Git, databases, Raspberry Pi, etc. (Reply “Linux” to receive essential resources.)

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.