8787 ulimit -c unlimited
8888 bin/spp build --phpv=8.5 --type=deb --packages=cli
8989
90+ - name : Hash link inputs
91+ if : ${{ always() && steps.build.outcome != 'cancelled' }}
92+ shell : bash
93+ run : |
94+ mkdir -p diag
95+ find source/php-src -name '*.o' -type f 2>/dev/null | sort | xargs -r sha256sum > diag/object-hashes.txt || true
96+ sha256sum buildroot/lib/*.a >> diag/object-hashes.txt 2>/dev/null || true
97+ wc -l diag/object-hashes.txt
98+
9099 - name : Re-run failing make with diagnostics
91100 if : ${{ steps.build.outcome == 'failure' }}
92101 shell : bash
@@ -145,11 +154,31 @@ jobs:
145154 gdb -q -batch -ex 'set pagination off' -ex run -ex 'info registers' -ex 'x/8i $rip' \
146155 -ex bt -ex 'thread apply all bt' --args "${LLD[@]}" > ../../diag/gdb-live.txt 2>&1 || true
147156 tail -40 ../../diag/gdb-live.txt || true
148- # 2) which LLVM pass dies: opt-bisect logs every pass to stderr until the crash
157+ # 2) pack a byte-exact reproducer: lld streams every input it opens into the
158+ # tar, so it survives the crash; replaying it locally settles whether the
159+ # trigger is in the inputs or in the runner environment
160+ rm -f sapi/cli/php
161+ "${LLD[@]}" --reproduce=../../lld-repro.tar > /dev/null 2>&1 || true
162+ ls -la ../../lld-repro.tar || true
163+ zstd -T0 --rm ../../lld-repro.tar -o ../../lld-repro.tar.zst || true
164+ # 3) environment discriminators on the affected VM
165+ rm -f sapi/cli/php
166+ if env -i PATH=/usr/bin:/bin HOME=/tmp "${LLD[@]}" > /dev/null 2>&1 && [ -f sapi/cli/php ]; then
167+ echo "ENV-I REPLAY OK (crash depends on environment variables)" | tee -a ../../diag/mitigations.txt
168+ else
169+ echo "ENV-I REPLAY FAIL (environment variables ruled out)" | tee -a ../../diag/mitigations.txt
170+ fi
171+ rm -f sapi/cli/php
172+ if taskset -c 0 "${LLD[@]}" > /dev/null 2>&1 && [ -f sapi/cli/php ]; then
173+ echo "TASKSET-1CPU REPLAY OK (crash depends on thread scheduling)" | tee -a ../../diag/mitigations.txt
174+ else
175+ echo "TASKSET-1CPU REPLAY FAIL (single-cpu still crashes)" | tee -a ../../diag/mitigations.txt
176+ fi
177+ # 4) which LLVM pass dies: opt-bisect logs every pass to stderr until the crash
149178 rm -f sapi/cli/php
150179 "${LLD[@]}" -mllvm -opt-bisect-limit=2147483647 2>&1 >/dev/null | tail -n 500 > ../../diag/bisect-tail.txt || true
151180 tail -3 ../../diag/bisect-tail.txt || true
152- # 3 ) lld-level mitigations (for --lto-O*/--threads the last occurrence wins)
181+ # 5 ) lld-level mitigations (for --lto-O*/--threads the last occurrence wins)
153182 for extra in '--lto-O2' '--lto-O1' '--lto-O0' '--threads=1'; do
154183 rm -f sapi/cli/php
155184 if "${LLD[@]}" $extra > /dev/null 2>&1 && [ -f sapi/cli/php ]; then
@@ -158,7 +187,7 @@ jobs:
158187 echo "LLD MITIGATION FAIL: $extra" | tee -a ../../diag/mitigations.txt
159188 fi
160189 done
161- # 4 ) production-path candidate: -O0 on the link line only; zig cc maps the link-time
190+ # 6 ) production-path candidate: -O0 on the link line only; zig cc maps the link-time
162191 # -O level to lld's --lto-O, and EXTRA_LDFLAGS_PROGRAM lands after EXTRA_CFLAGS' -O3
163192 MAKE_O0=$(printf '%s' "$MAKE_CMD" | sed "s|EXTRA_LDFLAGS_PROGRAM='\([^']*\)'|EXTRA_LDFLAGS_PROGRAM='\1 -O0'|")
164193 rm -f sapi/cli/php
@@ -167,7 +196,7 @@ jobs:
167196 else
168197 echo "MAKE MITIGATION FAIL: EXTRA_LDFLAGS_PROGRAM += -O0" | tee -a ../../diag/mitigations.txt
169198 fi
170- # 5 ) the mixed-LTO hypothesis: buildroot libs are ThinLTO bitcode (-flto=thin) but
199+ # 7 ) the mixed-LTO hypothesis: buildroot libs are ThinLTO bitcode (-flto=thin) but
171200 # the trailing -flto makes PHP objects full-LTO bitcode; the crash sits in LLVM's
172201 # prevailing-symbol resolution that reconciles the two. Rebuild PHP thin-only.
173202 MAKE_THIN=$(printf '%s' "$MAKE_CMD" | sed "s/ -flto\([ ']\)/\1/g")
@@ -189,6 +218,14 @@ jobs:
189218 diag
190219 log
191220
221+ - name : Upload lld reproducer
222+ if : ${{ always() }}
223+ uses : actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
224+ with :
225+ name : lld-repro
226+ path : lld-repro.tar.zst
227+ if-no-files-found : ignore
228+
192229 - name : Report result
193230 if : ${{ always() }}
194231 run : |
0 commit comments