Files
firmware/docs/notes
Oleksandr ShyshatskyiandClaude Opus 5 bcd38fae28 Six of the ten library paths were never loaded by anything
ANVIL_LIBS handed every mod process ten /usr/prog library directories. Four of
them are load-bearing and six have no consumer at all, which was established
by measurement rather than argument: /proc/PID/maps of the processes the mod
actually runs, plus a DT_NEEDED walk over every ELF in
/usr/prog/{PROGRAM,bin,nginx,mjpg-streamer,klipper,module,modules,wifi},
/usr/bin, /usr/sbin, /bin and /sbin.

That walk found exactly ONE consumer of ffmpeg, x264, opencv, nim and libzip
between them: /usr/prog/PROGRAM/software/firmwareExe -- FlashForge's Qt
binary, which this mod replaces with a shell script. curl is the interesting
one, because it did have a Python consumer: pycurl, in site-packages, which
does not import on this firmware at all. "undefined symbol:
curl_global_sslset", a symbol that arrived in curl 7.56 while /usr/prog ships
7.55.1, and the shipped pycurl links libssl.so.1.1 where this curl links
1.0.0.

The comment that stood here is replaced rather than deleted. It argued the
list should be the union, because which subset a script needs is a property of
the component set in moonraker.conf and the user edits that file. The
measurement empties that defence: no moonraker.conf edit can reach a library
through a module that cannot be imported in the first place. What replaces it
says what was measured, and what would have to be true to put an entry back --
some process the mod runs has to map it, which is a measurement and not an
argument.

Each of the four that stay now names the failure it prevents, and openssl's is
worth having written down: it is NOT for `import ssl`. _ssl and zlib are
BUILTIN on this interpreter, statically linked into libpython, so
libpython3.8.so.1.0 itself carries DT_NEEDED on libssl.so.1.0.0 -- take the
directory away and the interpreter does not start, before it has read a line
of anyone's python. The rootfs has 1.1 only, a different soname that cannot
stand in.

case-libpath.sh is the measurement, kept as a gate and running in both
directions. Each of the four is removed one at a time and required to produce
a real failure -- two of them the interpreter refusing to start, one an
ImportError from ctypes, one an OSError from libnacl, which is the shape that
once made a missing library read as a component crash. And a probe is run
twice: on the four shipped entries, and again on the full old ten-entry path.
The second run is the one that carries the weight. With every directory
available it still maps none of the six, while it does map libffi and
libsodium -- so it was loading libraries, it just never wanted those.

Two of the case's checks SKIP in the replica, honestly and for the same reason
case-moonraker.sh skips the identical one: only the payload directory is
mounted, so FlashForge's 2022 Moonraker tree stands in and has no
moonraker.server. The component-import proof needs a checkout where patch.sh
has staged the mod's own tree.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-26 22:07:57 +03:00
..