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:
parent
6e843f7750
commit
b4561c2363
@ -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.
|
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user