windows.cygwin: add TLS fix patch
This commit is contained in:
@@ -41,6 +41,12 @@
|
|||||||
# declared. Backport of https://cygwin.com/cgit/newlib-cygwin/commit/?id=73600d68227e125af24b7de7c3fccbd4eb66ee03
|
# declared. Backport of https://cygwin.com/cgit/newlib-cygwin/commit/?id=73600d68227e125af24b7de7c3fccbd4eb66ee03
|
||||||
./fix-winsize.patch
|
./fix-winsize.patch
|
||||||
]
|
]
|
||||||
|
++ lib.optional (!headersOnly) [
|
||||||
|
# https://cygwin.com/pipermail/cygwin-developers/2020-September/011970.html
|
||||||
|
# This is required for boost coroutines to work. After we get to the point
|
||||||
|
# where nix runs on cygwin, we can attempt to upstream this again.
|
||||||
|
./store-tls-pointer-in-win32-tls.patch
|
||||||
|
]
|
||||||
# After cygwin hosted builds are working, we should upstream this
|
# After cygwin hosted builds are working, we should upstream this
|
||||||
++ lib.optional (
|
++ lib.optional (
|
||||||
!headersOnly && stdenvNoLibc.hostPlatform != stdenvNoLibc.buildPlatform
|
!headersOnly && stdenvNoLibc.hostPlatform != stdenvNoLibc.buildPlatform
|
||||||
|
|||||||
@@ -0,0 +1,246 @@
|
|||||||
|
From f74059ffbcf53d8ff4db59ca9e7b07d58bd3e3c6 Mon Sep 17 00:00:00 2001
|
||||||
|
From: David McFarland <corngood@gmail.com>
|
||||||
|
Date: Fri, 4 Sep 2020 10:15:57 -0300
|
||||||
|
Subject: [PATCH] Cygwin: store tls pointer in win32 tls
|
||||||
|
|
||||||
|
Use WIN32 TLS instead of stack-relative pointers for TLS. This allows windows
|
||||||
|
fibers and boost coroutines to be used without crashing whenever a syscall is
|
||||||
|
made from a fiber.
|
||||||
|
|
||||||
|
NOTE: This should be submitted upstream, but there is a blocker first. In the
|
||||||
|
main branch there are conflicts with new ARM64 support. In addition to fixing
|
||||||
|
the conflicts, we should actually test whether ARM64 builds work too, first.
|
||||||
|
---
|
||||||
|
winsup/cygwin/create_posix_thread.cc | 2 ++
|
||||||
|
winsup/cygwin/cygtls.cc | 15 +++++++++++++++
|
||||||
|
winsup/cygwin/dcrt0.cc | 1 +
|
||||||
|
winsup/cygwin/fork.cc | 1 +
|
||||||
|
winsup/cygwin/include/cygwin/config.h | 2 +-
|
||||||
|
winsup/cygwin/init.cc | 12 ++++++++----
|
||||||
|
winsup/cygwin/local_includes/cygtls.h | 7 +++++--
|
||||||
|
winsup/cygwin/scripts/gendef | 15 ++++++++++-----
|
||||||
|
8 files changed, 43 insertions(+), 12 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/winsup/cygwin/create_posix_thread.cc b/winsup/cygwin/create_posix_thread.cc
|
||||||
|
index 3fcd61707..85c1a8af3 100644
|
||||||
|
--- a/winsup/cygwin/create_posix_thread.cc
|
||||||
|
+++ b/winsup/cygwin/create_posix_thread.cc
|
||||||
|
@@ -52,6 +52,7 @@ pthread_wrapper (PVOID arg)
|
||||||
|
/* Set stack values in TEB */
|
||||||
|
PTEB teb = NtCurrentTeb ();
|
||||||
|
teb->Tib.StackBase = wrapper_arg.stackbase;
|
||||||
|
+ _set_tls();
|
||||||
|
teb->Tib.StackLimit = wrapper_arg.stacklimit ?: wrapper_arg.stackaddr;
|
||||||
|
/* Set DeallocationStack value. If we have an application-provided stack,
|
||||||
|
we set DeallocationStack to NULL, so NtTerminateThread does not deallocate
|
||||||
|
@@ -250,6 +251,7 @@ create_new_main_thread_stack (PVOID &allocationbase)
|
||||||
|
return NULL;
|
||||||
|
NtCurrentTeb()->Tib.StackBase = ((PBYTE) allocationbase + stacksize);
|
||||||
|
NtCurrentTeb()->Tib.StackLimit = stacklimit;
|
||||||
|
+ _set_tls();
|
||||||
|
return ((PBYTE) allocationbase + stacksize - 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
diff --git a/winsup/cygwin/cygtls.cc b/winsup/cygwin/cygtls.cc
|
||||||
|
index 13d133f47..d23f9b42a 100644
|
||||||
|
--- a/winsup/cygwin/cygtls.cc
|
||||||
|
+++ b/winsup/cygwin/cygtls.cc
|
||||||
|
@@ -17,6 +17,20 @@ details. */
|
||||||
|
#include "sigproc.h"
|
||||||
|
#include "exception.h"
|
||||||
|
|
||||||
|
+extern DWORD cygtls_slot;
|
||||||
|
+
|
||||||
|
+void _set_tls(TEB *teb)
|
||||||
|
+{
|
||||||
|
+ TlsSetValue(cygtls_slot, teb->Tib.StackBase);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+_cygtls* _current_tls()
|
||||||
|
+{
|
||||||
|
+ register void *ret;
|
||||||
|
+ __asm __volatile__ ("movl cygtls_slot(%%rip),%%r10d\nmovq %%gs:0x1480(,%%r10d,8),%0" : "=r" (ret) : : "r10");
|
||||||
|
+ return (_cygtls *) ((PBYTE) ret - __CYGTLS_PADSIZE__);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/* Two calls to get the stack right... */
|
||||||
|
void
|
||||||
|
_cygtls::call (DWORD (*func) (void *, void *), void *arg)
|
||||||
|
@@ -25,6 +39,7 @@ _cygtls::call (DWORD (*func) (void *, void *), void *arg)
|
||||||
|
/* Initialize this thread's ability to respond to things like
|
||||||
|
SIGSEGV or SIGFPE. */
|
||||||
|
exception protect;
|
||||||
|
+ _set_tls();
|
||||||
|
_my_tls.call2 (func, arg, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc
|
||||||
|
index f4c09befd..e6ba488f2 100644
|
||||||
|
--- a/winsup/cygwin/dcrt0.cc
|
||||||
|
+++ b/winsup/cygwin/dcrt0.cc
|
||||||
|
@@ -462,6 +462,7 @@ child_info_fork::alloc_stack ()
|
||||||
|
StackBase in the child to be the same as in the parent, so that the
|
||||||
|
computation of _my_tls is correct. */
|
||||||
|
teb->Tib.StackBase = (PVOID) stackbase;
|
||||||
|
+ _set_tls(teb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
diff --git a/winsup/cygwin/fork.cc b/winsup/cygwin/fork.cc
|
||||||
|
index f88acdbbf..582f1a454 100644
|
||||||
|
--- a/winsup/cygwin/fork.cc
|
||||||
|
+++ b/winsup/cygwin/fork.cc
|
||||||
|
@@ -141,6 +141,7 @@ frok::child (volatile char * volatile here)
|
||||||
|
myself->pid, myself->ppid, __builtin_frame_address (0));
|
||||||
|
sigproc_printf ("hParent %p, load_dlls %d", hParent, load_dlls);
|
||||||
|
|
||||||
|
+ _set_tls();
|
||||||
|
/* Make sure threadinfo information is properly set up. */
|
||||||
|
if (&_my_tls != _main_tls)
|
||||||
|
{
|
||||||
|
diff --git a/winsup/cygwin/include/cygwin/config.h b/winsup/cygwin/include/cygwin/config.h
|
||||||
|
index 2a7083278..21ce484cf 100644
|
||||||
|
--- a/winsup/cygwin/include/cygwin/config.h
|
||||||
|
+++ b/winsup/cygwin/include/cygwin/config.h
|
||||||
|
@@ -37,7 +37,7 @@ extern inline struct _reent *__getreent (void)
|
||||||
|
{
|
||||||
|
register char *ret;
|
||||||
|
#ifdef __x86_64__
|
||||||
|
- __asm __volatile__ ("movq %%gs:8,%0" : "=r" (ret));
|
||||||
|
+ __asm __volatile__ ("movl cygtls_slot(%%rip),%%r10d\nmovq %%gs:0x1480(,%%r10d,8),%0" : "=r" (ret) : : "r10");
|
||||||
|
#else
|
||||||
|
#error unimplemented for this target
|
||||||
|
#endif
|
||||||
|
diff --git a/winsup/cygwin/init.cc b/winsup/cygwin/init.cc
|
||||||
|
index ce6484aff..392ac8600 100644
|
||||||
|
--- a/winsup/cygwin/init.cc
|
||||||
|
+++ b/winsup/cygwin/init.cc
|
||||||
|
@@ -11,7 +11,7 @@ details. */
|
||||||
|
#include "ntdll.h"
|
||||||
|
#include "shared_info.h"
|
||||||
|
|
||||||
|
-static DWORD _my_oldfunc;
|
||||||
|
+DWORD NO_COPY cygtls_slot;
|
||||||
|
|
||||||
|
static char *search_for = (char *) cygthread::stub;
|
||||||
|
unsigned threadfunc_ix[8];
|
||||||
|
@@ -22,7 +22,9 @@ static bool dll_finished_loading;
|
||||||
|
static void
|
||||||
|
threadfunc_fe (VOID *arg)
|
||||||
|
{
|
||||||
|
- _cygtls::call ((DWORD (*) (void *, void *)) TlsGetValue (_my_oldfunc), arg);
|
||||||
|
+ PVOID f = TlsGetValue (cygtls_slot);
|
||||||
|
+ _set_tls();
|
||||||
|
+ _cygtls::call ((DWORD (*) (void *, void *)) f, arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If possible, redirect the thread entry point to a cygwin routine which
|
||||||
|
@@ -59,7 +61,7 @@ munge_threadfunc ()
|
||||||
|
for (i = 0; threadfunc_ix[i]; i++)
|
||||||
|
if (!threadfunc || ebp[threadfunc_ix[i]] == threadfunc)
|
||||||
|
ebp[threadfunc_ix[i]] = (char *) threadfunc_fe;
|
||||||
|
- TlsSetValue (_my_oldfunc, threadfunc);
|
||||||
|
+ TlsSetValue (cygtls_slot, threadfunc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -78,6 +80,8 @@ dll_entry (HANDLE h, DWORD reason, void *static_load)
|
||||||
|
switch (reason)
|
||||||
|
{
|
||||||
|
case DLL_PROCESS_ATTACH:
|
||||||
|
+ cygtls_slot = TlsAlloc ();
|
||||||
|
+ _set_tls();
|
||||||
|
init_console_handler (false);
|
||||||
|
|
||||||
|
cygwin_hmodule = (HMODULE) h;
|
||||||
|
@@ -94,7 +98,6 @@ dll_entry (HANDLE h, DWORD reason, void *static_load)
|
||||||
|
memcpy (_REENT, _GLOBAL_REENT, sizeof (struct _reent));
|
||||||
|
|
||||||
|
dll_crt0_0 ();
|
||||||
|
- _my_oldfunc = TlsAlloc ();
|
||||||
|
dll_finished_loading = true;
|
||||||
|
break;
|
||||||
|
case DLL_PROCESS_DETACH:
|
||||||
|
@@ -102,6 +105,7 @@ dll_entry (HANDLE h, DWORD reason, void *static_load)
|
||||||
|
shared_destroy ();
|
||||||
|
break;
|
||||||
|
case DLL_THREAD_ATTACH:
|
||||||
|
+ _set_tls();
|
||||||
|
if (dll_finished_loading)
|
||||||
|
munge_threadfunc ();
|
||||||
|
break;
|
||||||
|
diff --git a/winsup/cygwin/local_includes/cygtls.h b/winsup/cygwin/local_includes/cygtls.h
|
||||||
|
index 306497a33..e3a216280 100644
|
||||||
|
--- a/winsup/cygwin/local_includes/cygtls.h
|
||||||
|
+++ b/winsup/cygwin/local_includes/cygtls.h
|
||||||
|
@@ -301,8 +301,11 @@ private:
|
||||||
|
#include "cygerrno.h"
|
||||||
|
#include "ntdll.h"
|
||||||
|
|
||||||
|
-#define _my_tls (*((_cygtls *) ((PBYTE) NtCurrentTeb()->Tib.StackBase \
|
||||||
|
- - __CYGTLS_PADSIZE__)))
|
||||||
|
+void _set_tls(TEB*);
|
||||||
|
+inline void _set_tls() { _set_tls(NtCurrentTeb()); }
|
||||||
|
+_cygtls* _current_tls();
|
||||||
|
+
|
||||||
|
+#define _my_tls (*_current_tls())
|
||||||
|
extern _cygtls *_main_tls;
|
||||||
|
extern _cygtls *_sig_tls;
|
||||||
|
|
||||||
|
diff --git a/winsup/cygwin/scripts/gendef b/winsup/cygwin/scripts/gendef
|
||||||
|
index 861a2405b..9a4479bd8 100755
|
||||||
|
--- a/winsup/cygwin/scripts/gendef
|
||||||
|
+++ b/winsup/cygwin/scripts/gendef
|
||||||
|
@@ -118,7 +118,8 @@ EOF
|
||||||
|
.seh_proc _sigfe_maybe
|
||||||
|
_sigfe_maybe: # stack is aligned on entry!
|
||||||
|
.seh_endprologue
|
||||||
|
- movq %gs:8,%r10 # location of bottom of stack
|
||||||
|
+ movl cygtls_slot(%rip),%r10d
|
||||||
|
+ movq %gs:0x1480(,%r10d,8),%r10 # location of bottom of stack
|
||||||
|
leaq _cygtls.initialized(%r10),%r11 # where we will be looking
|
||||||
|
cmpq %r11,%rsp # stack loc > than tls
|
||||||
|
jge 0f # yep. we don't have a tls.
|
||||||
|
@@ -131,7 +132,8 @@ _sigfe_maybe: # stack is aligned on entry!
|
||||||
|
.seh_proc _sigfe
|
||||||
|
_sigfe: # stack is aligned on entry!
|
||||||
|
.seh_endprologue
|
||||||
|
- movq %gs:8,%r10 # location of bottom of stack
|
||||||
|
+ movl cygtls_slot(%rip),%r10d
|
||||||
|
+ movq %gs:0x1480(,%r10d,8),%r10 # location of bottom of stack
|
||||||
|
1: movl \$1,%r11d
|
||||||
|
xchgl %r11d,_cygtls.stacklock(%r10) # try to acquire lock
|
||||||
|
testl %r11d,%r11d # it will be zero
|
||||||
|
@@ -154,7 +156,8 @@ _sigfe: # stack is aligned on entry!
|
||||||
|
_sigbe: # return here after cygwin syscall
|
||||||
|
# stack is aligned on entry!
|
||||||
|
.seh_endprologue
|
||||||
|
- movq %gs:8,%r10 # address of bottom of tls
|
||||||
|
+ movl cygtls_slot(%rip),%r10d
|
||||||
|
+ movq %gs:0x1480(,%r10d,8),%r10 # address of bottom of tls
|
||||||
|
1: movl \$1,%r11d
|
||||||
|
xchgl %r11d,_cygtls.stacklock(%r10) # try to acquire lock
|
||||||
|
testl %r11d,%r11d # it will be zero
|
||||||
|
@@ -249,7 +252,8 @@ sigdelayed:
|
||||||
|
2:
|
||||||
|
.seh_endprologue
|
||||||
|
|
||||||
|
- movq %gs:8,%r12 # get tls
|
||||||
|
+ movl cygtls_slot(%rip),%r12d
|
||||||
|
+ movq %gs:0x1480(,%r12d,8),%r12 # get tls
|
||||||
|
movl _cygtls.saved_errno(%r12),%r15d # temporarily save saved_errno
|
||||||
|
movq \$_cygtls.start_offset,%rcx # point to beginning of tls block
|
||||||
|
addq %r12,%rcx # and store as first arg to method
|
||||||
|
@@ -316,7 +320,8 @@ stabilize_sig_stack:
|
||||||
|
subq \$0x20,%rsp
|
||||||
|
.seh_stackalloc 32
|
||||||
|
.seh_endprologue
|
||||||
|
- movq %gs:8,%r12
|
||||||
|
+ movl cygtls_slot(%rip),%r12d
|
||||||
|
+ movq %gs:0x1480(,%r12d,8),%r12
|
||||||
|
1: movl \$1,%r10d
|
||||||
|
xchgl %r10d,_cygtls.stacklock(%r12) # try to acquire lock
|
||||||
|
testl %r10d,%r10d
|
||||||
|
--
|
||||||
|
2.50.1
|
||||||
|
|
||||||
Reference in New Issue
Block a user