The Step-4b RTL leaves for a static FreeBSD build. memcpy/memset/memcmp/
strlen are already target-invariant (runtime.cstub, pure Pascal — shared),
and the x86-64 jmp_buf is ABI-invariant (runtime.setjmp — shared), so this
step is small:
* runtime.syscall.freebsd gains getrandom (FreeBSD SYS 563, not Linux's
318) and an mremap stub. FreeBSD has no in-place-remap syscall, so
mremap is a plain function returning MAP_FAILED (-1); runtime.mem's
large-realloc path already treats an mremap failure as "grow the slow
way" (alloc a fresh region, memcpy, free the old), so exporting a failing
mremap gives the allocator its no-mremap fallback with zero allocator
changes.
* runtime.libc2.freebsd — the FreeBSD sibling of runtime.libc2.linux: the
atexit registry + `exit`, __cxa_atexit, abort, freestanding UTC
civil-calendar gmtime_r/localtime_r/timegm, mkstemp, and system. The
calendar math, atexit registry, and struct tm layout are target-invariant
(tm is identical on Linux/FreeBSD amd64), so the only differences from the
Linux unit are the syscall leaf it builds on (runtime.syscall.freebsd) and
the FreeBSD O_* flag values (O_CREAT=$0200, O_EXCL=$0800 — not Linux's
$40/$80).
Both units are standalone (nothing in the Linux build graph uses them), so
the Linux self-host is untouched — confirmed by the clean fixpoints/suite.
Test TestLink_FreeBSDSyscallLeaf_GetrandomAndMremapStub asserts getrandom
uses 563 (and NOT Linux's 318) and the mremap stub returns -1. Threads
(thr_new/_umtx_op) are Step 4c.