Fundamentals 15 min read

Why Do Linux Segmentation Faults Occur? ELF Layout, Memory Mapping & Debugging

This article explains how Linux programs are loaded, the distinction between ELF sections and segments, virtual‑to‑physical address translation, the role of the MMU, brk/sbrk usage, address‑space layout, and practical steps to reproduce and avoid segmentation faults.

ITPUB
ITPUB
ITPUB
Why Do Linux Segmentation Faults Occur? ELF Layout, Memory Mapping & Debugging

Background

When developing on Linux, encountering a Segmentation Fault is common. The error indicates that a process accessed memory without proper permission, but the underlying cause often lies in how the operating system loads and maps executable files.

ELF, Linking View vs. Execution View

Linux executables, object files (*.o) and shared libraries (*.so) all use the ELF format. The linker views an ELF file as a collection of Section s (e.g., .text, .data, .bss). When the loader creates a process, it treats the same file as a series of Segment s, each mapped into the process address space. The following diagrams illustrate the difference:

ELF sections
ELF sections
ELF segments
ELF segments

Memory Layout and the MMU

Each process has its own virtual address space. The Memory Management Unit (MMU) translates virtual addresses to physical memory. Accesses to addresses that are not mapped by the MMU trigger a segmentation fault. Typical layout (simplified) includes:

Code segment starting at 0x08048000

Data and BSS segments

Heap (managed via brk() / sbrk())

Stack (high addresses)

Process virtual address layout
Process virtual address layout

Program Header vs. Section Header

Object files (*.o) contain only a Section Header Table; they lack a Program Header Table. Shared libraries (*.so) have both. Executables must contain a Program Header Table for the loader, but the loader may ignore the Section Header Table. This design allows the loader to map only the necessary segments, improving memory utilization.

Randomized Address Space (ASLR)

Linux enables Address Space Layout Randomization via /proc/sys/kernel/randomize_va_space. Values:

0 – No randomization; addresses match those in the ELF file.

1 – Randomize stack only.

2 – Randomize stack, heap, and load address.

For reproducible experiments, disable ASLR:

echo "0" > /proc/sys/kernel/randomize_va_space

Practical Example: Observing the Brk

The following C program prints the start address of main, the end of the BSS segment, and the current brk value, then iterates over memory addresses to demonstrate where a segmentation fault occurs.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int bssvar;

int main(int argc, char **argv) {
    void *ptr;
    printf("main start = %p
", main);
    printf("bss end = %p
", (long)&bssvar + 4);
    ptr = sbrk(0);
    printf("current brk = %p
", (long *)ptr);
    sleep(8);
    int i = 0x08049628;
    for (;; i++) {
        printf("At:0x%x-0x%x
", i, *((char *)i));
    }
}

Running this program (with ASLR disabled) shows that addresses up to the current brk are accessible; accessing beyond triggers a segmentation fault.

Extending the Brk with brk()

By manually moving the break point, you can extend the heap:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int bssvar;

int main(int argc, char **argv) {
    void *ptr;
    printf("main start = %p
", main);
    printf("bss end = %p
", (long)&bssvar + 4);
    ptr = sbrk(0);
    printf("current brk = %p
", (long *)ptr);
    sleep(8);
    int i = 0x08049628;
    brk((char*)0x804A123); // manually set break
    for (;; i++) {
        printf("At:0x%x-0x%x
", i, *((char *)i));
    }
}

After setting the break to 0x804A123, the program can safely access memory up to the next page boundary (0x804B000) before a fault occurs.

Preventing Segmentation Faults

Most faults arise from accessing unmapped or protected regions, such as addresses before 0x08048000, after 0xC0000000, or beyond the current brk. Good practices include:

Always check pointers for NULL before dereferencing.

After freeing memory, set the pointer to NULL to avoid dangling references.

Understand the process’s virtual address layout and avoid hard‑coded addresses.

By following these guidelines and using tools like readelf -h to inspect ELF headers, developers can diagnose and eliminate segmentation faults more efficiently.

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.

LinuxELFmemory layoutsegmentation fault
ITPUB
Written by

ITPUB

Official ITPUB account sharing technical insights, community news, and exciting events.

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.