commit 28f2a06838d8f794b707e3e6dd2f70eadd14fc02
parent f082bcd0c6e5cfd8f98e04e80dec19f6a388f65b
Author: Ryan Sepassi <rsepassi@gmail.com>
Date: Mon, 8 Jun 2026 13:40:41 -0700
ld: default to PIE for hosted dynamic links (-lc without -static)
kit ld -lc produced "imported sym has no PLT entry (CALL26)" because
the link_dyn path (PLT/GOT/.rela.plt) is only entered when lopts.pie
is set, and kit ld intentionally does not default to PIE the way
kit cc does.
Fix: when the hosted profile is active (-lc) and the link is dynamic
(not -static, not -shared, not -r), implicitly set pie=1 — matching
what kit cc does. Explicit -no-pie with -lc is rejected with a clear
error since non-PIE ET_EXEC dynamic linking is not yet supported.
Diffstat:
1 file changed, 17 insertions(+), 0 deletions(-)
diff --git a/driver/cmd/ld.c b/driver/cmd/ld.c
@@ -1491,6 +1491,23 @@ static int ld_run_link(LdOptions* o) {
if (ld_apply_hosted_before_after(o) != 0) goto out;
+ /* Hosted dynamic link: default to PIE, matching what `kit cc` does.
+ * Without PIE the link_dyn path (PLT/GOT/.rela.plt) is not entered and
+ * any CALL26/PLT32 reloc against an imported symbol faults at apply time.
+ * Only override when the user has not made an explicit PIC choice.
+ * Non-PIE (ET_EXEC) dynamic linking is not yet supported; reject early. */
+ if (o->wants_hosted_libc && !o->static_link && !o->shared &&
+ !o->relocatable) {
+ if (o->pic_explicit && !o->pie) {
+ driver_errf(LD_TOOL,
+ "-lc with -no-pie is not supported; use -pie (default) "
+ "or -static for a static link");
+ goto out;
+ }
+ if (!o->pic_explicit)
+ o->pie = 1;
+ }
+
/* Auto-link kit's compiler runtime for any target that has a variant —
* including the freestanding riscv32-none-elf / riscv64-none-elf targets,
* whose runtime (and, for rv32, the float-ABI it was detected with) is