dwarves: el linker de zig se caía con --dependency-file — una línea, y sin escapar a gcc

`dwarves` estaba SELLADA y llevaba tiempo sin construir. Se destapó al arreglar los symlinks de
`bzip2`: su hash se movió, dwarves cayó a deuda, y al reconstruirla el link murió con
`Error running link command: Segmentation fault` — crash del linker, no error de símbolos.

**No lo rompió el cambio de bzip2, y se puede probar**: el `libbz2.a` y el `bzlib.h` nuevos son
byte-idénticos a los viejos (`cmp -s`); lo único que cambió fueron cuatro destinos de symlink. El
artefacto sellado tapaba una rotura que ya existía — el lab rueda desde Alpine edge y zig subió. El
rehash no causó la rotura: la DESTAPÓ.

## La causa, bisecada sobre la línea de enlace real

CMake deja la línea literal en `build/CMakeFiles/<target>.dir/link.txt`, y el árbol de post-mortem la
conserva. Rehecha a mano FUERA de takana y del sandbox, sustituyendo el wrapper por el `zig` del lab
y las rutas `/usr/lib/*` por las del store:

    tal cual                      → exit 139 (SIGSEGV)
    quitando `-static`            → exit 139     ⇒ no es el enlace estático
    quitando `--dependency-file`  → **exit 0**   ⇒ ES ESO

`-Xlinker --dependency-file=…` lo emite CMake ≥3.27 para que el LINKER calcule las dependencias de
enlace, y el `lld` de zig 0.16.0 segfaultea procesándolo. `-DCMAKE_LINK_DEPENDS_USE_LINKER=OFF` es la
palanca de upstream (cmake del corpus: 3.31.6).

**Es mejor que `compiler = "gcc"`**, que es como esquivé ayer el MISMO crash en los tres
`protoc-gen-upb*` de protobuf sin conocer la causa: deja la receta en el toolchain por defecto del
proyecto en vez de escapar de él.

⚠ **Y el alcance no son dos recetas: 153 del corpus usan CMake con zig.** Todas selladas, así que hoy
nadie lo ve — pero el crash depende de los inputs (dentro de protobuf caían 3 de ~10 ejecutables), o
sea que no se sabe cuáles fallan hasta que su hash se mueva. Deuda latente pura.

No se arregla poniendo la perilla en el lab: la mayoría de esas 153 traen su `cmake …` EXPLÍCITO en
la receta, así que tocar la fase por defecto no las tocaría **y** re-hashearía a las que sí usan la
heurística. Incompleto y disruptivo a la vez.

Verificado: los 10 ejecutables estáticos con 0 NEEDED —incluidos `codiff` y `dtagnames`, los dos que
segfaulteaban—, `pahole --version` → v1.30, y REPRODUCE bit a bit.
This commit is contained in:
Sergio
2026-09-12 04:13:53 +00:00
parent 86cec38e36
commit 097579546f
2 changed files with 29 additions and 0 deletions
+1
View File
@@ -82,3 +82,4 @@ kubectl ca95c5292688c838715727f9b909a0722d9fc98a778edefb2a4864e01678056e 2026-09
opensmtpd 51b185ef7e032a4ee10a6ac31799a7baf2b9ea0b95a1fd8f7fcc5239fd287a5b 2026-09-11 reproduce
crun ecf33acabf992acf1f204e7e942699abb179ff50e912e02c993e309cc1146a0f 2026-09-11 reproduce
qdrant 4bd8feca2dde5e63923a3b514cee35aeb8bbe9145c80ecb1dff5bfc005ea591c 2026-09-11 reproduce
dwarves c77953627a7f2913ce6b617cb1baebd45f701c6130a440f525e94c5e453f3b0f 2026-09-12 reproduce
1 # repro-verificado.tsv — qué artefactos se comprobaron que REPRODUCEN bit a bit, y cuándo.
82 opensmtpd
83 crun
84 qdrant
85 dwarves
+28
View File
@@ -96,8 +96,36 @@ build = ["busybox", "make", "cmake", "elfutils-libdw", "argp-standalone", "musl-
# Esto NO es cosmético: el día que se encienda `DEBUG_INFO_BTF` (SDD 25 H7), pahole corre DENTRO
# del sandbox del build del kernel, y un pahole dinámico fallaría ahí diciendo que no está.
[build.phases]
# ⚠ **`CMAKE_LINK_DEPENDS_USE_LINKER=OFF`: EL LINKER DE ZIG SE CAE CON `--dependency-file`.**
#
# Esta receta estaba SELLADA y llevaba tiempo sin construir. Se destapó el 2026-09-12 al arreglar los
# symlinks de `bzip2`: su hash se movió, dwarves cayó a deuda, y al reconstruirla:
#
# [ 71%] Linking C executable codiff
# Error running link command: Segmentation fault
#
# **No lo rompió el cambio de bzip2 y se puede probar**: el `libbz2.a` y el `bzlib.h` nuevos son
# byte-idénticos a los viejos (`cmp -s`); lo único que cambió fueron cuatro destinos de symlink. El
# artefacto sellado tapaba una rotura que ya existía — el lab rueda desde Alpine edge y zig subió.
#
# **La causa se aisló bisecando la línea de enlace**, no suponiendo. Con el `link.txt` que cmake deja
# en `build/CMakeFiles/codiff.dir/`, rehecho a mano FUERA de takana y del sandbox:
#
# tal cual → exit 139 (SIGSEGV)
# quitando `-static` → exit 139 ⇒ no es el enlace estático
# quitando `--dependency-file` → **exit 0** ⇒ ES ESO
#
# `-Xlinker --dependency-file=…` lo emite CMake ≥3.27 para que el LINKER calcule las dependencias de
# enlace, y el `lld` de zig 0.16.0 **segfaultea** al procesarlo. `CMAKE_LINK_DEPENDS_USE_LINKER=OFF`
# es la palanca que upstream expone justo para apagarlo (cmake del corpus: 3.31.6 ⇒ la soporta).
#
# ⚠ **Y NO ES UN PROBLEMA DE DWARVES**: es de *cualquier* proyecto CMake construido con zig en este
# corpus. El mismo crash mató a los tres `protoc-gen-upb*` de protobuf el día anterior, y allá se
# esquivó con `compiler = "gcc"` sin conocer la causa. Ésta es la causa, y el arreglo bueno — porque
# deja la receta en el toolchain por defecto del proyecto en vez de escapar del él.
configure = """
cmake -B build -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr -D__LIB=lib \
-DCMAKE_LINK_DEPENDS_USE_LINKER=OFF \
-DBUILD_SHARED_LIBS=OFF -DLIBBPF_EMBEDDED=ON \
-DARGP_LIBRARY=/usr/lib/libargp.a -DOBSTACK_LIBRARY=/usr/lib/libobstack.a -DCMAKE_C_STANDARD_LIBRARIES='-llzma -lbz2' -DCMAKE_C_FLAGS='-O2 -fno-sanitize=undefined' \
-DDWARF_LIBRARY=/usr/lib/libdw.a -DELF_LIBRARY=/usr/lib/libelf.a -DZLIB_LIBRARY=/usr/lib/libz.a -DCMAKE_EXE_LINKER_FLAGS='-static'