diff --git a/mak/SRCS b/mak/SRCS
index 2080323cb6..d1a9ba9725 100644
--- a/mak/SRCS
+++ b/mak/SRCS
@@ -280,7 +280,8 @@ SRCS=\
src\rt\sections.d \
src\rt\sections_android.d \
src\rt\sections_elf_shared.d \
- src\rt\sections_osx.d \
+ src\rt\sections_osx_x86.d \
+ src\rt\sections_osx_x86_64.d \
src\rt\sections_solaris.d \
src\rt\sections_win32.d \
src\rt\sections_win64.d \
diff --git a/posix.mak b/posix.mak
index 91c30606ba..e5d645bcd6 100644
--- a/posix.mak
+++ b/posix.mak
@@ -90,6 +90,12 @@ SRCS:=$(subst \,/,$(SRCS))
OBJS= $(ROOT)/errno_c.o $(ROOT)/bss_section.o $(ROOT)/threadasm.o
+ifeq ($(OS),osx)
+ifeq ($(MODEL), 64)
+ OBJS+=$(ROOT)/osx_tls.o
+endif
+endif
+
# build with shared library support
SHARED=$(if $(findstring $(OS),linux freebsd),1,)
diff --git a/src/rt/osx_tls.c b/src/rt/osx_tls.c
new file mode 100644
index 0000000000..6cdffff672
--- /dev/null
+++ b/src/rt/osx_tls.c
@@ -0,0 +1,51 @@
+/**
+ * Helpers for determining TLS memory ranges on OS X.
+ *
+ * This unfortunately cannot be entirely done in D, as the OS X API uses
+ * the Apple-specific blocks C extension.
+ *
+ * Copyright: David Nadlinger, 2012.
+ * License: Boost License 1.0.
+ * Authors: David Nadlinger
+ */
+
+#ifndef __APPLE__
+#ifndef __BLOCKS__
+ #error "Need a C compiler with Apple Blocks support – not building on OS X with Clang?"
+#endif
+#endif
+
+#include
+#include
+#include
+
+/*
+ * Declarations from dyld_priv.h, available on 10.7+.
+ */
+enum dyld_tlv_states {
+ dyld_tlv_state_allocated = 10,
+ dyld_tlv_state_deallocated = 20
+};
+typedef struct {
+ size_t info_size;
+ void * tlv_addr;
+ size_t tlv_size;
+} dyld_tlv_info;
+typedef void (^dyld_tlv_state_change_handler)(enum dyld_tlv_states state, const dyld_tlv_info *info);
+extern void dyld_register_tlv_state_change_handler(enum dyld_tlv_states state, dyld_tlv_state_change_handler handler);
+extern void dyld_enumerate_tlv_storage(dyld_tlv_state_change_handler handler);
+
+void _d_dyld_getTLSRange(void* arbitraryTLSSymbol, void** start, size_t* size) {
+ dyld_enumerate_tlv_storage(
+ ^(enum dyld_tlv_states state, const dyld_tlv_info *info) {
+ assert(state == dyld_tlv_state_allocated);
+ if (info->tlv_addr <= arbitraryTLSSymbol &&
+ arbitraryTLSSymbol < (info->tlv_addr + info->tlv_size)
+ ) {
+ // Found the range.
+ *start = info->tlv_addr;
+ *size = info->tlv_size;
+ }
+ }
+ );
+}
diff --git a/src/rt/sections.d b/src/rt/sections.d
index a0b72e8750..4e32a77663 100644
--- a/src/rt/sections.d
+++ b/src/rt/sections.d
@@ -26,7 +26,14 @@ else version (FreeBSD)
else version (Solaris)
public import rt.sections_solaris;
else version (Darwin)
- public import rt.sections_osx;
+{
+ version (X86_64)
+ public import rt.sections_osx_x86_64;
+ else version (X86)
+ public import rt.sections_osx_x86;
+ else
+ static assert(0, "unimplemented");
+}
else version (CRuntime_DigitalMars)
public import rt.sections_win32;
else version (CRuntime_Microsoft)
diff --git a/src/rt/sections_osx.d b/src/rt/sections_osx_x86.d
similarity index 89%
rename from src/rt/sections_osx.d
rename to src/rt/sections_osx_x86.d
index 21a179523f..dc8a4b7721 100644
--- a/src/rt/sections_osx.d
+++ b/src/rt/sections_osx_x86.d
@@ -1,16 +1,15 @@
/**
* Written in the D programming language.
- * This module provides OSX-specific support for sections.
+ * This module provides OS X x86 specific support for sections.
*
- * Copyright: Copyright Digital Mars 2008 - 2012.
+ * Copyright: Copyright Digital Mars 2008 - 2016.
* License: Distributed under the
* $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0).
* (See accompanying file LICENSE)
- * Authors: Walter Bright, Sean Kelly, Martin Nowak
- * Source: $(DRUNTIMESRC src/rt/_sections_osx.d)
+ * Authors: Walter Bright, Sean Kelly, Martin Nowak, Jacob Carlborg
+ * Source: $(DRUNTIMESRC src/rt/_sections_osx_x86.d)
*/
-
-module rt.sections_osx;
+module rt.sections_osx_x86;
version (OSX)
version = Darwin;
@@ -22,6 +21,7 @@ else version (WatchOS)
version = Darwin;
version(Darwin):
+version(X86):
// debug = PRINTF;
import core.stdc.stdio;
@@ -189,7 +189,6 @@ ref void[] getTLSBlockAlloc()
return *pary;
}
-
__gshared SectionGroup _sections;
extern (C) void sections_osx_onAddImage(in mach_header* h, intptr_t slide)
@@ -263,22 +262,8 @@ static immutable SegRef[] dataSegs = [{SEG_DATA, SECT_DATA},
ubyte[] getSection(in mach_header* header, intptr_t slide,
in char* segmentName, in char* sectionName)
{
- version (X86)
- {
- assert(header.magic == MH_MAGIC);
- auto sect = getsectbynamefromheader(header,
- segmentName,
- sectionName);
- }
- else version (X86_64)
- {
- assert(header.magic == MH_MAGIC_64);
- auto sect = getsectbynamefromheader_64(cast(mach_header_64*)header,
- segmentName,
- sectionName);
- }
- else
- static assert(0, "unimplemented");
+ assert(header.magic == MH_MAGIC);
+ auto sect = getsectbynamefromheader(header, segmentName, sectionName);
if (sect !is null && sect.size > 0)
return (cast(ubyte*)sect.addr + slide)[0 .. cast(size_t)sect.size];
diff --git a/src/rt/sections_osx_x86_64.d b/src/rt/sections_osx_x86_64.d
new file mode 100644
index 0000000000..1bfcef3680
--- /dev/null
+++ b/src/rt/sections_osx_x86_64.d
@@ -0,0 +1,185 @@
+/**
+ * Written in the D programming language.
+ * This module provides OS X x86-64 specific support for sections.
+ *
+ * Copyright: Copyright Digital Mars 2016.
+ * License: Distributed under the
+ * $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0).
+ * (See accompanying file LICENSE)
+ * Authors: Walter Bright, Sean Kelly, Martin Nowak, Jacob Carlborg
+ * Source: $(DRUNTIMESRC src/rt/_sections_osx_x86_64.d)
+ */
+module rt.sections_osx_x86_64;
+
+version (OSX)
+ version = Darwin;
+else version (iOS)
+ version = Darwin;
+else version (TVOS)
+ version = Darwin;
+else version (WatchOS)
+ version = Darwin;
+
+version(Darwin):
+version(X86_64):
+
+// debug = PRINTF;
+import core.stdc.stdio;
+import core.stdc.string, core.stdc.stdlib;
+import core.sys.posix.pthread;
+import core.sys.osx.mach.dyld;
+import core.sys.osx.mach.getsect;
+import rt.deh, rt.minfo;
+import rt.util.container.array;
+
+struct SectionGroup
+{
+ static int opApply(scope int delegate(ref SectionGroup) dg)
+ {
+ return dg(_sections);
+ }
+
+ static int opApplyReverse(scope int delegate(ref SectionGroup) dg)
+ {
+ return dg(_sections);
+ }
+
+ @property immutable(ModuleInfo*)[] modules() const
+ {
+ return _moduleGroup.modules;
+ }
+
+ @property ref inout(ModuleGroup) moduleGroup() inout
+ {
+ return _moduleGroup;
+ }
+
+ @property inout(void[])[] gcRanges() inout
+ {
+ return _gcRanges[];
+ }
+
+ @property immutable(FuncTable)[] ehTables() const
+ {
+ return _ehTables[];
+ }
+
+private:
+ immutable(FuncTable)[] _ehTables;
+ ModuleGroup _moduleGroup;
+ Array!(void[]) _gcRanges;
+}
+
+/****
+ * Boolean flag set to true while the runtime is initialized.
+ */
+__gshared bool _isRuntimeInitialized;
+
+/****
+ * Gets called on program startup just before GC is initialized.
+ */
+void initSections()
+{
+ _dyld_register_func_for_add_image(§ions_osx_onAddImage);
+ _isRuntimeInitialized = true;
+}
+
+/***
+ * Gets called on program shutdown just after GC is terminated.
+ */
+void finiSections()
+{
+ _sections._gcRanges.reset();
+ _isRuntimeInitialized = false;
+}
+
+void[] initTLSRanges()
+{
+ void* start = null;
+ size_t size = 0;
+ _d_dyld_getTLSRange(&dummyTlsSymbol, &start, &size);
+ assert(start && size, "Could not determine TLS range.");
+ return start[0 .. size];
+}
+
+void finiTLSRanges(void[] rng)
+{
+
+}
+
+void scanTLSRanges(void[] rng, scope void delegate(void* pbeg, void* pend) nothrow dg) nothrow
+{
+ dg(rng.ptr, rng.ptr + rng.length);
+}
+
+private:
+
+extern(C) void _d_dyld_getTLSRange(void*, void**, size_t*);
+
+__gshared SectionGroup _sections;
+ubyte dummyTlsSymbol;
+
+extern (C) void sections_osx_onAddImage(in mach_header* h, intptr_t slide)
+{
+ foreach (e; dataSegs)
+ {
+ auto sect = getSection(h, slide, e.seg.ptr, e.sect.ptr);
+ if (sect != null)
+ _sections._gcRanges.insertBack((cast(void*)sect.ptr)[0 .. sect.length]);
+ }
+
+ auto minfosect = getSection(h, slide, "__DATA", "__minfodata");
+ if (minfosect != null)
+ {
+ // no support for multiple images yet
+ // take the sections from the last static image which is the executable
+ if (_isRuntimeInitialized)
+ {
+ fprintf(stderr, "Loading shared libraries isn't yet supported on OSX.\n");
+ return;
+ }
+ else if (_sections.modules.ptr !is null)
+ {
+ fprintf(stderr, "Shared libraries are not yet supported on OSX.\n");
+ }
+
+ debug(PRINTF) printf(" minfodata\n");
+ auto p = cast(immutable(ModuleInfo*)*)minfosect.ptr;
+ immutable len = minfosect.length / (*p).sizeof;
+
+ _sections._moduleGroup = ModuleGroup(p[0 .. len]);
+ }
+
+ auto ehsect = getSection(h, slide, "__DATA", "__deh_eh");
+ if (ehsect != null)
+ {
+ debug(PRINTF) printf(" deh_eh\n");
+ auto p = cast(immutable(FuncTable)*)ehsect.ptr;
+ immutable len = ehsect.length / (*p).sizeof;
+
+ _sections._ehTables = p[0 .. len];
+ }
+}
+
+struct SegRef
+{
+ string seg;
+ string sect;
+}
+
+static immutable SegRef[] dataSegs = [{SEG_DATA, SECT_DATA},
+ {SEG_DATA, SECT_BSS},
+ {SEG_DATA, SECT_COMMON}];
+
+ubyte[] getSection(in mach_header* header, intptr_t slide,
+ in char* segmentName, in char* sectionName)
+{
+ assert(header.magic == MH_MAGIC_64);
+ auto sect = getsectbynamefromheader_64(cast(mach_header_64*)header,
+ segmentName,
+ sectionName);
+
+ if (sect !is null && sect.size > 0)
+ return (cast(ubyte*)sect.addr + slide)[0 .. cast(size_t)sect.size];
+ return null;
+}