From 6142cf958529954ce224e13bca15306fdfa70220 Mon Sep 17 00:00:00 2001 From: Andy Postnikov Date: Wed, 15 Jul 2026 19:59:23 +0200 Subject: [PATCH] Fix ARMv6 fiber asm: gate Cortex-M0 branch on __ARM_ARCH_6M__ The Boost.Context 1.91.0 sync (GH-22584) pulled in boostorg/context#325, "fix cortex-m0 support to aapcs_elf_gas target", which adds a fallback branch to make_fcontext/jump_fcontext for the Thumb-1 encoding limits of ARMv6-M. The branch is correct for Cortex-M0 but is gated on __ARM_ARCH >= 7, which is also false for classic ARMv6 in ARM state (Alpine armhf, Raspberry Pi 1/Zero) -- targets that can encode every instruction in the >= 7 branch and need none of the workaround. Two consequences. make_fcontext took `ldr a2, =finish', materialising the absolute address of finish through a literal pool in .text and emitting R_ARM_ABS32 against .text. In a PIE link that becomes an R_ARM_RELATIVE dynamic relocation inside the read-only text segment, tagging the binary DT_TEXTREL. musl supports DT_TEXTREL only for DSOs it maps itself; the main executable is kernel-mapped and handled by kernel_mapped_dso(), which never inspects it, so ldso writes to a read-only page and dies with SIGSEGV in do_relocs() before main(). Every SAPI, every invocation, no output. glibc masks this by mprotecting the segment writable, which is why only musl builds noticed. Separately, jump_fcontext -- the hot path on every fiber switch -- grew from 13 to 43 instructions on all ARMv6 builds, glibc included. Gate on __ARM_ARCH_6M__ instead, exactly the target #325 names. The result emits byte-identical .text to 8.6.0alpha1 on every ARM target except Cortex-M0, where it emits byte-identical .text to current master: each target gets back the code it had before the regression, and M0 keeps what #325 added. armv7 and arm64 are unaffected either way. Zend/asm is vendored and verified by the Verify Bundled Files workflow, so carry the same diff in .github/scripts/download-bundled and re-apply it from the sync script, as uriparser already does. --- .../download-bundled/boost-context.arm.patch | 71 +++++++++++++++++++ .../scripts/download-bundled/boost-context.sh | 6 ++ Zend/asm/jump_arm_aapcs_elf_gas.S | 4 +- Zend/asm/make_arm_aapcs_elf_gas.S | 10 +-- 4 files changed, 84 insertions(+), 7 deletions(-) create mode 100644 .github/scripts/download-bundled/boost-context.arm.patch diff --git a/.github/scripts/download-bundled/boost-context.arm.patch b/.github/scripts/download-bundled/boost-context.arm.patch new file mode 100644 index 000000000000..149ac43cc212 --- /dev/null +++ b/.github/scripts/download-bundled/boost-context.arm.patch @@ -0,0 +1,71 @@ +diff --git a/Zend/asm/jump_arm_aapcs_elf_gas.S b/Zend/asm/jump_arm_aapcs_elf_gas.S +index 4415a541fd3..647ae9f45ad 100644 +--- a/Zend/asm/jump_arm_aapcs_elf_gas.S ++++ b/Zend/asm/jump_arm_aapcs_elf_gas.S +@@ -50,7 +50,7 @@ jump_fcontext: + push {lr} + @ save hidden,V1-V8,LR + +- #if __ARM_ARCH >= 7 ++ #if !defined(__ARM_ARCH_6M__) + + push {a1,v1-v8,lr} + +@@ -102,7 +102,7 @@ jump_fcontext: + add sp, sp, #64 + + @ restore hidden,V1-V8,LR +- #if __ARM_ARCH >= 7 ++ #if !defined(__ARM_ARCH_6M__) + pop {a4,v1-v8,lr} + #else + +diff --git a/Zend/asm/make_arm_aapcs_elf_gas.S b/Zend/asm/make_arm_aapcs_elf_gas.S +index 2367c75a6a7..b5cf0c8fa09 100644 +--- a/Zend/asm/make_arm_aapcs_elf_gas.S ++++ b/Zend/asm/make_arm_aapcs_elf_gas.S +@@ -48,7 +48,7 @@ + make_fcontext: + @ shift address in A1 to lower 16 byte boundary + +- #if __ARM_ARCH >= 7 ++ #if !defined(__ARM_ARCH_6M__) + bic a1, a1, #15 + #else + lsrs a1, a1, #4 +@@ -56,7 +56,7 @@ make_fcontext: + #endif + + @ reserve space for context-data on context-stack +- #if __ARM_ARCH >= 7 ++ #if !defined(__ARM_ARCH_6M__) + sub a1, a1, #124 + #else + subs a1, #124 +@@ -66,7 +66,7 @@ make_fcontext: + str a3, [a1, #104] + + @ compute address of returned transfer_t +- #if __ARM_ARCH >= 7 ++ #if !defined(__ARM_ARCH_6M__) + add a2, a1, #108 + #else + mov a2, a1 +@@ -77,7 +77,7 @@ make_fcontext: + + + @ compute abs address of label finish +- #if __ARM_ARCH >= 7 ++ #if !defined(__ARM_ARCH_6M__) + adr a2, finish + #else + ldr a2, =finish +@@ -93,7 +93,7 @@ make_fcontext: + + finish: + @ exit code is zero +- #if __ARM_ARCH >=7 ++ #if !defined(__ARM_ARCH_6M__) + mov a1, #0 + #else + movs r3, #0 diff --git a/.github/scripts/download-bundled/boost-context.sh b/.github/scripts/download-bundled/boost-context.sh index 02febff73c3f..f553a962deb7 100755 --- a/.github/scripts/download-bundled/boost-context.sh +++ b/.github/scripts/download-bundled/boost-context.sh @@ -41,3 +41,9 @@ mv make_x86_64_ms_pe_gas.asm make_x86_64_ms_pe_gas.S # add extra files git restore LICENSE git restore save_xmm_x86_64_ms_masm.asm # added in GH-18352, not an upstream boost.context file + +# patch customized files +# gates the Cortex-M0 (ARMv6-M) fallback in the ARM fcontext assembly on +# __ARM_ARCH_6M__ instead of __ARM_ARCH < 7, which also matched classic ARMv6 +# and emitted a DT_TEXTREL there; drop once fixed upstream in boost.context +git apply -v ../../.github/scripts/download-bundled/boost-context.arm.patch diff --git a/Zend/asm/jump_arm_aapcs_elf_gas.S b/Zend/asm/jump_arm_aapcs_elf_gas.S index 4415a541fd3e..647ae9f45adc 100644 --- a/Zend/asm/jump_arm_aapcs_elf_gas.S +++ b/Zend/asm/jump_arm_aapcs_elf_gas.S @@ -50,7 +50,7 @@ jump_fcontext: push {lr} @ save hidden,V1-V8,LR - #if __ARM_ARCH >= 7 + #if !defined(__ARM_ARCH_6M__) push {a1,v1-v8,lr} @@ -102,7 +102,7 @@ jump_fcontext: add sp, sp, #64 @ restore hidden,V1-V8,LR - #if __ARM_ARCH >= 7 + #if !defined(__ARM_ARCH_6M__) pop {a4,v1-v8,lr} #else diff --git a/Zend/asm/make_arm_aapcs_elf_gas.S b/Zend/asm/make_arm_aapcs_elf_gas.S index 2367c75a6a77..b5cf0c8fa09b 100644 --- a/Zend/asm/make_arm_aapcs_elf_gas.S +++ b/Zend/asm/make_arm_aapcs_elf_gas.S @@ -48,7 +48,7 @@ make_fcontext: @ shift address in A1 to lower 16 byte boundary - #if __ARM_ARCH >= 7 + #if !defined(__ARM_ARCH_6M__) bic a1, a1, #15 #else lsrs a1, a1, #4 @@ -56,7 +56,7 @@ make_fcontext: #endif @ reserve space for context-data on context-stack - #if __ARM_ARCH >= 7 + #if !defined(__ARM_ARCH_6M__) sub a1, a1, #124 #else subs a1, #124 @@ -66,7 +66,7 @@ make_fcontext: str a3, [a1, #104] @ compute address of returned transfer_t - #if __ARM_ARCH >= 7 + #if !defined(__ARM_ARCH_6M__) add a2, a1, #108 #else mov a2, a1 @@ -77,7 +77,7 @@ make_fcontext: @ compute abs address of label finish - #if __ARM_ARCH >= 7 + #if !defined(__ARM_ARCH_6M__) adr a2, finish #else ldr a2, =finish @@ -93,7 +93,7 @@ make_fcontext: finish: @ exit code is zero - #if __ARM_ARCH >=7 + #if !defined(__ARM_ARCH_6M__) mov a1, #0 #else movs r3, #0