Skip to content

Make snapshot load position-independent (match libraries by basename)#1780

Open
dg1sbg wants to merge 1 commit into
clasp-developers:mainfrom
dg1sbg:fix/snapshot-relocatable-library-basename
Open

Make snapshot load position-independent (match libraries by basename)#1780
dg1sbg wants to merge 1 commit into
clasp-developers:mainfrom
dg1sbg:fix/snapshot-relocatable-library-basename

Conversation

@dg1sbg
Copy link
Copy Markdown
Contributor

@dg1sbg dg1sbg commented May 30, 2026

Problem

snapshot_load re-resolves the C++ libraries a snapshot references via core::library_with_name, which accepted a loaded library only if a recorded library name was a path suffix of the loaded library's path:

name.size() <= libName.size() && name == libName.substr(libName.size() - name.size())

The recorded name is the absolute path captured by dladdr at save time. So if a snapshot's libraries are later loaded from a different directory than at save — a relocated or bundled install, a different install prefix, or a different machine — the suffix test fails and snapshot_load aborts in snapshotSaveLoad.cc with "Unable to find library: …". On aarch64 Linux, a save-lisp-and-die :executable t image SIGABRTs before its banner once it (and its libraries) are moved.

Fix

Match libraries by basename (SONAME) instead of by save-time path suffix. The nm/dlsym load-address computation that follows already uses the matched, currently-loaded path, so the matcher was the only place bound to the save-time path.

This makes save-lisp-and-die executables and snapshot files relocatable across prefixes/machines — useful for redistributing images and for embedded deployment. It is not aarch64-specific; it helps every platform.

Testing

aarch64 Linux (Ubuntu 24.04, LLVM 18, boehmprecise): a :executable snapshot whose libLLVM/libstdc++/libclasp were relocated into a separate bundle directory and run via LD_LIBRARY_PATH now boots from its embedded snapshot and runs (*features* contains :clasp; fib, compile, funcall all work). Same-tree behavior is unchanged (the recorded path's basename equals the loaded basename).

🤖 Generated with Claude Code

snapshot_load resolves the C++ libraries a snapshot references via
core::library_with_name, which matched a recorded library by requiring its
(save-time) name to be a path SUFFIX of a currently-loaded library's path.
Because the recorded name is the absolute path captured by dladdr at save time,
a snapshot whose libraries are later loaded from a different directory -- a
relocated or bundled install, or a different prefix than the build tree --
fails the suffix test and snapshot_load aborts ("Unable to find library").

Match by basename (SONAME) instead. The subsequent nm/dlsym step already uses
the matched, currently-loaded path, so the matcher was the only place bound to
the save-time path. Snapshots now load regardless of where their libraries sit,
making save-lisp-and-die executables and snapshot files relocatable across
prefixes/machines.

Verified on aarch64 Linux: a boehmprecise :executable snapshot whose libLLVM /
libstdc++ / libclasp were relocated into a bundle directory now boots from its
embedded snapshot and runs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant