From ece1767ac96d3f4935722b29da538c232f58c967 Mon Sep 17 00:00:00 2001 From: DualFroz Date: Tue, 1 Sep 2026 16:32:03 +0200 Subject: [PATCH] chore: update Makefile and linker --- Makefile | 180 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- linker.ld | 5 ++ 2 files changed, 180 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index 807b9f8..90518dc 100644 --- a/Makefile +++ b/Makefile @@ -476,6 +476,84 @@ $(UBUILD)/timetest.elf: $(UBUILD)/timetest.o $(USERCOMMON) user/user.ld # `false && echo X || echo ...` line (shell.c's new `&&`/`||` conditional # chaining, kmain.c's new andOrDriverThread). USER_BASE picks up the slot # right after timetest.elf's (the last one reserved). +$(UBUILD)/false.elf: $(UBUILD)/false.o $(USERCOMMON) user/user.ld + $(LD) $(ULDFLAGS) --defsym USER_BASE=0x4E0000000 -o $@ $(UBUILD)/false.o $(USERCOMMON) + +# argecho is, like globcat/false above, never spawned by kmain.c directly -- +# loaded on demand when the real interactive shell processes a typed +# `argecho $?` line (shell.c's new `$?` expansion, kmain.c's extended +# andOrDriverThread). USER_BASE picks up the slot right after false.elf's +# (the last one reserved). +$(UBUILD)/argecho.elf: $(UBUILD)/argecho.o $(USERCOMMON) user/user.ld + $(LD) $(ULDFLAGS) --defsym USER_BASE=0x4F0000000 -o $@ $(UBUILD)/argecho.o $(USERCOMMON) + +# rmtest is spawned directly by kmain.c at boot, fully synchronous like +# timetest.elf/date.elf/nicetest.elf above -- no shell rendezvous, no +# injected keystroke. USER_BASE is the slot right after argecho.elf's (the +# last one reserved); nothing else references any address in or past this +# slot. +$(UBUILD)/rmtest.elf: $(UBUILD)/rmtest.o $(USERCOMMON) user/user.ld + $(LD) $(ULDFLAGS) --defsym USER_BASE=0x500000000 -o $@ $(UBUILD)/rmtest.o $(USERCOMMON) + +# permtest is spawned directly by kmain.c at boot, fully synchronous like +# rmtest.elf above -- no shell rendezvous, no injected keystroke. USER_BASE +# is the slot right after rmtest.elf's (the last one reserved); nothing +# else references any address in or past this slot. +$(UBUILD)/permtest.elf: $(UBUILD)/permtest.o $(USERCOMMON) user/user.ld + $(LD) $(ULDFLAGS) --defsym USER_BASE=0x510000000 -o $@ $(UBUILD)/permtest.o $(USERCOMMON) + +# identtest is spawned directly by kmain.c at boot, fully synchronous like +# permtest.elf above -- no shell rendezvous, no injected keystroke. USER_BASE +# is the slot right after permtest.elf's (the last one reserved); nothing +# else references any address in or past this slot. +$(UBUILD)/identtest.elf: $(UBUILD)/identtest.o $(USERCOMMON) user/user.ld + $(LD) $(ULDFLAGS) --defsym USER_BASE=0x520000000 -o $@ $(UBUILD)/identtest.o $(USERCOMMON) + +# dirpermtest is spawned directly by kmain.c at boot, fully synchronous like +# identtest.elf above -- no shell rendezvous, no injected keystroke. USER_BASE +# is the slot right after identtest.elf's (the last one reserved); nothing +# else references any address in or past this slot. +$(UBUILD)/dirpermtest.elf: $(UBUILD)/dirpermtest.o $(USERCOMMON) user/user.ld + $(LD) $(ULDFLAGS) --defsym USER_BASE=0x530000000 -o $@ $(UBUILD)/dirpermtest.o $(USERCOMMON) + +# grouptest is spawned directly by kmain.c at boot, fully synchronous like +# dirpermtest.elf above -- no shell rendezvous, no injected keystroke. USER_BASE +# is the slot right after dirpermtest.elf's (the last one reserved); nothing +# else references any address in or past this slot. +$(UBUILD)/grouptest.elf: $(UBUILD)/grouptest.o $(USERCOMMON) user/user.ld + $(LD) $(ULDFLAGS) --defsym USER_BASE=0x540000000 -o $@ $(UBUILD)/grouptest.o $(USERCOMMON) + +# pidfdtest is spawned directly by kmain.c at boot, fully synchronous like +# grouptest.elf above -- no shell rendezvous, no injected keystroke. USER_BASE +# is the slot right after grouptest.elf's (the last one reserved, verified by +# scanning every USER_BASE in this Makefile, not just assumed to be "one past +# the highest" -- see kmain.c's own nicetest/date address-space inconsistency, +# left as a warning for exactly this kind of addition); nothing else +# references any address in or past this slot. +$(UBUILD)/pidfdtest.elf: $(UBUILD)/pidfdtest.o $(USERCOMMON) user/user.ld + $(LD) $(ULDFLAGS) --defsym USER_BASE=0x550000000 -o $@ $(UBUILD)/pidfdtest.o $(USERCOMMON) + +# mmaptest is spawned directly by kmain.c at boot, fully synchronous like +# pidfdtest.elf above -- no shell rendezvous, no injected keystroke. USER_BASE +# is the slot right after pidfdtest.elf's (the last one reserved, verified by +# scanning every USER_BASE in this Makefile); nothing else references any +# address in or past this slot. +$(UBUILD)/mmaptest.elf: $(UBUILD)/mmaptest.o $(USERCOMMON) user/user.ld + $(LD) $(ULDFLAGS) --defsym USER_BASE=0x560000000 -o $@ $(UBUILD)/mmaptest.o $(USERCOMMON) + +# mmapprotvictim is only ever spawned at RUNTIME by mmaptest.elf itself +# (userSpawn), never directly by kmain.c -- same relationship killvictim.elf +# already has to killtest.elf. USER_BASE is the slot right after +# mmaptest.elf's own. +$(UBUILD)/mmapprotvictim.elf: $(UBUILD)/mmapprotvictim.o $(USERCOMMON) user/user.ld + $(LD) $(ULDFLAGS) --defsym USER_BASE=0x570000000 -o $@ $(UBUILD)/mmapprotvictim.o $(USERCOMMON) + +# mmapexecvictim is only ever spawned at RUNTIME by mmaptest.elf itself +# (userSpawn), exactly like mmapprotvictim.elf above -- never directly by +# kmain.c. USER_BASE is the slot right after mmapprotvictim.elf's own. +$(UBUILD)/mmapexecvictim.elf: $(UBUILD)/mmapexecvictim.o $(USERCOMMON) user/user.ld + $(LD) $(ULDFLAGS) --defsym USER_BASE=0x580000000 -o $@ $(UBUILD)/mmapexecvictim.o $(USERCOMMON) + $(MKTAR): tools/mktar.c | $(BUILD) gcc -O2 -Wall -Wextra -o $@ $< @@ -486,6 +564,85 @@ $(INITRD): $(MKTAR) $(USERPROGRAMS) $(FSFILES) --file bin/counter $(UBUILD)/counter.elf \ --file bin/sbrktest $(UBUILD)/sbrktest.elf \ --file bin/fileread $(UBUILD)/fileread.elf \ + --file bin/pipetest $(UBUILD)/pipetest.elf \ + --file bin/disktest $(UBUILD)/disktest.elf \ + --file bin/fstest $(UBUILD)/fstest.elf \ + --file bin/linktest $(UBUILD)/linktest.elf \ + --file bin/spawntarget $(UBUILD)/spawntarget.elf \ + --file bin/exectarget $(UBUILD)/exectarget.elf \ + --file bin/proctest $(UBUILD)/proctest.elf \ + --file bin/argtest $(UBUILD)/argtest.elf \ + --file bin/fifomaster $(UBUILD)/fifomaster.elf \ + --file bin/fifowriter $(UBUILD)/fifowriter.elf \ + --file bin/fiforeader $(UBUILD)/fiforeader.elf \ + --file bin/killtest $(UBUILD)/killtest.elf \ + --file bin/killvictim $(UBUILD)/killvictim.elf \ + --file bin/namedreader $(UBUILD)/namedreader.elf \ + --file bin/namedwriter $(UBUILD)/namedwriter.elf \ + --file bin/consolereader1 $(UBUILD)/consolereader1.elf \ + --file bin/consolereader2 $(UBUILD)/consolereader2.elf \ + --file bin/sigtest $(UBUILD)/sigtest.elf \ + --file bin/sigtarget $(UBUILD)/sigtarget.elf \ + --file bin/sigdefault $(UBUILD)/sigdefault.elf \ + --file bin/jobtest $(UBUILD)/jobtest.elf \ + --file bin/jobtarget $(UBUILD)/jobtarget.elf \ + --file bin/nesttest $(UBUILD)/nesttest.elf \ + --file bin/nesttarget $(UBUILD)/nesttarget.elf \ + --file bin/eintrtest $(UBUILD)/eintrtest.elf \ + --file bin/eintrtarget $(UBUILD)/eintrtarget.elf \ + --file bin/restarttest $(UBUILD)/restarttest.elf \ + --file bin/restarttarget $(UBUILD)/restarttarget.elf \ + --file bin/masktest $(UBUILD)/masktest.elf \ + --file bin/masktarget $(UBUILD)/masktarget.elf \ + --file bin/sigchldtest $(UBUILD)/sigchldtest.elf \ + --file bin/sigchldchild $(UBUILD)/sigchldchild.elf \ + --file bin/waitanytest $(UBUILD)/waitanytest.elf \ + --file bin/waitanyfast $(UBUILD)/waitanyfast.elf \ + --file bin/waitanyslow $(UBUILD)/waitanyslow.elf \ + --file bin/stopchldtest $(UBUILD)/stopchldtest.elf \ + --file bin/stopchldtarget $(UBUILD)/stopchldtarget.elf \ + --file bin/nodefertest $(UBUILD)/nodefertest.elf \ + --file bin/alarmtest $(UBUILD)/alarmtest.elf \ + --file bin/alarmdefault $(UBUILD)/alarmdefault.elf \ + --file bin/siginfotest $(UBUILD)/siginfotest.elf \ + --file bin/siginfotarget $(UBUILD)/siginfotarget.elf \ + --file bin/pgroupfg $(UBUILD)/pgroupfg.elf \ + --file bin/pgroupbg $(UBUILD)/pgroupbg.elf \ + --file bin/jobctlfg $(UBUILD)/jobctlfg.elf \ + --file bin/jobctlbg $(UBUILD)/jobctlbg.elf \ + --file bin/polltest $(UBUILD)/polltest.elf \ + --file bin/pollwriter $(UBUILD)/pollwriter.elf \ + --file bin/pipesrc $(UBUILD)/pipesrc.elf \ + --file bin/pipesink $(UBUILD)/pipesink.elf \ + --file bin/redirwriter $(UBUILD)/redirwriter.elf \ + --file bin/redirreader $(UBUILD)/redirreader.elf \ + --file bin/stderrwriter $(UBUILD)/stderrwriter.elf \ + --file bin/stderrreader $(UBUILD)/stderrreader.elf \ + --file bin/selfstoptest $(UBUILD)/selfstoptest.elf \ + --file bin/selfstoptarget $(UBUILD)/selfstoptarget.elf \ + --file bin/herestest $(UBUILD)/herestest.elf \ + --file bin/hcat $(UBUILD)/hcat.elf \ + --file bin/hsink $(UBUILD)/hsink.elf \ + --file bin/pipecat $(UBUILD)/pipecat.elf \ + --file bin/cwdtest $(UBUILD)/cwdtest.elf \ + --file bin/cwdtarget $(UBUILD)/cwdtarget.elf \ + --file bin/envprint $(UBUILD)/envprint.elf \ + --file bin/nicetest $(UBUILD)/nicetest.elf \ + --file bin/nicetarget $(UBUILD)/nicetarget.elf \ + --file bin/date $(UBUILD)/date.elf \ + --file bin/globcat $(UBUILD)/globcat.elf \ + --file bin/timetest $(UBUILD)/timetest.elf \ + --file bin/false $(UBUILD)/false.elf \ + --file bin/argecho $(UBUILD)/argecho.elf \ + --file bin/rmtest $(UBUILD)/rmtest.elf \ + --file bin/permtest $(UBUILD)/permtest.elf \ + --file bin/identtest $(UBUILD)/identtest.elf \ + --file bin/dirpermtest $(UBUILD)/dirpermtest.elf \ + --file bin/grouptest $(UBUILD)/grouptest.elf \ + --file bin/pidfdtest $(UBUILD)/pidfdtest.elf \ + --file bin/mmaptest $(UBUILD)/mmaptest.elf \ + --file bin/mmapprotvictim $(UBUILD)/mmapprotvictim.elf \ + --file bin/mmapexecvictim $(UBUILD)/mmapexecvictim.elf \ --file etc/motd.txt fsroot/etc/motd.txt \ --file etc/readme.txt fsroot/etc/readme.txt \ --file home/notes.txt fsroot/home/notes.txt @@ -495,14 +652,27 @@ $(ISO): $(KERNEL) $(INITRD) iso/boot/grub/grub.cfg @cp $(INITRD) iso/boot/initrd.img grub-mkrescue -o $(ISO) iso 2>/dev/null -run: $(ISO) - qemu-system-x86_64 -cdrom $(ISO) -serial stdio -m 128M +# Scratch disk backing /dev/disk0 (ata.c / vfs.c blockDev*). Zeroed, not +# committed: a fresh 8 MiB raw image is exactly as good as any other for a +# driver that owns the whole device and formats nothing on it. +$(DISK): | $(BUILD) + dd if=/dev/zero of=$@ bs=1M count=8 status=none -runserial: $(ISO) - qemu-system-x86_64 -cdrom $(ISO) -serial stdio -display none -m 128M -no-reboot +run: $(ISO) $(DISK) + qemu-system-x86_64 -cdrom $(ISO) $(DISKFLAGS) -serial stdio -m 128M -test: $(ISO) +runserial: $(ISO) $(DISK) + qemu-system-x86_64 -cdrom $(ISO) $(DISKFLAGS) -serial stdio -display none -m 128M -no-reboot + +test: $(ISO) $(DISK) sh tools/ci-test.sh clean: rm -rf $(BUILD) $(ISO) iso/boot/frostbyte.elf iso/boot/initrd.img + +# Auto-generated header dependencies (-MMD -MP above): without these, editing +# a widely-included header (e.g. sched.h) would not force a rebuild of every +# .c file that includes it, silently linking objects compiled against +# different struct layouts of the same type -- exactly the kind of ABI +# mismatch that corrupts memory at runtime instead of failing to build. +-include $(wildcard $(BUILD)/*.d) $(wildcard $(UBUILD)/*.d) diff --git a/linker.ld b/linker.ld index a353f4a..49fd65b 100644 --- a/linker.ld +++ b/linker.ld @@ -19,6 +19,7 @@ SECTIONS { *(.multiboot) *(.boot.text) + *(.boot.data) . = ALIGN(4096); *(.boot.pagetables) } :boot @@ -33,6 +34,10 @@ SECTIONS .rodata ALIGN(4096) : AT(ADDR(.rodata) - KERNEL_VMA) { *(.rodata .rodata.*) + . = ALIGN(8); + ktestArrayStart = .; + KEEP(*(.ktests .ktests.*)) + ktestArrayEnd = .; } :rodata .data ALIGN(4096) : AT(ADDR(.data) - KERNEL_VMA)