diff --git a/winsup/cygwin/DevDocs/how-cygtls-works.txt b/winsup/cygwin/DevDocs/how-cygtls-works.txt index e4f694118..633c4da96 100644 --- a/winsup/cygwin/DevDocs/how-cygtls-works.txt +++ b/winsup/cygwin/DevDocs/how-cygtls-works.txt @@ -4,8 +4,8 @@ All cygwin threads have separate context in an object of class _cygtls. The storage for this object is kept on the stack in the bottom __CYGTLS_PADSIZE__ bytes. Each thread references the storage via the Thread Environment Block (aka Thread Information Block), which Windows maintains for each user thread -in the system, with the address in the FS segment register. The memory -is laid out as in the NT_TIB structure from : +in the system, with the address in a segment register (FS on x86, GS on x86_64). +The memory is laid out as in the NT_TIB structure from : typedef struct _NT_TIB { struct _EXCEPTION_REGISTRATION_RECORD *ExceptionList; @@ -20,16 +20,10 @@ typedef struct _NT_TIB { struct _NT_TIB *Self; } NT_TIB,*PNT_TIB; -Cygwin sees it like this: - -extern exception_list *_except_list asm ("%fs:0"); // exceptions.cc -extern char *_tlsbase __asm__ ("%fs:4"); // cygtls.h -extern char *_tlstop __asm__ ("%fs:8"); // cygtls.h - -And accesses cygtls like this: - -#define _my_tls (((_cygtls *) _tlsbase)[-1]) // cygtls.h +Cygwin accesses cygtls like this (see cygtls.h): +#define _my_tls (*((_cygtls *) ((PBYTE) NtCurrentTeb()->Tib.StackBase \ + - __CYGTLS_PADSIZE__))) Initialization always goes through _cygtls::init_thread(). It works in the following ways: @@ -65,11 +59,4 @@ __CYGTLS_PADSIZE__ bytes down from there are overwritten. Debugging -You can examine the segment registers in gdb via "info w32 selector $fs" -(which is using GetThreadSelectorEntry()) to get results like this: - - Selector $fs - 0x03b: base=0x7ffdd000 limit=0x00000fff 32-bit Data (Read/Write, Exp-up) - Priviledge level = 3. Byte granular. - -"x/3x 0x7ffdd000" will give you _except_list, _tlsbase, and _tlstop. +You can examine the TIB in gdb via "info w32 tib" diff --git a/winsup/testsuite/winsup.api/cygload.cc b/winsup/testsuite/winsup.api/cygload.cc index faad5ce0e..f5ca8db9a 100644 --- a/winsup/testsuite/winsup.api/cygload.cc +++ b/winsup/testsuite/winsup.api/cygload.cc @@ -43,7 +43,10 @@ using std::string; cygwin::padding *cygwin::padding::_main = NULL; DWORD cygwin::padding::_mainTID = 0; -// A few cygwin constants. +// Cygwin signal constants +#undef SIGINT +#undef SIGTERM + static const int SIGHUP = 1; static const int SIGINT = 2; static const int SIGTERM = 15; // Cygwin won't deliver this one to us; @@ -68,17 +71,30 @@ cygwin::padding::padding () _end = _padding + sizeof (_padding); char *stackbase; -#ifdef __GNUC__ +#ifdef __GNUC__ /* GCC */ +# ifdef __x86_64__ + __asm__ ( + "mov %%gs:8, %0" + :"=r"(stackbase) + ); +# elif __X86__ __asm__ ( "movl %%fs:4, %0" :"=r"(stackbase) ); -#else +# else +# error Unknown architecture +# endif +#else /* !GCC assumed to be MSVC */ +# ifdef __X86__ __asm { mov eax, fs:[4]; mov stackbase, eax; } +#else +# error Unknown architecture +# endif #endif _stackbase = stackbase; diff --git a/winsup/testsuite/winsup.api/cygload.exp b/winsup/testsuite/winsup.api/cygload.exp index e7b439512..8ba8249bb 100644 --- a/winsup/testsuite/winsup.api/cygload.exp +++ b/winsup/testsuite/winsup.api/cygload.exp @@ -14,7 +14,13 @@ proc ws_spawn {cmd args} { verbose send "catchCode = $rv\n" } -ws_spawn "$MINGW_CXX $srcdir/$subdir/cygload.cc -o mingw-cygload.exe -lstdc++ -Wl,-e,_cygloadCRTStartup@0" +if { [string match "i686" $target_alias] } { + set entrypoint "_cygloadCRTStartup@0" +} else { + set entrypoint "cygloadCRTStartup" +} + +ws_spawn "$MINGW_CXX $srcdir/$subdir/cygload.cc -o mingw-cygload.exe -static -Wl,-e,$entrypoint" if { $rv != {0 {}} } { verbose -log "$rv"