ci(freebsd-amd64): flip libgc.a lane from XFAIL to blocking (etext/end fix validated) - #85
Conversation
tinycc 384614a ("tccelf: provide complete ELF boundary symbols") gives
the plain BSD-style etext/edata/end names PROVIDE semantics on every ELF
target, fixing the root cause of this platform's GC link failure: tcc
previously defined only the glibc-style _etext/_edata/_end, never the
plain names BDWGC's FreeBSD data-segment scan references directly.
The lane asserted that gc_alloc.c/hello.c MUST still fail on unresolved
etext/end - correct while the bug was live, but it hard-fails the moment
a fixed tcc.exe is published here, via its own "unexpected full pass"
guard. That is imminent: update_tccbin.yml's BSD job publishes on the
monthly cron with PUBLISH=true and no lock, and its skip-check will not
skip (shipped 85ba3ae8 != current mob), so the next scheduled run
republishes this branch with a fixed tcc.exe and breaks CI for the
opposite reason.
This STRENGTHENS the gate rather than relaxing it: a full pass of all
three shared tests is now the required baseline, where before only one
very specific failure shape was accepted. Nothing is downgraded to a
warning and no failure shape is tolerated. Also adds a blocking
mechanism check that references etext/edata/end directly from C, so a
future tcc.exe that satisfies the suite while regressing or mis-ordering
the boundary symbols is still caught.
Validated on a real FreeBSD 15.1 VM before flipping, with this branch's
EXACT libgc.a held byte-identical: the shipped tcc.exe (85ba3ae8) fails
on unresolved etext/end and nothing else, while a tcc.exe rebuilt from
tinycc 2be0218b (which contains 384614a) reports "3 passed, 0 failed"
and links the boundary probe with a sanely ordered range. tcc.exe was
the only variable between the two phases.
Co-Authored-By: WOZCODE <contact@withwoz.com>
|
Technically, your PR is the right follow-up, but we will not merge it yet. |
…ata <= end Per review on vlang#85. - Compare as uintptr_t rather than as pointers: relational comparison of pointers into distinct objects is undefined behaviour in C, so the previous pointer-level check was not one a compiler is obliged to evaluate the way it reads. Integer comparison of the converted addresses is well defined. - Assert the FULL ordering etext <= edata <= end rather than only etext < end. 384614a is about boundary symbols being finalized from the ordered loadable sections, so provided-but-mis-ordered is a distinct failure mode, and only the complete chain catches a middle symbol landing out of place. - Non-strict (<=) deliberately: an empty .data or .bss makes adjacent boundaries legitimately equal, and a strict < would fail such a build for no good reason. Co-Authored-By: WOZCODE <contact@withwoz.com>
|
Thanks — and you're right about the cron. I've corrected the PR description. On Probe hardened as requested in
uintptr_t text_end = (uintptr_t)etext;
uintptr_t data_end = (uintptr_t)edata;
uintptr_t bss_end = (uintptr_t)end;
printf("etext=0x%" PRIxPTR " edata=0x%" PRIxPTR " end=0x%" PRIxPTR "\n",
text_end, data_end, bss_end);
if (!(text_end <= data_end && data_end <= bss_end)) {
fprintf(stderr, "bad boundary range: expected etext <= edata <= end\n");
return 1;
}Re-validated on a real FreeBSD 15.1 VM rather than assumed. The hardened probe compiles, links and runs under tcc, and the ordering assertion holds on a real build. (Throwaway validation branch, since deleted.) No merge request from me — this sits until your producer safeguards are ready, to be merged as part of the coordinated publication so the red window stays bounded. Happy to adjust anything else in the meantime. One note for whenever that publication happens: |
|
@codex review |
|
Codex Review: Didn't find any major issues. Swish! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
Summary
tinycc
384614a("tccelf: provide complete ELF boundary symbols") gives the plain BSD-styleetext/edata/endnames PROVIDE semantics on every ELF target. That is the root cause of this platform's GC link failure: tcc previously defined only the glibc-style_etext/_edata/_end, never the plain names BDWGC's FreeBSD data-segment scan references directly.This flips the
libgc.alane from a signature-checked XFAIL to a normal blocking lane.Correction: this is NOT time-sensitive (my earlier claim was wrong)
An earlier revision of this description argued this was urgent because the monthly cron would publish a fixed
tcc.exeon 2026-08-01 03:17 UTC and break CI. That was incorrect and I've removed it.vlang/v'supdate_tccbin.ymlisdisabled_manuallyat the GitHub level, so no scheduled run can fire at all:Its last
schedulerun was 2026-07-01. I had verified the cron expression, thePUBLISHlogic, the absent BSD publish lock, and the skip-check — all accurate, and all irrelevant, because I never checked whether the workflow was enabled. Reading the YAML tells you what it would do, not whether it can run.So there is no automatic recovery: merging this before a fixed
tcc.exeis published would turn FreeBSD CI red and leave it red until someone manually publishes. Sequencing therefore has to be maintainer-driven, per the reviewer's plan below.This strengthens the gate, it does not relax it
A full pass of all three shared tests is now the required baseline, where before only one very specific failure shape was accepted. Nothing is downgraded to a warning; no failure shape is tolerated. The blocking no-GC crash lane is unchanged.
Also adds a second blocking step that references
etext/edata/enddirectly from C, so a futuretcc.exethat satisfies the suite while regressing or mis-ordering the boundary symbols is still caught. (Deliberately not annmcheck — tcc emits no full.symtabby default and linker-PROVIDEd symbols needn't appear there at all;nmreported all three "absent" for a binary that had just linked and run correctly.)Validation
Run on a real FreeBSD 15.1 VM before flipping, with this branch's exact
libgc.aheld byte-identical across both phases sotcc.exewas the only variable:tcc.exe(85ba3ae8, predates fix)unresolved reference to 'etext'/'end', and nothing else (exclusivity asserted)2be0218b, asserted to contain384614a;libgc.abyte-identical (cmp),tcc.execonfirmed replacedtcc.exe3 passed, 0 failedetext=0x400f0c edata=0x402110 end=0x402128— provided and correctly orderedThe rebuild used vlang/v's own official
thirdparty-freebsd-amd64_tcc.sh, i.e. exactly what the real publish pipeline runs. Full log: validation run (throwaway branch, since deleted).No producer-side change is needed for FreeBSD — unlike macos-amd64, where libgc itself was never rebuilt. A plain
tcc.exerebuild from current mob is sufficient.Expected CI on this PR
This PR's own run tests the currently shipped
tcc.exe, which still predates the fix — so the now-blocking lane is expected to fail here until a rebuilttcc.exeis published to this branch. That is the intended state, exactly as with the macos-amd64 gate conversion (#83), not a defect in this PR.Because the cron is disabled, this must be merged as part of a coordinated publication so the red window stays bounded:
update_tccbin.ymlre-enabled.tcc.exefor this branch rebuilt from a tinycc containing384614a(validated:2be0218bworks).I have pull-only access to both repos, so steps 1-2 need a maintainer.
Test plan
yaml.safe_load); every step's script syntax-checked under POSIXsh -n(the VM usessh, not bash).uintptr_tvalues (relational comparison of pointers into distinct objects is UB) and asserts the fulletext <= edata <= endchain, non-strict so an empty.data/.bssisn't a spurious failure. Re-validated on a real FreeBSD VM against a fixedtcc.exe.tcc.exeis published, confirm this branch's CI is fully green.