Index: import/object.di
===================================================================
--- import/object.di	(revision 282)
+++ import/object.di	(working copy)
@@ -223,6 +223,24 @@
     uint flags();
 }
 
+enum
+{
+    MIctorstart  = 1,   // we've started constructing it
+    MIctordone   = 2,   // finished construction
+    MIstandalone = 4,   // module ctor does not depend on other module
+                        // ctors being done first
+    MItlsctor    = 8,
+    MItlsdtor    = 0x10,
+    MIctor       = 0x20,
+    MIdtor       = 0x40,
+    MIxgetMembers = 0x80,
+    MIictor      = 0x100,
+    MIunitTest   = 0x200,
+    MIimportedModules = 0x400,
+    MIlocalClasses = 0x800,
+    MInew        = 0x80000000	// it's the "new" layout
+}
+
 struct ModuleInfo
 {
 /+
@@ -241,18 +259,32 @@
     void function() tlsdtor;
     void*[2] reserved;
 +/
+    @property uint isNew();
+
+    @property uint index();
+    @property void index(uint i);
+
+    @property uint flags();
+    @property void flags(uint f);
+
+    @property void function() tlsctor();
+    @property void function() tlsdtor();
+    @property void* xgetMembers();
+
+    @property void function() ctor();
+    @property void function() dtor();
+    @property void function() ictor();
+    
+    @property void function() unitTest();
+    @property ModuleInfo*[] importedModules();
+    @property TypeInfo_Class[] localClasses();    
+    
     @property string name();
-    @property void function() unitTest();
 
+    
     static int opApply(int delegate(ref ModuleInfo*));
 }
 
-ModuleInfo*[] _moduleinfo_tlsdtors;
-uint          _moduleinfo_tlsdtors_i;
-
-extern (C) void _moduleTlsCtor();
-extern (C) void _moduleTlsDtor();
-
 class Throwable : Object
 {
     interface TraceInfo
Index: src/core/dll_helper.d
===================================================================
--- src/core/dll_helper.d	(revision 282)
+++ src/core/dll_helper.d	(working copy)
@@ -1,6 +1,10 @@
 /**
- * This module provides OS specific helper function for DLL support
+ * This module provides OS specific helper function for shared DLL support
  *
+ * complements shared_dll_helper.d, but is the part that needs to exist
+ *  per binary. Apart from other symbols it relies on tls-values for the
+ *  binary
+ *
  * Copyright: Copyright Digital Mars 2010.
  * License:   <a href="http://www.boost.org/LICENSE_1_0.txt">Boost License 1.0</a>.
  * Authors:   Rainer Schuetze
@@ -12,18 +16,16 @@
  */
 
 module core.dll_helper;
-
+ 
 version( Windows )
 {
-    import std.c.windows.windows;
+    import core.sys.windows.windows;
     import core.stdc.string;
     import core.runtime;
+    import rt.moduleinit;
+    import rt.memory;
+    import core.shared_dll_helper;
 
-    public import core.thread_helper;
-
-    ///////////////////////////////////////////////////////////////////
-    // support fixing implicit TLS for dynamically loaded DLLs on Windows XP
-
     extern (C)
     {
 	extern __gshared void* _tlsstart;
@@ -33,366 +35,194 @@
     }
 
 private:
-    struct dll_helper_aux
+    extern (C) void _minit();
+    extern (C) void _moduleCtor();
+    extern (C) void _moduleDtor();
+
+public: 
+    version( sharedlib )
     {
-	// don't let symbols leak into other modules
-	struct LdrpTlsListEntry
+	// version(sharedlib) is used when linking against phobos_shared.lib, thus using 
+	//  shared runtime phobos.dll
+	pragma(lib,"snn_shared.lib");
+	
+	// patch relocations, fixup TLS storage, initialize runtime of a DLL using 
+	//  shared RTL and init module ctors and tls ctors for existing threads
+	// to be called from DllMain with reason DLL_PROCESS_ATTACH
+	bool shared_dll_process_attach( HINSTANCE hInstance, 
+					void* tlsstart, void* tlsend, void* tls_callbacks_a, int* tlsindex )
 	{
-	    LdrpTlsListEntry* next;
-	    LdrpTlsListEntry* prev;
-	    void* tlsstart;
-	    void* tlsend;
-	    void* ptr_tlsindex;
-	    void* callbacks;
-	    void* zerofill;
-	    int   tlsindex;
-	}
+	    dll_patchImportRelocations(hInstance);
+	    if( !dll_fixTLS( hInstance, tlsstart, tlsend, tls_callbacks_a, tlsindex ) )
+		return false;
+		    
+	    dll_add_tlsdata(*tlsindex, tlsend - tlsstart);
+	    initStaticDataGC();
+	    _minit();
+	    _moduleCtor();
 
-	alias extern(Windows)
-	void* fnRtlAllocateHeap(void* HeapHandle, uint Flags, uint Size);
-
-	// find a code sequence and return the (relative) address that follows
-	static void* findCodeReference( void* adr, int len, ref ubyte[] pattern, bool relative )
+	    // run tls ctors for all other threads
+	    void* ctx = cast(void*) GetCurrentThreadId();
+	    return enumProcessThreads(
+		function (uint id, void* context) { 
+		    if (cast(uint) context != id)
+			impersonate_thread( id, &_moduleTlsCtor );
+		    return true; 
+		}, ctx );
+	}
+	
+	// to be called from DllMain with reason DLL_PROCESS_ATTACH
+	// same as above, but takes tls-values from current static linkage
+	// (actually it does not make sense to call shared_dll_process_attach differently,
+	//  because it calls other functions like _minit and _moduleCtor, which are
+	//  always statically linked anyway)
+	bool shared_dll_process_attach( HINSTANCE hInstance )
 	{
-	    if( !adr )
-		return null;
-
-	    ubyte* code = cast(ubyte*) adr;
-	    for( int p = 0; p < len; p++ )
-	    {
-		if( code[ p .. p + pattern.length ] == pattern[ 0 .. $ ] )
-		{
-		    ubyte* padr = code + p + pattern.length;
-		    if( relative )
-			return padr + 4 + *cast(int*) padr;
-		    return *cast(void**) padr;
-		}
-	    }
-	    return null;
+	    return shared_dll_process_attach( hInstance, &_tlsstart, &_tlsend, &_tls_callbacks_a, &_tls_index );
 	}
-
-	// crawl through ntdll to find function _LdrpAllocateTls@0 and references
-	//  to _LdrpNumberOfTlsEntries, _NtdllBaseTag and _LdrpTlsList
-	// LdrInitializeThunk
-	// -> _LdrpInitialize@12
-	// -> _LdrpInitializeThread@4
-	// -> _LdrpAllocateTls@0
-	// -> je chunk
-	//     _LdrpNumberOfTlsEntries - number of entries in TlsList
-	//     _NtdllBaseTag           - tag used for RtlAllocateHeap
-	//     _LdrpTlsList            - root of the double linked list with TlsList entries
-
-	static __gshared int* pNtdllBaseTag; // remembered for reusage in addTlsData
-
-	static __gshared ubyte[] jmp_LdrpInitialize = [ 0x33, 0xED, 0xE9 ]; // xor ebp,ebp; jmp _LdrpInitialize
-	static __gshared ubyte[] jmp__LdrpInitialize = [ 0x5D, 0xE9 ]; // pop ebp; jmp __LdrpInitialize
-	static __gshared ubyte[] call_LdrpInitializeThread = [ 0xFF, 0x75, 0x08, 0xE8 ]; // push [ebp+8]; call _LdrpInitializeThread
-	static __gshared ubyte[] call_LdrpAllocateTls = [ 0x00, 0x00, 0xE8 ]; // jne 0xc3; call _LdrpAllocateTls
-	static __gshared ubyte[] jne_LdrpAllocateTls = [ 0x0f, 0x85 ]; // jne body_LdrpAllocateTls
-	static __gshared ubyte[] mov_LdrpNumberOfTlsEntries = [ 0x8B, 0x0D ]; // mov ecx, _LdrpNumberOfTlsEntries
-	static __gshared ubyte[] mov_NtdllBaseTag = [ 0x51, 0x8B, 0x0D ]; // push ecx; mov ecx, _NtdllBaseTag
-	static __gshared ubyte[] mov_LdrpTlsList = [ 0x8B, 0x3D ]; // mov edi, _LdrpTlsList
-
-	static LdrpTlsListEntry* addTlsListEntry( void** peb, void* tlsstart, void* tlsend, void* tls_callbacks_a, int* tlsindex )
+	    
+	// to be called from DllMain with reason DLL_PROCESS_DETACH
+	void shared_dll_process_detach( HINSTANCE hInstance, int tls_index )
 	{
-	    HANDLE hnd = GetModuleHandleA( "NTDLL" );
-	    assert( hnd, "cannot get module handle for ntdll" );
-	    ubyte* fn = cast(ubyte*) GetProcAddress( hnd, "LdrInitializeThunk" );
-	    assert( fn, "cannot find LdrInitializeThunk in ntdll" );
+	    // run tls dtors for all other threads
+	    void* ctx = cast(void*) GetCurrentThreadId();
+	    enumProcessThreads(
+		function (uint id, void* context) { 
+		    if (cast(uint) context != id)
+			impersonate_thread( id, &_moduleTlsDtor );
+		    return true; 
+		}, ctx );
 
-	    try
-	    {
-		void* pLdrpInitialize = findCodeReference( fn, 20, jmp_LdrpInitialize, true );
-		void* p_LdrpInitialize = findCodeReference( pLdrpInitialize, 40, jmp__LdrpInitialize, true );
-		void* pLdrpInitializeThread = findCodeReference( p_LdrpInitialize, 200, call_LdrpInitializeThread, true );
-		void* pLdrpAllocateTls = findCodeReference( pLdrpInitializeThread, 40, call_LdrpAllocateTls, true );
-		void* pBodyAllocateTls = findCodeReference( pLdrpAllocateTls, 40, jne_LdrpAllocateTls, true );
-
-		int* pLdrpNumberOfTlsEntries = cast(int*) findCodeReference( pBodyAllocateTls, 20, mov_LdrpNumberOfTlsEntries, false );
-		pNtdllBaseTag = cast(int*) findCodeReference( pBodyAllocateTls, 30, mov_NtdllBaseTag, false );
-		LdrpTlsListEntry* pLdrpTlsList = cast(LdrpTlsListEntry*)findCodeReference( pBodyAllocateTls, 60, mov_LdrpTlsList, false );
-
-		if( !pLdrpNumberOfTlsEntries || !pNtdllBaseTag || !pLdrpTlsList )
-		    return null;
-
-		fnRtlAllocateHeap* fnAlloc = cast(fnRtlAllocateHeap*) GetProcAddress( hnd, "RtlAllocateHeap" );
-		if( !fnAlloc )
-		    return null;
-
-		// allocate new TlsList entry (adding 0xC0000 to the tag is obviously a flag also usesd by
-		//  the nt-loader, could be the result of HEAP_MAKE_TAG_FLAGS(0,HEAP_NO_SERIALIZE|HEAP_GROWABLE)
-		//  but this is not documented in the msdn entry for RtlAlloateHeap
-		void* heap = peb[6];
-		LdrpTlsListEntry* entry = cast(LdrpTlsListEntry*) (*fnAlloc)( heap, *pNtdllBaseTag | 0xc0000, LdrpTlsListEntry.sizeof );
-		if( !entry )
-		    return null;
-
-		// fill entry
-		entry.tlsstart = tlsstart;
-		entry.tlsend = tlsend;
-		entry.ptr_tlsindex = tlsindex;
-		entry.callbacks = tls_callbacks_a;
-		entry.zerofill = null;
-		entry.tlsindex = *pLdrpNumberOfTlsEntries;
-
-		// and add it to the end of TlsList
-		*tlsindex = *pLdrpNumberOfTlsEntries;
-		entry.next = pLdrpTlsList;
-		entry.prev = pLdrpTlsList.prev;
-		pLdrpTlsList.prev.next = entry;
-		pLdrpTlsList.prev = entry;
-		(*pLdrpNumberOfTlsEntries)++;
-
-		return entry;
-	    }
-	    catch( Exception e )
-	    {
-		// assert( false, e.msg );
-		return null;
-	    }
+	    _moduleDtor();
+	    dll_remove_tlsdata(tls_index);
 	}
 
-	// reallocate TLS array and create a copy of the TLS data section
-	static bool addTlsData( void** teb, void* tlsstart, void* tlsend, int tlsindex )
+	// to be called from DllMain with reason DLL_PROCESS_DETACH
+	// same as above, but takes _tls_index from current static linkage
+	// (actually it does not make sense to call shared_dll_process_detach differently,
+	//  because it calls other functions like _moduleTlsDtor and _moduleDtor, which are
+	//  always statically linked anyway)
+	void shared_dll_process_detach( HINSTANCE hInstance )
 	{
-	    try
-	    {
-		HANDLE hnd = GetModuleHandleA( "NTDLL" );
-		assert( hnd, "cannot get module handle for ntdll" );
-
-		fnRtlAllocateHeap* fnAlloc = cast(fnRtlAllocateHeap*) GetProcAddress( hnd, "RtlAllocateHeap" );
-		if( !fnAlloc || !pNtdllBaseTag )
-		    return false;
-	
-		void** peb = cast(void**) teb[12];
-		void* heap = peb[6];
-
-		int sz = tlsend - tlsstart;
-		void* tlsdata = cast(void*) (*fnAlloc)( heap, *pNtdllBaseTag | 0xc0000, sz );
-		if( !tlsdata )
-		    return false;
-
-		// no relocations! not even self-relocations. Windows does not do them.
-		core.stdc.string.memcpy( tlsdata, tlsstart, sz ); 
-
-		// create copy of tls pointer array
-		void** array = cast(void**) (*fnAlloc)( heap, *pNtdllBaseTag | 0xc0000, (tlsindex + 1) * (void*).sizeof );
-		if( !array )
-		    return false;
-
-		if( tlsindex > 0 && teb[11] )
-		    core.stdc.string.memcpy( array, teb[11], tlsindex * (void*).sizeof);
-		array[tlsindex] = tlsdata;
-		teb[11] = cast(void*) array;
+	    shared_dll_process_detach( hInstance, _tls_index );
+	}
 	    
-		// let the old array leak, in case a oncurrent thread is still relying on it
-	    }
-	    catch( Exception e )
-	    {
-		// assert( false, e.msg );
-		return false;
-	    }
-	    return true;
+	void shared_dll_thread_attach()
+	{
+	    if( !_moduleinfo_tlsdtors_i )
+		_moduleTlsCtor();
 	}
-
-	alias bool BOOLEAN;
-
-	struct UNICODE_STRING
+	    
+	void shared_dll_thread_detach()
 	{
-	    short Length;
-	    short MaximumLength;
-	    wchar* Buffer;
+	    _moduleTlsCtor();
 	}
-
-	struct LIST_ENTRY
+    
+ 	void shared_dll_add_tlsdata()
 	{
-	    LIST_ENTRY* next;
-	    LIST_ENTRY* prev;
-        }
+	    dll_add_tlsdata(_tls_index, _tlsend - _tlsstart);
+	}
 
-	// the following structures can be found here: http://undocumented.ntinternals.net/
-	struct LDR_MODULE 
+	void shared_dll_remove_tlsdata()
 	{
-	    LIST_ENTRY      InLoadOrderModuleList;
-	    LIST_ENTRY      InMemoryOrderModuleList;
-	    LIST_ENTRY      InInitializationOrderModuleList;
-	    PVOID           BaseAddress;
-	    PVOID           EntryPoint;
-	    ULONG           SizeOfImage;
-	    UNICODE_STRING  FullDllName;
-	    UNICODE_STRING  BaseDllName;
-	    ULONG           Flags;
-	    SHORT           LoadCount;
-	    SHORT           TlsIndex;
-	    LIST_ENTRY      HashTableEntry;
-	    ULONG           TimeDateStamp;
+	    dll_remove_tlsdata(_tls_index);
 	}
 
-	struct PEB_LDR_DATA 
+        void shared_dll_patchImportRelocations(HMODULE mod)
 	{
-	    ULONG           Length;
-	    BOOLEAN         Initialized;
-	    PVOID           SsHandle;
-	    LIST_ENTRY      InLoadOrderModuleList;
-	    LIST_ENTRY      InMemoryOrderModuleList;
-	    LIST_ENTRY      InInitializationOrderModuleList;
+	    dll_patchImportRelocations(mod);
 	}
-
-	static LDR_MODULE* findLdrModule( HINSTANCE hInstance, void** peb )
+	
+	// dummy functions to satisfy symbols in dllstart.obj
+	// this should not be necessary if the dllstart object file from the shared version of
+	// snn.lib is used instead
+	extern(C)
 	{
-	    PEB_LDR_DATA* ldrData = cast(PEB_LDR_DATA*) peb[3];
-	    LIST_ENTRY* root = &ldrData.InLoadOrderModuleList;
-	    for(LIST_ENTRY* entry = root.next; entry != root; entry = entry.next)
+	    int __terminate_done;
+
+	    // don't do anything here, the relevant code is in phobos.dll
+	    void _cexit ()
 	    {
-		LDR_MODULE *ldrMod = cast(LDR_MODULE*) entry;
-		if(ldrMod.BaseAddress == hInstance)
-		    return ldrMod;
+		__terminate_done = 1;
 	    }
-	    return null;
-	}
 
-	static bool setDllTlsUsage( HINSTANCE hInstance, void** peb )
-	{
-	    try
+	    void _removethreadtableentry(uint id)
 	    {
-		LDR_MODULE *thisMod = findLdrModule( hInstance, peb );
-		if( !thisMod )
-		    return false;
-
-		thisMod.TlsIndex = -1;  // uses TLS (not the index itself)
-		thisMod.LoadCount = -1; // never unload
-		return true;
 	    }
-	    catch( Exception e )
-	    {
-		// assert( false, e.msg );
-		return false;
-	    }
 	}
     }
-    
-public:
-    /* *****************************************************
-     * Fix implicit thread local storage for the case when a DLL is loaded
-     * dynamically after process initialization.
-     * The link time variables are passed to allow placing this function into
-     * an RTL DLL itself.
-     * The problem is described in Bugzilla 3342 and
-     * http://www.nynaeve.net/?p=187, to quote from the latter:
-     *
-     * "When a DLL using implicit TLS is loaded, because the loader doesn't process the TLS
-     *  directory, the _tls_index value is not initialized by the loader, nor is there space
-     *  allocated for module's TLS data in the ThreadLocalStoragePointer arrays of running
-     *  threads. The DLL continues to load, however, and things will appear to work... until the
-     *  first access to a __declspec(thread) variable occurs, that is."
-     *
-     * _tls_index is initialized by the compiler to 0, so we can use this as a test.
-     */
-    bool dll_fixTLS( HINSTANCE hInstance, void* tlsstart, void* tlsend, void* tls_callbacks_a, int* tlsindex )
+    else // !sharedlib
     {
-	/* If the OS has allocated a TLS slot for us, we don't have to do anything
-	 * tls_index 0 means: the OS has not done anything, or it has allocated slot 0
-	 * Vista and later Windows systems should do this correctly and not need
-	 * this function.
-	 */
-	if( *tlsindex != 0 )
-	    return true;
+        // linking against phobos.lib, thus using static runtime
+    
+        // fixup TLS storage, initialize runtime and attach to threads
+        // to be called from DllMain with reason DLL_PROCESS_ATTACH
+        bool dll_process_attach( HINSTANCE hInstance, bool attach_threads,
+                                 void* tlsstart, void* tlsend, void* tls_callbacks_a, int* tlsindex )
+        {
+	    if( !dll_fixTLS( hInstance, tlsstart, tlsend, tls_callbacks_a, tlsindex ) )
+		return false;
 
-	void** peb;
-	asm 
-	{
-	    mov EAX,FS:[0x30]; 
-	    mov peb, EAX; 
-	}
-	dll_helper_aux.LDR_MODULE *ldrMod = dll_helper_aux.findLdrModule( hInstance, peb );
-	if( !ldrMod )
-	    return false; // not in module list, bail out
-	if( ldrMod.TlsIndex != 0 )
-	    return true;  // the OS has already setup TLS
-	    
-	dll_helper_aux.LdrpTlsListEntry* entry = dll_helper_aux.addTlsListEntry( peb, tlsstart, tlsend, tls_callbacks_a, tlsindex );
-	if( !entry )
-	    return false;
+	    thread_setNeedLock(true);
+	    Runtime.initialize();
 
-	if( !enumProcessThreads( 
-	    function (uint id, void* context) {
-		dll_helper_aux.LdrpTlsListEntry* entry = cast(dll_helper_aux.LdrpTlsListEntry*) context;
-		return dll_helper_aux.addTlsData( getTEB( id ), entry.tlsstart, entry.tlsend, entry.tlsindex );
-	    }, entry ) )
-	    return false;
-
-	ldrMod.TlsIndex = -1;  // flag TLS usage (not the index itself)
-	ldrMod.LoadCount = -1; // prevent unloading of the DLL,
-			       // since XP does not keep track of used TLS entries
-	return true;
-    }
-
-    // fixup TLS storage, initialize runtime and attach to threads
-    // to be called from DllMain with reason DLL_PROCESS_ATTACH
-    bool dll_process_attach( HINSTANCE hInstance, bool attach_threads,
-                             void* tlsstart, void* tlsend, void* tls_callbacks_a, int* tlsindex )
-    {
-	if( !dll_fixTLS( hInstance, tlsstart, tlsend, tls_callbacks_a, tlsindex ) )
-	    return false;
-
-	thread_setNeedLock(true);
-	Runtime.initialize();
-
-	if( !attach_threads )
-	    return true;
+	    if( !attach_threads )
+		return true;
 	    
-	// attach to all other threads
-	return enumProcessThreads(
-	    function (uint id, void* context) { 
-		if( !Thread.findThread( id ) )
-		{
-		    thread_attach( id );
-		    thread_moduleTlsCtor( id );
-		}
-		return true; 
-	    }, null );
-    }
-
-    // same as above, but only usable if druntime is linked statically
-    bool dll_process_attach( HINSTANCE hInstance, bool attach_threads = true )
-    {
-	return dll_process_attach( hInstance, attach_threads,
-	                           &_tlsstart, &_tlsend, &_tls_callbacks_a, &_tls_index );
-    }
-    
-    // to be called from DllMain with reason DLL_PROCESS_DETACH
-    void dll_process_detach( HINSTANCE hInstance, bool detach_threads = true )
-    {
-	// detach from all other threads
-	if( detach_threads )
-	    enumProcessThreads( 
+	    // attach to all other threads
+	    return enumProcessThreads(
 		function (uint id, void* context) { 
-		    if( id != GetCurrentThreadId() && Thread.findThread( id ) ) 
+		    if( !Thread.findThread( id ) )
 		    {
-			thread_moduleTlsDtor( id );
-			thread_detach( id ); 
+			thread_attach( id );
+			impersonate_thread( id, &_moduleTlsCtor );
 		    }
 		    return true; 
 		}, null );
+	}
+    
+	// same as above, but only usable if druntime is linked statically
+	bool dll_process_attach( HINSTANCE hInstance, bool attach_threads = true )
+	{
+	    return dll_process_attach( hInstance, attach_threads,
+				       &_tlsstart, &_tlsend, &_tls_callbacks_a, &_tls_index );
+	}
+    
+	// to be called from DllMain with reason DLL_PROCESS_DETACH
+	void dll_process_detach( HINSTANCE hInstance, bool detach_threads = true )
+	{
+	    // detach from all other threads
+	    if( detach_threads )
+		enumProcessThreads( 
+		    function (uint id, void* context) { 
+			if( id != GetCurrentThreadId() && Thread.findThread( id ) ) 
+			{
+			    impersonate_thread( id, &_moduleTlsDtor );
+			    thread_detach( id ); 
+			}
+			return true; 
+		    }, null );
 
-	Runtime.terminate();
-    }
+	    Runtime.terminate();
+	}
 
-    // to be called from DllMain with reason DLL_THREAD_ATTACH
-    void dll_thread_attach( bool attach_thread = true, bool initTls = true )
-    {
-	if( attach_thread && !Thread.findThread( GetCurrentThreadId() ) )
-	    thread_attachThis(); 
-	if( initTls && !_moduleinfo_tlsdtors_i ) // avoid duplicate calls
-	    _moduleTlsCtor();
-    }
+	// to be called from DllMain with reason DLL_THREAD_ATTACH
+	void dll_thread_attach( bool attach_thread = true, bool initTls = true )
+	{
+	    if( attach_thread && !Thread.findThread( GetCurrentThreadId() ) )
+		thread_attachThis(); 
+	    if( initTls && !_moduleinfo_tlsdtors_i ) // avoid duplicate calls
+		_moduleTlsCtor();
+	}
 
-    // to be called from DllMain with reason DLL_THREAD_DETACH
-    void dll_thread_detach( bool detach_thread = true, bool exitTls = true )
-    {
-	if( exitTls )
-	    _moduleTlsDtor();
-	if( detach_thread )
-	    thread_detachThis(); 
+	// to be called from DllMain with reason DLL_THREAD_DETACH
+	void dll_thread_detach( bool detach_thread = true, bool exitTls = true )
+	{
+	    if( exitTls )
+		_moduleTlsDtor();
+	    if( detach_thread )
+		thread_detachThis(); 
+	}
     }
 }
+
Index: src/core/shared_dll_helper.d
===================================================================
--- src/core/shared_dll_helper.d	(revision 0)
+++ src/core/shared_dll_helper.d	(revision 0)
@@ -0,0 +1,574 @@
+/**
+ * This module provides OS specific helper function for DLL support
+ * The functions in this file are independent of the actual linkage (shared or static)
+ *
+ * Copyright: Copyright Digital Mars 2010.
+ * License:   <a href="http://www.boost.org/LICENSE_1_0.txt">Boost License 1.0</a>.
+ * Authors:   Rainer Schuetze
+ *
+ *          Copyright Digital Mars 2010.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+module core.shared_dll_helper;
+
+version( Windows )
+{
+    import core.sys.windows.windows;
+    import core.stdc.string;
+    import core.runtime;
+    import rt.moduleinit;
+    import rt.memory;
+
+    extern(C) int stricmp(const(char)*s1, const(char)*s2); // from snn.lib, missing in core.stdc.string
+
+    public import core.thread_helper;
+
+    ///////////////////////////////////////////////////////////////////
+    // support fixing implicit TLS for dynamically loaded DLLs on Windows XP
+
+private:
+    struct dll_helper_aux
+    {
+	// don't let symbols leak into other modules
+	struct LdrpTlsListEntry
+	{
+	    LdrpTlsListEntry* next;
+	    LdrpTlsListEntry* prev;
+	    void* tlsstart;
+	    void* tlsend;
+	    void* ptr_tlsindex;
+	    void* callbacks;
+	    void* zerofill;
+	    int   tlsindex;
+	}
+
+	alias extern(Windows)
+	void* fnRtlAllocateHeap(void* HeapHandle, uint Flags, uint Size);
+
+	// find a code sequence and return the (relative) address that follows
+	static void* findCodeReference( void* adr, int len, ref ubyte[] pattern, bool relative )
+	{
+	    if( !adr )
+		return null;
+
+	    ubyte* code = cast(ubyte*) adr;
+	    for( int p = 0; p < len; p++ )
+	    {
+		if( code[ p .. p + pattern.length ] == pattern[ 0 .. $ ] )
+		{
+		    ubyte* padr = code + p + pattern.length;
+		    if( relative )
+			return padr + 4 + *cast(int*) padr;
+		    return *cast(void**) padr;
+		}
+	    }
+	    return null;
+	}
+
+	// crawl through ntdll to find function _LdrpAllocateTls@0 and references
+	//  to _LdrpNumberOfTlsEntries, _NtdllBaseTag and _LdrpTlsList
+	// LdrInitializeThunk
+	// -> _LdrpInitialize@12
+	// -> _LdrpInitializeThread@4
+	// -> _LdrpAllocateTls@0
+	// -> je chunk
+	//     _LdrpNumberOfTlsEntries - number of entries in TlsList
+	//     _NtdllBaseTag           - tag used for RtlAllocateHeap
+	//     _LdrpTlsList            - root of the double linked list with TlsList entries
+
+	static __gshared int* pNtdllBaseTag; // remembered for reusage in addTlsData
+
+	static __gshared ubyte[] jmp_LdrpInitialize = [ 0x33, 0xED, 0xE9 ]; // xor ebp,ebp; jmp _LdrpInitialize
+	static __gshared ubyte[] jmp__LdrpInitialize = [ 0x5D, 0xE9 ]; // pop ebp; jmp __LdrpInitialize
+	static __gshared ubyte[] call_LdrpInitializeThread = [ 0xFF, 0x75, 0x08, 0xE8 ]; // push [ebp+8]; call _LdrpInitializeThread
+	static __gshared ubyte[] call_LdrpAllocateTls = [ 0x00, 0x00, 0xE8 ]; // jne 0xc3; call _LdrpAllocateTls
+	static __gshared ubyte[] jne_LdrpAllocateTls = [ 0x0f, 0x85 ]; // jne body_LdrpAllocateTls
+	static __gshared ubyte[] mov_LdrpNumberOfTlsEntries = [ 0x8B, 0x0D ]; // mov ecx, _LdrpNumberOfTlsEntries
+	static __gshared ubyte[] mov_NtdllBaseTag = [ 0x51, 0x8B, 0x0D ]; // push ecx; mov ecx, _NtdllBaseTag
+	static __gshared ubyte[] mov_LdrpTlsList = [ 0x8B, 0x3D ]; // mov edi, _LdrpTlsList
+
+	static LdrpTlsListEntry* addTlsListEntry( void** peb, void* tlsstart, void* tlsend, void* tls_callbacks_a, int* tlsindex )
+	{
+	    HANDLE hnd = GetModuleHandleA( "NTDLL" );
+	    assert( hnd, "cannot get module handle for ntdll" );
+	    ubyte* fn = cast(ubyte*) GetProcAddress( hnd, "LdrInitializeThunk" );
+	    assert( fn, "cannot find LdrInitializeThunk in ntdll" );
+
+	    try
+	    {
+		void* pLdrpInitialize = findCodeReference( fn, 20, jmp_LdrpInitialize, true );
+		void* p_LdrpInitialize = findCodeReference( pLdrpInitialize, 40, jmp__LdrpInitialize, true );
+		void* pLdrpInitializeThread = findCodeReference( p_LdrpInitialize, 200, call_LdrpInitializeThread, true );
+		void* pLdrpAllocateTls = findCodeReference( pLdrpInitializeThread, 40, call_LdrpAllocateTls, true );
+		void* pBodyAllocateTls = findCodeReference( pLdrpAllocateTls, 40, jne_LdrpAllocateTls, true );
+
+		int* pLdrpNumberOfTlsEntries = cast(int*) findCodeReference( pBodyAllocateTls, 20, mov_LdrpNumberOfTlsEntries, false );
+		pNtdllBaseTag = cast(int*) findCodeReference( pBodyAllocateTls, 30, mov_NtdllBaseTag, false );
+		LdrpTlsListEntry* pLdrpTlsList = cast(LdrpTlsListEntry*)findCodeReference( pBodyAllocateTls, 60, mov_LdrpTlsList, false );
+
+		if( !pLdrpNumberOfTlsEntries || !pNtdllBaseTag || !pLdrpTlsList )
+		    return null;
+
+		fnRtlAllocateHeap* fnAlloc = cast(fnRtlAllocateHeap*) GetProcAddress( hnd, "RtlAllocateHeap" );
+		if( !fnAlloc )
+		    return null;
+
+		// allocate new TlsList entry (adding 0xC0000 to the tag is obviously a flag also usesd by
+		//  the nt-loader, could be the result of HEAP_MAKE_TAG_FLAGS(0,HEAP_NO_SERIALIZE|HEAP_GROWABLE)
+		//  but this is not documented in the msdn entry for RtlAlloateHeap
+		void* heap = peb[6];
+		LdrpTlsListEntry* entry = cast(LdrpTlsListEntry*) (*fnAlloc)( heap, *pNtdllBaseTag | 0xc0000, LdrpTlsListEntry.sizeof );
+		if( !entry )
+		    return null;
+
+		// fill entry
+		entry.tlsstart = tlsstart;
+		entry.tlsend = tlsend;
+		entry.ptr_tlsindex = tlsindex;
+		entry.callbacks = tls_callbacks_a;
+		entry.zerofill = null;
+		entry.tlsindex = *pLdrpNumberOfTlsEntries;
+
+		// and add it to the end of TlsList
+		*tlsindex = *pLdrpNumberOfTlsEntries;
+		entry.next = pLdrpTlsList;
+		entry.prev = pLdrpTlsList.prev;
+		pLdrpTlsList.prev.next = entry;
+		pLdrpTlsList.prev = entry;
+		(*pLdrpNumberOfTlsEntries)++;
+
+		return entry;
+	    }
+	    catch( Exception e )
+	    {
+		// assert( false, e.msg );
+		return null;
+	    }
+	}
+
+	// reallocate TLS array and create a copy of the TLS data section
+	static bool addTlsData( void** teb, void* tlsstart, void* tlsend, int tlsindex )
+	{
+	    try
+	    {
+		HANDLE hnd = GetModuleHandleA( "NTDLL" );
+		assert( hnd, "cannot get module handle for ntdll" );
+
+		fnRtlAllocateHeap* fnAlloc = cast(fnRtlAllocateHeap*) GetProcAddress( hnd, "RtlAllocateHeap" );
+		if( !fnAlloc || !pNtdllBaseTag )
+		    return false;
+	
+		void** peb = cast(void**) teb[12];
+		void* heap = peb[6];
+
+		int sz = tlsend - tlsstart;
+		void* tlsdata = cast(void*) (*fnAlloc)( heap, *pNtdllBaseTag | 0xc0000, sz );
+		if( !tlsdata )
+		    return false;
+
+		// no relocations! not even self-relocations. Windows does not do them.
+		core.stdc.string.memcpy( tlsdata, tlsstart, sz ); 
+
+		// create copy of tls pointer array
+		void** array = cast(void**) (*fnAlloc)( heap, *pNtdllBaseTag | 0xc0000, (tlsindex + 1) * (void*).sizeof );
+		if( !array )
+		    return false;
+
+		if( tlsindex > 0 && teb[11] )
+		    core.stdc.string.memcpy( array, teb[11], tlsindex * (void*).sizeof);
+		array[tlsindex] = tlsdata;
+		teb[11] = cast(void*) array;
+	    
+		// let the old array leak, in case a oncurrent thread is still relying on it
+	    }
+	    catch( Exception e )
+	    {
+		// assert( false, e.msg );
+		return false;
+	    }
+	    return true;
+	}
+
+	alias bool BOOLEAN;
+
+	struct UNICODE_STRING
+	{
+	    short Length;
+	    short MaximumLength;
+	    wchar* Buffer;
+	}
+
+	struct LIST_ENTRY
+	{
+	    LIST_ENTRY* next;
+	    LIST_ENTRY* prev;
+        }
+
+	// the following structures can be found here: http://undocumented.ntinternals.net/
+	struct LDR_MODULE 
+	{
+	    LIST_ENTRY      InLoadOrderModuleList;
+	    LIST_ENTRY      InMemoryOrderModuleList;
+	    LIST_ENTRY      InInitializationOrderModuleList;
+	    PVOID           BaseAddress;
+	    PVOID           EntryPoint;
+	    ULONG           SizeOfImage;
+	    UNICODE_STRING  FullDllName;
+	    UNICODE_STRING  BaseDllName;
+	    ULONG           Flags;
+	    SHORT           LoadCount;
+	    SHORT           TlsIndex;
+	    LIST_ENTRY      HashTableEntry;
+	    ULONG           TimeDateStamp;
+	}
+
+	struct PEB_LDR_DATA 
+	{
+	    ULONG           Length;
+	    BOOLEAN         Initialized;
+	    PVOID           SsHandle;
+	    LIST_ENTRY      InLoadOrderModuleList;
+	    LIST_ENTRY      InMemoryOrderModuleList;
+	    LIST_ENTRY      InInitializationOrderModuleList;
+	}
+
+	static LDR_MODULE* findLdrModule( HINSTANCE hInstance, void** peb )
+	{
+	    PEB_LDR_DATA* ldrData = cast(PEB_LDR_DATA*) peb[3];
+	    LIST_ENTRY* root = &ldrData.InLoadOrderModuleList;
+	    for(LIST_ENTRY* entry = root.next; entry != root; entry = entry.next)
+	    {
+		LDR_MODULE *ldrMod = cast(LDR_MODULE*) entry;
+		if(ldrMod.BaseAddress == hInstance)
+		    return ldrMod;
+	    }
+	    return null;
+	}
+
+	static bool setDllTlsUsage( HINSTANCE hInstance, void** peb )
+	{
+	    try
+	    {
+		LDR_MODULE *thisMod = findLdrModule( hInstance, peb );
+		if( !thisMod )
+		    return false;
+
+		thisMod.TlsIndex = -1;  // uses TLS (not the index itself)
+		thisMod.LoadCount = -1; // never unload
+		return true;
+	    }
+	    catch( Exception e )
+	    {
+		// assert( false, e.msg );
+		return false;
+	    }
+	}
+    }
+    
+public:
+    /* *****************************************************
+     * Fix implicit thread local storage for the case when a DLL is loaded
+     * dynamically after process initialization.
+     * The link time variables are passed to allow placing this function into
+     * an RTL DLL itself.
+     * The problem is described in Bugzilla 3342 and
+     * http://www.nynaeve.net/?p=187, to quote from the latter:
+     *
+     * "When a DLL using implicit TLS is loaded, because the loader doesn't process the TLS
+     *  directory, the _tls_index value is not initialized by the loader, nor is there space
+     *  allocated for module's TLS data in the ThreadLocalStoragePointer arrays of running
+     *  threads. The DLL continues to load, however, and things will appear to work... until the
+     *  first access to a __declspec(thread) variable occurs, that is."
+     *
+     * _tls_index is initialized by the compiler to 0, so we can use this as a test.
+     */
+    bool dll_fixTLS( HINSTANCE hInstance, void* tlsstart, void* tlsend, void* tls_callbacks_a, int* tlsindex )
+    {
+	/* If the OS has allocated a TLS slot for us, we don't have to do anything
+	 * tls_index 0 means: the OS has not done anything, or it has allocated slot 0
+	 * Vista and later Windows systems should do this correctly and not need
+	 * this function.
+	 */
+	if( *tlsindex != 0 )
+	    return true;
+
+	void** peb;
+	asm 
+	{
+	    mov EAX,FS:[0x30]; 
+	    mov peb, EAX; 
+	}
+	dll_helper_aux.LDR_MODULE *ldrMod = dll_helper_aux.findLdrModule( hInstance, peb );
+	if( !ldrMod )
+	    return false; // not in module list, bail out
+	if( ldrMod.TlsIndex != 0 )
+	    return true;  // the OS has already setup TLS
+	    
+	dll_helper_aux.LdrpTlsListEntry* entry = dll_helper_aux.addTlsListEntry( peb, tlsstart, tlsend, tls_callbacks_a, tlsindex );
+	if( !entry )
+	    return false;
+
+	if( !enumProcessThreads( 
+	    function (uint id, void* context) {
+		dll_helper_aux.LdrpTlsListEntry* entry = cast(dll_helper_aux.LdrpTlsListEntry*) context;
+		return dll_helper_aux.addTlsData( getTEB( id ), entry.tlsstart, entry.tlsend, entry.tlsindex );
+	    }, entry ) )
+	    return false;
+
+	ldrMod.TlsIndex = -1;  // flag TLS usage (not the index itself)
+	ldrMod.LoadCount = -1; // prevent unloading of the DLL,
+			       // since XP does not keep track of used TLS entries
+	return true;
+    }
+
+    ///////////////////////////////////////////////////////////////////
+    // support for DLL/EXE using shared phobos
+    private
+    {
+	struct dll_data_info
+	{
+	    int tls_index;
+	    int tls_size;
+	}
+	dll_data_info[] dll_data;
+    }
+
+    void dll_add_tlsdata( int tls_index, int tls_size )
+    {
+	// data segment added to gc by addRange
+	dll_data_info info = dll_data_info( tls_index, tls_size );
+	dll_data ~= info;
+    }
+
+    void dll_remove_tlsdata( int tls_index )
+    {
+	for( int i = 0; i < dll_data.length; i++ )
+	    if( dll_data[i].tls_index == tls_index )
+	    {
+		if( i < dll_data.length - 1 )
+		    dll_data[i] = dll_data[$ - 1];
+		dll_data.length = dll_data.length - 1;
+		break;
+	    }
+    }
+
+    private alias void delegate( void*, void* ) scanAllThreadsFn;
+
+    void dll_scan_tls( HANDLE thnd, scanAllThreadsFn scan )
+    {
+	if( dll_data.length > 0 )
+	    if( void** teb = getTEB( thnd ) )
+		if( void** tlsarray = cast(void**) teb[11] )
+		    foreach( ref dll_data_info data; dll_data )
+			scan( teb[data.tls_index], teb[data.tls_index] + data.tls_size );
+    }
+
+    ///////////////////////////////////////////////////////////////////
+    // patch relocations through import table
+
+    private struct dll_helper_aux2
+    {
+	// don't let symbols leak into other modules
+
+	// binary image information (from winnt.h)
+	struct IMAGE_DATA_DIRECTORY
+	{
+	    DWORD   VirtualAddress;
+	    DWORD   Size;
+	}
+
+	struct IMAGE_SECTION_HEADER {
+	    char    Name[8];
+	    union {
+		DWORD   PhysicalAddress;
+		DWORD   VirtualSize;
+	    }
+	    DWORD   VirtualAddress;
+	    DWORD   SizeOfRawData;
+	    DWORD   PointerToRawData;
+	    DWORD   PointerToRelocations;
+	    DWORD   PointerToLinenumbers;
+	    WORD    NumberOfRelocations;
+	    WORD    NumberOfLinenumbers;
+	    DWORD   Characteristics;
+	}
+
+	union IMAGE_THUNK_DATA32
+	{
+	    DWORD ForwarderString;      // PBYTE 
+	    DWORD Function;             // PDWORD
+	    DWORD Ordinal;
+	    DWORD AddressOfData;        // PIMAGE_IMPORT_BY_NAME
+	}
+
+	struct IMAGE_IMPORT_DESCRIPTOR
+	{
+	    union {
+		DWORD   Characteristics;            // 0 for terminating null import descriptor
+		DWORD   OriginalFirstThunk;         // RVA to original unbound IAT (PIMAGE_THUNK_DATA)
+	    };
+	    DWORD   TimeDateStamp;                  // 0 if not bound,
+						    // -1 if bound, and real date\time stamp
+						    //     in IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT (new BIND)
+						    // O.W. date/time stamp of DLL bound to (Old BIND)
+	    DWORD   ForwarderChain;                 // -1 if no forwarders
+	    DWORD   Name;
+	    DWORD   FirstThunk;                     // RVA to IAT (if bound this IAT has actual addresses)
+	}
+
+	static uint getImageSize(HINSTANCE hInstance)
+	{
+	    ubyte* mem = cast(ubyte*) hInstance;
+	    if(mem[0] != 'M' || mem[1] != 'Z')
+		return 0;
+	    int peoff = *cast(uint*)(mem + 0x3c);
+	    if(mem[peoff] != 'P' || mem[peoff + 1] != 'E')
+		return 0;
+
+	    return *cast(uint*)(mem + peoff + 20*4); // SizeOfImage
+	}
+
+	static IMAGE_DATA_DIRECTORY[] getDataDirectory(HINSTANCE hInstance)
+	{
+	    ubyte* mem = cast(ubyte*) hInstance;
+	    if(mem[0] != 'M' || mem[1] != 'Z')
+		return null;
+	    int peoff = *cast(uint*)(mem + 0x3c);
+	    if(mem[peoff] != 'P' || mem[peoff + 1] != 'E')
+		return null;
+	
+	    return (cast(IMAGE_DATA_DIRECTORY*)(mem + peoff + 0x78))[0..16];
+	}
+
+	static IMAGE_IMPORT_DESCRIPTOR[] getImportDescriptor(HINSTANCE hInstance)
+	{
+	    IMAGE_DATA_DIRECTORY[] dir = getDataDirectory(hInstance);
+	
+	    ubyte* mem = cast(ubyte*) hInstance;
+	    auto imp = cast(IMAGE_IMPORT_DESCRIPTOR*)(mem + dir[1].VirtualAddress);
+	    uint cnt = 0;
+	    while(cnt * IMAGE_IMPORT_DESCRIPTOR.sizeof < dir[1].Size && imp[cnt].Characteristics)
+		cnt++;
+	    return imp[0 .. cnt];
+	}
+
+	static void[] findRelocationSectionInMem(HINSTANCE hInstance)
+	{
+	    try
+	    {
+		IMAGE_DATA_DIRECTORY[] dir = getDataDirectory(hInstance);
+		
+		// read relocation entry in data directory
+		void* mem = cast(void*) hInstance;
+		return (mem + dir[5].VirtualAddress)[0 .. dir[5].Size];
+	    }
+	    catch(Exception e)
+	    {
+	    }
+	    return null;
+	}
+
+	static ubyte* getImportAdress(ubyte*[] iat, ubyte**ptr)
+	{
+	    uint idx = ptr - iat.ptr;
+	    if(idx < iat.length)
+		return iat[idx];
+	    return null;
+	}
+
+	static ubyte*[] getPhobosIAT(HINSTANCE hInstance)
+	{
+	    IMAGE_IMPORT_DESCRIPTOR[] imp = getImportDescriptor(hInstance);
+	
+	    for(int i = 0; i < imp.length; i++)
+	    {
+		char* name = cast(char*)(hInstance + imp[i].Name);
+		if(stricmp(name, "phobos.dll") == 0)
+		{
+		    ubyte** adr = cast(ubyte**)(hInstance + imp[i].FirstThunk);
+		    int cnt = 0;
+		    while(adr[cnt])
+			cnt++;
+		    return adr[0 .. cnt];
+		}
+	    }
+	    return null;
+	}
+
+	// use function instead of delegate to avoid allocation for closure
+	static void iterateRelocations(HINSTANCE hInstance, void* context, void function (void* context, uint rva) fn)
+	{
+	    void[] reloc = findRelocationSectionInMem(hInstance);
+	    if (!reloc.length)
+		return;
+
+	    void* relocbase = reloc.ptr;
+	    void* relocend = reloc.ptr + reloc.length;
+	    while(relocbase < relocend)
+	    {
+		uint virtadr = *cast(uint*) relocbase;
+		uint chksize = *cast(uint*) (relocbase + 4);
+
+		for (uint p = 8; p < chksize; p += 2)
+		{
+		    ushort entry = *cast(ushort*)(relocbase + p);
+		    ushort type = (entry >> 12) & 0xf;
+		    ushort off = entry & 0xfff;
+
+		    if(type == 3) // HIGHLOW
+			fn(context, virtadr + off);
+		}
+		relocbase += chksize;
+	    }
+	}
+
+    }
+
+    extern(Windows)
+    BOOL VirtualProtect(LPVOID lpAddress, DWORD dwSize, DWORD flNewProtect, PDWORD lpflOldProtect);
+
+    public void dll_patchImportRelocations(HINSTANCE hInstance)
+    {
+	static struct Context
+	{
+	    void* memStart;
+	    void* memEnd;
+	    ubyte*[] iat;
+	}
+	
+	Context ctx;
+	ctx.memStart = hInstance;
+	ctx.memEnd = hInstance + dll_helper_aux2.getImageSize(hInstance);
+	ctx.iat = dll_helper_aux2.getPhobosIAT(hInstance);
+	if(!ctx.iat)
+	    return;
+
+	DWORD oldProtect;
+	BOOL rc = VirtualProtect(ctx.memStart, ctx.memEnd - ctx.memStart, PAGE_EXECUTE_READWRITE, &oldProtect);
+	if(!rc)
+	    return;
+
+	dll_helper_aux2.iterateRelocations(hInstance, &ctx,
+	    function void (void* context, uint rva)
+	    {
+		Context* ctx = cast(Context*) context;
+		ubyte* adr = *cast(ubyte**)(ctx.memStart + rva);
+		if(adr >= ctx.memStart && adr < ctx.memEnd)
+		{
+		    if(adr[0] == 0xff && adr[1] == 0x25)
+		    {
+			adr += 2; // jmp dword ptr[adr]
+			ubyte** ptr = *cast(ubyte***)adr;
+			if(ubyte* impptr = dll_helper_aux2.getImportAdress(ctx.iat, ptr))
+			    *cast(ubyte**)(ctx.memStart + rva) = impptr;
+		}
+	    }
+	});
+
+	VirtualProtect(ctx.memStart, ctx.memStart - ctx.memEnd, oldProtect, &oldProtect);
+    }
+
+}
Index: src/core/thread.d
===================================================================
--- src/core/thread.d	(revision 282)
+++ src/core/thread.d	(working copy)
@@ -99,6 +99,7 @@
         import core.stdc.stdint : uintptr_t; // for _beginthreadex decl below
         import core.sys.windows.windows;
         import core.thread_helper;
+        import core.shared_dll_helper;
 
         const DWORD TLS_OUT_OF_INDEXES  = 0xFFFFFFFF;
 
@@ -114,6 +115,7 @@
             {
                 extern __thread int _tlsstart;
                 extern __thread int _tlsend;
+                extern __gshared int _tls_index;
             }
         }
         else
@@ -1796,7 +1798,7 @@
 	else
 	{
 	    thisThread.m_hndl = OpenThreadHandle( addr );
-	    thisThread.m_tls = GetTlsDataAddress( thisThread.m_hndl )[0 .. pend - pstart];
+	    thisThread.m_tls = GetTlsDataAddress( thisThread.m_hndl, _tls_index )[0 .. pend - pstart];
 	}
 
 	thisThread.m_isDaemon = true;
@@ -2310,6 +2312,7 @@
         version( Windows )
         {
             scan( t.m_reg.ptr, t.m_reg.ptr + t.m_reg.length );
+	    dll_scan_tls( t.m_hndl, scan );
         }
     }
 }
Index: src/core/thread_helper.d
===================================================================
--- src/core/thread_helper.d	(revision 282)
+++ src/core/thread_helper.d	(working copy)
@@ -15,16 +15,14 @@
 
 version( Windows )
 {
-    import std.c.windows.windows;
-    import std.c.stdlib;
+    import core.sys.windows.windows;
+    import stdlib = core.stdc.stdlib;
 
     public import core.thread;
 
     extern(Windows)
     HANDLE OpenThread(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwThreadId);
 
-    extern (C) extern __gshared int _tls_index;
-    
 private:
     ///////////////////////////////////////////////////////////////////
     struct thread_helper_aux
@@ -83,10 +81,14 @@
 	// get the thread environment block (TEB) of the thread with the given handle
 	static void** getTEB( HANDLE hnd )
 	{
-	    HANDLE nthnd = GetModuleHandleA( "NTDLL" );
-	    assert( nthnd, "cannot get module handle for ntdll" );
-	    fnNtQueryInformationThread* fn = cast(fnNtQueryInformationThread*) GetProcAddress( nthnd, "NtQueryInformationThread" );
-	    assert( fn, "cannot find NtQueryInformationThread in ntdll" );
+	    __gshared static fnNtQueryInformationThread* fn;
+	    if( !fn )
+	    {
+		HANDLE nthnd = GetModuleHandleA( "NTDLL" );
+		assert( nthnd, "cannot get module handle for ntdll" );
+		fn = cast(fnNtQueryInformationThread*) GetProcAddress( nthnd, "NtQueryInformationThread" );
+		assert( fn, "cannot find NtQueryInformationThread in ntdll" );
+	    }
 
 	    THREAD_BASIC_INFORMATION tbi;
 	    int Status = (*fn)(hnd, ThreadBasicInformation, &tbi, tbi.sizeof, null);
@@ -153,16 +155,16 @@
 	    char* buf;
 	    for( ; ; )
 	    {
-		buf = cast(char*) std.c.stdlib.malloc(sz);
+		buf = cast(char*) stdlib.malloc(sz);
 		if(!buf)
 	    	    return false;
 		rc = (*fn)( SystemProcessInformation, buf, sz, &retLength );
 		if( rc != STATUS_INFO_LENGTH_MISMATCH )
 		    break;
-		std.c.stdlib.free( buf );
+		stdlib.free( buf );
 		sz *= 2;
 	    }
-	    scope(exit) std.c.stdlib.free( buf );
+	    scope(exit) stdlib.free( buf );
 
 	    if(rc != 0)
 		return false;
@@ -200,7 +202,7 @@
 		return;
 	    }
 
-	    // temporarily set current TLS data pointer to the data pointer of the referenced thread
+	    // temporarily set current TLS array pointer to the array pointer of the referenced thread
 	    void** curteb = getTEB();
 	    void** teb    = getTEB( id );
 	    assert( teb && curteb );
@@ -210,14 +212,9 @@
 	    if( !curtlsarray || !tlsarray )
 		return;
 
-	    void** curtlsdata = cast(void**) curtlsarray[_tls_index];
-	    void** tlsdata    = cast(void**) tlsarray[_tls_index];
-	    if( !curtlsdata || !tlsdata )
-		return;
-
-	    curtlsarray[_tls_index] = tlsdata;
+	    curteb[11] = tlsarray;
 	    fn();
-	    curtlsarray[_tls_index] = curtlsdata;
+	    curteb[11] = curtlsarray;
         }
     }
 
@@ -227,27 +224,14 @@
     alias thread_helper_aux.getThreadStackBottom getThreadStackBottom;
     alias thread_helper_aux.OpenThreadHandle OpenThreadHandle;
     alias thread_helper_aux.enumProcessThreads enumProcessThreads;
+    alias thread_helper_aux.impersonate_thread impersonate_thread;
 
-    void* GetTlsDataAddress( HANDLE hnd )
+    void* GetTlsDataAddress( HANDLE hnd, int tls_index )
     {
 	if( void** teb = getTEB( hnd ) )
 	    if( void** tlsarray = cast(void**) teb[11] )
-		return tlsarray[_tls_index];
+		return tlsarray[tls_index];
 	return null;
     }
-    
-    ///////////////////////////////////////////////////////////////////
-    // run _moduleTlsCtor in the context of the given thread
-    void thread_moduleTlsCtor( uint id )
-    {
-	thread_helper_aux.impersonate_thread(id, &_moduleTlsCtor);
-    }
-
-    ///////////////////////////////////////////////////////////////////
-    // run _moduleTlsDtor in the context of the given thread
-    void thread_moduleTlsDtor( uint id )
-    {
-	thread_helper_aux.impersonate_thread(id, &_moduleTlsDtor);
-    }
 }
 
Index: src/object_.d
===================================================================
--- src/object_.d	(revision 282)
+++ src/object_.d	(working copy)
@@ -1578,336 +1578,8 @@
     }
 }
 
+extern extern (C) __gshared ModuleInfo*[] _moduleinfo_array;
 
-// Windows: this gets initialized by minit.asm
-// Posix: this gets initialized in _moduleCtor()
-extern (C) __gshared ModuleInfo*[] _moduleinfo_array;
-
-
-version (linux)
-{
-    // This linked list is created by a compiler generated function inserted
-    // into the .ctor list by the compiler.
-    struct ModuleReference
-    {
-        ModuleReference* next;
-        ModuleInfo*      mod;
-    }
-
-    extern (C) __gshared ModuleReference* _Dmodule_ref;   // start of linked list
-}
-
-version (FreeBSD)
-{
-    // This linked list is created by a compiler generated function inserted
-    // into the .ctor list by the compiler.
-    struct ModuleReference
-    {
-        ModuleReference* next;
-        ModuleInfo*      mod;
-    }
-
-    extern (C) __gshared ModuleReference* _Dmodule_ref;   // start of linked list
-}
-
-version (Solaris)
-{
-    // This linked list is created by a compiler generated function inserted
-    // into the .ctor list by the compiler.
-    struct ModuleReference
-    {
-        ModuleReference* next;
-        ModuleInfo*      mod;
-    }
-
-    extern (C) __gshared ModuleReference* _Dmodule_ref;   // start of linked list
-}
-
-version (OSX)
-{
-    extern (C)
-    {
-        extern __gshared void* _minfo_beg;
-        extern __gshared void* _minfo_end;
-    }
-}
-
-__gshared ModuleInfo*[] _moduleinfo_dtors;
-__gshared uint          _moduleinfo_dtors_i;
-
-ModuleInfo*[] _moduleinfo_tlsdtors;
-uint          _moduleinfo_tlsdtors_i;
-
-// Register termination function pointers
-extern (C) int _fatexit(void*);
-
-/**
- * Initialize the modules.
- */
-
-extern (C) void _moduleCtor()
-{
-    debug(PRINTF) printf("_moduleCtor()\n");
-    version (linux)
-    {
-        int len = 0;
-        ModuleReference *mr;
-
-        for (mr = _Dmodule_ref; mr; mr = mr.next)
-            len++;
-        _moduleinfo_array = new ModuleInfo*[len];
-        len = 0;
-        for (mr = _Dmodule_ref; mr; mr = mr.next)
-        {   _moduleinfo_array[len] = mr.mod;
-            len++;
-        }
-    }
-
-    version (FreeBSD)
-    {
-        int len = 0;
-        ModuleReference *mr;
-
-        for (mr = _Dmodule_ref; mr; mr = mr.next)
-            len++;
-        _moduleinfo_array = new ModuleInfo*[len];
-        len = 0;
-        for (mr = _Dmodule_ref; mr; mr = mr.next)
-        {   _moduleinfo_array[len] = mr.mod;
-            len++;
-        }
-    }
-
-    version (Solaris)
-    {
-        int len = 0;
-        ModuleReference *mr;
-
-        for (mr = _Dmodule_ref; mr; mr = mr.next)
-            len++;
-        _moduleinfo_array = new ModuleInfo*[len];
-        len = 0;
-        for (mr = _Dmodule_ref; mr; mr = mr.next)
-        {   _moduleinfo_array[len] = mr.mod;
-            len++;
-        }
-    }
-
-    version (OSX)
-    {
-        /* The ModuleInfo references are stored in the special segment
-         * __minfodata, which is bracketed by the segments __minfo_beg
-         * and __minfo_end. The variables _minfo_beg and _minfo_end
-         * are of zero size and are in the two bracketing segments,
-         * respectively.
-         */
-         size_t length = cast(ModuleInfo**)&_minfo_end - cast(ModuleInfo**)&_minfo_beg;
-         _moduleinfo_array = (cast(ModuleInfo**)&_minfo_beg)[0 .. length];
-         debug printf("moduleinfo: ptr = %p, length = %d\n", _moduleinfo_array.ptr, _moduleinfo_array.length);
-
-         debug foreach (m; _moduleinfo_array)
-         {
-             //printf("\t%p\n", m);
-             printf("\t%.*s\n", m.name);
-         }
-    }    
-
-    version (Windows)
-    {
-        // Ensure module destructors also get called on program termination
-        //_fatexit(&_STD_moduleDtor);
-    }
-
-    _moduleinfo_dtors = new ModuleInfo*[_moduleinfo_array.length];
-    debug(PRINTF) printf("_moduleinfo_dtors = x%x\n", cast(void*)_moduleinfo_dtors);
-    _moduleIndependentCtors();
-    _moduleCtor2(_moduleinfo_array, 0);
-    _moduleTlsCtor();
-}
-
-extern (C) void _moduleIndependentCtors()
-{
-    debug(PRINTF) printf("_moduleIndependentCtors()\n");
-    foreach (m; _moduleinfo_array)
-    {
-        if (m && m.ictor)
-        {
-            (*m.ictor)();
-        }
-    }
-}
-
-/********************************************
- * Run static constructors for shared global data.
- */
-void _moduleCtor2(ModuleInfo*[] mi, int skip)
-{
-    debug(PRINTF) printf("_moduleCtor2(): %d modules\n", mi.length);
-    for (uint i = 0; i < mi.length; i++)
-    {
-        ModuleInfo* m = mi[i];
-
-        debug(PRINTF) printf("\tmodule[%d] = %p\n", i, m);
-        if (!m)
-            continue;
-        debug(PRINTF) printf("\tmodule[%d] = '%.*s'\n", i, m.name);
-        if (m.flags & MIctordone)
-            continue;
-        debug(PRINTF) printf("\tmodule[%d] = '%.*s', m = x%x\n", i, m.name, m);
-
-        if (m.ctor || m.dtor)
-        {
-            if (m.flags & MIctorstart)
-            {   if (skip || m.flags & MIstandalone)
-                    continue;
-		throw new Exception("Cyclic dependency in module " ~ m.name);
-            }
-
-            m.flags = m.flags | MIctorstart;
-            _moduleCtor2(m.importedModules, 0);
-            if (m.ctor)
-                (*m.ctor)();
-            m.flags = (m.flags & ~MIctorstart) | MIctordone;
-
-            // Now that construction is done, register the destructor
-            //printf("\tadding module dtor x%x\n", m);
-            assert(_moduleinfo_dtors_i < _moduleinfo_dtors.length);
-            _moduleinfo_dtors[_moduleinfo_dtors_i++] = m;
-        }
-        else
-        {
-            m.flags = m.flags | MIctordone;
-            _moduleCtor2(m.importedModules, 1);
-        }
-    }
-}
-
-/********************************************
- * Run static constructors for thread local global data.
- */
-
-extern (C) void _moduleTlsCtor()
-{
-    debug(PRINTF) printf("_moduleTlsCtor()\n");
-
-    void* p = alloca(_moduleinfo_array.length * ubyte.sizeof);
-    auto flags = cast(ubyte[])p[0 .. _moduleinfo_array.length];
-    flags[] = 0;
-
-    foreach (i, m; _moduleinfo_array)
-    {
-	if (m)
-	    m.index = i;
-    }
-
-    _moduleinfo_tlsdtors = new ModuleInfo*[_moduleinfo_array.length];
-
-    void _moduleTlsCtor2(ModuleInfo*[] mi, int skip)
-    {
-	debug(PRINTF) printf("_moduleTlsCtor2(skip = %d): %d modules\n", skip, mi.length);
-	foreach (i, m; mi)
-	{
-	    debug(PRINTF) printf("\tmodule[%d] = '%p'\n", i, m);
-	    if (!m)
-		continue;
-	    debug(PRINTF) printf("\tmodule[%d] = '%.*s'\n", i, m.name);
-	    if (flags[m.index] & MIctordone)
-		continue;
-	    debug(PRINTF) printf("\tmodule[%d] = '%.*s', m = x%x\n", i, m.name, m);
-
-	    if (m.tlsctor || m.tlsdtor)
-	    {
-		if (flags[m.index] & MIctorstart)
-		{   if (skip || m.flags & MIstandalone)
-			continue;
-		    throw new Exception("Cyclic dependency in module " ~ m.name);
-		}
-
-		flags[m.index] |= MIctorstart;
-		_moduleTlsCtor2(m.importedModules, 0);
-		if (m.tlsctor)
-		    (*m.tlsctor)();
-		flags[m.index] &= ~MIctorstart;
-		flags[m.index] |= MIctordone;
-
-		// Now that construction is done, register the destructor
-		//printf("**** adding module tlsdtor %p, [%d]\n", m, _moduleinfo_tlsdtors_i);
-		assert(_moduleinfo_tlsdtors_i < _moduleinfo_tlsdtors.length);
-		_moduleinfo_tlsdtors[_moduleinfo_tlsdtors_i++] = m;
-	    }
-	    else
-	    {
-		flags[m.index] |= MIctordone;
-		_moduleTlsCtor2(m.importedModules, 1);
-	    }
-	}
-    }
-
-    _moduleTlsCtor2(_moduleinfo_array, 0);
-}
-
-
-/**
- * Destruct the modules.
- */
-
-// Starting the name with "_STD" means under Posix a pointer to the
-// function gets put in the .dtors segment.
-
-extern (C) void _moduleDtor()
-{
-    debug(PRINTF) printf("_moduleDtor(): %d modules\n", _moduleinfo_dtors_i);
-
-    _moduleTlsDtor();
-    for (uint i = _moduleinfo_dtors_i; i-- != 0;)
-    {
-        ModuleInfo* m = _moduleinfo_dtors[i];
-
-        debug(PRINTF) printf("\tmodule[%d] = '%.*s', x%x\n", i, m.name, m);
-        if (m.dtor)
-        {
-            (*m.dtor)();
-        }
-    }
-    debug(PRINTF) printf("_moduleDtor() done\n");
-}
-
-extern (C) void _moduleTlsDtor()
-{
-    debug(PRINTF) printf("_moduleTlsDtor(): %d modules\n", _moduleinfo_tlsdtors_i);
-    version(none)
-    {
-        printf("_moduleinfo_tlsdtors = %d,%p\n", _moduleinfo_tlsdtors);
-        foreach (i,m; _moduleinfo_tlsdtors[0..11])
-            printf("[%d] = %p\n", i, m);
-    }
-
-    for (uint i = _moduleinfo_tlsdtors_i; i-- != 0;)
-    {
-        ModuleInfo* m = _moduleinfo_tlsdtors[i];
-
-        debug(PRINTF) printf("\tmodule[%d] = '%.*s', x%x\n", i, m.name, m);
-        if (m.tlsdtor)
-        {
-            (*m.tlsdtor)();
-        }
-    }
-    debug(PRINTF) printf("_moduleTlsDtor() done\n");
-}
-
-// Alias the TLS ctor and dtor using "rt_" prefixes, since these routines
-// must be called by core.thread.
-
-extern (C) void rt_moduleTlsCtor()
-{
-    _moduleTlsCtor();
-}
-
-extern (C) void rt_moduleTlsDtor()
-{
-    _moduleTlsDtor();
-}
-
 ///////////////////////////////////////////////////////////////////////////////
 // Monitor
 ///////////////////////////////////////////////////////////////////////////////
Index: src/rt/cmain.d
===================================================================
--- src/rt/cmain.d	(revision 0)
+++ src/rt/cmain.d	(revision 0)
@@ -0,0 +1,210 @@
+module rt.cmain;
+
+private
+{
+    import rt.dmain2;
+    import rt.memory;
+    import rt.util.console;
+    import core.stdc.stddef;
+    import core.stdc.stdlib;
+    import core.stdc.string;
+    //import core.stdc.stdio;	// for printf()
+}
+
+version (Windows)
+{
+    private import core.stdc.wchar_;
+    private import core.sys.windows.windows;
+    private import core.dll_helper;
+
+    extern (Windows) alias int function() FARPROC;
+    extern (Windows) FARPROC    GetProcAddress(void*, in char*);
+    extern (Windows) void*      LoadLibraryA(in char*);
+    extern (Windows) int        FreeLibrary(void*);
+    extern (Windows) HMODULE    GetModuleHandleA(void*);
+    extern (Windows) void*      LocalFree(void*);
+    extern (Windows) wchar_t*   GetCommandLineW();
+    extern (Windows) wchar_t**  CommandLineToArgvW(wchar_t*, int*);
+    extern (Windows) export int WideCharToMultiByte(uint, uint, wchar_t*, int, char*, int, char*, int);
+    pragma(lib, "shell32.lib"); // needed for CommandLineToArgvW
+}
+
+extern (C) void _STI_monitor_staticctor();
+extern (C) void _STD_monitor_staticdtor();
+extern (C) void _STI_critical_init();
+extern (C) void _STD_critical_term();
+extern (C) void gc_init();
+extern (C) void gc_term();
+extern (C) void _minit();
+extern (C) void _moduleCtor();
+extern (C) void _moduleDtor();
+extern (C) void thread_joinAll();
+
+
+/***********************************
+ * The D main() function supplied by the user's program
+ */
+int main(char[][] args);
+
+/***********************************
+ * Substitutes for the C main() function.
+ * It's purpose is to wrap the call to the D main()
+ * function and catch any unhandled exceptions.
+ */
+
+extern (C) int main(int argc, char **argv)
+{
+    char[][] args;
+    int result;
+
+    version (OSX)
+    {   /* OSX does not provide a way to get at the top of the
+         * stack, except for the magic value 0xC0000000.
+         * But as far as the gc is concerned, argv is at the top
+         * of the main thread's stack, so save the address of that.
+         */
+        __osx_stack_end = cast(void*)&argv;
+    }
+
+    version (Posix)
+    {
+        _STI_monitor_staticctor();
+        _STI_critical_init();
+    }
+
+    version (Windows)
+    {
+	version(sharedlib)
+	    shared_dll_patchImportRelocations(GetModuleHandleA(null));
+
+        wchar_t*  wcbuf = GetCommandLineW();
+        size_t    wclen = wcslen(wcbuf);
+        int       wargc = 0;
+        wchar_t** wargs = CommandLineToArgvW(wcbuf, &wargc);
+        assert(wargc == argc);
+
+        char*     cargp = null;
+        size_t    cargl = WideCharToMultiByte(65001, 0, wcbuf, wclen, null, 0, null, 0);
+
+        cargp = cast(char*) alloca(cargl);
+        args  = ((cast(char[]*) alloca(wargc * (char[]).sizeof)))[0 .. wargc];
+
+        for (size_t i = 0, p = 0; i < wargc; i++)
+        {
+            int wlen = wcslen(wargs[i]);
+            int clen = WideCharToMultiByte(65001, 0, &wargs[i][0], wlen, null, 0, null, 0);
+            args[i]  = cargp[p .. p+clen];
+            p += clen; assert(p <= cargl);
+            WideCharToMultiByte(65001, 0, &wargs[i][0], wlen, &args[i][0], clen, null, 0);
+        }
+        LocalFree(wargs);
+        wargs = null;
+        wargc = 0;
+    }
+    else version (Posix)
+    {
+        char[]* am = cast(char[]*) malloc(argc * (char[]).sizeof);
+        scope(exit) free(am);
+
+        for (size_t i = 0; i < argc; i++)
+        {
+            auto len = strlen(argv[i]);
+            am[i] = argv[i][0 .. len];
+        }
+        args = am[0 .. argc];
+    }
+
+    bool trapExceptions = rt_trapExceptions;
+
+    void tryExec(scope void delegate() dg)
+    {
+
+        if (trapExceptions)
+        {
+            try
+            {
+                dg();
+            }
+            catch (Throwable e)
+            {
+                while (e)
+                {
+                    if (e.file)
+                    {
+                        // fprintf(stderr, "%.*s(%u): %.*s\n", e.file, e.line, e.msg);
+                        console (e.classinfo.name)("@")(e.file)("(")(e.line)("): ")(e.msg)("\n");
+                    }
+                    else
+                    {
+                        // fprintf(stderr, "%.*s\n", e.toString());
+                        console (e.toString)("\n");
+                    }
+                    if (e.info)
+                    {
+                        console ("----------------\n");
+                        foreach (t; e.info)
+                            console (t)("\n");
+                    }
+                    if (e.next)
+                        console ("\n");
+                    e = e.next;
+                }
+                result = EXIT_FAILURE;
+            }
+            catch (Object o)
+            {
+                // fprintf(stderr, "%.*s\n", o.toString());
+                console (o.toString)("\n");
+                result = EXIT_FAILURE;
+            }
+        }
+        else
+        {
+            dg();
+        }
+    }
+
+    // NOTE: The lifetime of a process is much like the lifetime of an object:
+    //       it is initialized, then used, then destroyed.  If initialization
+    //       fails, the successive two steps are never reached.  However, if
+    //       initialization succeeds, then cleanup will occur even if the use
+    //       step fails in some way.  Here, the use phase consists of running
+    //       the user's main function.  If main terminates with an exception,
+    //       the exception is handled and then cleanup begins.  An exception
+    //       thrown during cleanup, however, will abort the cleanup process.
+
+    void runMain()
+    {
+        result = main(args);
+    }
+
+    void runAll()
+    {
+	version(sharedlib)
+		shared_dll_add_tlsdata();
+	else
+		gc_init();
+        initStaticDataGC();
+        version (Windows)
+            _minit();
+        _moduleCtor();
+        if (runModuleUnitTests())
+            tryExec(&runMain);
+        thread_joinAll();
+        _d_isHalting = true;
+        _moduleDtor();
+	version(sharedlib)
+		shared_dll_remove_tlsdata();
+	else
+		gc_term();
+    }
+
+    tryExec(&runAll);
+
+    version (Posix)
+    {
+        _STD_critical_term();
+        _STD_monitor_staticdtor();
+    }
+    return result;
+}
Index: src/rt/dmain2.d
===================================================================
--- src/rt/dmain2.d	(revision 282)
+++ src/rt/dmain2.d	(working copy)
@@ -248,161 +248,3 @@
     return false;
 }
 
-/***********************************
- * The D main() function supplied by the user's program
- */
-int main(char[][] args);
-
-/***********************************
- * Substitutes for the C main() function.
- * It's purpose is to wrap the call to the D main()
- * function and catch any unhandled exceptions.
- */
-
-extern (C) int main(int argc, char **argv)
-{
-    char[][] args;
-    int result;
-
-    version (OSX)
-    {   /* OSX does not provide a way to get at the top of the
-         * stack, except for the magic value 0xC0000000.
-         * But as far as the gc is concerned, argv is at the top
-         * of the main thread's stack, so save the address of that.
-         */
-        __osx_stack_end = cast(void*)&argv;
-    }
-
-    version (Posix)
-    {
-        _STI_monitor_staticctor();
-        _STI_critical_init();
-    }
-
-    version (Windows)
-    {
-        wchar_t*  wcbuf = GetCommandLineW();
-        size_t    wclen = wcslen(wcbuf);
-        int       wargc = 0;
-        wchar_t** wargs = CommandLineToArgvW(wcbuf, &wargc);
-        assert(wargc == argc);
-
-        char*     cargp = null;
-        size_t    cargl = WideCharToMultiByte(65001, 0, wcbuf, wclen, null, 0, null, 0);
-
-        cargp = cast(char*) alloca(cargl);
-        args  = ((cast(char[]*) alloca(wargc * (char[]).sizeof)))[0 .. wargc];
-
-        for (size_t i = 0, p = 0; i < wargc; i++)
-        {
-            int wlen = wcslen(wargs[i]);
-            int clen = WideCharToMultiByte(65001, 0, &wargs[i][0], wlen, null, 0, null, 0);
-            args[i]  = cargp[p .. p+clen];
-            p += clen; assert(p <= cargl);
-            WideCharToMultiByte(65001, 0, &wargs[i][0], wlen, &args[i][0], clen, null, 0);
-        }
-        LocalFree(wargs);
-        wargs = null;
-        wargc = 0;
-    }
-    else version (Posix)
-    {
-        char[]* am = cast(char[]*) malloc(argc * (char[]).sizeof);
-        scope(exit) free(am);
-
-        for (size_t i = 0; i < argc; i++)
-        {
-            auto len = strlen(argv[i]);
-            am[i] = argv[i][0 .. len];
-        }
-        args = am[0 .. argc];
-    }
-
-    bool trapExceptions = rt_trapExceptions;
-
-    void tryExec(scope void delegate() dg)
-    {
-
-        if (trapExceptions)
-        {
-            try
-            {
-                dg();
-            }
-            catch (Throwable e)
-            {
-                while (e)
-                {
-                    if (e.file)
-                    {
-                        // fprintf(stderr, "%.*s(%u): %.*s\n", e.file, e.line, e.msg);
-                        console (e.classinfo.name)("@")(e.file)("(")(e.line)("): ")(e.msg)("\n");
-                    }
-                    else
-                    {
-                        // fprintf(stderr, "%.*s\n", e.toString());
-                        console (e.toString)("\n");
-                    }
-                    if (e.info)
-                    {
-                        console ("----------------\n");
-                        foreach (t; e.info)
-                            console (t)("\n");
-                    }
-                    if (e.next)
-                        console ("\n");
-                    e = e.next;
-                }
-                result = EXIT_FAILURE;
-            }
-            catch (Object o)
-            {
-                // fprintf(stderr, "%.*s\n", o.toString());
-                console (o.toString)("\n");
-                result = EXIT_FAILURE;
-            }
-        }
-        else
-        {
-            dg();
-        }
-    }
-
-    // NOTE: The lifetime of a process is much like the lifetime of an object:
-    //       it is initialized, then used, then destroyed.  If initialization
-    //       fails, the successive two steps are never reached.  However, if
-    //       initialization succeeds, then cleanup will occur even if the use
-    //       step fails in some way.  Here, the use phase consists of running
-    //       the user's main function.  If main terminates with an exception,
-    //       the exception is handled and then cleanup begins.  An exception
-    //       thrown during cleanup, however, will abort the cleanup process.
-
-    void runMain()
-    {
-        result = main(args);
-    }
-
-    void runAll()
-    {
-        gc_init();
-        initStaticDataGC();
-        version (Windows)
-            _minit();
-        _moduleCtor();
-        if (runModuleUnitTests())
-            tryExec(&runMain);
-        thread_joinAll();
-        _d_isHalting = true;
-        _moduleDtor();
-        gc_term();
-    }
-
-    tryExec(&runAll);
-
-    version (Posix)
-    {
-        _STD_critical_term();
-        _STD_monitor_staticdtor();
-    }
-    return result;
-}
Index: src/rt/llmath.d
===================================================================
--- src/rt/llmath.d	(revision 282)
+++ src/rt/llmath.d	(working copy)
@@ -461,6 +461,7 @@
 
 // Convert real in ST0 to ulong
 
+version(Windows) { /* already in snn.lib */ } else {
 ulong __LDBLULLNG()
 {
     version (OSX)
@@ -528,5 +529,5 @@
         }
     }
 }
+}
 
-
Index: src/rt/moduleinit.d
===================================================================
--- src/rt/moduleinit.d	(revision 0)
+++ src/rt/moduleinit.d	(revision 0)
@@ -0,0 +1,344 @@
+module rt.moduleinit;
+
+import core.stdc.stdlib : alloca;
+
+// Windows: this gets initialized by minit.asm
+// Posix: this gets initialized in _moduleCtor()
+extern (C) __gshared ModuleInfo*[] _moduleinfo_array;
+
+version (linux)
+{
+    // This linked list is created by a compiler generated function inserted
+    // into the .ctor list by the compiler.
+    struct ModuleReference
+    {
+        ModuleReference* next;
+        ModuleInfo*      mod;
+    }
+
+    extern (C) __gshared ModuleReference* _Dmodule_ref;   // start of linked list
+}
+
+version (FreeBSD)
+{
+    // This linked list is created by a compiler generated function inserted
+    // into the .ctor list by the compiler.
+    struct ModuleReference
+    {
+        ModuleReference* next;
+        ModuleInfo*      mod;
+    }
+
+    extern (C) __gshared ModuleReference* _Dmodule_ref;   // start of linked list
+}
+
+version (Solaris)
+{
+    // This linked list is created by a compiler generated function inserted
+    // into the .ctor list by the compiler.
+    struct ModuleReference
+    {
+        ModuleReference* next;
+        ModuleInfo*      mod;
+    }
+
+    extern (C) __gshared ModuleReference* _Dmodule_ref;   // start of linked list
+}
+
+version (OSX)
+{
+    extern (C)
+    {
+        extern __gshared void* _minfo_beg;
+        extern __gshared void* _minfo_end;
+    }
+}
+
+__gshared ModuleInfo*[] _moduleinfo_dtors;
+__gshared uint          _moduleinfo_dtors_i;
+
+ModuleInfo*[] _moduleinfo_tlsdtors;
+uint          _moduleinfo_tlsdtors_i;
+
+// Register termination function pointers
+extern (C) int _fatexit(void*);
+
+/**
+ * Initialize the modules.
+ */
+
+extern (C) void _moduleCtor()
+{
+    debug(PRINTF) printf("_moduleCtor()\n");
+    version (linux)
+    {
+        int len = 0;
+        ModuleReference *mr;
+
+        for (mr = _Dmodule_ref; mr; mr = mr.next)
+            len++;
+        _moduleinfo_array = new ModuleInfo*[len];
+        len = 0;
+        for (mr = _Dmodule_ref; mr; mr = mr.next)
+        {   _moduleinfo_array[len] = mr.mod;
+            len++;
+        }
+    }
+
+    version (FreeBSD)
+    {
+        int len = 0;
+        ModuleReference *mr;
+
+        for (mr = _Dmodule_ref; mr; mr = mr.next)
+            len++;
+        _moduleinfo_array = new ModuleInfo*[len];
+        len = 0;
+        for (mr = _Dmodule_ref; mr; mr = mr.next)
+        {   _moduleinfo_array[len] = mr.mod;
+            len++;
+        }
+    }
+
+    version (Solaris)
+    {
+        int len = 0;
+        ModuleReference *mr;
+
+        for (mr = _Dmodule_ref; mr; mr = mr.next)
+            len++;
+        _moduleinfo_array = new ModuleInfo*[len];
+        len = 0;
+        for (mr = _Dmodule_ref; mr; mr = mr.next)
+        {   _moduleinfo_array[len] = mr.mod;
+            len++;
+        }
+    }
+
+    version (OSX)
+    {
+        /* The ModuleInfo references are stored in the special segment
+         * __minfodata, which is bracketed by the segments __minfo_beg
+         * and __minfo_end. The variables _minfo_beg and _minfo_end
+         * are of zero size and are in the two bracketing segments,
+         * respectively.
+         */
+         size_t length = cast(ModuleInfo**)&_minfo_end - cast(ModuleInfo**)&_minfo_beg;
+         _moduleinfo_array = (cast(ModuleInfo**)&_minfo_beg)[0 .. length];
+         debug printf("moduleinfo: ptr = %p, length = %d\n", _moduleinfo_array.ptr, _moduleinfo_array.length);
+
+         debug foreach (m; _moduleinfo_array)
+         {
+             //printf("\t%p\n", m);
+             printf("\t%.*s\n", m.name);
+         }
+    }    
+
+    version (Windows)
+    {
+        // Ensure module destructors also get called on program termination
+        //_fatexit(&_STD_moduleDtor);
+    }
+
+    _moduleinfo_dtors = new ModuleInfo*[_moduleinfo_array.length];
+    debug(PRINTF) printf("_moduleinfo_dtors = x%x\n", cast(void*)_moduleinfo_dtors);
+    _moduleIndependentCtors();
+    _moduleCtor2(_moduleinfo_array, 0);
+    _moduleTlsCtor();
+}
+
+extern (C) void _moduleIndependentCtors()
+{
+    debug(PRINTF) printf("_moduleIndependentCtors()\n");
+    foreach (m; _moduleinfo_array)
+    {
+        if (m && m.ictor)
+        {
+            (*m.ictor)();
+        }
+    }
+}
+
+private bool _isExternalModule(ModuleInfo* mi)
+{
+    foreach (m; _moduleinfo_array)
+	if (m is mi)
+	    return false;
+    return true;
+}
+
+/********************************************
+ * Run static constructors for shared global data.
+ */
+void _moduleCtor2(ModuleInfo*[] mi, int skip)
+{
+    debug(PRINTF) printf("_moduleCtor2(): %d modules\n", mi.length);
+    for (uint i = 0; i < mi.length; i++)
+    {
+        ModuleInfo* m = mi[i];
+
+        debug(PRINTF) printf("\tmodule[%d] = %p\n", i, m);
+        if (!m)
+            continue;
+        debug(PRINTF) printf("\tmodule[%d] = '%.*s'\n", i, m.name);
+	if (_isExternalModule(m))
+	    continue;
+        if (m.flags & MIctordone)
+            continue;
+        debug(PRINTF) printf("\tmodule[%d] = '%.*s', m = x%x\n", i, m.name, m);
+
+        if (m.ctor || m.dtor)
+        {
+            if (m.flags & MIctorstart)
+            {   if (skip || m.flags & MIstandalone)
+                    continue;
+		throw new Exception("Cyclic dependency in module " ~ m.name);
+            }
+
+            m.flags = m.flags | MIctorstart;
+            _moduleCtor2(m.importedModules, 0);
+            if (m.ctor)
+                (*m.ctor)();
+            m.flags = (m.flags & ~MIctorstart) | MIctordone;
+
+            // Now that construction is done, register the destructor
+            //printf("\tadding module dtor x%x\n", m);
+            assert(_moduleinfo_dtors_i < _moduleinfo_dtors.length);
+            _moduleinfo_dtors[_moduleinfo_dtors_i++] = m;
+        }
+        else
+        {
+            m.flags = m.flags | MIctordone;
+            _moduleCtor2(m.importedModules, 1);
+        }
+    }
+}
+
+/********************************************
+ * Run static constructors for thread local global data.
+ */
+
+extern (C) void _moduleTlsCtor()
+{
+    debug(PRINTF) printf("_moduleTlsCtor()\n");
+
+    void* p = alloca(_moduleinfo_array.length * ubyte.sizeof);
+    auto flags = cast(ubyte[])p[0 .. _moduleinfo_array.length];
+    flags[] = 0;
+
+    foreach (i, m; _moduleinfo_array)
+    {
+	if (m)
+	    m.index = i;
+    }
+
+    _moduleinfo_tlsdtors = new ModuleInfo*[_moduleinfo_array.length];
+
+    void _moduleTlsCtor2(ModuleInfo*[] mi, int skip)
+    {
+	debug(PRINTF) printf("_moduleTlsCtor2(skip = %d): %d modules\n", skip, mi.length);
+	foreach (i, m; mi)
+	{
+	    debug(PRINTF) printf("\tmodule[%d] = '%p'\n", i, m);
+	    if (!m)
+		continue;
+	    debug(PRINTF) printf("\tmodule[%d] = '%.*s'\n", i, m.name);
+	    if (_isExternalModule(m))
+		continue;
+	    if (flags[m.index] & MIctordone)
+		continue;
+	    debug(PRINTF) printf("\tmodule[%d] = '%.*s', m = x%x\n", i, m.name, m);
+
+	    if (m.tlsctor || m.tlsdtor)
+	    {
+		if (flags[m.index] & MIctorstart)
+		{   if (skip || m.flags & MIstandalone)
+			continue;
+		    throw new Exception("Cyclic dependency in module " ~ m.name);
+		}
+
+		flags[m.index] |= MIctorstart;
+		_moduleTlsCtor2(m.importedModules, 0);
+		if (m.tlsctor)
+		    (*m.tlsctor)();
+		flags[m.index] &= ~MIctorstart;
+		flags[m.index] |= MIctordone;
+
+		// Now that construction is done, register the destructor
+		//printf("**** adding module tlsdtor %p, [%d]\n", m, _moduleinfo_tlsdtors_i);
+		assert(_moduleinfo_tlsdtors_i < _moduleinfo_tlsdtors.length);
+		_moduleinfo_tlsdtors[_moduleinfo_tlsdtors_i++] = m;
+	    }
+	    else
+	    {
+		flags[m.index] |= MIctordone;
+		_moduleTlsCtor2(m.importedModules, 1);
+	    }
+	}
+    }
+
+    _moduleTlsCtor2(_moduleinfo_array, 0);
+}
+
+
+/**
+ * Destruct the modules.
+ */
+
+// Starting the name with "_STD" means under Posix a pointer to the
+// function gets put in the .dtors segment.
+
+extern (C) void _moduleDtor()
+{
+    debug(PRINTF) printf("_moduleDtor(): %d modules\n", _moduleinfo_dtors_i);
+
+    _moduleTlsDtor();
+    for (uint i = _moduleinfo_dtors_i; i-- != 0;)
+    {
+        ModuleInfo* m = _moduleinfo_dtors[i];
+
+        debug(PRINTF) printf("\tmodule[%d] = '%.*s', x%x\n", i, m.name, m);
+        if (m.dtor)
+        {
+            (*m.dtor)();
+        }
+    }
+    debug(PRINTF) printf("_moduleDtor() done\n");
+}
+
+extern (C) void _moduleTlsDtor()
+{
+    debug(PRINTF) printf("_moduleTlsDtor(): %d modules\n", _moduleinfo_tlsdtors_i);
+    version(none)
+    {
+        printf("_moduleinfo_tlsdtors = %d,%p\n", _moduleinfo_tlsdtors);
+        foreach (i,m; _moduleinfo_tlsdtors[0..11])
+            printf("[%d] = %p\n", i, m);
+    }
+
+    for (uint i = _moduleinfo_tlsdtors_i; i-- != 0;)
+    {
+        ModuleInfo* m = _moduleinfo_tlsdtors[i];
+
+        debug(PRINTF) printf("\tmodule[%d] = '%.*s', x%x\n", i, m.name, m);
+        if (m.tlsdtor)
+        {
+            (*m.tlsdtor)();
+        }
+    }
+    debug(PRINTF) printf("_moduleTlsDtor() done\n");
+}
+
+// Alias the TLS ctor and dtor using "rt_" prefixes, since these routines
+// must be called by core.thread.
+
+extern (C) void rt_moduleTlsCtor()
+{
+    _moduleTlsCtor();
+}
+
+extern (C) void rt_moduleTlsDtor()
+{
+    _moduleTlsDtor();
+}
+
Index: win32.mak
===================================================================
--- win32.mak	(revision 282)
+++ win32.mak	(working copy)
@@ -1,8 +1,7 @@
 
 DMD=dmd
+LIB=lib
 
-CC=dmc
-
 DOCDIR=doc
 IMPDIR=import
 
@@ -14,8 +13,6 @@
 DRUNTIME=lib\druntime.lib
 GCSTUB=lib\gcstub.obj
 
-target : $(DOCS) $(IMPORTS) $(DRUNTIME) $(GCSTUB)
-
 MANIFEST= \
 	LICENSE_1_0.txt \
 	README.txt \
@@ -97,6 +94,7 @@
 	src/core/sync/semaphore.d \
 	src/core/thread.d \
 	src/core/thread_helper.d \
+	src/core/shared_dll_helper.d \
 	src/core/dll_helper.d \
 	src/core/threadasm.S \
 	src/core/vararg.d \
@@ -124,6 +122,7 @@
 	src/rt/deh.c \
 	src/rt/deh2.d \
 	src/rt/dmain2.d \
+	src/rt/cmain.d \
 	src/rt/invariant.d \
 	src/rt/invariant_.d \
 	src/rt/lifetime.d \
@@ -132,6 +131,7 @@
 	src/rt/memory.d \
 	src/rt/memory_osx.c \
 	src/rt/memset.d \
+	src/rt/moduleinit.d \
 	src/rt/minit.asm \
 	src/rt/monitor.c \
 	src/rt/obj.d \
@@ -187,7 +187,7 @@
 	src/gc/gcx.d \
 	src/gcstub/gc.d
 
-SRCS= \
+SRCS_SHARED= \
 	src\core\bitop.d \
 	src\core\cpuid.d \
 	src\core\exception.d \
@@ -195,7 +195,7 @@
 	src\core\runtime.d \
 	src\core\thread.d \
 	src\core\thread_helper.d \
-	src\core\dll_helper.d \
+	src\core\shared_dll_helper.d \
 	src\core\vararg.d \
 	\
 	src\core\sync\barrier.d \
@@ -234,12 +234,10 @@
 	src\rt\invariant_.d \
 	src\rt\lifetime.d \
 	src\rt\llmath.d \
-	src\rt\memory.d \
 	src\rt\memset.d \
 	src\rt\obj.d \
 	src\rt\qsort.d \
 	src\rt\switch_.d \
-	src\rt\trace.d \
 	\
 	src\rt\util\console.d \
 	src\rt\util\ctype.d \
@@ -300,6 +298,34 @@
 	\
 	$(IMPDIR)\core\sys\windows\windows.d
 
+# modules used by the static library
+SRCS_STATIC = \
+	src\core\dll_helper.d \
+	src\rt\trace.d \
+	src\rt\memory.d \
+	src\rt\cmain.d \
+	src\rt\moduleinit.d
+
+# modules used to build the shared library
+SRCS_DYNAMIC = \
+	src\rt\memory.d \
+	src\rt\moduleinit.d
+
+# modules needed to link against the shared library
+SRCS_SHAREDRTL = \
+	src\core\dll_helper.d \
+	src\rt\memory.d \
+	src\rt\cmain.d \
+	src\rt\moduleinit.d
+
+SRCS = $(SRCS_SHARED) $(SRCS_STATIC)
+
+OBJS_SHAREDRTL = \
+	lib\dll_helper.obj \
+	lib\memory.obj \
+	lib\cmain.obj \
+	lib\moduleinit.obj
+
 # NOTE: trace.d and cover.d are not necessary for a successful build
 #       as both are used for debugging features (profiling and coverage)
 # NOTE: a pre-compiled minit.obj has been provided in dmd for Win32 and
@@ -333,6 +359,7 @@
 	$(IMPDIR)\core\runtime.di \
 	$(IMPDIR)\core\thread.di \
 	$(IMPDIR)\core\thread_helper.di \
+	$(IMPDIR)\core\shared_dll_helper.di \
 	$(IMPDIR)\core\dll_helper.di \
 	$(IMPDIR)\core\vararg.di \
 	\
@@ -344,6 +371,8 @@
 	$(IMPDIR)\core\sync\barrier.di \
 	$(IMPDIR)\core\sync\rwmutex.di
 
+target : $(DOCS) $(IMPORTS) $(DRUNTIME) $(GCSTUB)
+
 ######################## Doc .html file generation ##############################
 
 doc: $(DOCS)
@@ -421,6 +450,9 @@
 $(IMPDIR)\core\dll_helper.di : src\core\dll_helper.d
 	$(DMD) -c -d -o- -Iimport -Isrc -Hf$@ $**
 
+$(IMPDIR)\core\shared_dll_helper.di : src\core\shared_dll_helper.d
+	$(DMD) -c -d -o- -Iimport -Isrc -Hf$@ $**
+
 $(IMPDIR)\core\vararg.di : src\core\vararg.d
 	$(DMD) -c -d -o- -Iimport -Isrc -Hf$@ $**
 
@@ -475,6 +507,25 @@
 $(DRUNTIME): $(OBJS) $(SRCS) win32.mak
 	$(DMD) -lib -of$(DRUNTIME) $(DFLAGS) $(SRCS) $(OBJS)
 
+################### shared Library modules #####################
+
+druntime_dll: $(OBJS) lib\druntime.obj lib\druntime_dynamic.lib $(OBJS_SHAREDRTL)
+
+lib\druntime.obj: $(SRCS_SHARED) win32.mak
+	$(DMD) -c -of$@ -exportall -sharedlib $(DFLAGS) $(SRCS_SHARED)
+
+# druntime_dynamic.lib should not export symbols, and is used for the DLL itself
+lib\druntime_dynamic.lib: $(SRCS_DYNAMIC) $(OBJS) win32.mak
+	$(DMD) -lib -of$@ $(DFLAGS) $(SRCS_DYNAMIC) $(OBJS)
+
+# these objs should not export symbols, and are used for each binary using phobos.dll
+$(OBJS_SHAREDRTL): $(SRCS_SHAREDRTL) win32.mak
+	$(DMD) -c -odlib -sharedlib $(DFLAGS) $(SRCS_SHAREDRTL)
+
+DLL_FILES_TO_CLEAN = $(OBJS_SHAREDRTL) lib\druntime.obj lib\druntime_dynamic.lib
+
+################### other targets ##############################
+	
 unittest : $(SRCS) $(DRUNTIME)
 	$(DMD) $(UDFLAGS) -L/co -unittest src\unittest.d $(SRCS) $(DRUNTIME)
 
@@ -489,3 +540,5 @@
 
 clean:
 	del $(DOCS) $(IMPORTS) $(DRUNTIME) $(OBJS_TO_DELETE) $(GCSTUB)
+	del $(DLL_FILES_TO_CLEAN)
+	
\ No newline at end of file
