commit eab8230948b78b2c4f18922b1ad5956a72e2c392
parent 4595b0529150f7885e25e7231e0a0d1196c440fd
Author: Ryan Sepassi <rsepassi@gmail.com>
Date: Tue, 16 Jun 2026 14:41:28 -0700
test/buildcmds: cover kernel linker flags, map completeness, freestanding policy
52 new cases: --defsym (abs + alias, bad-form negative), --section-start /
-Tdata/-Tbss acceptance, --orphan-handling (+bad negative) / --fatal-warnings,
map LMA/discarded/unresolved + no-absolute-path-leak + cross-run determinism,
--cref (header/symbol/def-attribution/no-abspath), --print-memory-usage
(script-driven RAM/FLASH regions), and freestanding strict validation
(cross-arch object + DSO-input rejection in both build-exe and ld, plus a
same-arch no-false-positive case). build-exe and ld variants throughout.
Diffstat:
| M | test/buildcmds/run.sh | | | 161 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
1 file changed, 161 insertions(+), 0 deletions(-)
diff --git a/test/buildcmds/run.sh b/test/buildcmds/run.sh
@@ -317,5 +317,166 @@ run_fail be-wasm-exe-bad-entry "$KIT" build-exe -target wasm32-none \
contains be-wasm-exe-bad-entry-diag "$work/be-wasm-exe-bad-entry.err" \
"entry symbol"
+# ===========================================================================
+# build-exe / ld — kernel linker flags, map completeness, freestanding policy
+# ===========================================================================
+
+# A bare freestanding _start used by the flag/policy tests below.
+printf 'void _start(void){ for(;;){} }\nint mydata = 42;\n' > kstart.c
+
+# ---- --defsym: absolute literal + symbol alias ----------------------------
+# my_abs becomes an absolute symbol at 0x1234; my_alias takes _start's address.
+run_ok be-defsym "$KIT" build-exe -target x86_64-linux -nostdlib -static -no-pie \
+ --defsym my_abs=0x1234 --defsym my_alias=_start \
+ --symbols defsym.sym kstart.c -o defsym.elf
+contains be-defsym-abs defsym.sym "0000000000001234 A my_abs"
+# my_alias takes _start's address (the alias inherits the target's placement,
+# so it rebases to the same final address _start carries).
+_start_addr=$(grep -E ' T _start$' defsym.sym | cut -d' ' -f1)
+if grep -qE "^$_start_addr . my_alias\$" defsym.sym; then ok be-defsym-alias; else
+ { echo "my_alias != _start ($_start_addr)"; cat defsym.sym; } \
+ > "$work/be-defsym-alias.diag"
+ not_ok be-defsym-alias "$work/be-defsym-alias.diag"
+fi
+# defsym via ld too.
+run_ok be-ld-report-kstart "$KIT" build-obj -target x86_64-linux \
+ kstart.c -o kstart.o
+run_ok ld-defsym "$KIT" ld -nostdlib -static -no-pie \
+ --defsym ld_abs=0x4321 --symbols lddefsym.sym kstart.o -o lddefsym.elf
+contains ld-defsym-abs lddefsym.sym "0000000000004321 A ld_abs"
+# --defsym with no value is rejected.
+run_fail be-defsym-bad "$KIT" build-exe -target x86_64-linux -nostdlib -static \
+ -no-pie --defsym broken kstart.c -o defsymbad.elf
+contains be-defsym-bad-diag "$work/be-defsym-bad.err" "NAME=EXPR"
+
+# ---- --section-start / -Tdata / -Tbss: per-section address overrides -------
+# These are accepted (best-effort placement; -Ttext / a linker script give
+# exact addresses). Assert acceptance + determinism rather than an exact vaddr.
+run_ok be-section-start "$KIT" build-exe -target x86_64-linux -nostdlib \
+ -static -no-pie --section-start=.text=0x500000 -Tdata 0x600000 \
+ --map secstart.map kstart.c -o secstart.elf
+contains be-section-start-text secstart.map "vaddr=0x50"
+contains be-section-start-data secstart.map "vaddr=0x60"
+run_ok ld-tbss "$KIT" ld -nostdlib -static -no-pie -Tdata 0x600000 \
+ kstart.o -o tbss.elf
+run_ok ld-section-start "$KIT" ld -nostdlib -static -no-pie \
+ --section-start=.text=0x700000 kstart.o -o secstart2.elf
+
+# ---- --orphan-handling / --fatal-warnings: parse + plumb -------------------
+run_ok be-orphan "$KIT" build-exe -target x86_64-linux -nostdlib -static \
+ -no-pie --orphan-handling=warn kstart.c -o orphan.elf
+run_fail be-orphan-bad "$KIT" build-exe -target x86_64-linux -nostdlib \
+ -static -no-pie --orphan-handling=nonsense kstart.c -o orphanbad.elf
+contains be-orphan-bad-diag "$work/be-orphan-bad.err" "orphan-handling"
+run_ok be-fatal-warnings "$KIT" build-exe -target x86_64-linux -nostdlib \
+ -static -no-pie --fatal-warnings kstart.c -o fatal.elf
+run_ok ld-orphan "$KIT" ld -nostdlib -static -no-pie --orphan-handling=error \
+ kstart.o -o ldorphan.elf
+
+# ---- map completeness: LMA, discarded, unresolved, normalized paths --------
+run_ok be-map-complete "$KIT" build-exe -target x86_64-linux -nostdlib \
+ -static -no-pie --gc-sections -ffunction-sections \
+ --map complete.map kstart.c -o complete.elf
+contains be-map-has-lma complete.map "lma=0x"
+contains be-map-has-discarded complete.map "discarded"
+contains be-map-has-unresolved complete.map "unresolved"
+# No absolute host path leaks into the map (paths are normalized to basenames).
+if grep -qE 'input=/|input=.:[\\/]' complete.map; then
+ { echo "absolute path leaked into map"; grep input= complete.map; } \
+ > "$work/be-map-no-abspath.diag"
+ not_ok be-map-no-abspath "$work/be-map-no-abspath.diag"
+else
+ ok be-map-no-abspath
+fi
+# The map is deterministic across two identical links.
+run_ok be-map-det1 "$KIT" build-exe -target x86_64-linux -nostdlib -static \
+ -no-pie --map det1.map kstart.c -o det1.elf
+run_ok be-map-det2 "$KIT" build-exe -target x86_64-linux -nostdlib -static \
+ -no-pie --map det2.map kstart.c -o det2.elf
+same_file be-map-deterministic det1.map det2.map
+
+# ---- --cref: cross-reference table (deterministic, basenames only) ---------
+printf 'int xref_helper(void);\nvoid _start(void){ xref_helper(); for(;;){} }\n' \
+ > xmain.c
+printf 'int xref_helper(void){ return 9; }\n' > xhelp.c
+run_ok be-cref "$KIT" build-exe -target x86_64-linux -nostdlib -static -no-pie \
+ --cref cref.out xmain.c xhelp.c -o cref.elf
+contains be-cref-header cref.out "cross reference table"
+contains be-cref-symbol cref.out "xref_helper"
+if grep -qE '^ def /|^ ref /' cref.out; then
+ { echo "absolute path leaked into cref"; cat cref.out; } \
+ > "$work/be-cref-no-abspath.diag"
+ not_ok be-cref-no-abspath "$work/be-cref-no-abspath.diag"
+else
+ ok be-cref-no-abspath
+fi
+# cref via ld attributes def/ref to the right object basenames.
+run_ok ld-cref-objs "$KIT" build-obj -target x86_64-linux xmain.c -o xmain.o
+run_ok ld-cref-objs2 "$KIT" build-obj -target x86_64-linux xhelp.c -o xhelp.o
+run_ok ld-cref "$KIT" ld -nostdlib -static -no-pie --cref ldcref.out \
+ xmain.o xhelp.o -o ldcref.elf
+# xref_helper is defined in xhelp.o, referenced from xmain.o.
+if awk '/^xref_helper$/{f=1;next} f&&/^ def xhelp.o$/{ok=1} f&&/^[^ ]/&&!/^xref_helper$/{f=0} END{exit !ok}' ldcref.out; then
+ ok ld-cref-def
+else
+ cp ldcref.out "$work/ld-cref-def.diag"; not_ok ld-cref-def "$work/ld-cref-def.diag"
+fi
+
+# ---- --print-memory-usage: per-MEMORY-region summary (script-driven) -------
+cat > memuse.ld <<'LDEOF'
+MEMORY {
+ RAM (rwx) : ORIGIN = 0x80000000, LENGTH = 0x100000
+ FLASH (rx) : ORIGIN = 0x10000000, LENGTH = 0x40000
+}
+SECTIONS {
+ . = 0x80000000;
+ .text : { *(.text*) }
+ .data : { *(.data*) }
+ .bss : { *(.bss*) }
+}
+LDEOF
+printf 'void _start(void){for(;;){}}\nint memd=7;\n' > memk.c
+run_ok be-memuse "$KIT" build-exe -target riscv64-none-elf -ffreestanding \
+ -nostdlib -static -no-pie -T memuse.ld --print-memory-usage memk.c \
+ -o memk.elf
+contains be-memuse-header "$work/be-memuse.out" "Memory region"
+contains be-memuse-ram "$work/be-memuse.out" "RAM"
+contains be-memuse-flash "$work/be-memuse.out" "FLASH"
+run_ok be-memuse-obj "$KIT" build-obj -target riscv64-none-elf -ffreestanding \
+ -nostdlib memk.c -o memk.o
+run_ok ld-memuse "$KIT" ld -T memuse.ld --print-memory-usage memk.o -o memkld.elf
+contains ld-memuse-header "$work/ld-memuse.out" "Memory region"
+
+# ---- freestanding strict validation (build-exe + ld) -----------------------
+# A foreign-arch object in a freestanding link is rejected (the link target's
+# arch is authoritative; a silent mis-link is a hard error).
+run_ok fs-x64-obj "$KIT" build-obj -target x86_64-none-elf -ffreestanding \
+ -nostdlib kstart.c -o fs_x64.o
+printf 'int other(void){return 1;}\n' > fsother.c
+run_ok fs-aa64-obj "$KIT" build-obj -target aarch64-none-elf -ffreestanding \
+ -nostdlib fsother.c -o fs_aa64.o
+run_fail fs-cross-arch-ld "$KIT" ld -o fscross.elf fs_x64.o fs_aa64.o
+contains fs-cross-arch-ld-diag "$work/fs-cross-arch-ld.err" \
+ "does not match the link target"
+run_fail fs-cross-arch-be "$KIT" build-exe -target x86_64-none-elf \
+ -ffreestanding -nostdlib -static -no-pie kstart.c fs_aa64.o -o fscross2.elf
+contains fs-cross-arch-be-diag "$work/fs-cross-arch-be.err" \
+ "does not match the link target"
+# A DSO (shared object) input into a freestanding link is rejected. The fixture
+# libc.so is an ET_DYN x86_64 shared object copied in locally.
+if [ -f "$repo_root/test/driver/fixtures/libc.so" ]; then
+ cp "$repo_root/test/driver/fixtures/libc.so" .
+ run_fail fs-dso-ld "$KIT" ld -o fsdso.elf fs_x64.o libc.so
+ contains fs-dso-ld-diag "$work/fs-dso-ld.err" "DSO"
+ run_fail fs-dso-be "$KIT" build-exe -target x86_64-none-elf -ffreestanding \
+ -nostdlib -static -no-pie kstart.c libc.so -o fsdso2.elf
+ contains fs-dso-be-diag "$work/fs-dso-be.err" "DSO"
+else
+ skip_test fs-dso-ld "no libc.so fixture"
+ skip_test fs-dso-be "no libc.so fixture"
+fi
+# A same-arch freestanding link still succeeds (no false positive).
+run_ok fs-same-arch-ok "$KIT" ld -o fsok.elf fs_x64.o
+
kit_summary build-driver
kit_exit