amd64: fix GOT-indirect addressing bug in dictionary fast-path lookup
vm_find_word() and dict_find_word_heat_aware() reference the same extern globals (sf_fc_list/sf_fc_count/sf_fc_cap) but GCC compiled cross-TU references to them with GOT-indirect addressing (R_X86_64_REX_GOTPCRELX) under -fPIC. This freestanding, statically-linked UEFI PE image has no dynamic linker to populate a GOT, so those reads silently returned NULL instead of the array's real address -- amd64-only, and exquisitely sensitive to unrelated code-size changes since the choice between direct and GOT-indirect addressing is a per-call-site GCC heuristic. Fix: -fno-pic -fno-pie for amd64 only (ARCH_CFLAGS, overriding COMMON_CFLAGS's -fPIC, which riscv64's -shared loader link still needs). Also removes -DPLATFORM_TIME_NO_INLINE, a prior one-off workaround for the identical bug applied to sf_monotonic_ns() specifically, now redundant. Adds R_X86_64_PC32/R_X86_64_PLT32 handling to elf_apply_relocations() as a robustness fix for the non-monolithic split-build path (dead code for the current monolithic boot, where OVMF's own PE loader relocates the image, not this loader). Verified: all three architectures boot clean and pass the full item-4.2 Hermes self-test, including MSG-DELIVER-ALL, which previously triggered the corruption on amd64 only. Write-up in FABRIC.md under item 4.2. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
56ad128e2e
commit
0a7f144367
+21
-7
@@ -121,7 +121,18 @@ ifeq ($(ARCH),amd64)
|
||||
LD := ld
|
||||
OBJCOPY := objcopy
|
||||
endif
|
||||
ARCH_CFLAGS := -m64 -march=x86-64 -mno-red-zone -DARCH_AMD64
|
||||
# -fno-pic -fno-pie: this is a fixed-base, statically-linked freestanding
|
||||
# image with no dynamic linker to populate a GOT at load time. -fPIC (set
|
||||
# in COMMON_CFLAGS, needed by riscv64's -shared link pipeline) makes GCC
|
||||
# emit R_X86_64_REX_GOTPCRELX (GOT-indirect) addressing for some cross-TU
|
||||
# extern globals depending on per-call-site codegen heuristics; the "GOT
|
||||
# slot" is just an unpopulated .bss cell here, so those reads silently
|
||||
# return NULL instead of the real address. Root-caused 2026-08-06 via
|
||||
# dict_find_word_heat_aware() reading sf_fc_count as NULL while
|
||||
# vm_find_word() (same globals, same TU as the definition) read it
|
||||
# correctly. These flags come after COMMON_CFLAGS on the command line so
|
||||
# they win for amd64 only; riscv64/aarch64 keep -fPIC.
|
||||
ARCH_CFLAGS := -m64 -march=x86-64 -mno-red-zone -DARCH_AMD64 -fno-pic -fno-pie
|
||||
LOADER_LINKER_SCRIPT := linker/starkernel-loader-amd64.ld
|
||||
KERNEL_LINKER_SCRIPT := linker/starkernel-kernel-amd64.ld
|
||||
|
||||
@@ -173,10 +184,14 @@ LOADER_LD ?= $(LD)
|
||||
# ==============================================================================
|
||||
|
||||
# Common flags for all arches / both loader and kernel.
|
||||
# -fPIC + -fvisibility=hidden: keeps all symbols local, prevents GOT references
|
||||
# for internal function pointers (PE has no GOT).
|
||||
# -DPLATFORM_TIME_NO_INLINE: routes sf_monotonic_ns() through shim wrappers to
|
||||
# avoid GOTPCREL relocations that crash at runtime in the PE environment.
|
||||
# -fPIC + -fvisibility=hidden: needed by riscv64's -shared loader link
|
||||
# pipeline (amd64 overrides back to -fno-pic/-fno-pie in its ARCH_CFLAGS
|
||||
# above -- see that comment for why: -fPIC made GCC emit GOT-indirect
|
||||
# addressing for some cross-TU extern globals, and this freestanding image
|
||||
# has no dynamic linker to populate a GOT, so those reads silently returned
|
||||
# NULL. PLATFORM_TIME_NO_INLINE (removed 2026-08-06) was a symbol-specific
|
||||
# workaround for the same underlying bug, made unnecessary once amd64 got
|
||||
# the real fix; see FABRIC.md for the write-up).
|
||||
COMMON_CFLAGS := \
|
||||
-std=c99 -Wall -Werror -Wextra \
|
||||
-ffreestanding -nostdlib -fno-builtin \
|
||||
@@ -184,8 +199,7 @@ COMMON_CFLAGS := \
|
||||
$(ARCH_CFLAGS) \
|
||||
-I$(KERNEL_INC) -Iinclude -Isrc \
|
||||
-include $(STARFORTH_CONFIG_HEADER) \
|
||||
-DPARITY_MODE=$(PARITY_MODE) \
|
||||
-DPLATFORM_TIME_NO_INLINE
|
||||
-DPARITY_MODE=$(PARITY_MODE)
|
||||
|
||||
VMCORE_CFLAGS_COMMON := \
|
||||
$(filter-out -I$(KERNEL_INC),$(COMMON_CFLAGS)) \
|
||||
|
||||
Reference in New Issue
Block a user