https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=84a608608969523b9ef374cd0f5383bbcd020b39
commit 84a608608969523b9ef374cd0f5383bbcd020b39 Author: Igor Podgainoi <[email protected]> AuthorDate: Thu Feb 19 08:44:01 2026 +0000 Commit: Corinna Vinschen <[email protected]> CommitDate: Wed Mar 11 15:49:34 2026 +0100 Cygwin: signal: Fix stabilize_sig_stack/setjmp/longjmp on AArch64 This commit fixes the AArch64 implementation of the following three functions: stabilize_sig_stack, setjmp and longjmp. Changes made: * Fixed code indentation in all three functions. * Corrected some comments and added additional ones. * Added missing SEH directives. * Changed the locking algorithm in stabilize_sig_stack to Test and Test-and-Set (TTAS). * Stopped returning a value in x0 in stabilize_sig_stack to avoid unnecessary clobbering. This should make it more similar to the x86_64 version. * Using x10 instead of x0 in setjmp and longjmp where needed as per the previous change. * Fixed bug in setjmp where the SP value after the prologue was used, instead of the original one. * Fixed bug in setjmp where the stackptr was saved at the wrong offset into jmp_buf (should be 0). * Now saving and restoring x0 in setjmp and x0/x1 in longjmp around the call to stabilize_sig_stack. This should make it more similar to the x86_64 version. * Removed the prologue and epilogue in longjmp, as the function never returns. * Changed logic in longjmp to take the return value directly from the second argument. This should make it more similar to the x86_64 version. * Fixed bug in longjmp where the TLS stack pointer restoration used an invalid base register. * Using zero registers instead of an immediate 0 where possible. Tests fixed on AArch64: winsup.api/mmaptest02.exe winsup.api/mmaptest03.exe winsup.api/ltp/mmap05.exe Signed-off-by: Igor Podgainoi <[email protected]> Diff: --- winsup/cygwin/scripts/gendef | 277 ++++++++++++++++++++++--------------------- 1 file changed, 142 insertions(+), 135 deletions(-) diff --git a/winsup/cygwin/scripts/gendef b/winsup/cygwin/scripts/gendef index fb325ea01f73..7097da2e61c6 100755 --- a/winsup/cygwin/scripts/gendef +++ b/winsup/cygwin/scripts/gendef @@ -624,81 +624,83 @@ _sigdelayed_end: .global _sigdelayed_end .seh_proc stabilize_sig_stack stabilize_sig_stack: - // prologue - stp fp, lr, [sp, #-0x10]! // save FP and LR registers - .seh_save_fplr_x 0x10 - mov fp, sp // set frame pointer for unwinder - .seh_set_fp - .seh_endprologue + // prologue + stp fp, lr, [sp, #-0x10]! // save FP and LR registers + .seh_save_fplr_x 0x10 + mov fp, sp // set frame pointer for unwinder + .seh_set_fp + .seh_endprologue - ldr x10, [x18, #0x8] // load TLS block base pointer into x10 + ldr x10, [x18, #0x8] // load TLS block base pointer into x10 - // try to acquire the lock - mov w9, #1 // value to store (1 == locked) - ldr x11, =_cygtls.stacklock // load the symbol offset - add x12, x10, x11 // x12 = tls_base + &stacklock + // try to acquire the lock + mov w9, #1 // value to store (1 == locked) + ldr x11, =_cygtls.stacklock // load the symbol offset + add x12, x10, x11 // x12 = tls_base + &stacklock 1: - ldaxr w13, [x12] // load old lock value - stlxr w14, w9, [x12] // attempt to store 1 - cbnz w14, 1b // if store failed, retry - cbz w13, 2f // if lock was acquired, continue - yield // yield to allow other threads to run - b 1b // retry acquiring the lock + ldaxr w13, [x12] // load old lock value + cbnz w13, 2f // if already locked, wait + stxr w14, w9, [x12] // attempt to acquire the lock + cbnz w14, 1b // if locking failed, retry + b 3f // lock acquired, continue 2: - // lock acquired, increment incyg counter - ldr x11, =_cygtls.incyg // load the symbol offset - add x12, x10, x11 // x12 = tls_base + &incyg - ldr w9, [x12] // load current value of incyg - add w9, w9, #1 // increment incyg counter - str w9, [x12] // store back incremented value - - // check current_sig - ldr x11, =_cygtls.current_sig // load the symbol offset - ldr w9, [x10, x11] // load current value of current_sig - cbz w9, 3f // if no current signal, jump to cleanup - - // release lock before calling signal handler - ldr x11, =_cygtls.stacklock // load the symbol offset - add x12, x10, x11 // x12 = tls_base + &stacklock - ldr w9, [x12] // load current value of stacklock - sub w9, w9, #1 // decrement stacklock - stlr w9, [x12] // store with release semantics - - // prepare arg and call handler - ldr x0, =_cygtls.start_offset // load the symbol offset - add x0, x10, x0 // x0 = tls_base + &start_offset - bl _ZN7_cygtls19call_signal_handlerEv - - // call may clobber x10, restore TLS base - ldr x10, [x18, #0x8] // reload tls_base - - // decrement incyg - ldr x11, =_cygtls.incyg - add x12, x10, x11 - ldr w9, [x12] - sub w9, w9, #1 - str w9, [x12] - - // loop to handle another signal - b 1b + yield // yield to allow other threads to run + b 1b // retry acquiring the lock 3: - // no signal to handle, decrement incyg counter - ldr x11, =_cygtls.incyg - add x12, x10, x11 - ldr w9, [x12] - sub w9, w9, #1 - str w9, [x12] - - mov x0, x10 // return TLS address in x0 (return register) - - // epilogue - .seh_startepilogue - ldp fp, lr, [sp], #0x10 - .seh_endepilogue - ret - .seh_endproc + // lock acquired, increment incyg counter + ldr x11, =_cygtls.incyg // load the symbol offset + add x12, x10, x11 // x12 = tls_base + &incyg + ldr w9, [x12] // load current value of incyg + add w9, w9, #1 // increment incyg counter + str w9, [x12] // store back incremented value + + // check current_sig + ldr x11, =_cygtls.current_sig // load the symbol offset + ldr w9, [x10, x11] // load current value of current_sig + cbz w9, 4f // if no current signal, jump to cleanup + + // release lock before calling signal handler + ldr x11, =_cygtls.stacklock // load the symbol offset + add x12, x10, x11 // x12 = tls_base + &stacklock + ldr w9, [x12] // load current value of stacklock + sub w9, w9, #1 // decrement stacklock + stlr w9, [x12] // store with release semantics + + // prepare arg and call handler + ldr x0, =_cygtls.start_offset // load the symbol offset + add x0, x10, x0 // x0 = tls_base + &start_offset + bl _ZN7_cygtls19call_signal_handlerEv + + // call may clobber x10, restore TLS base + ldr x10, [x18, #0x8] // reload tls_base, use as return value + + // decrement incyg + ldr x11, =_cygtls.incyg // load the symbol offset + add x12, x10, x11 // x12 = tls_base + &incyg + ldr w9, [x12] // load current value of incyg + sub w9, w9, #1 // decrement incyg counter + str w9, [x12] // store back decremented value + + // loop to handle another signal + b 1b + +4: + // no signal to handle, decrement incyg counter + ldr x11, =_cygtls.incyg // load the symbol offset + add x12, x10, x11 // x12 = tls_base + &incyg + ldr w9, [x12] // load current value of incyg + sub w9, w9, #1 // decrement incyg counter + str w9, [x12] // store back decremented value + + // epilogue + .seh_startepilogue + ldp fp, lr, [sp], #0x10 // restore FP and LR registers + .seh_save_fplr_x 0x10 + .seh_endepilogue + ret + .seh_endproc EOF } } @@ -867,19 +869,21 @@ sigsetjmp: .seh_proc setjmp setjmp: // prologue - stp fp, lr, [sp, #-0x10]! // push frame pointer (x29) and link register (x30) - mov fp, sp // set frame pointer + stp fp, lr, [sp, #-0x10]! // save FP and LR registers + .seh_save_fplr_x 0x10 + mov fp, sp // set frame pointer for unwinder + .seh_set_fp .seh_endprologue // save callee-saved registers from jump buffer - stp x19, x20, [x0, #0x08] // save x19, x20 - stp x21, x22, [x0, #0x18] // save x21, x22 - stp x23, x24, [x0, #0x28] // save x23, x24 - stp x25, x26, [x0, #0x38] // save x25, x26 - stp x27, x28, [x0, #0x48] // save x27, x28 - stp x29, x30, [x0, #0x58] // save frame ptr (x29) and return addr (x30) - - mov x1, sp // get the current stack pointer + stp x19, x20, [x0, #0x08] // save x19, x20 + stp x21, x22, [x0, #0x18] // save x21, x22 + stp x23, x24, [x0, #0x28] // save x23, x24 + stp x25, x26, [x0, #0x38] // save x25, x26 + stp x27, x28, [x0, #0x48] // save x27, x28 + stp x29, x30, [x0, #0x58] // save x29 (FP) and x30 (LR) + + add x1, sp, #0x10 // get the old stack pointer str x1, [x0, #0x68] // save SP mrs x1, fpcr // get fp control register @@ -888,35 +892,39 @@ setjmp: str x1, [x0, #0x78] // save FPSR // save fp registers (d8-d15) - stp d8, d9, [x0, #0x80] // save d8, d9 - stp d10, d11, [x0, #0x90] // save d10, d11 - stp d12, d13, [x0, #0xA0] // save d12, d13 - stp d14, d15, [x0, #0xB0] // save d14, d15 + stp d8, d9, [x0, #0x80] // save d8, d9 + stp d10, d11, [x0, #0x90] // save d10, d11 + stp d12, d13, [x0, #0xA0] // save d12, d13 + stp d14, d15, [x0, #0xB0] // save d14, d15 - mov x9, x0 // save jmp_buf pointer in x9 - # // save TLS stack pointer - # ldr x1, [sp] - # str x1, [x0, #0xB8] + // save TLS stack pointer + ldr x1, [sp, #0x10] // get the TLS stack pointer + str x1, [x0, #0xB8] // save TLS stack pointer - bl stabilize_sig_stack // call stabilize_sig_stack (returns TLS in x0) + str x0, [sp, #-0x10]! // save jmp_buf before call + bl stabilize_sig_stack // call stabilize_sig_stack (returns TLS in x10) + ldr x0, [sp], #0x10 // restore jmp_buf after call // store the stack pointer to jump_buf - ldr x2, =_cygtls.stackptr // load the symbol address/offset - add x2, x0, x2 // Final address of stackptr + ldr x2, =_cygtls.stackptr // load the symbol offset + add x2, x10, x2 // x2 = tls_base + &stackptr ldr x3, [x2] // load current value of stackptr - str x3, [x0, #0xB8] // store stackptr into jmp_buf + str x3, [x0] // store stackptr into jmp_buf // decrement the stack lock - ldr x2, =_cygtls.stacklock // load the symbol address/offset - add x2, x0, x2 // Final address of stacklock + ldr x2, =_cygtls.stacklock // load the symbol offset + add x2, x10, x2 // x2 = tls_base + &stacklock ldr w3, [x2] // load current stacklock value sub w3, w3, #1 // decrement - str w3, [x2] //store back + str w3, [x2] // store back - mov w0, #0 // return 0 + mov w0, wzr // return 0 // epilogue + .seh_startepilogue ldp fp, lr, [sp], #0x10 // restore saved FP and LR registers + .seh_save_fplr_x 0x10 + .seh_endepilogue ret .seh_endproc @@ -952,66 +960,65 @@ siglongjmp: .seh_proc longjmp longjmp: // prologue - stp fp, lr, [sp, #-0x20]! // save FP and LR registers, allocate additional 16 bytes for function arguments - stp x0, x1, [sp, #0x10] // save function arguments (jump buffer and return value) - mov fp, sp // establishing frame chain .seh_endprologue 1: - bl stabilize_sig_stack // call stabilize_sig_stack which returns TLS pointer in x0 - ldr x2, [sp, #0x10] // get jump buffer pointer from stack - ldr x10, [x2] // get old signal stack from jump buffer + stp x0, x1, [sp, #-0x10]! // save function args (jmp_buf and return value) + bl stabilize_sig_stack // call stabilize_sig_stack (returns TLS in x10) + ldp x2, x3, [sp], #0x10 // restore jmp_buf and return value to x2 and x3 + ldr x9, [x2] // get old signal stack from jump buffer // restore stack pointer in TLS - ldr x11, =_cygtls.stackptr - add x11, x0, x11 - str x10, [x11] + ldr x11, =_cygtls.stackptr // load the symbol offset + add x11, x10, x11 // x11 = tls_base + &stackptr + str x9, [x11] // store signal stack into stackptr // release lock by decrementing counter - ldr x11, =_cygtls.stacklock - add x11, x0, x11 - ldr w12, [x11] - sub w12, w12, #1 - str w12, [x11] + ldr x11, =_cygtls.stacklock // load the symbol offset + add x11, x10, x11 // x11 = tls_base + &stacklock + ldr w12, [x11] // load current stacklock value + sub w12, w12, #1 // decrement + str w12, [x11] // store back // we're not in cygwin anymore, clear "in cygwin" flag - ldr x11, =_cygtls.incyg - add x11, x0, x11 - mov w12, #0 - str w12, [x11] + ldr x11, =_cygtls.incyg // load the symbol offset + add x11, x10, x11 // x11 = tls_base + &incyg + mov w12, wzr // clear the incyg counter + str w12, [x11] // store back the new value - // get saved return value before SP is restored - ldr x0, [sp, #0x10] + // use second argument as the return value + mov x0, x3 // move saved return value to x0 // restore callee-saved registers from jump buffer - ldp x19, x20, [x2, #0x08] // restore x19, x20 - ldp x21, x22, [x2, #0x18] // restore x21, x22 - ldp x23, x24, [x2, #0x28] // restore x23, x24 - ldp x25, x26, [x2, #0x38] // restore x25, x26 - ldp x27, x28, [x2, #0x48] // restore x27, x28 - ldp fp, lr, [x2, #0x58] // restore x29 (frame pointer) and x30 (link register) - ldr x10, [x2, #0x68] // get saved stack pointer - mov sp, x10 // restore stack pointer - ldr x10, [x2, #0x70] // load floating-point control register - msr fpcr, x10 // restore FPCR - ldr x10, [x2, #0x78] // load floating-point status register - msr fpsr, x10 // restore FPSR + ldp x19, x20, [x2, #0x08] // restore x19, x20 + ldp x21, x22, [x2, #0x18] // restore x21, x22 + ldp x23, x24, [x2, #0x28] // restore x23, x24 + ldp x25, x26, [x2, #0x38] // restore x25, x26 + ldp x27, x28, [x2, #0x48] // restore x27, x28 + ldp x29, x30, [x2, #0x58] // restore x29 (FP) and x30 (LR) + ldr x10, [x2, #0x68] // get saved stack pointer + mov sp, x10 // restore stack pointer + ldr x10, [x2, #0x70] // load floating-point control register + msr fpcr, x10 // restore FPCR + ldr x10, [x2, #0x78] // load floating-point status register + msr fpsr, x10 // restore FPSR // restore floating-point registers (d8-d15) - ldp d8, d9, [x2, #0x80] - ldp d10, d11, [x2, #0x90] - ldp d12, d13, [x2, #0xA0] - ldp d14, d15, [x2, #0xB0] + ldp d8, d9, [x2, #0x80] // restore d8, d9 + ldp d10, d11, [x2, #0x90] // restore d10, d11 + ldp d12, d13, [x2, #0xA0] // restore d12, d13 + ldp d14, d15, [x2, #0xB0] // restore d14, d15 // restore TLS stack pointer - ldr x1, [x0, #0xB8] - str x1, [sp] + ldr x1, [x2, #0xB8] // get the saved TLS stack pointer + str x1, [sp] // restore TLS stack pointer // ensure return value is non-zero (C standard requirement) - cbnz x0, 0f - mov x0, #1 + cbnz x0, 0f // if return value non-zero, return + mov x0, #1 // set return value to 1 0: // epilogue - add sp, sp, #0x10 // FP and LR are already restored, just restore SP as it would be popped + .seh_startepilogue + .seh_endepilogue ret .seh_endproc EOF
