Skip to content

Build-time physics check for form-X binaries (rules A/B): fail at link time instead of crashing at run time #396

Description

@Sunrisepeak

Context

xlings' closure design (openxlings/xlings .agents/docs/2026-08-09-ecosystem-closure-design.md) defines three enforcement points for the runtime-closure contract. Points 1 (index CI) and 2 (xlings client, install-time, warn-only) landed on 2026-08-09. Point 3 is mcpp's, because mcpp's default toolchain config is what puts user binaries into form X:

llvm@22.x clang.cfg:
  -Wl,--dynamic-linker=<xpkgs>/xim-x-glibc/<ver>/lib64/ld-linux-x86-64.so.2
  -Wl,-rpath,<xpkgs>/xim-x-glibc/<ver>/lib64

A form-X binary (our loader + our libc) has no host fallback: our ld.so's compiled-in cache path exists on no machine, so any host library entering the process resolves only by RPATH — or fails at run time with an error that names neither the package nor the cause. #392 is this exact shape: host libtinfo.so.6 entered via the GL/GLX chain, our glibc 2.39 could not serve GLIBC_2.42, and the user saw a symbol-version error pointing at a library they never chose.

What point 3 should check (physics only, NO policy)

At link time, for the binary just produced:

  • Rule B (same-source): the PT_INTERP the driver injected and the libc.so.6 that RPATH will resolve must come from one glibc payload. Mixing (host interp + our libc, or two payload versions) is a pre-main crash with a GLIBC_PRIVATE / vDSO message.
  • Rule A (version floor): if the link pulled in ANY host library (-l resolved outside the xlings store), then our_glibc >= host_glibc must hold — glibc is backward-compatible only.

Deliberately not checked: whether the user links host libraries at all. That is the user's choice (xlings rule D applies to index packages only). Point 3 can therefore fail hard from day one — everything it rejects is a binary that cannot run.

Suggested failure messages (from the design doc, C2.4)

rule B: PT_INTERP comes from glibc@2.39 but RPATH resolves libc from glibc@2.44 —
        one process cannot have two libcs.
rule A: this binary is anchored to glibc 2.39 while the host is 2.43 and the link
        pulled in host libtinfo.so.6 — symbols up to GLIBC_2.43 may be required.
        Fix: use a runtime >= the host (xlings subos new <name> --runtime glibc@2.44).

Mitigations already landed on the xlings side (2026.8.9.1)

These remove the common triggers, but they do not remove the class: any host library newer than the chosen runtime reproduces it, and only the build tool sees the link set early enough to say so.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions