Skip to content

Commit 6c14011

Browse files
pkubajnobu
authored andcommitted
[ppc64le] Add ELFv2 global entry prologue to coroutine_transfer
The hand-written `coroutine_transfer` in `coroutine/ppc64le/Context.S` lacks the ELFv2 ABI global entry prologue. When the function is reached via the PLT (lazy resolution path), r2 (TOC pointer) is left pointing at whatever the resolver had loaded — typically the dynamic linker's own TOC — instead of libruby's TOC. The wrong r2 propagates through the fiber switch into `fiber_entry`, which jumps into `fiber_restore_thread` → `rb_current_ec_set`. The first PLT thunk inside the new fiber (`__plt___tls_get_addr` for the `ruby_current_ec` thread-local) computes its GOT entry as `r2 + offset` and segfaults dereferencing the bogus address. This manifests as a SIGSEGV on any code path that uses fibers — including `Enumerator#next`, so even a one-liner crashes: ruby -e 'a=[1,2,3]; e=a.to_enum; loop { p e.next }' # [BUG] Segmentation fault at 0x000000081009ac38 Reproduced on FreeBSD 16-CURRENT/powerpc64le with Ruby 4.0.4. The same asm exists unchanged in 3.3 and 3.4, so they are likely affected as well. Linux ppc64le may not hit this if its rtld preserves the caller's r2 across PLT resolution, but per the ELFv2 ABI spec §2.3.1.2 a global function entered via the PLT is responsible for setting up its own r2 from r12 — relying on the resolver is non-conformant. The fix adds the standard two-instruction global entry prologue plus a `.localentry` directive of 8, matching what the compiler emits for ordinary C functions (e.g. `rb_current_ec_set` carries `<other: 0x60>`, i.e. STO_PPC64_LOCAL=3). The local entry point now lands at the original first instruction (`addi 1,1,-160`), so `coroutine_initialize` in `Context.h` continues to work unchanged — `start + 8` (which skips fiber_entry's global prologue to reach its local entry) is still correct because the offset between global and local entry is identical across all functions in this module. References: - Power Architecture 64-Bit ELF V2 ABI Specification, §2.3.1.2 "Function Calling Sequence" - STO_PPC64_LOCAL encoding: §3.3 "Symbol Values"
1 parent efd35db commit 6c14011

1 file changed

Lines changed: 7 additions & 0 deletions

File tree

coroutine/ppc64le/Context.S

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,18 @@
11
#define TOKEN_PASTE(x,y) x##y
22

3+
.abiversion 2
34
.text
45
.align 2
56

67
.globl PREFIXED_SYMBOL(coroutine_transfer)
78
.type PREFIXED_SYMBOL(coroutine_transfer), @function
89
PREFIXED_SYMBOL(coroutine_transfer):
10+
# Global entry: set up TOC pointer (r2) from r12.
11+
# Required by ELFv2 ABI when this function is reached via the PLT.
12+
addis 2, 12, .TOC. - PREFIXED_SYMBOL(coroutine_transfer)@ha
13+
addi 2, 2, .TOC. - PREFIXED_SYMBOL(coroutine_transfer)@l
14+
.localentry PREFIXED_SYMBOL(coroutine_transfer), .-PREFIXED_SYMBOL(coroutine_transfer)
15+
916
# Make space on the stack for caller registers
1017
addi 1,1,-160
1118

0 commit comments

Comments
 (0)