Fix executable save-lisp-and-die snapshot on aarch64 Linux#1779
Conversation
On aarch64 Linux, (save-lisp-and-die ... :executable t) failed to produce a
working executable. Two bugs in snapshot_save_impl (snapshotSaveLoad.cc), in
the _TARGET_OS_LINUX _Executable path:
1. The objcopy that wraps the snapshot blob into an object hardcoded
--output-target elf64-x86-64 --binary-architecture i386. On aarch64 objcopy
rejects this ("architecture i386 unknown"), leaving the mkstemp object empty,
which ld.gold then rejects ("file is empty"). Select the output target and
binary architecture by build arch instead (elf64-littleaarch64/aarch64 on ARM64).
2. Both `if (system(cmd) < 0)` checks only detect fork failure, not a non-zero
command exit, so the failing objcopy and link were ignored and execution fell
through to exit(0) -- the build reported success with no artifact. Check for any
non-zero result and exit(1) with the command and code.
Verified on aarch64 Linux (Ubuntu 24.04, llvm 18, boehmprecise): ninja
snapshot-boehmprecise now yields a working ARM64 PIE executable that boots from
its embedded snapshot. x86-64 Linux behavior is unchanged.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
The two failing checks here — Root cause is tracked in #1782: on macOS arm64, Clasp's native (cleavir-emitted) objects carry compact-unwind entries but no So the red here is pre-existing and orthogonal to this change; it can be reviewed on the green jobs. (#1781 is a separate, related Apple-Silicon fix — JIT W^X literal writes — but does not address #1782.) |
Problem
On aarch64 Linux,
(save-lisp-and-die … :executable t)does not produce a working executable. The snapshot data is written correctly, but the binary-object wrap step fails:Two bugs in
snapshot_save_impl(src/gctools/snapshotSaveLoad.cc), in the_TARGET_OS_LINUX_Executablepath:Hardcoded x86-64 objcopy target. The objcopy that wraps the snapshot blob into an object hardcodes
--output-target elf64-x86-64 --binary-architecture i386. On aarch64, objcopy rejects this (architecture i386 unknown), leaving themkstempobject file empty, whichld.goldthen rejects (file is empty). The Darwin path uses-sectcreateand is unaffected; x86-64 Linux happens to match the hardcoded values, which is why CI (x86-64 Linux + aarch64 macOS) never caught it.system()return value mis-checked. Bothif (system(cmd.c_str()) < 0)guards only detect fork failure (system()returns-1); they miss a non-zero exit status. So the failing objcopy and the subsequent failing link are ignored and execution falls through toexit(0)— the build reports success with no artifact produced.Fix
--output-target/--binary-architectureby build architecture:__x86_64__→elf64-x86-64/i386(unchanged),__aarch64__→elf64-littleaarch64/aarch64,#errorotherwise.system()checks detect any non-zero result andexit(1)with the command and code, so a failed snapshot can no longer masquerade as success.Testing
aarch64 Linux (Ubuntu 24.04, clang/llvm 18,
boehmprecisevariant):ninja snapshot-boehmprecisenow produces a working ~212 MBELF 64-bit … ARM aarch64PIE executable that boots from its embedded snapshot and runs (smoke:*features*contains:clasp,fib(25)=75025,(compile …)+funcallwork). x86-64 Linux behavior is unchanged (identical target/arch values as before).🤖 Generated with Claude Code