[newlib-cygwin] Cygwin: Aarch64: optimize pthread_wrapper register usage

Jeremy Drake via Cygwin-cvs <[email protected]> Tue, 1 Jul 2025 20:08:14 +0000 (GMT)
Newsgroups gmane.os.cygwin.cvs
Message-ID <[email protected]>
https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=10380e9f446640c8d1bd4d60ec085bb31efa26f1

commit 10380e9f446640c8d1bd4d60ec085bb31efa26f1
Author: Thirumalai Nagalingam <thirumalai.nagalingam-ftNtnR/FhrXEC4y91aVriVaTQe2KTcn/@public.gmane.org>
Date:   Tue Jul 1 18:17:24 2025 +0000

    Cygwin: Aarch64: optimize pthread_wrapper register usage
    
    This patch resolves issues related to unsafe access to deallocated
    stack memory in the pthread wrapper for AArch64.
    
    Key changes:
    - Removed use of x19 by directly loading the thread function and
      argument using LDP from [WRAPPER_ARG], freeing one register.
    - Stored thread function and argument in x20 and x21 before
      VirtualFree to preserve them across calls.
    - Used x1 as a temporary register to load the stack base,
      subtract CYGTLS, and update SP.
    - Moved the thread argument back into x0 after VirtualFree and
      before calling the thread function.
    
    Earlier, `wrapper_arg` lived on the stack, which was freed via
    `VirtualFree`, risking segfaults on later access. Now, the thread
    `func` and `arg` are loaded before the stack is freed, stored in
    callee-saved registers, and restored to `x0` before calling the
    thread function.
    
    Fixes: f4ba145056db ("Aarch64: Add inline assembly pthread wrapper")
    Signed-off-by: Thirumalai Nagalingam <[email protected]>

Diff:
---
 winsup/cygwin/create_posix_thread.cc | 21 +++++++++++----------
 1 file changed, 11 insertions(+), 10 deletions(-)

diff --git a/winsup/cygwin/create_posix_thread.cc b/winsup/cygwin/create_posix_thread.cc
index 592aaf1a5..17bb607f7 100644
--- a/winsup/cygwin/create_posix_thread.cc
+++ b/winsup/cygwin/create_posix_thread.cc
@@ -103,18 +103,19 @@ pthread_wrapper (PVOID arg)
   /* Sets up a new thread stack, frees the original OS stack,
    * and calls the thread function with its arg using AArch64 ABI. */
   __asm__ __volatile__ ("\n\
-	   mov     x19, %[WRAPPER_ARG]  // x19 = &wrapper_arg              \n\
-	   ldp     x0, x10, [x19, #16]  // x0 = stackaddr, x10 = stackbase \n\
-	   sub     sp, x10, %[CYGTLS]   // sp = stackbase - (CYGTLS)       \n\
-	   mov     fp, xzr              // clear frame pointer (x29)       \n\
-	   mov     x1, xzr              // x1 = 0 (dwSize)                 \n\
-	   mov     x2, #0x8000          // x2 = MEM_RELEASE                \n\
-	   bl      VirtualFree          // free original stack             \n\
-	   ldp     x19, x0, [x19]       // x19 = func, x0 = arg            \n\
-	   blr     x19                  // call thread function            \n"
+	   ldp     x20, x21, [%[WRAPPER_ARG]]    // x20 = thread func, x21 = thread arg \n\
+	   ldp     x0, x1, [%[WRAPPER_ARG], #16] // x0 = stackaddr, x1 = stackbase	\n\
+	   sub     sp, x1, %[CYGTLS]  		 // sp = stackbase - (CYGTLS)    	\n\
+	   mov     fp, xzr              	 // clear frame pointer (x29)    	\n\
+						 // x0 already has stackaddr		\n\
+	   mov     x1, xzr              	 // x1 = 0 (dwSize)              	\n\
+	   mov     x2, #0x8000          	 // x2 = MEM_RELEASE             	\n\
+	   bl      VirtualFree          	 // free original stack          	\n\
+	   mov     x0, x21  			 // Move arg into x0			\n\
+	   blr     x20                  	 // call thread function         	\n"
 	   : : [WRAPPER_ARG] "r" (&wrapper_arg),
 	       [CYGTLS] "r" (__CYGTLS_PADSIZE__)
-	   : "x0", "x1", "x2", "x10", "x19", "x29", "memory");
+	   : "x0", "x1", "x2", "x20", "x21", "x29", "memory");
 #else
 #error unimplemented for this target
 #endif