From 07a25c9ec1deb7bcdf45d37d51a5b18d91fd1083 Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Sun, 27 Aug 2017 18:14:58 +0200 Subject: [PATCH 1/2] fix issue 17788: MSCOFF: with VS2017 15.3.1 segment .tls is no longer written to a separate image section, so _tls_start and _tls_end no longer happen to work as both __gshared and TLS section offsets. --- src/rt/sections_win64.d | 47 +++++++++++++++++++++++++++++++---------- 1 file changed, 36 insertions(+), 11 deletions(-) diff --git a/src/rt/sections_win64.d b/src/rt/sections_win64.d index 92bafc8b82..8d81e50904 100644 --- a/src/rt/sections_win64.d +++ b/src/rt/sections_win64.d @@ -108,12 +108,40 @@ void finiSections() nothrow @nogc .free(_sections._gcRanges.ptr); } -void[] initTLSRanges() nothrow @nogc -{ - auto pbeg = cast(void*)&_tls_start; - auto pend = cast(void*)&_tls_end; - return pbeg[0 .. pend - pbeg]; -} +void[] initTLSRanges() nothrow @nogc +{ + void* pbeg; + void* pend; + version(Win32) + { + asm @nogc nothrow + { + mov EAX, _tls_index; + mov ECX, FS:[0x2C]; // _tls_array + mov EAX, [ECX+4*EAX]; + mov pbeg, EAX; + add EAX, [_tls_used+4]; // end + sub EAX, [_tls_used+0]; // start + mov pend, EAX; + } + } + else + { + asm @nogc nothrow + { + xor RAX, RAX; + mov EAX, _tls_index; + mov RCX, 0x58; + mov RCX, GS:[RCX]; // _tls_array (immediate value causes fixup) + mov RAX, [RCX+8*RAX]; + mov pbeg, RAX; + add RAX, [_tls_used+8]; // end + sub RAX, [_tls_used+0]; // start + mov pend, RAX; + } + } + return pbeg[0 .. pend - pbeg]; +} void finiTLSRanges(void[] rng) nothrow @nogc { @@ -198,12 +226,9 @@ extern(C) uint _DP_end; uint _TP_beg; uint _TP_end; - } - extern - { - int _tls_start; - int _tls_end; + void*[2] _tls_used; // start, end + int _tls_index; } } From 9676365f661bb3af8eda567151cbe5379acc62e6 Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Mon, 28 Aug 2017 09:03:02 +0200 Subject: [PATCH 2/2] fix ws, add comment, use D_InlineAsm versions --- src/rt/sections_win64.d | 80 ++++++++++++++++++++++------------------- 1 file changed, 44 insertions(+), 36 deletions(-) diff --git a/src/rt/sections_win64.d b/src/rt/sections_win64.d index 8d81e50904..8b5f53f4f3 100644 --- a/src/rt/sections_win64.d +++ b/src/rt/sections_win64.d @@ -108,40 +108,48 @@ void finiSections() nothrow @nogc .free(_sections._gcRanges.ptr); } -void[] initTLSRanges() nothrow @nogc -{ - void* pbeg; - void* pend; - version(Win32) - { - asm @nogc nothrow - { - mov EAX, _tls_index; - mov ECX, FS:[0x2C]; // _tls_array - mov EAX, [ECX+4*EAX]; - mov pbeg, EAX; - add EAX, [_tls_used+4]; // end - sub EAX, [_tls_used+0]; // start - mov pend, EAX; - } - } - else - { - asm @nogc nothrow - { - xor RAX, RAX; - mov EAX, _tls_index; - mov RCX, 0x58; - mov RCX, GS:[RCX]; // _tls_array (immediate value causes fixup) - mov RAX, [RCX+8*RAX]; - mov pbeg, RAX; - add RAX, [_tls_used+8]; // end - sub RAX, [_tls_used+0]; // start - mov pend, RAX; - } - } - return pbeg[0 .. pend - pbeg]; -} +void[] initTLSRanges() nothrow @nogc +{ + void* pbeg; + void* pend; + // with VS2017 15.3.1, the linker no longer puts TLS segments into a + // separate image section. That way _tls_start and _tls_end no + // longer generate offsets into .tls, but DATA. + // Use the TEB entry to find the start of TLS instead and read the + // length from the TLS directory + version(D_InlineAsm_X86) + { + asm @nogc nothrow + { + mov EAX, _tls_index; + mov ECX, FS:[0x2C]; // _tls_array + mov EAX, [ECX+4*EAX]; + mov pbeg, EAX; + add EAX, [_tls_used+4]; // end + sub EAX, [_tls_used+0]; // start + mov pend, EAX; + } + } + else version(D_InlineAsm_X86_64) + { + asm @nogc nothrow + { + xor RAX, RAX; + mov EAX, _tls_index; + mov RCX, 0x58; + mov RCX, GS:[RCX]; // _tls_array (immediate value causes fixup) + mov RAX, [RCX+8*RAX]; + mov pbeg, RAX; + add RAX, [_tls_used+8]; // end + sub RAX, [_tls_used+0]; // start + mov pend, RAX; + } + } + else + static assert(false, "Architecture not supported."); + + return pbeg[0 .. pend - pbeg]; +} void finiTLSRanges(void[] rng) nothrow @nogc { @@ -227,8 +235,8 @@ extern(C) uint _TP_beg; uint _TP_end; - void*[2] _tls_used; // start, end - int _tls_index; + void*[2] _tls_used; // start, end + int _tls_index; } }