( bzt | 2023. 07. 18., k – 12:56 )

Huh, rövid FreeBSD helyzetjelentés. Hát, őszintén szólva többet vártam a FreeBSD-től.

TL;DR: alakul, mint púposgyerek az úthenger alatt, de még nem megy, viszont már tudom, mi volt a baja.

És akkor egy szösszennet arról, miken mentem keresztül. Először is, ledöbbentett, mennyire használhatatlan a doksi. Nagyon bő, meg sok infó van benne, csak épp olyanok, amiket millió másik helyen is megtalálsz. Arról, ami igazán FreeBSD specifikus, konrkétan egy mukkot sem ejtenek. Érdemes megnézni, mennyit írnak a boot loaderről és a kernel handoverről, az egyetlen dologról, ami igazán érdekelne a doksiból: https://docs.freebsd.org/en/books/arch-handbook/boot/#boot-loader és akkor nézzük meg a hivatkozott loader(8) man oldalt is...

Másodszor, a FreeBSD na az bizony egy higher-half kernel, így élből page faultot dobott az első adatelérésnél. Mivel nincs IDT-je, ezért ez tripple fault, amit CPU úgy kezel, hogy újraindul. Sebaj, beraktam a támogatást a Simpleboot-ba. mostantól támogatja a higher-half kerneleket is! :-) Viszont itt még nincs vége. Továbbra is triple fault.

Alaposan körbejártam, ezúttal azért van a hiba, mert a FreeBSD-t rosszul írták meg. Komolyan. Erre tökre nem számítottam. A hibát az okozza, hogy egy iskolapéldaszerű segfault-ot produkál. Olvasni próbál egy olyan adatterületről, ami a szegmensein kívül helyzkedik el. Konkrétan a 0xffffffff80000000 címről, a 0020:ffffffff80c55f93 címen található "mov edx, dword ptr ds:[rax]" utasítás okozza. Csakhogy

readelf -l kernel

Elf file type is EXEC (Executable file)
Entry point 0xffffffff8038b000
There are 11 program headers, starting at offset 64

Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
PHDR 0x0000000000000040 0xffffffff80200040 0x0000000000200040
0x0000000000000268 0x0000000000000268 R 0x8
INTERP 0x00000000000002a8 0xffffffff802002a8 0x00000000002002a8
0x000000000000000d 0x000000000000000d R 0x1
[Requesting program interpreter: /red/herring]
LOAD 0x0000000000000000 0xffffffff80200000 0x0000000000200000
0x000000000018aa98 0x000000000018aa98 R 0x200000
LOAD 0x000000000018b000 0xffffffff8038b000 0x000000000038b000
0x0000000000dfd150 0x0000000000dfd150 R E 0x200000
LOAD 0x0000000000f88150 0xffffffff81188150 0x0000000001188150
0x0000000000675154 0x0000000000675154 R 0x200000
LOAD 0x0000000001600000 0xffffffff81800000 0x0000000001800000
0x0000000000000140 0x0000000000000140 RW 0x200000
LOAD 0x0000000001601000 0xffffffff81801000 0x0000000001801000
0x00000000001c38e8 0x00000000005ff000 RW 0x200000
DYNAMIC 0x0000000001600000 0xffffffff81800000 0x0000000001800000
0x0000000000000140 0x0000000000000140 RW 0x8
GNU_RELRO 0x0000000001600000 0xffffffff81800000 0x0000000001800000
0x0000000000000140 0x0000000000000140 R 0x1
GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 RW 0x0
NOTE 0x00000000015fd1d4 0xffffffff817fd1d4 0x00000000017fd1d4
0x0000000000000024 0x0000000000000024 R 0x4

Jól látszik, hogy ez a címterület bizony kívül esik az összes szegmensen. Ez még hagyján, de úgy nyúlkál a fordító által definiált memórián kívülre, hogy előtte nem állított be page fault handlert.

Hogy minek kéne lennie ezen a címen, az passz, sehol nem találom a doksikban. Valószínűleg valami rendszerbetöltő által átadott struktúrának kéne lennie, vagy ilyesmi. Gondoltam teszek egy próbát, és belapoztam ide egy üres lapot. És itt ért a második meglepetés. A kód most már tovább fut, viszont nem ellenőrzi az adatokat, így persze előbb utóbb hülyeséget csinál, és továbbra is segfault a vége.

Szóval röviden összefoglalva: a FreeBSD kernel nem képes maga belapozni a területeit, olyan adatterületekre nyúlkál, ami a fordító által definiált tartományon kívülre esik, és az innen beolvasott adatokat még csak nem is ellenőrzi, hogy érvényesek-e. Na szép, mondhatom.

Folyt. köv., próbálok rájönni, mit is kéne rakni a 0xffffffff80000000 címre, hogy ne crasheljen el. Talán ha step-by-step végrehajtást használok úgy, hogy közben mellette olvasom a locore.S (nem túl bő) kommentjeit, kiderül.