feat: docs & ARCH 2.2, 2.3, 2.4
This commit is contained in:
151
kernel/docs/boot/linker.md
Normal file
151
kernel/docs/boot/linker.md
Normal file
@@ -0,0 +1,151 @@
|
||||
# Линкер-скрипты: архитектурные детали
|
||||
|
||||
## Назначение
|
||||
|
||||
Линкер-скрипты управляют расположением секций ELF-образа ядра.
|
||||
Для каждой архитектуры — свой скрипт, но все они следуют одной схеме.
|
||||
|
||||
## Общая структура
|
||||
|
||||
```
|
||||
OUTPUT_FORMAT(...) ← формат ELF (зависит от архитектуры)
|
||||
ENTRY(kmain) ← точка входа
|
||||
|
||||
PHDRS ← сегменты (program headers)
|
||||
{
|
||||
text PT_LOAD;
|
||||
rodata PT_LOAD;
|
||||
data PT_LOAD;
|
||||
}
|
||||
|
||||
SECTIONS ← расположение секций
|
||||
{
|
||||
. = 0xffffffff80000000; ← база higher half
|
||||
|
||||
.text : { *(.text .text.*) } :text
|
||||
|
||||
. = ALIGN(MAXPAGESIZE);
|
||||
.rodata : { *(.rodata .rodata.*) } :rodata
|
||||
|
||||
. = ALIGN(MAXPAGESIZE);
|
||||
.data : {
|
||||
*(.data .data.*)
|
||||
KEEP(*(.requests_start_marker))
|
||||
KEEP(*(.requests))
|
||||
KEEP(*(.requests_end_marker))
|
||||
} :data
|
||||
|
||||
.bss : { *(.bss .bss.*) *(COMMON) } :data
|
||||
|
||||
/DISCARD/ : { *(.eh_frame*) *(.note .note.*) }
|
||||
}
|
||||
```
|
||||
|
||||
## Детали
|
||||
|
||||
### OUTPUT_FORMAT
|
||||
|
||||
| Архитектура | Формат |
|
||||
|-------------|--------|
|
||||
| x86_64 | `elf64-x86-64` |
|
||||
| aarch64 | `elf64-littleaarch64` |
|
||||
| riscv64 | `elf64-littleriscv` |
|
||||
| loongarch64 | `elf64-loongarch` |
|
||||
|
||||
### Базовый адрес: 0xFFFFFFFF80000000
|
||||
|
||||
Ядро размещается в **higher half** — верхней 2 GiB виртуального
|
||||
адресного пространства. Это стандартная практика для x86-64:
|
||||
|
||||
```
|
||||
0x0000_0000_0000_00000 ─── user space (не используется ядром)
|
||||
0xFFFF_8000_0000_00000 ─── kernel space (higher half)
|
||||
0xFFFF_FFFF_FFFF_FFFF ─── конец
|
||||
```
|
||||
|
||||
Любой адрес в области 0xFFFF800000000000 — 0xFFFFFFFFFFFFFFFF корректен;
|
||||
0xFFFFFFFF80000000 выбран как начало typical higher half региона.
|
||||
|
||||
### PHDRS: PT_LOAD сегменты
|
||||
|
||||
Bootloader загружает только PT_LOAD сегменты. Их три:
|
||||
|
||||
1. **text**: код + inline-константы.
|
||||
2. **rodata**: неизменяемые данные (строки, таблицы).
|
||||
3. **data**: изменяемые данные + BSS.
|
||||
|
||||
### Section alignment
|
||||
|
||||
```ld
|
||||
. = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||
```
|
||||
|
||||
MAXPAGESIZE = 0x1000 (4 KiB). Каждая секция начинается с новой страницы,
|
||||
что даёт bootloader'у правильные MMU permissionы:
|
||||
- text = read + execute (no write)
|
||||
- rodata = read (no write, no execute)
|
||||
- data = read + write (no execute)
|
||||
|
||||
### Limine Requests в .data
|
||||
|
||||
```ld
|
||||
KEEP(*(.requests_start_marker))
|
||||
KEEP(*(.requests))
|
||||
KEEP(*(.requests_end_marker))
|
||||
```
|
||||
|
||||
- `KEEP` — запрещает линкеру выбрасывать эти секции (dead code elimination).
|
||||
- `.requests_start_marker` и `.requests_end_marker` — маркеры границ.
|
||||
- Bootloader сканирует память между ними, чтобы найти requests.
|
||||
|
||||
### BSS
|
||||
|
||||
```ld
|
||||
.bss : {
|
||||
*(.bss .bss.*)
|
||||
*(COMMON)
|
||||
} :data
|
||||
```
|
||||
|
||||
- BSS — неинициализированные глобальные переменные.
|
||||
- Занимает место в виртуальной памяти, но не в ELF-файле.
|
||||
- Bootloader обнуляет BSS перед передачей управления.
|
||||
|
||||
### DISCARD
|
||||
|
||||
```ld
|
||||
/DISCARD/ : {
|
||||
*(.eh_frame*)
|
||||
*(.note .note.*)
|
||||
}
|
||||
```
|
||||
|
||||
- `.eh_frame*` — исключительные фреймы C++/Rust unwinding.
|
||||
- `.note.*` — ELF notes.
|
||||
- Не нужны bare-metal ядру, могут вызвать проблемы.
|
||||
|
||||
## Архитектурные различия
|
||||
|
||||
### RISC-V
|
||||
|
||||
```ld
|
||||
.data : {
|
||||
*(.data .data.*)
|
||||
KEEP(*(.requests_start_marker))
|
||||
KEEP(*(.requests))
|
||||
KEEP(*(.requests_end_marker))
|
||||
*(.sdata .sdata.*) ← RISC-V: small data
|
||||
} :data
|
||||
|
||||
.bss : {
|
||||
*(.sbss .sbss.*) ← RISC-V: small BSS
|
||||
*(.bss .bss.*)
|
||||
*(COMMON)
|
||||
} :data
|
||||
```
|
||||
|
||||
RISC-V имеет `.sdata`/`.sbss` секции для small data (GP-relative addressing).
|
||||
|
||||
### AArch64 и LoongArch64
|
||||
|
||||
Идентичны x86_64, за исключением OUTPUT_FORMAT.
|
||||
Reference in New Issue
Block a user