ELF Hello World Tutorial Generate the example Updated 2025-07-16
hello_world.asm
section .data
hello_world db "Hello world!", 10
hello_world_len equ $ - hello_world
section .text
global _start
_start:
mov rax, 1
mov rdi, 1
mov rsi, hello_world
mov rdx, hello_world_len
syscall
mov rax, 60
mov rdi, 0
syscallCompiled with:
nasm -w+all -f elf64 -o 'hello_world.o' 'hello_world.asm'
ld -o 'hello_world.out' 'hello_world.o' ELF Hello World Tutorial Global file structure Updated 2025-07-16
An ELF file contains the following parts:
- ELF header. Points to the position of the section header table and the program header table.
- Section header table (optional on executable). Each has
e_shnumsection headers, each pointing to the position of a section. - N sections, with
N <= e_shnum(optional on executable) - Program header table (only on executable). Each has
e_phnumprogram headers, each pointing to the position of a segment. - N segments, with
N <= e_phnum(only on executable)
The order of those parts is not fixed: the only fixed thing is the ELF header that must be the first thing on the file: Generic docs say:
In pictures: sample object file with three sections:
+-------------------+
| ELF header |---+
+---------> +-------------------+ | e_shoff
| | |<--+
| Section | Section header 0 |
| | |---+ sh_offset
| Header +-------------------+ |
| | Section header 1 |---|--+ sh_offset
| Table +-------------------+ | |
| | Section header 2 |---|--|--+
+---------> +-------------------+ | | |
| Section 0 |<--+ | |
+-------------------+ | | sh_offset
| Section 1 |<-----+ |
+-------------------+ |
| Section 2 |<--------+
+-------------------+But nothing (except sanity) prevents the following topology:
+-------------------+
| ELF header |---+ e_shoff
+-------------------+ |
| Section 1 |<--|--+
+---------> +-------------------+ | |
| | |<--+ | sh_offset
| Section | Section header 0 | |
| | |------|---------+
| Header +-------------------+ | |
| | Section header 1 |------+ |
| Table +-------------------+ |
| | Section header 2 |---+ | sh_offset
+---------> +-------------------+ | sh_offset |
| Section 2 |<--+ |
+-------------------+ |
| Section 0 |<---------------+
+-------------------+But some newbies may prefer PNGs :-)
ELF Hello World Tutorial How to learn Updated 2025-07-16
Spin like mad between:
- standards
- high level generators. We use the assembler
asand linkerld. - hexdumps
- file decompilers. We use
readelf. It makes it faster to read the ELF file by turning it into human readable output. But you must have seen one byte-by-byte example first, and think howreadelfoutput maps to the standard. - low-level generators: stand-alone libraries that let you control every field of the ELF files you generated. github.com/BR903/ELFkickers, github.com/sqall01/ZwoELF and many more on GitHub.
- consumer: the
execsystem call of the Linux kernel can parse ELF files to starts processes: github.com/torvalds/linux/blob/v4.11/fs/binfmt_elf.c, stackoverflow.com/questions/8352535/how-does-kernel-get-an-executable-binary-file-running-under-linux/31394861#31394861
ELF Hello World Tutorial Index 0 section Updated 2025-07-16
Contained in bytes 0x40 to 0x7F.
The first section is always magic: www.sco.com/developers/gabi/2003-12-17/ch4.sheader.html says:
If the number of sections is greater than or equal to SHN_LORESERVE (0xff00), e_shnum has the value SHN_UNDEF (0) and the actual number of section header table entries is contained in the sh_size field of the section header at index 0 (otherwise, the sh_size member of the initial entry contains 0).
There are also other magic sections detailed in
Figure 4-7: Special Section Indexes. ELF Hello World Tutorial Introduction Updated 2025-07-16
ELF Hello World Tutorial Minimal ELF file Updated 2025-07-16
It is non-trivial to determine what is the smallest legal ELF file, or the smaller one that will do something trivial in Linux.
Some impressive attempts:
ELF Hello World Tutorial Object hd Updated 2025-07-16
Running:gives:
hd hello_world.o00000000 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 |.ELF............|
00000010 01 00 3e 00 01 00 00 00 00 00 00 00 00 00 00 00 |..>.............|
00000020 00 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00 |........@.......|
00000030 00 00 00 00 40 00 00 00 00 00 40 00 07 00 03 00 |....@.....@.....|
00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00000080 01 00 00 00 01 00 00 00 03 00 00 00 00 00 00 00 |................|
00000090 00 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 |................|
000000a0 0d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000000b0 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000000c0 07 00 00 00 01 00 00 00 06 00 00 00 00 00 00 00 |................|
000000d0 00 00 00 00 00 00 00 00 10 02 00 00 00 00 00 00 |................|
000000e0 27 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |'...............|
000000f0 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000100 0d 00 00 00 03 00 00 00 00 00 00 00 00 00 00 00 |................|
00000110 00 00 00 00 00 00 00 00 40 02 00 00 00 00 00 00 |........@.......|
00000120 32 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |2...............|
00000130 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000140 17 00 00 00 02 00 00 00 00 00 00 00 00 00 00 00 |................|
00000150 00 00 00 00 00 00 00 00 80 02 00 00 00 00 00 00 |................|
00000160 a8 00 00 00 00 00 00 00 05 00 00 00 06 00 00 00 |................|
00000170 04 00 00 00 00 00 00 00 18 00 00 00 00 00 00 00 |................|
00000180 1f 00 00 00 03 00 00 00 00 00 00 00 00 00 00 00 |................|
00000190 00 00 00 00 00 00 00 00 30 03 00 00 00 00 00 00 |........0.......|
000001a0 34 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |4...............|
000001b0 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000001c0 27 00 00 00 04 00 00 00 00 00 00 00 00 00 00 00 |'...............|
000001d0 00 00 00 00 00 00 00 00 70 03 00 00 00 00 00 00 |........p.......|
000001e0 18 00 00 00 00 00 00 00 04 00 00 00 02 00 00 00 |................|
000001f0 04 00 00 00 00 00 00 00 18 00 00 00 00 00 00 00 |................|
00000200 48 65 6c 6c 6f 20 77 6f 72 6c 64 21 0a 00 00 00 |Hello world!....|
00000210 b8 01 00 00 00 bf 01 00 00 00 48 be 00 00 00 00 |..........H.....|
00000220 00 00 00 00 ba 0d 00 00 00 0f 05 b8 3c 00 00 00 |............<...|
00000230 bf 00 00 00 00 0f 05 00 00 00 00 00 00 00 00 00 |................|
00000240 00 2e 64 61 74 61 00 2e 74 65 78 74 00 2e 73 68 |..data..text..sh|
00000250 73 74 72 74 61 62 00 2e 73 79 6d 74 61 62 00 2e |strtab..symtab..|
00000260 73 74 72 74 61 62 00 2e 72 65 6c 61 2e 74 65 78 |strtab..rela.tex|
00000270 74 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |t...............|
00000280 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000290 00 00 00 00 00 00 00 00 01 00 00 00 04 00 f1 ff |................|
000002a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000002b0 00 00 00 00 03 00 01 00 00 00 00 00 00 00 00 00 |................|
000002c0 00 00 00 00 00 00 00 00 00 00 00 00 03 00 02 00 |................|
000002d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000002e0 11 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 |................|
000002f0 00 00 00 00 00 00 00 00 1d 00 00 00 00 00 f1 ff |................|
00000300 0d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000310 2d 00 00 00 10 00 02 00 00 00 00 00 00 00 00 00 |-...............|
00000320 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000330 00 68 65 6c 6c 6f 5f 77 6f 72 6c 64 2e 61 73 6d |.hello_world.asm|
00000340 00 68 65 6c 6c 6f 5f 77 6f 72 6c 64 00 68 65 6c |.hello_world.hel|
00000350 6c 6f 5f 77 6f 72 6c 64 5f 6c 65 6e 00 5f 73 74 |lo_world_len._st|
00000360 61 72 74 00 00 00 00 00 00 00 00 00 00 00 00 00 |art.............|
00000370 0c 00 00 00 00 00 00 00 01 00 00 00 02 00 00 00 |................|
00000380 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000390 ELF Hello World Tutorial
.rela.text Updated 2025-07-16Section type:
sh_type == SHT_RELA.Common name: "relocation section".
.rela.text holds relocation data which says how the address should be modified when the final executable is linked. This points to bytes of the text area that must be modified when linking happens to point to the correct memory locations.Basically, it translates the object text containing the placeholder 0x0 address:to the actual executable code containing the final 0x6000d8:
a: 48 be 00 00 00 00 00 movabs $0x0,%rsi
11: 00 00 004000ba: 48 be d8 00 60 00 00 movabs $0x6000d8,%rsi
4000c1: 00 00 00It was pointed to by
sh_info = 6 of the .symtab section.readelf -r hello_world.o outputs:Relocation section '.rela.text' at offset 0x3b0 contains 1 entries:
Offset Info Type Sym. Value Sym. Name + Addend
00000000000c 000200000001 R_X86_64_64 0000000000000000 .data + 0The section does not exist in the executable.
The actual bytes are:
00000370 0c 00 00 00 00 00 00 00 01 00 00 00 02 00 00 00 |................|
00000380 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|The
struct represented is:typedef struct {
Elf64_Addr r_offset;
Elf64_Xword r_info;
Elf64_Sxword r_addend;
} Elf64_Rela;So:
- 370 0:
r_offset= 0xC: address into the.textwhose address this relocation will modify - 370 8:
r_info= 0x200000001. Contains 2 fields:ELF64_R_TYPE= 0x1: meaning depends on the exact architecture.ELF64_R_SYM= 0x2: index of the section to which the address points, so.datawhich is at index 2.
The AMD64 ABI says that type1is calledR_X86_64_64and that it represents the operationS + Awhere:This address is added to the section on which the relocation operates. - 380 0:
r_addend= 0
ELF Hello World Tutorial
.rel.text Updated 2025-07-16 ELF Hello World Tutorial Section header table Updated 2025-07-16
Array of
Elf64_Shdr structs.Each entry contains metadata about a given section.
e_shoff of the ELF header gives the starting position, 0x40 here.So the table takes bytes from 0x40 to
0x40 + 7 + 0x40 - 1 = 0x1FF.Some section names are reserved for certain section types: www.sco.com/developers/gabi/2003-12-17/ch4.sheader.html#special_sections e.g.
.text requires a SHT_PROGBITS type and SHF_ALLOC + SHF_EXECINSTRRunning:outputs:
readelf -S hello_world.oThere are 7 section headers, starting at offset 0x40:
Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
[ 0] NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[ 1] .data PROGBITS 0000000000000000 00000200
000000000000000d 0000000000000000 WA 0 0 4
[ 2] .text PROGBITS 0000000000000000 00000210
0000000000000027 0000000000000000 AX 0 0 16
[ 3] .shstrtab STRTAB 0000000000000000 00000240
0000000000000032 0000000000000000 0 0 1
[ 4] .symtab SYMTAB 0000000000000000 00000280
00000000000000a8 0000000000000018 5 6 4
[ 5] .strtab STRTAB 0000000000000000 00000330
0000000000000034 0000000000000000 0 0 1
[ 6] .rela.text RELA 0000000000000000 00000370
0000000000000018 0000000000000018 4 2 4
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), l (large)
I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
O (extra OS processing required) o (OS specific), p (processor specific)The
struct represented by each entry is:typedef struct {
Elf64_Word sh_name;
Elf64_Word sh_type;
Elf64_Xword sh_flags;
Elf64_Addr sh_addr;
Elf64_Off sh_offset;
Elf64_Xword sh_size;
Elf64_Word sh_link;
Elf64_Word sh_info;
Elf64_Xword sh_addralign;
Elf64_Xword sh_entsize;
} Elf64_Shdr; ELF Hello World Tutorial Section vs segment Updated 2025-07-16
- section: exists before linking, in object files.Major information sections contain for the linker: is this section:
- segment: exists after linking, in the executable file.Contains information about how each segment should be loaded into memory by the OS, notably location and permissions.
ELF Hello World Tutorial
SHN_ABS Updated 2025-07-16hello_world_len points to the special st_shndx == SHN_ABS == 0xF1FF.0xF1FF is chosen so as to not conflict with other sections.st_value == 0xD == 13 which is the value we have stored there on the assembly: the length of the string Hello World!.This is small optimization that our assembler does for us and which has ELF support.
ELF Hello World Tutorial
.shstrtab Updated 2025-07-16Section type:
sh_type == SHT_STRTAB.Common name: "section header string table".
This section gets pointed to by the
e_shstrnd field of the ELF header itself.String indexes of this section are are pointed to by the
sh_name field of section headers, which denote strings.This section does not have outputs:
SHF_ALLOC marked, so it will not appear on the executing program.readelf -x .shstrtab hello_world.oHex dump of section '.shstrtab':
0x00000000 002e6461 7461002e 74657874 002e7368 ..data..text..sh
0x00000010 73747274 6162002e 73796d74 6162002e strtab..symtab..
0x00000020 73747274 6162002e 72656c61 2e746578 strtab..rela.tex
0x00000030 7400 t. Eligius pool Updated 2025-07-16
Created by Luke Dashjr.
The pool is named after Saint Eligius, patron of miners[ref]
Eligius also means to "choose" or "chosen" in Latin: en.wiktionary.org/wiki/Eligius, same root as "to elect" in modern English presumably.
Saint Eligius by Petrus Christus
. Source. Eligius pool is named after Saint Eligius, patron of goldsmiths and miners[ref] ELF Hello World Tutorial Standards Updated 2025-07-16
ELF is specified by the LSB:
The LSB basically links to other standards with minor extensions, in particular:
- Generic (both by SCO):
- System V ABI 4.1 (1997) www.sco.com/developers/devspecs/gabi41.pdf, no 64 bit, although a magic number is reserved for it. Same for core files. This is the first document you should look at when searching for information.
- System V ABI Update DRAFT 17 (2003) www.sco.com/developers/gabi/2003-12-17/contents.html, adds 64 bit. Only updates chapters 4 and 5 of the previous document: the others remain valid and are still referenced.
- Architecture specific (by the processor vendor):
A handy summary can be found at:
man elf ELF Hello World Tutorial
.strtab Updated 2025-07-16Holds strings for the symbol table.
This section has
sh_type == SHT_STRTAB.It is pointed to by outputs:
sh_link == 5 of the .symtab section.readelf -x .strtab hello_world.oHex dump of section '.strtab':
0x00000000 0068656c 6c6f5f77 6f726c64 2e61736d .hello_world.asm
0x00000010 0068656c 6c6f5f77 6f726c64 0068656c .hello_world.hel
0x00000020 6c6f5f77 6f726c64 5f6c656e 005f7374 lo_world_len._st
0x00000030 61727400 art.This implies that it is an ELF level limitation that global variables cannot contain NUL characters.
ELF Hello World Tutorial
STT_NOTYPE Updated 2025-07-16Then come the most important symbols:
Num: Value Size Type Bind Vis Ndx Name
4: 0000000000000000 0 NOTYPE LOCAL DEFAULT 1 hello_world
5: 000000000000000d 0 NOTYPE LOCAL DEFAULT ABS hello_world_len
6: 0000000000000000 0 NOTYPE GLOBAL DEFAULT 2 _start ELF Hello World Tutorial
STT_SECTION Updated 2025-07-16There are two such entries, one pointing to
.data and the other to .text (section indexes 1 and 2).Num: Value Size Type Bind Vis Ndx Name
2: 0000000000000000 0 SECTION LOCAL DEFAULT 1
3: 0000000000000000 0 SECTION LOCAL DEFAULT 2TODO what is their purpose?
ELF Hello World Tutorial
.symtab Updated 2025-07-16Section type:
sh_type == SHT_SYMTAB.A good high level tool to disassemble that section is:which gives:
nm hello_world.o0000000000000000 T _start
0000000000000000 d hello_world
000000000000000d a hello_world_lenThis is however a high level view that omits some types of symbols and in which the symbol types . A more detailed disassembly can be obtained with:which gives:
readelf -s hello_world.oSymbol table '.symtab' contains 7 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000000 0 FILE LOCAL DEFAULT ABS hello_world.asm
2: 0000000000000000 0 SECTION LOCAL DEFAULT 1
3: 0000000000000000 0 SECTION LOCAL DEFAULT 2
4: 0000000000000000 0 NOTYPE LOCAL DEFAULT 1 hello_world
5: 000000000000000d 0 NOTYPE LOCAL DEFAULT ABS hello_world_len
6: 0000000000000000 0 NOTYPE GLOBAL DEFAULT 2 _startThe binary format of the table is documented at www.sco.com/developers/gabi/2003-12-17/ch4.symtab.html
The data is:which gives:
readelf -x .symtab hello_world.oHex dump of section '.symtab':
0x00000000 00000000 00000000 00000000 00000000 ................
0x00000010 00000000 00000000 01000000 0400f1ff ................
0x00000020 00000000 00000000 00000000 00000000 ................
0x00000030 00000000 03000100 00000000 00000000 ................
0x00000040 00000000 00000000 00000000 03000200 ................
0x00000050 00000000 00000000 00000000 00000000 ................
0x00000060 11000000 00000100 00000000 00000000 ................
0x00000070 00000000 00000000 1d000000 0000f1ff ................
0x00000080 0d000000 00000000 00000000 00000000 ................
0x00000090 2d000000 10000200 00000000 00000000 -...............
0x000000a0 00000000 00000000 ........The entries are of type:
typedef struct {
Elf64_Word st_name;
unsigned char st_info;
unsigned char st_other;
Elf64_Half st_shndx;
Elf64_Addr st_value;
Elf64_Xword st_size;
} Elf64_Sym; ELF Hello World Tutorial
.text section Updated 2025-07-16Now that we've done one section manually, let's graduate and use the
readelf -S of the other sections: [Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
[ 2] .text PROGBITS 0000000000000000 00000210
0000000000000027 0000000000000000 AX 0 0 16.text is executable but not writable: if we try to write to it Linux segfaults. Let's see if we really have some code there:objdump -d hello_world.ohello_world.o: file format elf64-x86-64
Disassembly of section .text:
0000000000000000 <_start>:
0: b8 01 00 00 00 mov $0x1,%eax
5: bf 01 00 00 00 mov $0x1,%edi
a: 48 be 00 00 00 00 00 movabs $0x0,%rsi
11: 00 00 00
14: ba 0d 00 00 00 mov $0xd,%edx
19: 0f 05 syscall
1b: b8 3c 00 00 00 mov $0x3c,%eax
20: bf 00 00 00 00 mov $0x0,%edi
25: 0f 05 syscallIf we grep
b8 01 00 00 on the hd, we see that this only occurs at 00000210, which is what the section says. And the Size is 27, which matches as well. So we must be talking about the right section.The most interesting part is line to pass the address of the string to the system call. Currently, the This modification is possible because of the data of the
a which does:movabs $0x0,%rsi0x0 is just a placeholder. After linking happens, it will be modified to contain:4000ba: 48 be d8 00 60 00 00 movabs $0x6000d8,%rsi.rela.text section. There are unlisted articles, also show them or only show them.

