version(CRuntime_Microsoft) { extern(C) { extern __gshared void* __ImageBase; extern __gshared uint _DP_beg; extern __gshared uint _DP_end; extern __gshared uint _TP_beg; extern __gshared uint _TP_end; } alias _DPbegin = _DP_beg; alias _DPend = _DP_end; alias _TPbegin = _TP_beg; alias _TPend = _TP_end; __gshared void[] dataSection; shared static this() { import core.internal.traits : externDFunc; alias findImageSection = externDFunc!("rt.sections_win64.findImageSection", void[] function(void* handle, string name) nothrow @nogc); dataSection = findImageSection(&__ImageBase, ".data"); } void[] tlsRange; static this() { import core.internal.traits : externDFunc; alias initTLSRanges = externDFunc!("rt.sections_win64.initTLSRanges", void[] function() nothrow @nogc); tlsRange = initTLSRanges(); } version = ptrref_supported; } else version(Win32) { extern(C) { extern __gshared void* _DPbegin; extern __gshared void* _DPend; extern __gshared uint _TPbegin; extern __gshared uint _TPend; extern int _tlsstart; extern int _tlsend; } void[] tlsRange; static this() { tlsRange = (cast(void*)&_tlsstart)[0.. cast(void*)&_tlsend - cast(void*)&_tlsstart]; } version = ptrref_supported; } struct Struct { int x; Struct* next; } class Class { void* ptr; } struct Struc(T) { static T vtls; static __gshared T vgshared; } __gshared Struct* gsharedStrctPtr2 = new Struct(7, new Struct(8, null)); int tlsInt; void* tlsVar; shared int sharedInt; shared void* sharedVar; __gshared void* gsharedVar; __gshared void* gsharedVar2; immutable int[] arr = [1, 2, 3]; string tlsStr; __gshared Struct gsharedStrct; Struct[3] tlsStrcArr; Class tlsClss; // expression initializers string[] strArr = [ "a", "b" ]; __gshared Class gsharedClss = new Class; __gshared Struct* gsharedStrctPtr = new Struct(7, new Struct(8, null)); debug(PRINT) import core.stdc.stdio; void main() { version(ptrref_supported) testRefPtr(); } version(ptrref_supported): bool findTlsPtr(const(void)* ptr) { debug(PRINT) printf("findTlsPtr %p\n", ptr); for (uint* p = &_TPbegin; p < &_TPend; p++) { void* addr = tlsRange.ptr + *p; debug(PRINT) printf(" try %p\n", addr); assert(*p < tlsRange.length); if (addr == ptr) return true; } return false; } bool findDataPtr(const(void)* ptr) { debug(PRINT) printf("findDataPtr %p\n", ptr); for (auto p = &_DPbegin; p < &_DPend; p++) { debug(PRINT) printf(" try %p\n", cast(void*) cast(size_t) *p); version(CRuntime_Microsoft) void* addr = dataSection.ptr + *p; else void* addr = *p; if (addr == ptr) return true; } return false; } void testRefPtr() { debug(PRINT) printf("&_DPbegin %p\n", &_DPbegin); debug(PRINT) printf("&_DPend %p\n", &_DPend); debug(PRINT) printf("&_TPbegin %p\n", &_TPbegin); debug(PRINT) printf("&_TPend %p\n", &_TPend); assert(!findDataPtr(cast(void*)&sharedInt)); assert(!findTlsPtr(&tlsInt)); assert(findDataPtr(cast(void*)&sharedVar)); assert(findDataPtr(&gsharedVar)); assert(findDataPtr(&gsharedStrct.next)); assert(findDataPtr(&(gsharedClss))); assert(findDataPtr(&(gsharedClss.ptr))); assert(findTlsPtr(&tlsVar)); assert(findTlsPtr(&tlsClss)); assert(findTlsPtr(&tlsStrcArr[0].next)); assert(findTlsPtr(&tlsStrcArr[1].next)); assert(findTlsPtr(&tlsStrcArr[2].next)); assert(!findTlsPtr(cast(size_t*)&tlsStr)); // length assert(findTlsPtr(cast(size_t*)&tlsStr + 1)); // ptr // monitor is manually managed assert(!findDataPtr(cast(size_t*)cast(void*)Class.classinfo + 1)); assert(!findDataPtr(cast(size_t*)cast(void*)Class.classinfo + 1)); assert(!findDataPtr(&arr)); assert(!findTlsPtr(&arr)); assert(!findDataPtr(cast(size_t*)&arr + 1)); assert(!findTlsPtr(cast(size_t*)&arr + 1)); assert(findDataPtr(cast(size_t*)&strArr[0] + 1)); // ptr in _DATA! assert(findDataPtr(cast(size_t*)&strArr[1] + 1)); // ptr in _DATA! strArr[1] = "c"; assert(findDataPtr(&gsharedStrctPtr)); assert(findDataPtr(&gsharedStrctPtr.next)); assert(findDataPtr(&gsharedStrctPtr.next.next)); assert(findDataPtr(&(Struc!(int*).vgshared))); assert(!findDataPtr(&(Struc!(int).vgshared))); assert(findTlsPtr(&(Struc!(int*).vtls))); assert(!findTlsPtr(&(Struc!(int).vtls))); }