kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

commit 3beca0093e126f7b015b802d8f67bf78eecd1cf3
parent ba66f6d185d5821bdbd424aa95957d9af2fdfdca
Author: Ryan Sepassi <rsepassi@gmail.com>
Date:   Wed, 17 Jun 2026 08:07:16 -0700

ld: keep GNU-ld non-PIE default after fill_options

driver_link_flags_fill_options derives lopts.pie via driver_link_pie, which
defaults hosted targets (target.pic == KIT_PIC_PIE) to PIE — correct for the
cc/build compiler drivers but not for a raw linker, which must match GNU ld /
lld's non-PIE ET_EXEC default (PIE is opt-in via -pie; a PIE default with no
guaranteed dynamic loader faults). Override lopts.pie back to ld's documented
policy after fill_options; freestanding_strict is then derived from it.

Diffstat:
Mdriver/cmd/ld.c | 20+++++++++++++++-----
1 file changed, 15 insertions(+), 5 deletions(-)

diff --git a/driver/cmd/ld.c b/driver/cmd/ld.c @@ -3142,15 +3142,25 @@ static int ld_run_link(LdOptions* o) { : o->shared ? KIT_LINK_OUTPUT_SHARED : KIT_LINK_OUTPUT_EXE; /* The shared flag model fills entry/text-base/defsym/section-start/orphan/ - * fatal-warnings/build-id/gc/strip/pe-subsystem/interp/soname/rpath and the - * PIE decision (driver_link_pie, equivalent to the old - * o->pie && !o->shared && !o->relocatable; -shared/-r never PIE — a - * freestanding or static link has no dynamic loader to apply a PIE image's - * relocations). Callers that want a hosted PIE executable pass -pie. */ + * fatal-warnings/build-id/gc/strip/pe-subsystem/interp/soname/rpath. It also + * derives lopts.pie via driver_link_pie, but ld overrides that below. */ if (driver_link_flags_fill_options(&o->lf, o->target, o->pie, o->shared, o->relocatable, output_kind, script, &lopts, &rpath_slices) != 0) goto out; + /* GNU ld and lld default to a non-PIE ET_EXEC; PIE is opt-in via -pie. The + * linker imposes no hosted-PIE default the way a compiler driver does (kit + * cc still defaults hosted executables to PIE through the link API) — a + * freestanding or static link has no dynamic loader to apply a PIE image's + * relocations or choose its base, so a PIE default produces a binary that + * faults under a direct/qemu loader (its writable segments sit below + * mmap_min_addr at the vaddr-0 PIE base). -shared/-r never PIE. Callers that + * want a hosted PIE executable pass -pie explicitly (as the musl dynamic + * lane and real compiler drivers do); the hosted-libc dynamic lane forces + * o->pie = 1 above. So override the shared driver_link_pie decision (which + * would default hosted target.pic == KIT_PIC_PIE targets to PIE) back to + * ld's policy. */ + lopts.pie = o->pie && !o->shared && !o->relocatable; /* Strict freestanding policy: a `*-none-*` (FREESTANDING) static non-PIE * executable must reject dynamic-link artifacts and cross-input * target/format mismatches. Only the EXE lane imposes it; -r/-shared do