flat assembler
Message board for the users of flat assembler.

Index > Linux > Explain Like I'm 5: Segments in ELF files.

Thread Post new topic Reply to topic

Joined: 21 Apr 2013
Posts: 5
Location: Bloomington
aaditmshah 13 Mar 2018, 22:44
Consider the following hello world program:

format ELF64 executable 0
entry main

segment readable executable

    mov rax, 1
    mov rdi, 1
    mov rsi, msg
    mov rdx, len

    mov rax, 60
    xor rdi, rdi

segment readable writeable

msg db "Hello World!", 10
len = $ - msg    

What do the segment directives in this program do? I tried experimenting with it to understand what they do. First, I removed the executable permission flag from the first segment. To my surprise, the code still worked. Next, I removed the readable permission flag from the second segment and the code still worked. Finally, I removed both the segment directives and the code still worked fine.

So, what do these segment directive do? Explain like I'm 5.
Post 13 Mar 2018, 22:44
View user's profile Send private message Send e-mail Visit poster's website Reply with quote

Joined: 09 Nov 2018
Posts: 77
bzt 25 Nov 2018, 13:48
Since you got no answers, I'll try to explain.

The ELF format has two separate views: sections and segments. Sections are used when linking. You typically create different sections for different types of code (.text, .text.init, .text.fini, etc.) and data (.data.readonly, .data.initialized, .bss (uninitialized data) etc.). Sections do not have memory addresses associated with them, only file offsets. When you link your object files, the linker uses these sections to concatenate code and data in their final place. With a linker script you can control what sections you want to see in the object file. With fasm, you can use directives in your assembly file to define those sections.

On the final step of linking, when you're producing an executable, those sections are assigned with a virtual memory address (VMA), and according to their attibutes (read, write, execute, initialized etc.) they are gather together into segments. With fasm, you can eliminate this step, and you can create an executable directly using segment directives. When you run your executable, the loader (that's called ld-linux.so under Linux) does not know anything about your sections, it only sees those segments.

To understand this a bit better, I suggest to use "readelf -a hello" on your compiled code. You'll see Program Headers (those are the segments that needs to be loaded into memory at different VMAs), a segment mapping of sections (telling you which section ended up in which segment), and a Section Headers table (only used by the linker). You'll see that both segments and sections are referencing the same parts of your ELF file.

For example: if you have code section (called text) and read only data (called .data.ro), then you have two different sections, which are used as two independent entities by the linker (one is code and the other is data after all). Despite of this, it's very likely that they will be concatenated into the same single segment, because you have to load and map both non-writable, and the loader does not need to know if the bytes it's loading are code or data.

Post 25 Nov 2018, 13:48
View user's profile Send private message Reply with quote
Tomasz Grysztar

Joined: 16 Jun 2003
Posts: 8346
Location: Kraków, Poland
Tomasz Grysztar 25 Nov 2018, 14:29
This was also discussed in several other threads, like here.
Post 25 Nov 2018, 14:29
View user's profile Send private message Visit poster's website Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  

< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum

Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.