Permalink
Browse files

fix Issue 4854 - Regression(2.047, Mac 10.5 only) writefln Segmentati…

…on fault if no globals
  • Loading branch information...
1 parent b7bfe42 commit 73cf2c150665cb17d9365a6e3d6cf144d76312d6 @WalterBright WalterBright committed Mar 8, 2012
Showing with 140 additions and 7 deletions.
  1. +90 −6 src/core/thread.d
  2. +5 −1 src/rt/dmain2.d
  3. +45 −0 src/rt/memory_osx.d
View
@@ -18,6 +18,7 @@ module core.thread;
public import core.time; // for Duration
+//import core.stdc.stdio;
// this should be true for most architectures
version = StackGrowsDown;
@@ -282,6 +283,13 @@ else version( Posix )
{
extern (C)
{
+ __gshared void[][2] _tls_data_array;
+ }
+ }
+ else version(none)
+ {
+ extern (C)
+ {
extern __gshared
{
void* _tls_beg;
@@ -355,7 +363,21 @@ else version( Posix )
obj.m_main.bstack = &obj;
obj.m_main.tstack = obj.m_main.bstack;
- version( OSX )
+ version (OSX)
+ {
+ // NOTE: OSX does not support TLS, so we do it ourselves. The TLS
+ // data output by the compiler is bracketed by _tls_data_array[2],
+ // so make a copy of it for each thread.
+ const sz0 = (_tls_data_array[0].length + 15) & ~cast(size_t)15;
+ const sz2 = sz0 + _tls_data_array[1].length;
+ auto p = malloc( sz2 );
+ assert( p );
+ obj.m_tls = p[0 .. sz2];
+ memcpy( p, _tls_data_array[0].ptr, _tls_data_array[0].length );
+ memcpy( p + sz0, _tls_data_array[1].ptr, _tls_data_array[1].length );
+ scope (exit) { free( p ); obj.m_tls = null; }
+ }
+ else version (none)
{
// NOTE: OSX does not support TLS, so we do it ourselves. The TLS
// data output by the compiler is bracketed by _tls_beg and
@@ -1354,7 +1376,23 @@ private:
m_call = Call.NO;
m_curr = &m_main;
- version( OSX )
+ version (OSX)
+ {
+ //printf("test2 %p %p\n", _tls_data_array[0].ptr, &_tls_data_array[1][length]);
+ //printf("test2 %p %p\n", &_tls_beg, &_tls_end);
+ // NOTE: OSX does not support TLS, so we do it ourselves. The TLS
+ // data output by the compiler is bracketed by _tls_data_array2],
+ // so make a copy of it for each thread.
+ const sz0 = (_tls_data_array[0].length + 15) & ~cast(size_t)15;
+ const sz2 = sz0 + _tls_data_array[1].length;
+ auto p = malloc( sz2 );
+ assert( p );
+ m_tls = p[0 .. sz2];
+ memcpy( p, _tls_data_array[0].ptr, _tls_data_array[0].length );
+ memcpy( p + sz0, _tls_data_array[1].ptr, _tls_data_array[1].length );
+ // The free must happen at program end, if anywhere.
+ }
+ else version (none)
{
// NOTE: OSX does not support TLS, so we do it ourselves. The TLS
// data output by the compiler is bracketed by _tls_beg and
@@ -1974,7 +2012,23 @@ extern (C) Thread thread_attachThis()
assert( thisThread.m_tmach != thisThread.m_tmach.init );
}
- version( OSX )
+ version (OSX)
+ {
+ //printf("test3 %p %p\n", _tls_data_array[0].ptr, &_tls_data_array[1][length]);
+ //printf("test3 %p %p\n", &_tls_beg, &_tls_end);
+ // NOTE: OSX does not support TLS, so we do it ourselves. The TLS
+ // data output by the compiler is bracketed by _tls_data_array[2],
+ // so make a copy of it for each thread.
+ const sz0 = (_tls_data_array[0].length + 15) & ~cast(size_t)15;
+ const sz2 = sz0 + _tls_data_array[1].length;
+ auto p = gc_malloc( sz2 );
+ assert( p );
+ thisThread.m_tls = p[0 .. sz2];
+ memcpy( p, _tls_data_array[0].ptr, _tls_data_array[0].length );
+ memcpy( p + sz0, _tls_data_array[1].ptr, _tls_data_array[1].length );
+ // used gc_malloc so no need to free
+ }
+ else version (none)
{
// NOTE: OSX does not support TLS, so we do it ourselves. The TLS
// data output by the compiler is bracketed by _tls_beg and
@@ -2059,7 +2113,24 @@ version( Windows )
assert( thisThread.m_tmach != thisThread.m_tmach.init );
}
- version( OSX )
+ version (OSX)
+ {
+ // NOTE: OSX does not support TLS, so we do it ourselves. The TLS
+ // data output by the compiler is bracketed by _tls_data_array[2],
+ // so make a copy of it for each thread.
+ const sz0 = (_tls_data_array[0].length + 15) & ~cast(size_t)15;
+ const sz2 = sz0 + _tls_data_array[1].length;
+ auto p = gc_malloc( sz2 );
+ assert( p );
+ obj.m_tls = p[0 .. sz2];
+ memcpy( p, _tls_data_array[0].ptr, _tls_data_array[0].length );
+ memcpy( p + sz0, _tls_data_array[1].ptr, _tls_data_array[1].length );
+ // used gc_malloc so no need to free
+
+ if( t.m_addr == pthread_self() )
+ Thread.setThis( thisThread );
+ }
+ else version (none)
{
// NOTE: OSX does not support TLS, so we do it ourselves. The TLS
// data output by the compiler is bracketed by _tls_beg and
@@ -4232,8 +4303,21 @@ version( OSX )
{
// NOTE: p is an address in the TLS static data emitted by the
// compiler. If it isn't, something is disastrously wrong.
- assert( p >= cast(void*) &_tls_beg && p < cast(void*) &_tls_end );
auto obj = Thread.getThis();
- return obj.m_tls.ptr + (p - cast(void*) &_tls_beg);
+
+ if (p >= _tls_data_array[0].ptr && p < &_tls_data_array[0][length])
+ {
+ return obj.m_tls.ptr + (p - _tls_data_array[0].ptr);
+ }
+ else if (p >= _tls_data_array[1].ptr && p < &_tls_data_array[1][length])
+ {
+ size_t sz = (_tls_data_array[0].length + 15) & ~cast(size_t)15;
+ return obj.m_tls.ptr + sz + (p - _tls_data_array[1].ptr);
+ }
+ else
+ assert(0);
+
+ //assert( p >= cast(void*) &_tls_beg && p < cast(void*) &_tls_end );
+ //return obj.m_tls.ptr + (p - cast(void*) &_tls_beg);
}
}
View
@@ -98,6 +98,8 @@ version (OSX)
{
// The bottom of the stack
extern (C) __gshared void* __osx_stack_end = cast(void*)0xC0000000;
+
+ extern (C) extern (C) void _d_osx_image_init2();
}
/***********************************
@@ -348,6 +350,8 @@ extern (C) int main(int argc, char** argv)
* of the main thread's stack, so save the address of that.
*/
__osx_stack_end = cast(void*)&argv;
+
+ _d_osx_image_init2();
}
version (FreeBSD) version (D_InlineAsm_X86)
@@ -375,7 +379,7 @@ extern (C) int main(int argc, char** argv)
version (Windows)
{
wchar_t* wcbuf = GetCommandLineW();
- size_t wclen = wcslen(wcbuf);
+ size_t wclen = wcslen(wcbuf);
int wargc = 0;
wchar_t** wargs = CommandLineToArgvW(wcbuf, &wargc);
assert(wargc == argc);
View
@@ -20,6 +20,7 @@ import src.core.sys.osx.mach.getsect;
extern (C) extern __gshared ModuleInfo*[] _moduleinfo_array;
extern (C) extern __gshared ubyte[] _deh_eh_array;
+extern (C) extern __gshared ubyte[][2] _tls_data_array;
extern (C) void gc_addRange( void* p, size_t sz );
extern (C) void gc_removeRange( void* p );
@@ -124,3 +125,47 @@ extern (C) void _d_osx_image_init()
_dyld_register_func_for_add_image( &onAddImage );
_dyld_register_func_for_remove_image( &onRemoveImage );
}
+
+/*********************************
+ * The following is done separately because it must be done before Thread gets initialized.
+ */
+
+extern (C) void onAddImage2(in mach_header* h, intptr_t slide)
+{
+ //printf("onAddImage2()\n");
+
+ if (auto sect = getSection(h, slide, "__DATA", "__tls_data"))
+ {
+ //printf(" tls_data %p %p\n", &sect[0], &sect[length]);
+ /* BUG: this will fail if there are multiple images with __tls_data
+ * sections. Not set up to handle that.
+ */
+ if (!_tls_data_array[0].ptr)
+ _tls_data_array[0] = sect.ptr[0 .. sect.length];
+ }
+
+ if (auto sect = getSection(h, slide, "__DATA", "__tlscoal_nt"))
+ {
+ //printf(" tlscoal_nt %p %p\n", &sect[0], &sect[length]);
+ /* BUG: this will fail if there are multiple images with __tlscoal_nt
+ * sections. Not set up to handle that.
+ */
+ if (!_tls_data_array[1].ptr)
+ _tls_data_array[1] = sect.ptr[0 .. sect.length];
+ }
+}
+
+
+extern (C) void onRemoveImage2(in mach_header* h, intptr_t slide)
+{
+ //printf("onRemoveImage2()\n");
+}
+
+
+extern (C) void _d_osx_image_init2()
+{
+ //printf("_d_osx_image_init2()\n");
+ _dyld_register_func_for_add_image( &onAddImage2 );
+ _dyld_register_func_for_remove_image( &onRemoveImage2 );
+}
+

0 comments on commit 73cf2c1

Please sign in to comment.