Repository navigation
package: the payload ships the HSA runtime set it opens, and the release refuses one that resolves outside it (Refs #1411) - #1506
Conversation
…ase refuses one that resolves outside it (Refs #1411) The c22 install's llama-server maps 64 files out of /work-c22/hrx-toolchain/... - the ROCm core runtime set - and ldd shows none of them, because libhsa is opened BY NAME at run time (ggml-hrx-dmabuf.cpp:29, dlopen("libhsa-runtime64.so.1")). Pruning that toolchain therefore kills both services, and no dependency row can see it. Two things were missing, and this is both halves: 1. The payload ships the whole set. scripts/mk-plugin-package.sh staged what ldd resolves, which covers the runtime, rocprofiler-register and the 8 rocm_sysdeps entries - but NOT libhsa-amd-aqlprofile64.so.1, which the runtime opens by name itself. It is staged now, beside the runtime, and the build refuses when it is not where the runtime was found. NOTICE-BINARY gains the set's licences, checked against upstream rather than assumed: ROCr is the University of Illinois/NCSA licence, aqlprofile and rocprofiler-register are MIT, and the rocm_sysdeps entries keep their upstream licences (bzip2, libdrm MIT, elfutils, liblzma public domain, libnuma LGPL-2.1, zlib, zstd). 2. The release check fails when anything resolves outside the payload. The #1461 rows move from weekly.sh into scripts/pack-check.sh (so a test can source them) and gain runtime_selfcontained: - no packed ELF may declare an absolute RUNPATH/RPATH entry; - every library ldd resolves for every packed ELF must be inside the payload or a system directory; - the HSA runtime set has to be present beside the backend: libhsa-runtime64.so.1, libhsa-amd-aqlprofile64.so.1, librocprofiler-register.so.0 and at least 8 rocm_sysdeps entries. It runs for both packages, next to the build-path row. tests/pack_check_test.sh (ctest pack_check, in CI) exercises both rows on synthetic trees and asserts each row's own message: a clean tree as the control, a build-machine path, an absolute RUNPATH, a RELATIVE rpath that resolves outside the payload, and a runtime set without aqlprofile. That last arm earned its keep: it failed on the first version of the row, because ldd prints the path it was given unnormalised ("<tree>/bin/../../outside/libx.so"), so a prefix test read a library that had left the payload as "inside" it. The row canonicalises each resolved path now, and the arm is what proves it. Measured 2026-11-08, the red arm on the install that is live today (~/.local/share/1bit-embed-c22/lemonade-onebit-rc-2026-11-03-c22): 19 FAIL lines, rc 1, including every packed library's /work-c22 RUNPATH (libhrx.so.0, libllama.so.0.0.1, llama-server, libggml-hrx.so.0.18.0, libloomc.so.0, ...) and "the HSA runtime set ships without libhsa-runtime64.so.1 / libhsa-amd-aqlprofile64.so.1 / librocprofiler-register.so.0" plus "0 rocm_sysdeps entries". Not run, by owner order: no package build, no new install directory, no drop-in change, no service restart, and no /work-c22 independence run. The end-to-end proof (a fixed payload serving on HRX0 with /work-c22 hidden, and the two services switched to it) is deferred to the release gate once the open issues are solved; #1411 stays open with that noted. checks: bash -n on the touched scripts; shellcheck -S warning adds nothing (weekly.sh keeps its three pre-existing findings); tools/copyright.py --check rc 0; ctest pack_check runs here (5/5 arms) and in CI.
…1411) CI's build job compiles with gcc-16 and ships no bare `cc`, so the first version of the test failed there with "no C compiler (cc)" - the row was right and the harness assumed a name. It probes $CC, cc, gcc, gcc-16, gcc-15, clang now, and only refuses when the box has none at all (which cannot build this repository either, so that is a failure and not a skip).
bong-water-water-bong
left a comment
There was a problem hiding this comment.
VERDICT: READY at 449b3538f555f7596e8747466ab2920e4a3437c0
The right two halves for a runtime the backend dlopens by name, where ldd can't see it:
- the payload now ships
libhsa-amd-aqlprofile64.so.1beside the runtime, and the build refuses when it isn't found; - the release refuses a payload that resolves anything outside itself.
Checked at this head (a831785 + 449b353, base on main):
- The move is complete.
build_path_strings(#1475's row) now lives inscripts/pack-check.sh, whichweekly.shsources (:59-60), and both rows run for both packages::429-430for the engine tarball and:479-480for the Lemonade package. Nothing from #1461 was dropped in the move. - The test passes:
tests/pack_check_test.sh(bash, asadd_testatCMakeLists.txt:256runs it) →pack_check: all rows PASS. That covers the clean control, a runtime set without aqlprofile, an absoluteRUNPATH, a relative rpath that escapes the tree, and a build-machine path. The escaping case is the one that needed the canonicalisation (lddprints the unnormalisedbin/../../outside/…), and it's pinned. - The allowlist is tight:
/lib/*,/lib64/*,/usr/lib/*,/usr/lib64/*and the payload's own canonical path. So/opt/rocm-therock,/usr/local/libor a leftover/work-*/hrx-toolchainall fail, which is exactly the c22 shape. bash -npasses onpack-check.sh,weekly.shandmk-plugin-package.sh;tools/copyright.py --checkis rc 0.
Leaving #1411 open for the live install and service check, per the owner's order, is the right scope.
|
CI at It failed on the first push, and the reason is worth recording: the CI build job compiles with |
…payloads are self-contained (Refs #1411) The row this PR adds runs for both packages, and the second one is the payload the services actually run from: the Lemonade + onebit package carries the engine tarball as 1bit/. That tarball shipped no HSA runtime at all - measured: 0 files in c33's lemonade-onebit payload - so the new row would have failed every roll on it, correctly but uselessly, until the set arrived where both packages inherit it. mk-plugin-package.sh had been overlaying the set for the engine package only. So the packer stages it, from the toolchain THIS build used (read out of the build's CMakeCache, so a build cannot be packed against a toolchain it did not use), and refuses if the toolchain, the core lib directory or any of the three roots is missing. The set is the transitive NEEDED closure of libhsa-runtime64, libhsa-amd-aqlprofile64 and librocprofiler-register - not every file in rocm_sysdeps/lib, which also holds libraries nothing here opens: my first version globbed them all and shipped 36 files, taking the payload from 17.5 to 30.5 MB for nothing. Closure only, flat beside the backend, unmodified (NOTICE-BINARY promises the set as built, so it is staged after pack_localize/strip, the way the licences are). Measured 2026-11-08, packing the existing c33 build tree (no rebuild): hrx/llama/bin: + the HSA runtime set (12 files: the runtime, its aqlprofile agent, the profiling shim and rocm_sysdeps) payload 19.9 MB, was 17.5 the 12 are exactly the owner's list - libhsa-runtime64.so.1, libhsa-amd-aqlprofile64.so.1, librocprofiler-register.so.0 and the 8 rocm_sysdeps the runtime links (bz2, drm, drm_amdgpu, elf, liblzma, numa, z, zstd) - and libhsa/libhsa-amd-aqlprofile64 are byte-identical to the toolchain's (sha256), so what ships is what TheRock built runtime_selfcontained <unpacked tarball> -> ok ... and the HSA runtime set it dlopens ships beside it rc 0
|
One more commit, The row runs for both packages, and the second one is what the services actually run.
Measured by packing the existing c33 build tree, no rebuild: That is the green arm on a real packed tree; the red arm is the c22 install in the body (19 FAIL lines). Still nothing installed, nothing restarted, |
bong-water-water-bong
left a comment
There was a problem hiding this comment.
VERDICT: READY at ba60557f8dce54c5afa1a661c11dfd532d90a26d
The premise is exactly right, and I measured all three parts of it on this box:
1. libhsa opens the agent by NAME, so ldd cannot see it
strings libhsa-runtime64.so.1 | grep aqlprofile -> libhsa-amd-aqlprofile64.so (a bare soname)
readelf -d libhsa-runtime64.so.1 | grep -c aqlprofile -> 0 (not in the dynamic section)
2. the agent exists beside the runtime in the toolchain
/opt/rocm-therock/…/_rocm_sdk_core/lib/libhsa-amd-aqlprofile64.so.1 present
3. and the shipped payload does NOT carry it
find <c32 payload> -name '*aqlprofile*' -> nothing
So the sentence in the comment is not a hypothesis — "a payload built from ldd alone ships a runtime that reaches for it wherever the machine happens to offer it — which is how engine #1411's c22 install ended up mapping 64 files out of a builder's toolchain" is the direct consequence of those three facts: the runtime is present, the dependency is invisible to ldd, and the loader therefore resolves the agent from whatever path is on the machine, including a builder's tree baked into LD_LIBRARY_PATH.
And the harness that catches it runs green here:
$ bash tests/pack_check_test.sh
PASS #1411: a runtime set without aqlprofile fails
PASS #1411: an absolute RUNPATH fails
RUNPATH Library runpath: [$ORIGIN/../../../../outside] (real readelf output in the failing fixture)
PASS #1411: a library resolved outside the payload fails
PASS #1461: a build-machine path in a packed ELF fails
pack_check: all rows PASS
Four pack_check failures that are all the same disease — the payload is not self-contained — each proven on a synthetic payload rather than asserted. The "a library resolved outside the payload fails" row in particular is what would have caught c22 directly: it does not care why a library came from outside.
The build refusing when the agent is not beside the runtime ([ -n "$aq" ] || { echo "no $pat beside $libhsa: …") is the right failure: adding the file silently would ship an empty promise, and a payload that cannot satisfy a dlopen must fail at build time rather than on a user's machine.
All four scripts parse (mk-plugin-package.sh, package-linux.sh, weekly.sh, tests/pack_check_test.sh). The weekly.sh diff moves the logic into package-linux.sh (−46/+38), which is where a payload's closure belongs.
Not run: a full c34 roll (the release lane's next cut). What I can take — the dlopen premise, the missing file in the shipped payload, and the harness's four arms — is measured.
The c22 install's
llama-servermaps 64 files under/work-c22/hrx-toolchain/…— the ROCm core runtime set — andlddshows none of them, because the backend opens the runtime by name at run time:So pruning that toolchain kills both services, and no dependency row can see it. This is the two halves that were missing: the payload ships the set, and the release refuses a payload that resolves outside itself.
Refs #1411 — left open deliberately: no package was built, no install directory created, no drop-in touched, no service restarted. Live verification is deferred to the release gate (owner order).
1. The payload ships the whole runtime set
scripts/mk-plugin-package.shstaged whatlddresolves, which coverslibhsa-runtime64.so.1,librocprofiler-register.so.0and the 8rocm_sysdepsentries — but notlibhsa-amd-aqlprofile64.so.1, which the runtime opens by name itself. It ships beside the runtime now, and the build refuses when it is not where the runtime was found.NOTICE-BINARYgains the set's licences, checked against upstream rather than assumed:rocr-runtime/LICENSE.txt)ROCm/aqlprofile)ROCm/rocprofiler-register)2. The release check fails when anything resolves outside the payload
The #1461 rows move out of
weekly.shintoscripts/pack-check.sh(so a test can source them) and gainruntime_selfcontained:RUNPATH/RPATHentry;lddresolves for every packed ELF must be inside the payload or a system directory;libhsa-runtime64.so.1,libhsa-amd-aqlprofile64.so.1,librocprofiler-register.so.0, and at least 8rocm_sysdepsentries.It runs for both packages, next to the build-path row.
3. Its unit test, in CI
tests/pack_check_test.sh— ctestpack_check, registered inCMakeLists.txt— builds synthetic trees with the C compiler and asserts each row's own message:The escaping arm earned its keep: it failed on the first version of the row.
lddprints the path it was given unnormalised —<tree>/bin/../../outside/libx.so— so a prefix test counted a library that had left the payload as "inside" it. The row canonicalises each resolved path now, and that arm is what proves it.Red arm, measured on the install that is live today
runtime_selfcontained ~/.local/share/1bit-embed-c22/lemonade-onebit-rc-2026-11-03-c22→ 19 FAIL lines, rc 1, includingThe green arm on a fixed payload is the release gate's job, since building and installing one is exactly what was deferred.
Deferred by owner order (not done here)
No package build, no new install directory under
~/.local/share, no drop-in edit (never mind.bak), no restart ofcoder-llm(:8090) or1bit-canonical(:8095), and no/work-c22-hidden independence run. Those happen at the release gate once all issues are solved;/work-c22and the two running services are untouched.Scope and checks
scripts/mk-plugin-package.sh,scripts/pack-check.sh(new),scripts/weekly.sh,tests/pack_check_test.sh(new),CMakeLists.txt,NOTICE-BINARY.bash -nclean on the touched scripts;shellcheck -S warningadds nothing (weekly.shkeeps its three pre-existing findings);tools/copyright.py --checkrc 0;ctest pack_check5/5 here.