From 445b596238190fbe87255ffefafe6971266af3ed Mon Sep 17 00:00:00 2001 From: E M <5089238+emizzle@users.noreply.github.com> Date: Mon, 22 Jun 2026 17:13:00 +1000 Subject: [PATCH] fix: harden linux release builds against GCC's -march=native bug on Zen4 The linux-amd64 release build was intermittently failing with: 'asm' operand has impossible constraints in secp256k1's hand-written x86_64 assembly (scalar_4x64_impl.h, USE_ASM_X86_64 path). Root cause, confirmed against upstream (bitcoin-core/secp256k1#1623): on GCC 11 (Ubuntu 22.04's default), -march=native's CPU autodetection misidentifies early AMD Zen4 chips as znver3 while still enabling -mavx512f via CPUID feature probing. -march=znver3 -mavx512f is an invalid combination matching no real CPU -- GCC 11 predates Zen4 entirely -- and its register allocator cannot satisfy the asm's constraints under it. Upstream confirmed this is fixed by a GCC version that knows about znver4 (13+), and closed the report as a GCC autodetection bug, not a secp256k1 defect. This explains the apparent intermittency: it only reproduces on whichever physical Zen4 host GitHub's runner fleet happens to assign to a given job. Two independent changes address this: - Bump the linux-amd64 and linux-arm64 release builders from ubuntu-22.04(-arm) to ubuntu-24.04(-arm), kept on the same Ubuntu version across both architectures. Ubuntu 24.04 ships GCC 13 by default (GCC isn't installed separately in this workflow -- the runner image's preinstalled toolchain comes from its Ubuntu base), which correctly recognizes znver4 and produces a valid -march=native expansion. - Also pass -d:disableMarchNative on the linux-amd64 build (matrix- scoped; arm64/macOS don't compile the affected x86_64 asm path). This is kept even after the GCC bump because -march=native is independently unsound for a publicly distributed binary: it bakes in whatever instruction set extensions the build runner's CPU happens to have (e.g. AVX-512) into the shipped binary, which would crash with an illegal instruction on end-user machines lacking that extension -- a separate, permanent concern from the GCC 11 bug. --- .github/workflows/release.yml | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 29464ce0..43991325 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -40,15 +40,15 @@ jobs: outputs: matrix: ${{ steps.matrix.outputs.matrix }} steps: - - name: Compute matrix - id: matrix - uses: fabiocaccamo/create-matrix-action@v5 - with: - matrix: | - os {linux}, cpu {amd64}, builder {ubuntu-22.04}, nim_version {${{ env.nim_version }}}, shell {bash --noprofile --norc -e -o pipefail} - os {linux}, cpu {arm64}, builder {ubuntu-22.04-arm}, nim_version {${{ env.nim_version }}}, shell {bash --noprofile --norc -e -o pipefail} - os {macos}, cpu {arm64}, builder {macos-14}, nim_version {${{ env.nim_version }}}, shell {bash --noprofile --norc -e -o pipefail} - os {windows}, cpu {amd64}, builder {windows-latest}, nim_version {${{ env.nim_version }}}, shell {msys2} + - name: Compute matrix + id: matrix + uses: fabiocaccamo/create-matrix-action@v5 + with: + matrix: | + os {linux}, cpu {amd64}, builder {ubuntu-24.04}, nim_version {${{ env.nim_version }}}, shell {bash --noprofile --norc -e -o pipefail} + os {linux}, cpu {arm64}, builder {ubuntu-24.04-arm}, nim_version {${{ env.nim_version }}}, shell {bash --noprofile --norc -e -o pipefail} + os {macos}, cpu {arm64}, builder {macos-14}, nim_version {${{ env.nim_version }}}, shell {bash --noprofile --norc -e -o pipefail} + os {windows}, cpu {amd64}, builder {windows-latest}, nim_version {${{ env.nim_version }}}, shell {msys2} # Build build: @@ -106,7 +106,14 @@ jobs: - name: Build Logos Storage binary run: | - make NIMFLAGS="--out:${{ env.build_dir }}/${{ env.storage_binary }} ${{ env.nim_flags }}" + nim_flags="${{ env.nim_flags }}" + # secp256k1's x86_64 inline asm can hit a GCC register-allocation + # failure when -march=native expands against this runner's CPU, so + # pin a fixed baseline instead. arm64/macOS don't use that asm path. + if [[ "${{ matrix.os }}" == "linux" && "${{ matrix.cpu }}" == "amd64" ]]; then + nim_flags="${nim_flags} -d:disableMarchNative" + fi + make NIMFLAGS="--out:${{ env.build_dir }}/${{ env.storage_binary }} ${nim_flags}" - name: Package ${{ env.storage_binary_base }} Linux (compress and preserve perms) if: matrix.os == 'linux'