diff --git a/docs/todo/INDEX.md b/docs/todo/INDEX.md index 6d70ef7..1dfdc67 100644 --- a/docs/todo/INDEX.md +++ b/docs/todo/INDEX.md @@ -12,15 +12,15 @@ nowhere else. This file is a list, not an order and not a log. | | open | partially done | done | total | |---|---|---|---|---| | measurement | 5 | 1 | 0 | 6 | -| infrastructure | 7 | 0 | 2 | 9 | +| infrastructure | 6 | 0 | 3 | 9 | | blocked | 7 | 0 | 2 reclassified | 9 | -| **total** | **19** | **1** | **2 done, 2 reclassified** | **24** | +| **total** | **18** | **1** | **3 done, 2 reclassified** | **24** | By priority, across the open and partially-done rows: | priority | count | |---|---| -| high | 6 | +| high | 5 | | medium | 7 | | low | 0 | | blocked (no priority, because a machine unblocks these rather than a decision) | 7 | @@ -45,7 +45,7 @@ By priority, across the open and partially-done rows: | T-15 | [A corpus test with a fresh process per library](infrastructure.md) | infrastructure | medium | open | | T-16 | [Delete the path that would mask the failure](infrastructure.md) | infrastructure | medium | open | | T-17 | [The IBT property note is documented and is not there](infrastructure.md) | infrastructure | medium | open | -| T-18 | [There is no release](infrastructure.md) | infrastructure | high | open | +| T-18 | [There is no release](infrastructure.md) | infrastructure | high | done | | B-01 to B-09 | [the blocked list](blocked.md), nine rows. ⚠ **Two of them are not blocked**; the correction is at the foot of that file and the work is T-02 and T-06 | blocked | n/a | 7 open, 2 reclassified | --- diff --git a/docs/todo/PROGRESS.md b/docs/todo/PROGRESS.md index 7bf71bb..0a23b0a 100644 --- a/docs/todo/PROGRESS.md +++ b/docs/todo/PROGRESS.md @@ -8,63 +8,95 @@ ## Where the work is right now -[v0.2.6](https://github.com/pkgforge-dev/cross-libc-dlopen/releases/tag/v0.2.6) is +[v0.2.9](https://github.com/pkgforge-dev/cross-libc-dlopen/releases/tag/v0.2.9) is published. | workflow | latest on `main` | |---|---| | `gates` | ✅ | | `secret-sweep` | ✅ | -| `release` | ✅ on `v0.2.6` | - -**This branch fixes the host lookup that stopped on a library the loader would -refuse, on branch `fix/gl-fwd-wrong-class`, and needs a release once merged. -`v0.2.6` was released from `main` before it, so no released artefact carries -the fix.** +| `release` | ✅ on `v0.2.9` | + +`v0.2.9` adds the three NixOS host directories: `/run/opengl-driver/lib` and +`/run/current-system/sw/lib` join the shim's fixed host list, the assembled +`--library-path`, and the libva `/dri` list. NixOS is neither FHS nor a +host that writes `/etc/ld.so.conf`, so before this each of the three failed +differently and silently. + +⚠ **The three cases ran in the container; no NixOS host was behind them.** E104, +E105 and E106 create `/run/opengl-driver/lib`, which needs root, so the container +suite runs all three and reports MATCH, which is why the local total is higher +than the previous release's. Where `/run` is not writable each SKIPS by name +instead. ⛔ **Nothing in this tree has run the shims on a NixOS host.** The cases +prove the lists carry the directories and that a library placed there is found; +they do not prove the directories are where a real NixOS system puts its GPU +userspace, and +[`../report/10-measured-versus-assumed.md`](../report/10-measured-versus-assumed.md) +does not yet carry that distinction. Writing it there is open work, not a +citation. + +The mechanism was also confirmed here as an A/B independent of the suite: the +fake-libva contract run against the `v0.2.8` source prints `NO-DRIVER`, and +against the shipped source prints `DRIVER=NIX`. The published binaries carry +the directory strings. + +`v0.2.8` remains the first release carrying the ppc64le resolver frame repair +(PR #60). `v0.2.7` and earlier ship a `gl-fwd.so` whose `glfwd_resolve_asm` +saved r5 and r6 where the C callee writes its caller's LR and TOC slots, so the +first call of any GL entry point taking a third or fourth integer argument was +handed garbage. Issue #59 is the report. --- ## ⛔ The work order -### 1. `glfwd_try_soname` must not stop on a library the loader will refuse +### 1. `glfwd_try_vendor` accepts a matching filename without checking its class + +`glfwd_try_soname` skips a candidate of the other ELF class, and +`glfwd_try_vendor` does not. A host whose only vendor library is the wrong +class is therefore reported as having one. It is a different path, reached only +when the bundle carries a dispatcher, so it needs a bundled-dispatcher case to +measure. Nothing in this session's change touches it. -`glfwd_try_soname` took the first directory in which its own soname existed, and -`glfwd_each_dir` stopped the walk there. A candidate of the other ELF class -cannot load, so a host whose own answer named a 32bit library directory first -produced a target that could not load, and the directory after it was never -reached. Reproduced by removing `libGL.so.1` from the host-drivers demo AppDir, -which forces the host path, and naming the 32bit directory first with -`CROSS_LIBC_DLOPEN_GL_HOST_DIR`. +### 2. Wire `make gl-fwd-qemu-check` into a runner -The repair reads the candidate's ELF ident and skips a candidate of the other -class, so the walk continues. `docs/report/09-the-second-boundary.md` 9.21 has -the transcript, E103 is the case, and `docs/report/08-test-results.md` owns the -new totals. +The case that caught the ppc64le frame exists and fails on the old source, but +nothing runs it: `gates.yml` builds ppc64le and runs +`scripts/verify-artifacts.sh`, which never executes a trampoline. The target is +run by hand today. ⚠ This is issue #59's first loose end and it is the reason +that class of bug reached a release at all. -### 2. What is still open +### 3. The stale totals in `docs/ground-truth.md` -`glfwd_try_vendor` accepts a matching filename without checking its class, so a -host whose only vendor library is the wrong class is reported as having one. It -is a different path, reached only when the bundle carries a dispatcher, and it -needs a bundled-dispatcher case to measure. Nothing in this session's change -touches it. +It still states the evidence table as 22/22 (issue #45). The home for the +totals is [`../report/08-test-results.md`](../report/08-test-results.md), which +carries the current pair. This is the last document of the release-shaped +staleness class that issue #46 opened, and T-18 is closed. --- ## ⚠ What a new session should distrust -- **E103 forces the order through `/etc/ld.so.conf.d`, and a host whose own - answer puts the 64bit directory first never reaches the defect.** Debian 10 - is such a host: `libc6-i386` names `/usr/lib32` and `/lib32` in - `zz_i386-biarch-compat.conf`, which sorts after `x86_64-linux-gnu.conf`. So - the case pins the predicate, not a claim about any one distribution. -- **The host-drivers demo AppDir bundles the glvnd dispatcher, so the shim - takes the bundled path on a glvnd host and never reaches the host lookup.** - Removing `libGL.so.1` from that AppDir is what exposes the path, and the - deletion is a harness step rather than a change to any shipped AppImage. -- **A Qt6 GLX path does not link `libGL.so.1`.** `libqxcb-glx-integration.so` - and `libQt6Gui.so.6` need `libGLX.so.0` and `libOpenGL.so.0`, so which arm a - Qt application reaches depends on what else in its AppDir links - `libGL.so.1`. Check `readelf -d` before assuming. -- **`docs/todo/INDEX.md` carries the counts it carried before this session.** - Reconcile them if an entry moves. +- **The scheduled `appimage-suite` on `main` is red, and the failure is + upstream's, not this tree's.** Both architectures fail at + `experiments/41-extract.sh` with `no dispatcher slot in AppDir/lib.`: the + `demo` release of `Anylinux-AppImages` no longer carries + `cross-libc-dlopen.so` or `foreign-dlopen.so` in `lib/`. The extraction + refuses rather than guessing, which is what it was built to do. Verify against + the upstream asset before treating it as a defect here. +- **The release gate is not the wide suite.** `release.yml` runs the evidence + table on x86_64 and aarch64 and then builds all five architectures. It does + not run `run-appimage.sh`, so a green `v0.2.9` does not mean the AppImage + suite is green. +- **The NixOS directories are a host class nobody has run.** The three cases + prove the lists carry the directories and that a library placed there is + found. No NixOS host has been behind the shims, and + [`../report/10-measured-versus-assumed.md`](../report/10-measured-versus-assumed.md) + is where that distinction belongs if it is not already written there. +- **A tag's tree, not its commit, is what CI tested.** `v0.2.8` and `v0.2.9` + are both squashed commits, so their hashes appear in no run. Check + `git rev-parse ^{tree}` against the PR head's tree before concluding a + tag went untested. +- **`docs/todo/INDEX.md`'s counts are checked by hand.** `sh scripts/check-drift.sh` + reconciles the rows against the entries and does not check the totals, so a + future closure moves numbers no gate reads. diff --git a/docs/todo/infrastructure.md b/docs/todo/infrastructure.md index deaceae..4cf930a 100644 --- a/docs/todo/infrastructure.md +++ b/docs/todo/infrastructure.md @@ -378,7 +378,7 @@ cites exists, and every module a tool imports is reachable from that tool's own - **Source.** The operator, at the end of the port session. - **Category** infrastructure, **Priority** high, **Effort** medium, - **Status** open + **Status** done - **Problem.** `scripts/build.sh` produces verified artefacts and a manifest, and nothing publishes them. A consumer who wants `gl-fwd.so` has to build it, which means having a container engine and this repository. @@ -397,3 +397,51 @@ cites exists, and every module a tool imports is reachable from that tool's own - **Prove.** A release exists whose assets' checksums match `build-manifest.json` for both architectures, and whose body was not written by hand. + +### Correction: the title was true when it was written and has not been since v0.1.0 + +The title is kept because it is how this entry has been cited everywhere else. +The premise above is superseded, and the correction is written here rather +than edited into it. + +`v0.2.8` is published, and so are the eight releases before it. The workflow +that publishes them is [`release.yml`](../../.github/workflows/release.yml), +which builds **five** architectures, not the two the premise names: x86_64, +aarch64, riscv64, ppc64le and loongarch64. The aarch64 premise in particular is +disproved on every release: the `build and package aarch64` job cross-compiles +it on the floor and the `evidence table (aarch64)` job runs the suite on +`ubuntu-24.04-arm`. + +**Acceptance command and its output**, run against the published release: + +```console +$ gh release list --repo pkgforge-dev/cross-libc-dlopen --limit 3 +v0.2.8 Latest v0.2.8 2026-10-22T10:48:20Z +v0.2.7 v0.2.7 2026-09-24T18:29:17Z +v0.2.6 v0.2.6 2026-09-13T10:01:17Z + +$ gh release download v0.2.8 --repo pkgforge-dev/cross-libc-dlopen +$ for a in x86_64 aarch64 riscv64 ppc64le loongarch64; do +> sha256sum -c cross-libc-dlopen-$a.sha256 --quiet && echo "$a: ok" +> done +x86_64: ok +aarch64: ok +riscv64: ok +ppc64le: ok +loongarch64: ok + +$ tar -tf cross-libc-dlopen-x86_64.tar | grep -c / +0 +``` + +The release carries 40 assets. Every one of the five `.sha256` files verifies +against the assets it names, both archives per architecture are flat (no +nested directory, as the entry required), and the manifest inside the archive +matches the loose files beside it. The body was generated by +[`../../scripts/release-notes.sh`](../../scripts/release-notes.sh) from +`build-manifest.json`, so no checksum in it was typed. + +⚠ **What the closure does not prove.** The ancestor refusal in `release.yml` +passes on every tag because every tagged commit is on `main`; it has never been +seen to refuse a tag that was not. That remains T-10's subject, not this +entry's.