Bug 297225 - lang/sbcl: fails to build on FreeBSD 15.x — stale x86-64 bootstrap binary segfaults
Summary: lang/sbcl: fails to build on FreeBSD 15.x — stale x86-64 bootstrap binary seg...
Status: Closed FIXED
Alias: None
Product: Ports & Packages
Classification: Unclassified
Component: Individual Port(s) (show other bugs)
Version: Latest
Hardware: amd64 Any
: --- Affects Only Me
Assignee: Kirill Ponomarev
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2026-08-02 00:11 UTC by Robert Cina
Modified: 2026-08-02 17:00 UTC (History)
0 users

See Also:
bugzilla: maintainer-feedback? (krion)


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Robert Cina 2026-08-02 00:11:04 UTC
Category: ports bug
Port: lang/sbcl (sbcl-2.6.7,1)

Problem description:

Building lang/sbcl from source fails on FreeBSD 15.1-STABLE (amd64). The port's build process uses a prebuilt SBCL binary (sbcl-1.2.7-x86-64-freebsd, dated ~2015) as the cross-compilation host (--xc-host). This bootstrap binary segfaults immediately when invoked, before it can compile anything:

Segmentation fault (core dumped)
No working host Common Lisp implementation.
See ./INSTALL, the "SOURCE DISTRIBUTION" section
*** Error code 1

Steps to reproduce:

sh
poudriere testport -j <freebsd15-jail> -p <portstree> -o lang/sbcl -i

or simply cd /usr/ports/lang/sbcl && make build on a FreeBSD 15.x amd64 system.

Investigation so far:

Ruled out ASLR: disabling via proccontrol -m aslr -s disable on the bootstrap binary made no difference.
Ruled out security.bsd.map_at_zero: setting sysctl security.bsd.map_at_zero=1 made no difference.
elfctl -e +noaslr cannot be applied to the binary at all — it predates FreeBSD's ELF feature-control-note mechanism, so there's no note to toggle.
Tried the port's alternate CCL bootstrap option (OPTIONS_SINGLE_BOOTSTRAP=ABCL CCL CMUCL SBCL) instead — lang/ccl (1.13, also from ~2015) builds, but its resulting fx86cl64 binary fails with:
  minimal initial mmap: Cannot allocate memory

when trying to reserve its heap at a fixed low address — same underlying class of problem (old Lisp runtimes assuming fixed-address memory layouts that modern FreeBSD's memory-mapping policies don't permit), just a different failure mode (ENOMEM vs SIGSEGV).

Confirmed via sbcl.org/platform-table.html that upstream SBCL has never published a FreeBSD x86-64 binary newer than 1.2.7 — so there's no simple drop-in replacement distfile available from the SBCL project itself.
As a local workaround, I used an existing pkg-installed SBCL 2.6.6 to build 2.6.7 by manually substituting it as --xc-host, which built successfully — confirming the bootstrap binary itself (not the source or build flags) is the actual blocker.

Suggested directions for a real fix (not something I'm able to submit as a ready patch, since it'd need a legitimately redistributable binary source rather than a self-built one):

Point the port's bootstrap fetch at FreeBSD's own official pkg repository build of sbcl instead of the stale SourceForge tarball, since that binary is already correctly built for the current release/ABI by the FreeBSD package-build infrastructure.
Or default BOOTSTRAP to ABCL (JVM-based, sidesteps the fixed-address-mmap issue entirely) on FreeBSD/amd64 rather than SBCL/CCL, if ABCL is confirmed to build/work reliably there.

Environment:

FreeBSD 15.1-STABLE amd64
Building via poudriere with lang/sbcl port, default options except as noted
Comment 1 Kirill Ponomarev freebsd_committer freebsd_triage 2026-08-02 07:44:14 UTC
Thanks for the report. I cannot reproduce this, and I suspect the failure is
specific to your build environment rather than to the bootstrap binary itself.

What I tested, on FreeBSD 15.1-RELEASE-p2 amd64 (default sysctls:
kern.elf64.aslr.enable=1, pie_enable=1, stack=1, shared_page=1,
security.bsd.map_at_zero=0), using the exact distfile the port uses:

  $ ldd src/runtime/sbcl
      libutil.so.9 => not found (0)
      libm.so.5 => /lib/libm.so.5
      libc.so.7 => /lib/libc.so.7
      libsys.so.7 => /lib/libsys.so.7

  $ ./src/runtime/sbcl --core output/sbcl.core --noinform ...
  ld-elf.so.1: Shared object "libutil.so.9" not found, required by "sbcl"

With libutil.so.9 from compat14x-amd64-14.2.1402000.20251120_1 in the library
path:

  $ ./src/runtime/sbcl --core output/sbcl.core --noinform --disable-debugger \
      --no-sysinit --no-userinit --eval '(progn (print (lisp-implementation-version)) (sb-ext:quit))'
  "1.2.7"
  exit 0

and the same under `proccontrol -m aslr -s enable`, also exit 0.

So on a stock FreeBSD 15.1 amd64 kernel the 1.2.7 bootstrap runs fine. Note
also that the missing-libutil case is not a segfault: it fails in rtld with a
clear message. Your report shows SIGSEGV, which means the library was found
and something else went wrong.

The port already handles the libutil bump:

  .if ${OSVERSION} >= 1500000
  BUILD_DEPENDS+=     ${LOCALBASE}/lib/compat/libutil.so.9:misc/compat14x
  .endif

added in cb22d37deda98b705c0406889d5da1bb2a5cb425 (2025-11-08). And the
official package builders do build this port on 15.x — FreeBSD:15:amd64
currently ships sbcl-2.6.6,1.

Could you please provide:

  1. `uname -a` of the build host, and the poudriere jail version
     (`poudriere jail -l`).
  2. The revision of the ports tree you built from (`git -C <portstree> rev-parse HEAD`),
     to confirm it contains cb22d37deda9.
  3. Inside the jail (poudriere testport -i): `pkg info -x compat14x` and
     `ldd work/sbcl-1.2.7-x86-64-freebsd/src/runtime/sbcl`.
  4. A backtrace from the core file:
     `gdb work/sbcl-1.2.7-x86-64-freebsd/src/runtime/sbcl <core>` then `bt`.
  5. The full make.sh output around the failure (work/.build_log or the
     poudriere build log), not just the last two lines.

Regarding the suggested directions: fetching the bootstrap from the FreeBSD
package repository is not workable — distfiles must have a stable URL and a
fixed checksum recorded in distinfo, which pkg repository contents do not
provide. Switching the default BOOTSTRAP to ABCL would pull in a JVM as a
build dependency for every consumer of the port, which is a much heavier
change than this problem warrants, especially while the current bootstrap
demonstrably works.
Comment 2 Robert Cina 2026-08-02 12:04:20 UTC
Thanks for looking into this — you're right that the missing-libutil case isn't what I'm hitting; that resolves correctly in my environment (see below). Here's everything requested:

1. uname -a / jail version:

Host:

FreeBSD alto.my.domain 15.1-STABLE FreeBSD 15.1-STABLE stable/15-n284649-23216f6309c6 GENERIC amd64

Poudriere jail:

JAILNAME VERSION             OSVERSION ARCH  METHOD       TIMESTAMP           PATH
15amd64  15.1-STABLE 1501501 1501501   amd64 src=/usr/src 2026-07-29 19:29:04 /hdd/poudriere/jails/15amd64

Note this is a -STABLE snapshot built from src=/usr/src (stable/15-n284649-23216f6309c6), not 15.1-RELEASE-p2 — possibly relevant given the crash pattern below.

2. Ports tree revision: confirmed my tree includes the compat14x fix — libutil.so.9 resolves correctly (see ldd below), and the build log shows that dependency installing and being found cleanly during build-depends. This isn't a stale-tree issue.

3. pkg info -x compat14x / ldd:

compat14x-amd64-14.2.1402000.20251120_1

/wrkdirs/usr/ports/lang/sbcl/work/sbcl-1.2.7-x86-64-freebsd/src/runtime/sbcl:
        libutil.so.9 => /usr/local/lib/compat/libutil.so.9 (0x18f95caee000)
        libm.so.5 => /lib/libm.so.5 (0x18f95cc44000)
        libc.so.7 => /lib/libc.so.7 (0x18f95d5b3000)
        libsys.so.7 => /lib/libsys.so.7 (0x18f95dd3b000)
        [vdso] (0x18f95b940000)

All libraries resolve cleanly — matches your working case, not your initial missing-libutil case.

4. Backtrace from the core file:

Core was generated by `/wrkdirs/usr/ports/lang/sbcl/work/sbcl-1.2.7-x86-64-freebsd/src/runtime/sbcl --c'.
Program terminated with signal SIGSEGV, Segmentation fault.
Address not mapped to object.
#0  0x0000001040000000 in ?? ()
#1  0x0000000000000000 in ?? ()

Memory map at crash time:

          Start Addr           End Addr       Size     Offset   Flags   File
            0x400000           0x42b000    0x2b000        0x0  r-x CN-- .../src/runtime/sbcl
            0x62a000           0x62b000     0x1000    0x2a000  rw- C--- .../src/runtime/sbcl
            0x62b000           0x635000     0xa000        0x0  rw- ----
          0x20000000         0x200fe000    0xfe000        0x0  rwx ----
          0x20100000         0x201ff000    0xff000        0x0  rwx ----
        0x1000000000       0x1040000000 0x40000000        0x0  rwx ----
      0x178e65003000     0x178e65009000     0x6000        0x0  r-- CN-- /libexec/ld-elf.so.1
      0x178e65009000     0x178e65021000    0x18000     0x5000  r-x CN-- /libexec/ld-elf.so.1
      0x178e65021000     0x178e65022000     0x1000    0x1c000  r-- C--- /libexec/ld-elf.so.1
      0x178e65022000     0x178e65023000     0x1000        0x0  r-- ----
      0x178e65023000     0x178e65025000     0x2000     0x1000  rw- ----
      0x1d246ea00000     0x1d246ea47000    0x47000        0x0  rw- ----
      0x1d246ec00000     0x1d246f600000   0xa00000        0x0  rw- ----
      0x7ffffffff000     0x800000000000     0x1000        0x0  --- ----

Notably, the crash address 0x1040000000 is exactly the first byte past the end of the 0x1000000000–0x1040000000 (1GB) heap mapping — this isn't a jump into arbitrary unmapped memory, it's execution running off the precise top edge of that heap region by one address unit.

Given the -STABLE vs -RELEASE-p2 discrepancy and how precisely the crash address lines up with a mapping boundary, my guess is something in a recent -STABLE commit touches mmap/heap-region sizing in a way that hasn't reached RELEASE yet — but that's speculation on my part. Happy to test any specific hypothesis or run additional diagnostics.

5. Full build log:

<details> <summary>Full poudriere build log (click to expand)</summary>
build started at 2026-08-02T07:53:13-04:00
port directory: /usr/ports/lang/sbcl
package name: sbcl-2.6.7_1,1
building for: FreeBSD 15amd64-Default 15.1-STABLE FreeBSD 15.1-STABLE 1501501 amd64
maintained by: krion@FreeBSD.org
port version: 2.6.7
port revision: 1
Makefile datestamp: Aug  2 07:52:36 2026
[00:00:09] Inspecting /hdd/poudriere/data/.m/15amd64-Default/ref//usr/ports/lang/sbcl for modifications to git checkout... no
Port dir unclean checkout: no
Poudriere version: poudriere-git-3.4.99.20260425
Host OSVERSION: 1501501
Jail OSVERSION: 1501501
Builder Id: 
Builder jail path: /hdd/poudriere/data/.m/15amd64-Default/ref
Ref jail path: /hdd/poudriere/data/.m/15amd64-Default/ref
Job Idx: 
Jail Id (no networking)  : 27
Jail Name (no networking): 15amd64-Default
Jail Id (networking)     : 28
Jail Name (networking)   : 15amd64-Default-n

---Begin Environment---
SHELL=/bin/sh
OSVERSION=1501501
UNAME_v=FreeBSD 15.1-STABLE 1501501
UNAME_r=15.1-STABLE
BLOCKSIZE=K
MAIL=/var/mail/root
MM_CHARSET=UTF-8
LANG=C.UTF-8
STATUS=1
HOME=/root
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:/root/bin
MAKE_OBJDIR_CHECK_WRITABLE=0
LOCALBASE=/usr/local
USER=root
POUDRIERE_NAME=poudriere-git
POUDRIERE_VERSION=3.4.99.20260425
LC_COLLATE=C
POUDRIERE_BUILD_TYPE=bulk
PACKAGE_BUILDING=yes
SAVED_TERM=xterm-256color
OUTPUT_REDIRECTED_STDERR=4
OUTPUT_REDIRECTED=1
PWD=/hdd/poudriere/data/.m/15amd64-Default/ref/.p
OUTPUT_REDIRECTED_STDOUT=3
NO_WARNING_PKG_INSTALL_EOL=yes
P_PORTS_FEATURES=FLAVORS SUBPACKAGES SELECTED_OPTIONS
MASTERNAME=15amd64-Default
OLDPWD=/hdd/poudriere/data/.m/15amd64-Default/ref/.p/pool
POUDRIERE_PKGNAME=poudriere-git-3.4.99.20260425
PREFIX=/usr/local
POUDRIEREPATH=/usr/local/bin/poudriere
---End Environment---

---Begin Poudriere Port Flags/Env---
PORT_FLAGS=
PKGENV=PACKAGES=/tmp/pkgs PKGREPOSITORY=/tmp/pkgs PKGLATESTREPOSITORY=/tmp/pkgs/Latest
FLAVOR=
MAKE_ARGS=
---End Poudriere Port Flags/Env---

---Begin OPTIONS List---
===> The following configuration options are available for sbcl-2.6.7_1,1:
     COMPRESSION=on: Enable core compression
     DOCS=on: Build and/or install documentation
     GARBAGE_COLLECTOR=off: Enable mark-region parallel garbage collector
     LINKABLE_RUNTIME=off: Enable SB-LINKABLE-RUNTIME feature (experimental)
     QSHOW=off: C runtime with low-level debugging output
     SAFEPOINT=off: Using safepoints instead of signals
     SIMD=off: Enable SB-SIMD (requires CPUs supporting AVX2)
     THREADS=on: Threading support
     UNICODE=on: Unicode support
     XREF=off: XREF data for SBCL internals
====> Supported languages of the build host: you have to select exactly one of them
     CCL=off: Clozure Common Lisp
     SBCL=on: Steel Bank Common Lisp
===> Use 'make config' to modify these settings
---End OPTIONS List---

--MAINTAINER--
krion@FreeBSD.org
--End MAINTAINER--

--PORTVERSION--
2.6.7
--End PORTVERSION--

--PORTREVISION--
1
--End PORTREVISION--

--CONFIGURE_ARGS--

--End CONFIGURE_ARGS--

--CONFIGURE_ENV--
MAKE=/usr/local/bin/gmake XDG_DATA_HOME=/wrkdirs/usr/ports/lang/sbcl/work  XDG_CONFIG_HOME=/wrkdirs/usr/ports/lang/sbcl/work  XDG_CACHE_HOME=/wrkdirs/usr/ports/lang/sbcl/work/.cache  HOME=/wrkdirs/usr/ports/lang/sbcl/work TMPDIR="/tmp" PATH=/wrkdirs/usr/ports/lang/sbcl/work/.bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:/root/bin PKG_CONFIG_LIBDIR=/wrkdirs/usr/ports/lang/sbcl/work/.pkgconfig:/usr/local/libdata/pkgconfig:/usr/local/share/pkgconfig:/usr/libdata/pkgconfig SHELL=/bin/sh CONFIG_SHELL=/bin/sh CMAKE_PREFIX_PATH="/usr/local"
--End CONFIGURE_ENV--

--MAKE_ENV--
XDG_DATA_HOME=/wrkdirs/usr/ports/lang/sbcl/work  XDG_CONFIG_HOME=/wrkdirs/usr/ports/lang/sbcl/work  XDG_CACHE_HOME=/wrkdirs/usr/ports/lang/sbcl/work/.cache  HOME=/wrkdirs/usr/ports/lang/sbcl/work TMPDIR="/tmp" PATH=/wrkdirs/usr/ports/lang/sbcl/work/.bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:/root/bin PKG_CONFIG_LIBDIR=/wrkdirs/usr/ports/lang/sbcl/work/.pkgconfig:/usr/local/libdata/pkgconfig:/usr/local/share/pkgconfig:/usr/libdata/pkgconfig MK_DEBUG_FILES=no MK_KERNEL_SYMBOLS=no SHELL=/bin/sh NO_LINT=YES PREFIX=/usr/local  LOCALBASE=/usr/local  CC="cc" CFLAGS="-O2 -pipe  -fstack-protector-strong -isystem /usr/local/include -fno-strict-aliasing "  CPP="cpp" CPPFLAGS="-isystem /usr/local/include"  LDFLAGS=" -L/usr/local/lib " LIBS=""  CXX="c++" CXXFLAGS="-O2 -pipe -fstack-protector-strong -isystem /usr/local/include -fno-strict-aliasing   -isystem /usr/local/include " BSD_INSTALL_PROGRAM="install  -s -m 555"  BSD_INSTALL_LIB="install  -s -m 0644"  BSD_INSTALL_SCRIPT="install  -m 555"  BSD_INSTALL_DATA="install  -m 0644"  BSD_INSTALL_MAN="install  -m 444"
--End MAKE_ENV--

--PLIST_SUB--
PORTDOCS="" LINKABLE_RUNTIME="@comment " SIMD="@comment " OSREL=15.1 PREFIX=%D LOCALBASE=/usr/local  RESETPREFIX=/usr/local LIB32DIR=lib DOCSDIR="share/doc/sbcl"  EXAMPLESDIR="share/examples/sbcl"  DATADIR="share/sbcl"  WWWDIR="www/sbcl"  ETCDIR="etc/sbcl"
--End PLIST_SUB--

--SUB_LIST--
PREFIX=/usr/local LOCALBASE=/usr/local  DATADIR=/usr/local/share/sbcl DOCSDIR=/usr/local/share/doc/sbcl EXAMPLESDIR=/usr/local/share/examples/sbcl  WWWDIR=/usr/local/www/sbcl ETCDIR=/usr/local/etc/sbcl
--End SUB_LIST--

---Begin make.conf---
USE_PACKAGE_DEPENDS=yes
BATCH=yes
WRKDIRPREFIX=/wrkdirs
PORTSDIR=/usr/ports
PACKAGES=/packages
DISTDIR=/distfiles
FORCE_PACKAGE=yes
PACKAGE_BUILDING=yes
PACKAGE_BUILDING_FLAVORS=yes
#### /usr/local/etc/poudriere.d/make.conf ####
DISABLE_LICENSES=yes
PORTS_MODULES=nvidia-driver
x11_kitty_UNSET= DOCS
DEFAULT_VERSIONS+= postgresql=18
WITH_CCACHE_BUILD=yes
CCACHE_DIR=/root/.ccache
#### Misc Poudriere ####
.include "/etc/make.conf.ports_env"
GID=0
UID=0
---End make.conf---
--Resource limits--
cpu time               (seconds, -t)  unlimited
file size           (512-blocks, -f)  unlimited
data seg size           (kbytes, -d)  67108864
stack size              (kbytes, -s)  524288
core file size      (512-blocks, -c)  unlimited
max memory size         (kbytes, -m)  unlimited
locked memory           (kbytes, -l)  unlimited
max user processes              (-u)  63507
open files                      (-n)  4096
virtual mem size        (kbytes, -v)  62914560
swap limit              (kbytes, -w)  unlimited
socket buffer size       (bytes, -b)  unlimited
pseudo-terminals                (-p)  unlimited
kqueues                         (-k)  unlimited
umtx shared locks               (-o)  unlimited
pipebuf                 (kbytes, -y)  unlimited
--End resource limits--
times start [shell] (user/sys/real): 0m0.658s 0m1.700s 0m9.000s
times start [child] (user/sys/real): 0m13.002s 0m18.278s 0m9.000s
=======================<phase: check-sanity   >============================
===== env: DEVELOPER_MODE=yes DEVELOPER=1 STRICT_DEPENDS=yes USER=root UID=0 GID=0
===========================================================================
=======================<phase: pkg-depends    >============================
===== env: DEVELOPER_MODE=yes USE_PACKAGE_DEPENDS_ONLY=1 USER=root UID=0 GID=0
===>   sbcl-2.6.7_1,1 depends on file: /usr/local/sbin/pkg - not found
===>   Installing existing package /packages/All/pkg-2.8.1_1.pkg
[15amd64-Default] Installing pkg-2.8.1_1...
[15amd64-Default] Extracting pkg-2.8.1_1: .......... done
===>   sbcl-2.6.7_1,1 depends on file: /usr/local/sbin/pkg - found
===>   Returning to build of sbcl-2.6.7_1,1
===========================================================================
=======================<phase: fetch-depends  >============================
===== env: DEVELOPER_MODE=yes USE_PACKAGE_DEPENDS_ONLY=1 USER=root UID=0 GID=0
===========================================================================
=======================<phase: fetch          >============================
===== env: DEVELOPER_MODE=yes STRICT_DEPENDS=yes USER=root UID=0 GID=0
===>   sbcl-2.6.7_1,1 depends on file: /usr/local/sbin/pkg - found
===> Fetching all distfiles required by sbcl-2.6.7_1,1 for building
===========================================================================
=======================<phase: checksum       >============================
===== env: DEVELOPER_MODE=yes STRICT_DEPENDS=yes USER=root UID=0 GID=0
===>   sbcl-2.6.7_1,1 depends on file: /usr/local/sbin/pkg - found
===> Fetching all distfiles required by sbcl-2.6.7_1,1 for building
=> SHA256 Checksum OK for sbcl-2.6.7-source.tar.bz2.
=> SHA256 Checksum OK for sbcl-1.2.7-x86-64-freebsd-binary.tar.bz2.
===========================================================================
=======================<phase: extract-depends>============================
===== env: DEVELOPER_MODE=yes USE_PACKAGE_DEPENDS_ONLY=1 USER=root UID=0 GID=0
===========================================================================
=======================<phase: extract        >============================
===== env: DEVELOPER_MODE=yes STRICT_DEPENDS=yes USER=root UID=0 GID=0
===>   sbcl-2.6.7_1,1 depends on file: /usr/local/sbin/pkg - found
===> Fetching all distfiles required by sbcl-2.6.7_1,1 for building
===>  Extracting for sbcl-2.6.7_1,1
=> SHA256 Checksum OK for sbcl-2.6.7-source.tar.bz2.
=> SHA256 Checksum OK for sbcl-1.2.7-x86-64-freebsd-binary.tar.bz2.
===========================================================================
=======================<phase: patch-depends  >============================
===== env: DEVELOPER_MODE=yes USE_PACKAGE_DEPENDS_ONLY=1 USER=root UID=0 GID=0
===========================================================================
=======================<phase: patch          >============================
===== env: DEVELOPER_MODE=yes DEVELOPER=1 STRICT_DEPENDS=yes USER=root UID=0 GID=0
===>  Patching for sbcl-2.6.7_1,1
===>  Applying FreeBSD patches for sbcl-2.6.7_1,1 from /usr/ports/lang/sbcl/files
===========================================================================
=======================<phase: build-depends  >============================
===== env: DEVELOPER_MODE=yes USE_PACKAGE_DEPENDS_ONLY=1 USER=root UID=0 GID=0
===>   sbcl-2.6.7_1,1 depends on package: gmake>=4.4.1 - not found
===>   Installing existing package /packages/All/gmake-4.4.1.pkg
[15amd64-Default] Installing gmake-4.4.1...
[15amd64-Default] `-- Installing gettext-runtime-1.0_1...
[15amd64-Default] |   `-- Installing indexinfo-0.3.1_1...
[15amd64-Default] |   `-- Extracting indexinfo-0.3.1_1: . done
[15amd64-Default] `-- Extracting gettext-runtime-1.0_1: .......... done
[15amd64-Default] Extracting gmake-4.4.1: .......... done
===>   sbcl-2.6.7_1,1 depends on package: gmake>=4.4.1 - found
===>   Returning to build of sbcl-2.6.7_1,1
===>   sbcl-2.6.7_1,1 depends on file: /usr/local/bin/makeinfo - not found
===>   Installing existing package /packages/All/texinfo-7.3_1,1.pkg
[15amd64-Default] Installing texinfo-7.3_1,1...
[15amd64-Default] `-- Installing libiconv-1.18_1...
[15amd64-Default] `-- Extracting libiconv-1.18_1: .......... done
[15amd64-Default] `-- Installing libunistring-1.4.2...
[15amd64-Default] `-- Extracting libunistring-1.4.2: .......... done
[15amd64-Default] `-- Installing p5-Locale-libintl-1.37...
[15amd64-Default] |   `-- Installing perl5-5.42.2...
[15amd64-Default] |   `-- Extracting perl5-5.42.2: .......... done
[15amd64-Default] `-- Extracting p5-Locale-libintl-1.37: .......... done
[15amd64-Default] `-- Installing p5-Text-Unidecode-1.30...
[15amd64-Default] `-- Extracting p5-Text-Unidecode-1.30: .......... done
[15amd64-Default] `-- Installing p5-Unicode-EastAsianWidth-12.0...
[15amd64-Default] `-- Extracting p5-Unicode-EastAsianWidth-12.0: ... done
[15amd64-Default] Extracting texinfo-7.3_1,1: .......... done
===>   sbcl-2.6.7_1,1 depends on file: /usr/local/bin/makeinfo - found
===>   Returning to build of sbcl-2.6.7_1,1
===>   sbcl-2.6.7_1,1 depends on file: /usr/local/lib/compat/libutil.so.9 - not found
===>   Installing existing package /packages/All/compat14x-amd64-14.2.1402000.20251120_1.pkg
[15amd64-Default] Installing compat14x-amd64-14.2.1402000.20251120_1...
[15amd64-Default] Extracting compat14x-amd64-14.2.1402000.20251120_1: .......... done
===>   sbcl-2.6.7_1,1 depends on file: /usr/local/lib/compat/libutil.so.9 - found
===>   Returning to build of sbcl-2.6.7_1,1
===>   sbcl-2.6.7_1,1 depends on file: /usr/local/bin/ccache - not found
===>   Installing existing package /packages/All/ccache-3.7.12_9.pkg
[15amd64-Default] Installing ccache-3.7.12_9...
[15amd64-Default] Extracting ccache-3.7.12_9: ......... done
Create compiler links...
create symlink for cc
create symlink for cc (world)
create symlink for c++
create symlink for c++ (world)
create symlink for CC
create symlink for CC (world)
create symlink for clang
create symlink for clang (world)
create symlink for clang++
create symlink for clang++ (world)
===>   sbcl-2.6.7_1,1 depends on file: /usr/local/bin/ccache - found
===>   Returning to build of sbcl-2.6.7_1,1
===========================================================================
=======================<phase: lib-depends    >============================
===== env: DEVELOPER_MODE=yes USE_PACKAGE_DEPENDS_ONLY=1 USER=root UID=0 GID=0
===>   sbcl-2.6.7_1,1 depends on shared library: libgmp.so - not found
===>   Installing existing package /packages/All/gmp-6.3.0.pkg
[15amd64-Default] Installing gmp-6.3.0...
[15amd64-Default] Extracting gmp-6.3.0: .......... done
===>   sbcl-2.6.7_1,1 depends on shared library: libgmp.so - found (/usr/local/lib/libgmp.so)
===>   Returning to build of sbcl-2.6.7_1,1
===>   sbcl-2.6.7_1,1 depends on shared library: libmpfr.so - not found
===>   Installing existing package /packages/All/mpfr-4.2.2,1.pkg
[15amd64-Default] Installing mpfr-4.2.2,1...
[15amd64-Default] Extracting mpfr-4.2.2,1: .......... done
===>   sbcl-2.6.7_1,1 depends on shared library: libmpfr.so - found (/usr/local/lib/libmpfr.so)
===>   Returning to build of sbcl-2.6.7_1,1
===>   sbcl-2.6.7_1,1 depends on shared library: libzstd.so - not found
===>   Installing existing package /packages/All/zstd-1.5.7_2.pkg
[15amd64-Default] Installing zstd-1.5.7_2...
[15amd64-Default] `-- Installing liblz4-1.10.0_2,1...
[15amd64-Default] `-- Extracting liblz4-1.10.0_2,1: .......... done
[15amd64-Default] Extracting zstd-1.5.7_2: .......... done
===>   sbcl-2.6.7_1,1 depends on shared library: libzstd.so - found (/usr/local/lib/libzstd.so)
===>   Returning to build of sbcl-2.6.7_1,1
===========================================================================
=>> Recording filesystem state for prebuild... done
=======================<phase: configure      >============================
===== env: DEVELOPER_MODE=yes STRICT_DEPENDS=yes USER=root UID=0 GID=0
===>   sbcl-2.6.7_1,1 depends on package: gmake>=4.4.1 - found
===>   sbcl-2.6.7_1,1 depends on file: /usr/local/bin/makeinfo - found
===>   sbcl-2.6.7_1,1 depends on file: /usr/local/lib/compat/libutil.so.9 - found
===>   sbcl-2.6.7_1,1 depends on file: /usr/local/bin/ccache - found
===>   sbcl-2.6.7_1,1 depends on shared library: libgmp.so - found (/usr/local/lib/libgmp.so)
===>   sbcl-2.6.7_1,1 depends on shared library: libmpfr.so - found (/usr/local/lib/libmpfr.so)
===>   sbcl-2.6.7_1,1 depends on shared library: libzstd.so - found (/usr/local/lib/libzstd.so)
===>  Configuring for sbcl-2.6.7_1,1
===========================================================================
=======================<phase: build          >============================
===== env: DEVELOPER_MODE=yes STRICT_DEPENDS=yes USER=root UID=0 GID=0
===>  Building for sbcl-2.6.7_1,1
(cd /wrkdirs/usr/ports/lang/sbcl/work/sbcl-2.6.7 && /bin/sh make.sh --prefix="/usr/local" --xc-host="/wrkdirs/usr/ports/lang/sbcl/work/sbcl-1.2.7-x86-64-freebsd/src/runtime/sbcl --core /wrkdirs/usr/ports/lang/sbcl/work/sbcl-1.2.7-x86-64-freebsd/output/sbcl.core --noinform --disable-debugger --no-sysinit --no-userinit" --with-sb-core-compression --with-gencgc --without-mark-region-gc --without-sb-linkable-runtime --without-sb-qshow --without-sb-safepoint --without-sb-thruption --without-sb-wtimer --without-sb-simd --with-sb-thread --with-sb-unicode --without-sb-xref-for-internals)
Segmentation fault (core dumped)
No working host Common Lisp implementation.
See ./INSTALL, the "SOURCE DISTRIBUTION" section
*** Error code 1

Stop.
make: stopped making "build" in /usr/ports/lang/sbcl
Comment 3 Robert Cina 2026-08-02 12:08:01 UTC
As a workaround on my end, I've confirmed that substituting a working modern SBCL binary as the bootstrap (in place of the stale 1.2.7 one) builds successfully — this reinforces that the 1.2.7 binary itself is the actual blocker, not something else in my environment. I don't have a way to offer this as a real patch since it relies on a binary that only exists on my machine, but wanted to mention it in case it's a useful data point.
Comment 4 Kirill Ponomarev freebsd_committer freebsd_triage 2026-08-02 13:17:35 UTC
Thanks, that's exactly what I needed, the libutil angle is settled, your
environment resolves it correctly.

The most interesting datum here is the one you flagged yourself: you are on
stable/15-n284649-23216f6309c6 with a jail built from that same source, while
my working case is 15.1-RELEASE-p2. So a base-system difference between
stable/15 and releng/15.1 is a plausible hypothesis. I looked through the
stable/15 history in sys/vm and sys/kern/imgact_elf.c since 15.1-RELEASE and
did not find an obvious candidate touching mmap or heap placement on amd64,
but that is far from conclusive.

Two remarks on the data before we settle on that explanation:

- The memory map you posted contains ld-elf.so.1 but no libc.so.7,
  libm.so.5, libutil.so.9 and no stack mapping, which does not match the
  ldd output from the same binary. If that listing was trimmed, could you
  post the full `procstat -v <core>` (or `info proc mappings` in gdb)
  unabridged?
- The backtrace has two frames and #1 is 0x0, i.e. the stack was not
  unwound. "Execution ran off the top edge of the heap" is one reading of
  PC == 0x1040000000, but an indirect call through a pointer that happens
  to equal the end of dynamic space produces the same picture. Without a
  usable stack we cannot tell those apart.

The experiment that would actually decide this: on the same host, with the
same kernel, create a poudriere jail from 15.1-RELEASE instead of from
/usr/src, and build there:

poudriere jail -c -j 151amd64 -v 15.1-RELEASE -m ftp
poudriere testport -j 151amd64 -p <portstree> -o lang/sbcl

The kernel is unchanged, only the userland differs. If the build succeeds,
the trigger is in the stable/15 userland (rtld, libc) rather than in the
kernel. If it still segfaults, it is the kernel. Either way the answer points
at the base system, not at the port, and the PR should be reassigned
accordingly.

On the workaround: substituting a modern SBCL does confirm the 1.2.7 binary is
what trips over this, but it does not tell us that 1.2.7 is at fault, a
current SBCL is a PIE with a different memory layout and a different GC so it
simply may not touch whatever changed. And it cannot become the port's
bootstrap: distfiles need a stable URL and a checksum in distinfo, which
neither a self-built binary nor the pkg repository provides, and upstream
still publishes no FreeBSD x86-64 binary newer than 1.2.7 as you noted.
Defaulting BOOTSTRAP to ABCL would drag a JVM into the build dependencies of
every consumer which is a lot of weight for a problem that so far reproduces
on exactly one machine.
Comment 5 Robert Cina 2026-08-02 13:52:36 UTC
Ran the experiment:

sh
poudriere jail -c -j 151amd64 -v 15.1-RELEASE -m ftp
poudriere testport -j 151amd64 -p Default -o lang/sbcl -i

Same host, same kernel, genuinely different (RELEASE) userland. Result: segfaults identically.

Segmentation fault (core dumped)
No working host Common Lisp implementation.

procstat -v on the fresh core from this jail (confirmed fresh — different PID/timestamp/addresses from my earlier stable/15 core, not a stale leftover):

  PID              START                END PRT  RES PRES REF SHD FLAG  TP PATH
76572           0x400000           0x42b000 r-x   43  139   3   1 CN--- vn .../src/runtime/sbcl
76572           0x62a000           0x62b000 rw-    1    0   1   0 C---- vn .../src/runtime/sbcl
76572           0x62b000           0x635000 rw-    4    4   1   0 ----- sw
76572         0x20000000         0x200fe000 rwx    0    0   0   0 ----- --
76572         0x20100000         0x201ff000 rwx    0    0   0   0 ----- --
76572       0x1000000000       0x1040000000 rwx 114129 114129   1   0 --S-- sw
76572     0x178d6531b000     0x178d65321000 r--    6   30   9   0 CN--- vn /libexec/ld-elf.so.1
76572     0x178d65321000     0x178d65339000 r-x   24   30   9   0 CN--- vn /libexec/ld-elf.so.1
76572     0x178d65339000     0x178d6533a000 r--    1    3   2   0 ----- sw
76572     0x178d6533a000     0x178d6533c000 rw-    2    3   2   0 ----- sw
76572     0x3be217e00000     0x3be217e47000 rw-   33   33   1   0 ----- sw
76572     0x3be218000000     0x3be218a00000 rw-   35   35   1   0 ----- sw
76572     0x7ffffffff000     0x800000000000 ---    0    0   0   0 ----- gd

Same signature as before: the large rwx/superpage heap mapping at 0x1000000000–0x1040000000 is present and fully resident, but there's no libc.so.7, libm.so.5, libutil.so.9, or stack mapping — even though ldd confirms those are needed. This matches the earlier stable/15 result almost exactly (same heap region, same missing mappings), just with different randomized addresses for the shared objects.

Since the kernel is identical between my two jails but the userland genuinely differs (RELEASE vs stable/15), and both crash identically with the same pattern, this rules out a stable/15-userland-specific cause. That leaves either the kernel itself, or something specific to this machine (CPU, hardware, or a non-default kernel config on my end) that's independent of both the FreeBSD version and userland — which would also explain why it doesn't reproduce on your side at all.

I'm not sure what would meaningfully narrow this further without deeper knowledge of the SBCL 1.2.7 runtime's startup sequence — happy to try anything else you'd suggest, but at this point I suspect this may be specific to my hardware/kernel config rather than a general FreeBSD version issue.
Comment 6 Kirill Ponomarev freebsd_committer freebsd_triage 2026-08-02 14:11:57 UTC
The procstat -v output in comment 5 reproduces exactly the anomaly I pointed
out in comment #4. It lists ld-elf.so.1 and the 0x1000000000-0x1040000000
dynamic space (rwx, superpage-backed, 114129 resident pages, ~445 MB) but it
contains no libc.so.7, no libm.so.5, no libutil.so.9 and no stack mapping

That combination cannot describe a real process image. To map and populate
445 MB of dynamic space the runtime must have reached its own main(), and it
cannot get there before rtld has loaded the libraries that ldd lists for the
very same binary - which your own output in comment 3 confirms resolve
correctly.

Please run the bootstrap under ktrace instead: ktrace -di -f /tmp/kt <the
make.sh --xc-host invocation>, then kdump -f /tmp/kt | tail -100. And, from
gdb on the core, info sharedlibrary. If that also reports no libc, the core
is malformed and nothing can be concluded from it.

BTW the description cites OPTIONS_SINGLE_BOOTSTRAP=ABCL CCL CMUCL SBCL, while the OPTIONS list in the build log you attached offers only CCL and SBCL
Comment 7 Robert Cina 2026-08-02 15:30:41 UTC
Good catch — you were right that something was off, but it turns out to be procstat -v's listing that's unreliable for this core, not the core itself.

gdb's info sharedlibrary on the same core shows all libraries loaded correctly:

From                To                  Syms Read   Shared Object Library
                                        No          [vdso]
0x0000001021b4cb00  0x0000001021b56e6c  Yes (*)     /usr/local/lib/compat/libutil.so.9
0x0000001022c1e9e0  0x0000001022c4460c  Yes (*)     /lib/libm.so.5
0x0000001023470010  0x00000010235c33cc  Yes (*)     /lib/libc.so.7
0x000000102422ce30  0x000000102423253c  Yes (*)     /lib/libsys.so.7
0x0000178d65321b70  0x0000178d65338161  Yes (*)     /libexec/ld-elf.so.1

This matches the ktrace too — the very first syscall is readlink("/etc/malloc.conf"), libc/jemalloc's own startup probe, confirming libc was already loaded and running at that point. So procstat -v's omission of these mappings was a procstat quirk on this core specifically, not evidence of anything wrong with the process. Apologies for not cross-checking with gdb before reporting the memory map originally.

The ktrace/kdump tail narrows things down further, though:

CALL  mmap(0x20000000,0xfe000,...MAP_FIXED...)      -> succeeds
CALL  mmap(0x20100000,0xff000,...MAP_FIXED...)      -> succeeds
CALL  mmap(0x1000000000,0x40000000,...MAP_FIXED...) -> succeeds, returns 0x1000000000
PSIG  SIGSEGV SIG_DFL code=SEGV_MAPERR
NAMI  "sbcl.core"

All three fixed-address mmaps (including the 1GB heap reservation) succeed cleanly — no ENOMEM, no failed mapping. The crash happens immediately after, and the last named file reference before the signal is sbcl.core itself — meaning the fault occurs while the runtime is loading the Lisp core image into the space it just reserved, not while running Lisp code and not during shared library loading.

On the OPTIONS discrepancy — confirmed, and there's a straightforward explanation: the Makefile defines all four in OPTIONS_SINGLE_BOOTSTRAP= ABCL CCL CMUCL SBCL, but immediately follows with OPTIONS_EXCLUDE= ABCL CMUCL, silently removing those two from what's actually selectable — matching what the build log showed. Not an inconsistency on my end, just the exclude list not being obvious from the OPTIONS_SINGLE_BOOTSTRAP line alone.
Comment 8 Kirill Ponomarev freebsd_committer freebsd_triage 2026-08-02 16:03:01 UTC
`info sharedlibrary` reads rtld's link_map, ie the list of objects rtld has loaded. That list lives in rtld's own allocations and survives the destruction of the mappings it describes. `procstat -v` on the core reports the actual VM state at the moment of the fault. The two are not in conflict, they answer different questions.

Now look at the load addresses from your own gdb output:

libutil.so.9   0x1021b4cb00
libm.so.5      0x1022c1e9e0
libc.so.7      0x1023470010
libsys.so.7    0x102422ce30
ld-elf.so.1    0x178d65321b70

The first four are inside 0x1000000000-0x1040000000, i.e. inside SBCL's dynamic space. The fifth is not. And procstat lists exactly ld-elf.so.1 and exactly omits those four. That is not a procstat quirk, that is the cause:

CALL mmap(0x1000000000,0x40000000,...MAP_FIXED...) -> succeeds

MAP_FIXED does not fail on a collision, it silently unmaps whatever was there. The 1.2.7 runtime reserved its 1 GB heap on top of libc, libm, libutil and libsys. The first call through the PLT after that is your SIGSEGV, and PC == 0x1040000000 is a jump through a now-garbage pointer, not "execution running off the top edge of the heap".

The same reading disposes of the other conclusion in comment 7: NAMI "sbcl.core" appears *after* PSIG SIGSEGV because kern.corefile is "%N.core", so that is the kernel writing the core dump of the process named sbcl. The
Lisp core image would have been opened by its full path: /wrkdirs/.../output/sbcl.core. So the fault happens immediately after the third mmap and before the image is touched at all which is exactly what a vanished libc produces.

As for why this reproduces on your machine and not on mine: FreeBSD places an mmap request without MAP_FIXED at round_page(vm_daddr+lim_max(RLIMIT_DATA)). Measured on 15.1/amd64 (ASLR disabled via proccontrol, PIE binary):

ulimit -d 32 GiB  ->  libc.so.7 at 0x801068000
ulimit -d  8 GiB  ->  libc.so.7 at 0x201068000
ulimit -d  1 GiB  ->  libc.so.7 at 0x41068000

Linear. 64 GiB is exactly 0x1000000000, the start of SBCL 1.2.7's dynamic space.

Compare the Resource limits section of the two build logs:

yours:  data seg size (kbytes, -d)  67108864   ->  64 GiB
mine:   data seg size (kbytes, -d)  33554432   ->  32 GiB

32 GiB is the default (kern.maxdsiz = 34359738368). Yours is raised to 64G, presumably via /boot/loader.conf or login.conf and that puts the shared library mappings precisely where the bootstrap runtime is about to reserve its heap.

Could you please confirm:

- sysctl kern.maxdsiz, and grep maxdsiz /boot/loader.conf /etc/login.conf
- a rebuild with the default limit in effect (ulimit -d 33554432 in the builder or removing the maxdsiz override) - I expect it to build
Comment 9 Robert Cina 2026-08-02 16:41:56 UTC
Found it — you were exactly right. It's /boot/loader.conf, not /etc/login.conf (I misread which file it was in earlier):

# Set max data segment size to 64 GB
kern.maxdsiz="68719476736"

This was a leftover tuning change from experimenting with an unrelated port build a while back, and I'd completely forgotten it was there. After removing it and rebooting, a fresh poudriere testport run against the stock 1.2.7 bootstrap built and installed successfully with no errors — no manual ulimit override needed, just the corrected default.

Thanks for working through this so thoroughly — the mmap/libc-load-address analysis was excellent and much appreciated, especially given this ultimately traced back to a config change on my end rather than anything in the port or base system. Sorry for the run-around this caused; happy to close this out as resolved (not a bug) on my end, or however you'd prefer to handle it.