refer wiki: https://en.wikipedia.org/wiki/Executable_and_Linkable_Format
https://pdos.csail.mit.edu/6.828/2018/labs/lab1/
need refine when have time. The point is to notice the relationship between program header and section header and the mapping. The readelf -a illustrates this relationship very nicely.
To make sense out of boot/main.c you'll need to know what an ELF binary is. When you compile and link a C program such as the JOS kernel, the compiler transforms each C source ('.c') file into an object ('.o') file containing assembly language instructions encoded in the binary format expected by the hardware. The linker then combines all of the compiled object files into a single binary image such as obj/kern/kernel, which in this case is a binary in the ELF format, which stands for "Executable and Linkable Format".
File layout
Each ELF file is made up of one ELF header, followed by file data. The data can include:
- Program header table, describing zero or more memory segments
- Section header table, describing zero or more sections
- Data referred to by entries in the program header table or section header table
The segments (program header) contain information that is needed for run time execution of the file, while sections contain important data for linking and relocation.
The boot loader uses the ELF segments (program headers) to decide how to load the sections. The program headers specify which parts of the ELF object to load into memory and the destination address each should occupy.
sections, each of which is a contiguous chunk of code or data intended to be loaded into memory at a specified address.
hfyin@hfyin-VirtualBox:~/projects/6.828/jos/obj$ readelf -a kern/kernel
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: EXEC (Executable file)
Machine: Intel 80386
Version: 0x1
Entry point address: 0x10000c
Start of program headers: 52 (bytes into file) ## at the start of file
Start of section headers: 86776 (bytes into file) ## a the end of file
Flags: 0x0
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 3
Size of section headers: 40 (bytes)
Number of section headers: 15
Section header string table index: 14
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .text PROGBITS f0100000 001000 0019e9 00 AX 0 0 16
[ 2] .rodata PROGBITS f0101a00 002a00 0006c0 00 A 0 0 32
[ 3] .stab PROGBITS f01020c0 0030c0 003b95 0c A 4 0 4
[ 4] .stabstr STRTAB f0105c55 006c55 001948 00 A 0 0 1
[ 5] .data PROGBITS f0108000 009000 009300 00 WA 0 0 4096
[ 6] .got PROGBITS f0111300 012300 000008 00 WA 0 0 4
[ 7] .got.plt PROGBITS f0111308 012308 00000c 04 WA 0 0 4
[ 8] .data.rel.local PROGBITS f0112000 013000 001000 00 WA 0 0 4096
[ 9] .data.rel.ro.loca PROGBITS f0113000 014000 000044 00 WA 0 0 4
[10] .bss PROGBITS f0113060 014060 000648 00 WA 0 0 32
[11] .comment PROGBITS 00000000 0146a8 00002b 01 MS 0 0 1
[12] .symtab SYMTAB 00000000 0146d4 0007c0 10 13 66 4
[13] .strtab STRTAB 00000000 014e94 0003e6 00 0 0 1
[14] .shstrtab STRTAB 00000000 01527a 00007d 00 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
L (link order), O (extra OS processing required), G (group), T (TLS),
C (compressed), x (unknown), o (OS specific), E (exclude),
p (processor specific)
There are no section groups in this file.
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x001000 0xf0100000 0x00100000 0x0759d 0x0759d R E 0x1000
LOAD 0x009000 0xf0108000 0x00108000 0x0b6a8 0x0b6a8 RW 0x1000
GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RWE 0x10
Section to Segment mapping:
Segment Sections...
00 .text .rodata .stab .stabstr
01 .data .got .got.plt .data.rel.local .data.rel.ro.local .bss
02
Examine the full list of the names, sizes, and link addresses of all the sections in the kernel executable by typing:
athena% objdump -h obj/kern/kernel
Take particular note of the "VMA" (or link address) and the "LMA" (or load address) of the .text section. The load address of a section is the memory address at which that section should be loaded into memory.
The link address of a section is the memory address from which the section expects to execute. The linker encodes the link address in the binary in various ways, such as when the code needs the address of a global variable, with the result that a binary usually won't work if it is executing from an address that it is not linked for. (It is possible to generate position-independent code that does not contain any such absolute addresses. This is used extensively by modern shared libraries, but it has performance and complexity costs, so we won't be using it in 6.828.)
ELF program headers to decide how to load the sections. The program headers specify which parts of the ELF object to load into memory and the destination address each should occupy. You can inspect the program headers by typing:
athena% objdump -x obj/kern/kernel
The program headers are then listed under "Program Headers" in the output of objdump. The areas of the ELF object that need to be loaded into memory are those that are marked as "LOAD". Other information for each program header is given, such as the virtual address ("vaddr"), the physical address ("paddr"), and the size of the loaded area ("memsz" and "filesz").