< BACK TO TERMINAL

Owning Memory: Memory Layout Basics

Introduction

When a new process is created, the Kernel assigns it a structured Virtual Address Space. This Virtual Address Space is divided into segments.

To ensure consistent and clear terminology, this post focuses on ELF binaries on Linux x86-32.

Memory Segments

These segments are well-known and can be visually represented as the layout below.

File-backed vs Runtime-managed Segments

Memory segments fall into two categories:

You can find every standard ELF section in the Linux Standard Base Specification.

The Layout

Below is a quick breakdown of each Segment, ordered from low addresses to high addresses.

Text Segment (.text)

The text segment contains your program’s executable machine code.

Example (x86-32 machine code bytes):

31 C0 C3

Disassembly:

xor eax, eax
ret

Data Segment (.data)

The data segment stores initialized global and static variables.

Example:

int g_counter = 1337;          // .data
static char banner[] = "hi";   // .data

BSS Segment (.bss)

The BSS segment stores uninitialized (or zero-initialized) global and static variables.

Example:

int g_flag;               // .bss
static char buf[4096];    // .bss

Heap Segment

The heap is where dynamic memory is allocated explicitly by the programmer (e.g., via malloc or new).

The Heap grows upward (towards higher addresses).

Example:

#include <stdlib.h>

int main(void) {
    int *p = malloc(sizeof *p); // allocate space for one int on the heap
    *p = 42;                    // write into the allocated heap memory
    free(p);                    // release the heap memory
}

Memory Mapping Segment (Libraries)

This region (often called the Memory Mapping Segment) is located between the heap and the stack. It contains the Shared libraries (e.g., libc.so, ld-linux.so).

Stack Segment

The stack is a LIFO (Last-In First-Out) structure used for function calls (Stack Frames), local variables, and temporary values.

The Stack grows downward (towards lower addresses).

Example:

#include <stdio.h>

int main(void) {
    int a = 0; // local variable (stack)

    printf("%p\n", (void *)&a); // print the address of a
}

Arguments and Environment Variables Segment

At the very top of the user space (just before the kernel boundary), the OS places:

  1. Arguments (argv): Command line arguments.
  2. Environment (envp): Environment variables (e.g., PATH, HOME).
  3. Auxiliary Vector: Info passed from the OS to the program loader.

Kernel Space Segment

User processes run in user space and cannot directly read or write addresses in the kernel space. This area is reserved for the kernel code, kernel data structures, and hardware drivers. Attempting to access this range from user mode triggers a Segmentation Fault.

Next steps

See Owning Memory: Understanding the Stack Frame

← Previous articleNext article →