4
0
mirror of git://sourceware.org/git/newlib-cygwin.git synced 2025-02-19 07:22:14 +08:00

Cygwin: testsuite: Add x86_64 code to "dynamically load cygwin" test

This still needs some more voudou to actually work.

Also update how-cygtls-works.txt a bit
This commit is contained in:
Jon Turney 2020-11-26 16:50:43 +00:00
parent 6e843f7750
commit b4561c2363
No known key found for this signature in database
GPG Key ID: C7C86F0370285C81
3 changed files with 32 additions and 23 deletions

View File

@ -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__ 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 bytes. Each thread references the storage via the Thread Environment Block
(aka Thread Information Block), which Windows maintains for each user thread (aka Thread Information Block), which Windows maintains for each user thread
in the system, with the address in the FS segment register. The memory in the system, with the address in a segment register (FS on x86, GS on x86_64).
is laid out as in the NT_TIB structure from <w32api/winnt.h>: The memory is laid out as in the NT_TIB structure from <w32api/winnt.h>:
typedef struct _NT_TIB { typedef struct _NT_TIB {
struct _EXCEPTION_REGISTRATION_RECORD *ExceptionList; struct _EXCEPTION_REGISTRATION_RECORD *ExceptionList;
@ -20,16 +20,10 @@ typedef struct _NT_TIB {
struct _NT_TIB *Self; struct _NT_TIB *Self;
} NT_TIB,*PNT_TIB; } NT_TIB,*PNT_TIB;
Cygwin sees it like this: Cygwin accesses cygtls like this (see cygtls.h):
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
#define _my_tls (*((_cygtls *) ((PBYTE) NtCurrentTeb()->Tib.StackBase \
- __CYGTLS_PADSIZE__)))
Initialization always goes through _cygtls::init_thread(). It works Initialization always goes through _cygtls::init_thread(). It works
in the following ways: in the following ways:
@ -65,11 +59,4 @@ __CYGTLS_PADSIZE__ bytes down from there are overwritten.
Debugging Debugging
You can examine the segment registers in gdb via "info w32 selector $fs" You can examine the TIB in gdb via "info w32 tib"
(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.

View File

@ -43,7 +43,10 @@ using std::string;
cygwin::padding *cygwin::padding::_main = NULL; cygwin::padding *cygwin::padding::_main = NULL;
DWORD cygwin::padding::_mainTID = 0; DWORD cygwin::padding::_mainTID = 0;
// A few cygwin constants. // Cygwin signal constants
#undef SIGINT
#undef SIGTERM
static const int SIGHUP = 1; static const int SIGHUP = 1;
static const int SIGINT = 2; static const int SIGINT = 2;
static const int SIGTERM = 15; // Cygwin won't deliver this one to us; static const int SIGTERM = 15; // Cygwin won't deliver this one to us;
@ -68,17 +71,30 @@ cygwin::padding::padding ()
_end = _padding + sizeof (_padding); _end = _padding + sizeof (_padding);
char *stackbase; char *stackbase;
#ifdef __GNUC__ #ifdef __GNUC__ /* GCC */
# ifdef __x86_64__
__asm__ (
"mov %%gs:8, %0"
:"=r"(stackbase)
);
# elif __X86__
__asm__ ( __asm__ (
"movl %%fs:4, %0" "movl %%fs:4, %0"
:"=r"(stackbase) :"=r"(stackbase)
); );
#else # else
# error Unknown architecture
# endif
#else /* !GCC assumed to be MSVC */
# ifdef __X86__
__asm __asm
{ {
mov eax, fs:[4]; mov eax, fs:[4];
mov stackbase, eax; mov stackbase, eax;
} }
#else
# error Unknown architecture
# endif
#endif #endif
_stackbase = stackbase; _stackbase = stackbase;

View File

@ -14,7 +14,13 @@ proc ws_spawn {cmd args} {
verbose send "catchCode = $rv\n" 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 {}} } { if { $rv != {0 {}} } {
verbose -log "$rv" verbose -log "$rv"