libphobos: Move rt.sections modules to gcc.sections
authorIain Buclaw <ibuclaw@gdcproject.org>
Sat, 13 Apr 2019 15:29:15 +0000 (15:29 +0000)
committerIain Buclaw <ibuclaw@gcc.gnu.org>
Sat, 13 Apr 2019 15:29:15 +0000 (15:29 +0000)
These modules depend on a mixture between how the compiler emits
run-time module information, and what functions are exposed by the
platform to inquire about loaded global and thread-local data sections.

As the upstream implementation is written to work only with how the
reference D compiler writes out data, much of what is present does not
apply to the GCC D front-end.  So it has been moved to a non-upstream
location in the source tree, where most of it will be rewritten once
each port has been completed.

The only tested module sections/elf_shared.d has been cleaned up so that
all deprecated declarations have been removed, as well as the brittle
module collision checking, which required bss_sections.c.  All other
ports have been left unchanged apart from a commonizing of attributes.

libphobos/ChangeLog:

2019-04-13  Iain Buclaw  <ibuclaw@gdcproject.org>

* libdruntime/Makefile.am (DRUNTIME_CSOURCES): Remove bss_sections.c.
(DRUNTIME_DSOURCES): Rename rt/sections_* modules to gcc/sections/*.
* libdruntime/Makefile.in: Regenerate.
* libdruntime/gcc/sections/android.d: New file.
* libdruntime/gcc/sections/elf_shared.d: New file.
* libdruntime/gcc/sections/osx.d: New file.
* libdruntime/gcc/sections/package.d: New file.
* libdruntime/gcc/sections/solaris.d: New file.
* libdruntime/gcc/sections/win32.d: New file.
* libdruntime/gcc/sections/win64.d: New file.
* libdruntime/rt/bss_section.c: Remove.
* libdruntime/rt/sections.d: Publicly import gcc.sections.
* libdruntime/rt/sections_android.d: Remove.
* libdruntime/rt/sections_elf_shared.d: Remove.
* libdruntime/rt/sections_osx.d: Remove.
* libdruntime/rt/sections_solaris.d: Remove.
* libdruntime/rt/sections_win32.d: Remove.
* libdruntime/rt/sections_win64.d: Remove.

From-SVN: r270341

18 files changed:
libphobos/ChangeLog
libphobos/libdruntime/Makefile.am
libphobos/libdruntime/Makefile.in
libphobos/libdruntime/gcc/sections/android.d [new file with mode: 0644]
libphobos/libdruntime/gcc/sections/elf_shared.d [new file with mode: 0644]
libphobos/libdruntime/gcc/sections/osx.d [new file with mode: 0644]
libphobos/libdruntime/gcc/sections/package.d [new file with mode: 0644]
libphobos/libdruntime/gcc/sections/solaris.d [new file with mode: 0644]
libphobos/libdruntime/gcc/sections/win32.d [new file with mode: 0644]
libphobos/libdruntime/gcc/sections/win64.d [new file with mode: 0644]
libphobos/libdruntime/rt/bss_section.c [deleted file]
libphobos/libdruntime/rt/sections.d
libphobos/libdruntime/rt/sections_android.d [deleted file]
libphobos/libdruntime/rt/sections_elf_shared.d [deleted file]
libphobos/libdruntime/rt/sections_osx.d [deleted file]
libphobos/libdruntime/rt/sections_solaris.d [deleted file]
libphobos/libdruntime/rt/sections_win32.d [deleted file]
libphobos/libdruntime/rt/sections_win64.d [deleted file]

index 3220b1ec35f797718692fe6403ed50b45b04c9b9..3dd4bbd68fa32864b3a156daa5f1cce9f3988d9c 100644 (file)
@@ -1,3 +1,24 @@
+2019-04-13  Iain Buclaw  <ibuclaw@gdcproject.org>
+
+       * libdruntime/Makefile.am (DRUNTIME_CSOURCES): Remove bss_sections.c.
+       (DRUNTIME_DSOURCES): Rename rt/sections_* modules to gcc/sections/*.
+       * libdruntime/Makefile.in: Regenerate.
+       * libdruntime/gcc/sections/android.d: New file.
+       * libdruntime/gcc/sections/elf_shared.d: New file.
+       * libdruntime/gcc/sections/osx.d: New file.
+       * libdruntime/gcc/sections/package.d: New file.
+       * libdruntime/gcc/sections/solaris.d: New file.
+       * libdruntime/gcc/sections/win32.d: New file.
+       * libdruntime/gcc/sections/win64.d: New file.
+       * libdruntime/rt/bss_section.c: Remove.
+       * libdruntime/rt/sections.d: Publicly import gcc.sections.
+       * libdruntime/rt/sections_android.d: Remove.
+       * libdruntime/rt/sections_elf_shared.d: Remove.
+       * libdruntime/rt/sections_osx.d: Remove.
+       * libdruntime/rt/sections_solaris.d: Remove.
+       * libdruntime/rt/sections_win32.d: Remove.
+       * libdruntime/rt/sections_win64.d: Remove.
+
 2019-04-12  Iain Buclaw  <ibuclaw@gdcproject.org>
 
        * configure.ac (AM_INIT_AUTOMAKE): Add subdir-objects.
index abefb435dc71dba2f4b901f61a3a2d001114c0b5..8e36ce214499f354f399b1197af720f80572eec5 100644 (file)
@@ -122,7 +122,7 @@ DRUNTIME_DSOURCES_GENERATED = gcc/config.d gcc/libbacktrace.d
 # https://www.gnu.org/software/automake/manual/html_node/Wildcards.html
 DRUNTIME_SSOURCES = core/threadasm.S
 
-DRUNTIME_CSOURCES = core/stdc/errno_.c rt/bss_section.c
+DRUNTIME_CSOURCES = core/stdc/errno_.c
 
 DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \
        core/checkedint.d core/cpuid.d core/demangle.d core/exception.d \
@@ -140,14 +140,14 @@ DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \
        core/sync/config.d core/sync/exception.d core/sync/mutex.d \
        core/sync/rwmutex.d core/sync/semaphore.d core/thread.d core/time.d \
        core/vararg.d gcc/attribute.d gcc/backtrace.d gcc/builtins.d gcc/deh.d \
-       gcc/unwind/arm.d gcc/unwind/arm_common.d gcc/unwind/c6x.d \
-       gcc/unwind/generic.d gcc/unwind/package.d gcc/unwind/pe.d object.d \
-       rt/aApply.d rt/aApplyR.d rt/aaA.d rt/adi.d rt/arrayassign.d \
-       rt/arraycast.d rt/arraycat.d rt/cast_.d rt/config.d rt/critical_.d \
-       rt/deh.d rt/dmain2.d rt/invariant.d rt/lifetime.d rt/memory.d \
-       rt/minfo.d rt/monitor_.d rt/obj.d rt/qsort.d rt/sections.d \
-       rt/sections_android.d rt/sections_elf_shared.d rt/sections_osx.d \
-       rt/sections_solaris.d rt/sections_win32.d rt/sections_win64.d \
+       gcc/sections/android.d gcc/sections/elf_shared.d gcc/sections/osx.d \
+       gcc/sections/package.d gcc/sections/solaris.d gcc/sections/win32.d \
+       gcc/sections/win64.d gcc/unwind/arm.d gcc/unwind/arm_common.d \
+       gcc/unwind/c6x.d gcc/unwind/generic.d gcc/unwind/package.d \
+       gcc/unwind/pe.d object.d rt/aApply.d rt/aApplyR.d rt/aaA.d rt/adi.d \
+       rt/arrayassign.d rt/arraycast.d rt/arraycat.d rt/cast_.d rt/config.d \
+       rt/critical_.d rt/deh.d rt/dmain2.d rt/invariant.d rt/lifetime.d \
+       rt/memory.d rt/minfo.d rt/monitor_.d rt/obj.d rt/qsort.d rt/sections.d \
        rt/switch_.d rt/tlsgc.d rt/typeinfo/ti_Acdouble.d \
        rt/typeinfo/ti_Acfloat.d rt/typeinfo/ti_Acreal.d \
        rt/typeinfo/ti_Adouble.d rt/typeinfo/ti_Afloat.d rt/typeinfo/ti_Ag.d \
index 4bfd04c3db50272d2d505c0bfae48ac9ebc5cb60..0a27afac545b804f41d315c81a26a06636134de8 100644 (file)
@@ -194,7 +194,10 @@ am__objects_1 = core/atomic.lo core/attribute.lo core/bitop.lo \
        core/sync/exception.lo core/sync/mutex.lo core/sync/rwmutex.lo \
        core/sync/semaphore.lo core/thread.lo core/time.lo \
        core/vararg.lo gcc/attribute.lo gcc/backtrace.lo \
-       gcc/builtins.lo gcc/deh.lo gcc/unwind/arm.lo \
+       gcc/builtins.lo gcc/deh.lo gcc/sections/android.lo \
+       gcc/sections/elf_shared.lo gcc/sections/osx.lo \
+       gcc/sections/package.lo gcc/sections/solaris.lo \
+       gcc/sections/win32.lo gcc/sections/win64.lo gcc/unwind/arm.lo \
        gcc/unwind/arm_common.lo gcc/unwind/c6x.lo \
        gcc/unwind/generic.lo gcc/unwind/package.lo gcc/unwind/pe.lo \
        object.lo rt/aApply.lo rt/aApplyR.lo rt/aaA.lo rt/adi.lo \
@@ -202,31 +205,29 @@ am__objects_1 = core/atomic.lo core/attribute.lo core/bitop.lo \
        rt/config.lo rt/critical_.lo rt/deh.lo rt/dmain2.lo \
        rt/invariant.lo rt/lifetime.lo rt/memory.lo rt/minfo.lo \
        rt/monitor_.lo rt/obj.lo rt/qsort.lo rt/sections.lo \
-       rt/sections_android.lo rt/sections_elf_shared.lo \
-       rt/sections_osx.lo rt/sections_solaris.lo rt/sections_win32.lo \
-       rt/sections_win64.lo rt/switch_.lo rt/tlsgc.lo \
-       rt/typeinfo/ti_Acdouble.lo rt/typeinfo/ti_Acfloat.lo \
-       rt/typeinfo/ti_Acreal.lo rt/typeinfo/ti_Adouble.lo \
-       rt/typeinfo/ti_Afloat.lo rt/typeinfo/ti_Ag.lo \
-       rt/typeinfo/ti_Aint.lo rt/typeinfo/ti_Along.lo \
-       rt/typeinfo/ti_Areal.lo rt/typeinfo/ti_Ashort.lo \
-       rt/typeinfo/ti_C.lo rt/typeinfo/ti_byte.lo \
-       rt/typeinfo/ti_cdouble.lo rt/typeinfo/ti_cent.lo \
-       rt/typeinfo/ti_cfloat.lo rt/typeinfo/ti_char.lo \
-       rt/typeinfo/ti_creal.lo rt/typeinfo/ti_dchar.lo \
-       rt/typeinfo/ti_delegate.lo rt/typeinfo/ti_double.lo \
-       rt/typeinfo/ti_float.lo rt/typeinfo/ti_idouble.lo \
-       rt/typeinfo/ti_ifloat.lo rt/typeinfo/ti_int.lo \
-       rt/typeinfo/ti_ireal.lo rt/typeinfo/ti_long.lo \
-       rt/typeinfo/ti_n.lo rt/typeinfo/ti_ptr.lo \
-       rt/typeinfo/ti_real.lo rt/typeinfo/ti_short.lo \
-       rt/typeinfo/ti_ubyte.lo rt/typeinfo/ti_ucent.lo \
-       rt/typeinfo/ti_uint.lo rt/typeinfo/ti_ulong.lo \
-       rt/typeinfo/ti_ushort.lo rt/typeinfo/ti_void.lo \
-       rt/typeinfo/ti_wchar.lo rt/util/array.lo \
-       rt/util/container/array.lo rt/util/container/common.lo \
-       rt/util/container/hashtab.lo rt/util/container/treap.lo \
-       rt/util/random.lo rt/util/typeinfo.lo rt/util/utf.lo
+       rt/switch_.lo rt/tlsgc.lo rt/typeinfo/ti_Acdouble.lo \
+       rt/typeinfo/ti_Acfloat.lo rt/typeinfo/ti_Acreal.lo \
+       rt/typeinfo/ti_Adouble.lo rt/typeinfo/ti_Afloat.lo \
+       rt/typeinfo/ti_Ag.lo rt/typeinfo/ti_Aint.lo \
+       rt/typeinfo/ti_Along.lo rt/typeinfo/ti_Areal.lo \
+       rt/typeinfo/ti_Ashort.lo rt/typeinfo/ti_C.lo \
+       rt/typeinfo/ti_byte.lo rt/typeinfo/ti_cdouble.lo \
+       rt/typeinfo/ti_cent.lo rt/typeinfo/ti_cfloat.lo \
+       rt/typeinfo/ti_char.lo rt/typeinfo/ti_creal.lo \
+       rt/typeinfo/ti_dchar.lo rt/typeinfo/ti_delegate.lo \
+       rt/typeinfo/ti_double.lo rt/typeinfo/ti_float.lo \
+       rt/typeinfo/ti_idouble.lo rt/typeinfo/ti_ifloat.lo \
+       rt/typeinfo/ti_int.lo rt/typeinfo/ti_ireal.lo \
+       rt/typeinfo/ti_long.lo rt/typeinfo/ti_n.lo \
+       rt/typeinfo/ti_ptr.lo rt/typeinfo/ti_real.lo \
+       rt/typeinfo/ti_short.lo rt/typeinfo/ti_ubyte.lo \
+       rt/typeinfo/ti_ucent.lo rt/typeinfo/ti_uint.lo \
+       rt/typeinfo/ti_ulong.lo rt/typeinfo/ti_ushort.lo \
+       rt/typeinfo/ti_void.lo rt/typeinfo/ti_wchar.lo \
+       rt/util/array.lo rt/util/container/array.lo \
+       rt/util/container/common.lo rt/util/container/hashtab.lo \
+       rt/util/container/treap.lo rt/util/random.lo \
+       rt/util/typeinfo.lo rt/util/utf.lo
 am__objects_2 = gc/bits.lo gc/config.lo gc/gcinterface.lo \
        gc/impl/conservative/gc.lo gc/impl/manual/gc.lo gc/os.lo \
        gc/pooltable.lo gc/proxy.lo
@@ -425,8 +426,7 @@ am__objects_27 = $(am__objects_1) $(am__objects_3) $(am__objects_5) \
        $(am__objects_13) $(am__objects_15) $(am__objects_17) \
        $(am__objects_19) $(am__objects_21) $(am__objects_23) \
        $(am__objects_25) $(am__objects_26)
-am__objects_28 = core/stdc/libgdruntime_la-errno_.lo \
-       rt/libgdruntime_la-bss_section.lo
+am__objects_28 = core/stdc/libgdruntime_la-errno_.lo
 am__objects_29 = core/libgdruntime_la-threadasm.lo
 am__objects_30 = $(am__objects_27) $(am__objects_28) $(am__objects_29)
 am_libgdruntime_la_OBJECTS = $(am__objects_30)
@@ -719,7 +719,7 @@ DRUNTIME_DSOURCES_GENERATED = gcc/config.d gcc/libbacktrace.d
 # Can't use wildcards here:
 # https://www.gnu.org/software/automake/manual/html_node/Wildcards.html
 DRUNTIME_SSOURCES = core/threadasm.S
-DRUNTIME_CSOURCES = core/stdc/errno_.c rt/bss_section.c
+DRUNTIME_CSOURCES = core/stdc/errno_.c
 DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \
        core/checkedint.d core/cpuid.d core/demangle.d core/exception.d \
        core/internal/abort.d core/internal/arrayop.d core/internal/convert.d \
@@ -736,14 +736,14 @@ DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \
        core/sync/config.d core/sync/exception.d core/sync/mutex.d \
        core/sync/rwmutex.d core/sync/semaphore.d core/thread.d core/time.d \
        core/vararg.d gcc/attribute.d gcc/backtrace.d gcc/builtins.d gcc/deh.d \
-       gcc/unwind/arm.d gcc/unwind/arm_common.d gcc/unwind/c6x.d \
-       gcc/unwind/generic.d gcc/unwind/package.d gcc/unwind/pe.d object.d \
-       rt/aApply.d rt/aApplyR.d rt/aaA.d rt/adi.d rt/arrayassign.d \
-       rt/arraycast.d rt/arraycat.d rt/cast_.d rt/config.d rt/critical_.d \
-       rt/deh.d rt/dmain2.d rt/invariant.d rt/lifetime.d rt/memory.d \
-       rt/minfo.d rt/monitor_.d rt/obj.d rt/qsort.d rt/sections.d \
-       rt/sections_android.d rt/sections_elf_shared.d rt/sections_osx.d \
-       rt/sections_solaris.d rt/sections_win32.d rt/sections_win64.d \
+       gcc/sections/android.d gcc/sections/elf_shared.d gcc/sections/osx.d \
+       gcc/sections/package.d gcc/sections/solaris.d gcc/sections/win32.d \
+       gcc/sections/win64.d gcc/unwind/arm.d gcc/unwind/arm_common.d \
+       gcc/unwind/c6x.d gcc/unwind/generic.d gcc/unwind/package.d \
+       gcc/unwind/pe.d object.d rt/aApply.d rt/aApplyR.d rt/aaA.d rt/adi.d \
+       rt/arrayassign.d rt/arraycast.d rt/arraycat.d rt/cast_.d rt/config.d \
+       rt/critical_.d rt/deh.d rt/dmain2.d rt/invariant.d rt/lifetime.d \
+       rt/memory.d rt/minfo.d rt/monitor_.d rt/obj.d rt/qsort.d rt/sections.d \
        rt/switch_.d rt/tlsgc.d rt/typeinfo/ti_Acdouble.d \
        rt/typeinfo/ti_Acfloat.d rt/typeinfo/ti_Acreal.d \
        rt/typeinfo/ti_Adouble.d rt/typeinfo/ti_Afloat.d rt/typeinfo/ti_Ag.d \
@@ -1083,6 +1083,16 @@ gcc/attribute.lo: gcc/$(am__dirstamp)
 gcc/backtrace.lo: gcc/$(am__dirstamp)
 gcc/builtins.lo: gcc/$(am__dirstamp)
 gcc/deh.lo: gcc/$(am__dirstamp)
+gcc/sections/$(am__dirstamp):
+       @$(MKDIR_P) gcc/sections
+       @: > gcc/sections/$(am__dirstamp)
+gcc/sections/android.lo: gcc/sections/$(am__dirstamp)
+gcc/sections/elf_shared.lo: gcc/sections/$(am__dirstamp)
+gcc/sections/osx.lo: gcc/sections/$(am__dirstamp)
+gcc/sections/package.lo: gcc/sections/$(am__dirstamp)
+gcc/sections/solaris.lo: gcc/sections/$(am__dirstamp)
+gcc/sections/win32.lo: gcc/sections/$(am__dirstamp)
+gcc/sections/win64.lo: gcc/sections/$(am__dirstamp)
 gcc/unwind/$(am__dirstamp):
        @$(MKDIR_P) gcc/unwind
        @: > gcc/unwind/$(am__dirstamp)
@@ -1115,12 +1125,6 @@ rt/monitor_.lo: rt/$(am__dirstamp)
 rt/obj.lo: rt/$(am__dirstamp)
 rt/qsort.lo: rt/$(am__dirstamp)
 rt/sections.lo: rt/$(am__dirstamp)
-rt/sections_android.lo: rt/$(am__dirstamp)
-rt/sections_elf_shared.lo: rt/$(am__dirstamp)
-rt/sections_osx.lo: rt/$(am__dirstamp)
-rt/sections_solaris.lo: rt/$(am__dirstamp)
-rt/sections_win32.lo: rt/$(am__dirstamp)
-rt/sections_win64.lo: rt/$(am__dirstamp)
 rt/switch_.lo: rt/$(am__dirstamp)
 rt/tlsgc.lo: rt/$(am__dirstamp)
 rt/typeinfo/$(am__dirstamp):
@@ -1627,7 +1631,6 @@ core/sys/solaris/time.lo: core/sys/solaris/$(am__dirstamp)
 gcc/config.lo: gcc/$(am__dirstamp)
 gcc/libbacktrace.lo: gcc/$(am__dirstamp)
 core/stdc/libgdruntime_la-errno_.lo: core/stdc/$(am__dirstamp)
-rt/libgdruntime_la-bss_section.lo: rt/$(am__dirstamp)
 core/libgdruntime_la-threadasm.lo: core/$(am__dirstamp)
 
 libgdruntime.la: $(libgdruntime_la_OBJECTS) $(libgdruntime_la_DEPENDENCIES) $(EXTRA_libgdruntime_la_DEPENDENCIES) 
@@ -1703,6 +1706,8 @@ mostlyclean-compile:
        -rm -f gc/impl/manual/*.lo
        -rm -f gcc/*.$(OBJEXT)
        -rm -f gcc/*.lo
+       -rm -f gcc/sections/*.$(OBJEXT)
+       -rm -f gcc/sections/*.lo
        -rm -f gcc/unwind/*.$(OBJEXT)
        -rm -f gcc/unwind/*.lo
        -rm -f gcstub/*.$(OBJEXT)
@@ -1743,9 +1748,6 @@ core/libgdruntime_la-threadasm.lo: core/threadasm.S
 core/stdc/libgdruntime_la-errno_.lo: core/stdc/errno_.c
        $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgdruntime_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o core/stdc/libgdruntime_la-errno_.lo `test -f 'core/stdc/errno_.c' || echo '$(srcdir)/'`core/stdc/errno_.c
 
-rt/libgdruntime_la-bss_section.lo: rt/bss_section.c
-       $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgdruntime_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rt/libgdruntime_la-bss_section.lo `test -f 'rt/bss_section.c' || echo '$(srcdir)/'`rt/bss_section.c
-
 mostlyclean-libtool:
        -rm -f *.lo
 
@@ -1785,6 +1787,7 @@ clean-libtool:
        -rm -rf gc/impl/conservative/.libs gc/impl/conservative/_libs
        -rm -rf gc/impl/manual/.libs gc/impl/manual/_libs
        -rm -rf gcc/.libs gcc/_libs
+       -rm -rf gcc/sections/.libs gcc/sections/_libs
        -rm -rf gcc/unwind/.libs gcc/unwind/_libs
        -rm -rf gcstub/.libs gcstub/_libs
        -rm -rf rt/.libs rt/_libs
@@ -1931,6 +1934,7 @@ distclean-generic:
        -rm -f gc/impl/conservative/$(am__dirstamp)
        -rm -f gc/impl/manual/$(am__dirstamp)
        -rm -f gcc/$(am__dirstamp)
+       -rm -f gcc/sections/$(am__dirstamp)
        -rm -f gcc/unwind/$(am__dirstamp)
        -rm -f gcstub/$(am__dirstamp)
        -rm -f rt/$(am__dirstamp)
diff --git a/libphobos/libdruntime/gcc/sections/android.d b/libphobos/libdruntime/gcc/sections/android.d
new file mode 100644 (file)
index 0000000..f00bb89
--- /dev/null
@@ -0,0 +1,184 @@
+// Bionic-specific support for sections.
+// Copyright (C) 2019 Free Software Foundation, Inc.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+module gcc.sections.android;
+
+version (CRuntime_Bionic):
+
+// debug = PRINTF;
+debug(PRINTF) import core.stdc.stdio;
+import core.stdc.stdlib : malloc, free;
+import rt.deh, rt.minfo;
+import core.sys.posix.pthread;
+import core.stdc.stdlib : calloc;
+import core.stdc.string : memcpy;
+
+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 nothrow @nogc
+    {
+        return _moduleGroup.modules;
+    }
+
+    @property ref inout(ModuleGroup) moduleGroup() inout nothrow @nogc
+    {
+        return _moduleGroup;
+    }
+
+    @property immutable(FuncTable)[] ehTables() const nothrow @nogc
+    {
+        auto pbeg = cast(immutable(FuncTable)*)&__start_deh;
+        auto pend = cast(immutable(FuncTable)*)&__stop_deh;
+        return pbeg[0 .. pend - pbeg];
+    }
+
+    @property inout(void[])[] gcRanges() inout nothrow @nogc
+    {
+        return _gcRanges[];
+    }
+
+private:
+    ModuleGroup _moduleGroup;
+    void[][1] _gcRanges;
+}
+
+void initSections() nothrow @nogc
+{
+    pthread_key_create(&_tlsKey, null);
+
+    auto mbeg = cast(immutable ModuleInfo**)&__start_minfo;
+    auto mend = cast(immutable ModuleInfo**)&__stop_minfo;
+    _sections.moduleGroup = ModuleGroup(mbeg[0 .. mend - mbeg]);
+
+    auto pbeg = cast(void*)&_tlsend;
+    auto pend = cast(void*)&__bss_end__;
+    // _tlsend is a 32-bit int and may not be 64-bit void*-aligned, so align pbeg.
+    version (D_LP64) pbeg = cast(void*)(cast(size_t)(pbeg + 7) & ~cast(size_t)7);
+    _sections._gcRanges[0] = pbeg[0 .. pend - pbeg];
+}
+
+void finiSections() nothrow @nogc
+{
+    pthread_key_delete(_tlsKey);
+}
+
+void[]* initTLSRanges() nothrow @nogc
+{
+    return &getTLSBlock();
+}
+
+void finiTLSRanges(void[]* rng) nothrow @nogc
+{
+    .free(rng.ptr);
+    .free(rng);
+}
+
+void scanTLSRanges(void[]* rng, scope void delegate(void* pbeg, void* pend) nothrow dg) nothrow
+{
+    dg(rng.ptr, rng.ptr + rng.length);
+}
+
+/* NOTE: The Bionic C library ignores thread-local data stored in the normal
+ *       .tbss/.tdata ELF sections, which are marked with the SHF_TLS/STT_TLS
+ *       flags.  So instead we roll our own by keeping TLS data in the
+ *       .tdata/.tbss sections but removing the SHF_TLS/STT_TLS flags, and
+ *       access the TLS data using this function and the _tlsstart/_tlsend
+ *       symbols as delimiters.
+ *
+ *       This function is called by the code emitted by the compiler.  It
+ *       is expected to translate an address in the TLS static data to
+ *       the corresponding address in the TLS dynamic per-thread data.
+ */
+
+extern(C) void* __tls_get_addr( void* p ) nothrow @nogc
+{
+    debug(PRINTF) printf("  __tls_get_addr input - %p\n", p);
+    immutable offset = cast(size_t)(p - cast(void*)&_tlsstart);
+    auto tls = getTLSBlockAlloc();
+    assert(offset < tls.length);
+    return tls.ptr + offset;
+}
+
+private:
+
+__gshared pthread_key_t _tlsKey;
+
+ref void[] getTLSBlock() nothrow @nogc
+{
+    auto pary = cast(void[]*)pthread_getspecific(_tlsKey);
+    if (pary is null)
+    {
+        pary = cast(void[]*).calloc(1, (void[]).sizeof);
+        if (pthread_setspecific(_tlsKey, pary) != 0)
+        {
+            import core.stdc.stdio;
+            perror("pthread_setspecific failed with");
+            assert(0);
+        }
+    }
+    return *pary;
+}
+
+ref void[] getTLSBlockAlloc() nothrow @nogc
+{
+    auto pary = &getTLSBlock();
+    if (!pary.length)
+    {
+        auto pbeg = cast(void*)&_tlsstart;
+        auto pend = cast(void*)&_tlsend;
+        auto p = .malloc(pend - pbeg);
+        memcpy(p, pbeg, pend - pbeg);
+        *pary = p[0 .. pend - pbeg];
+    }
+    return *pary;
+}
+
+__gshared SectionGroup _sections;
+
+extern(C)
+{
+    /* Symbols created by the compiler/linker and inserted into the
+     * object file that 'bracket' sections.
+     */
+    extern __gshared
+    {
+        void* __start_deh;
+        void* __stop_deh;
+        void* __start_minfo;
+        void* __stop_minfo;
+
+        size_t __bss_end__;
+
+        int _tlsstart;
+        int _tlsend;
+    }
+}
diff --git a/libphobos/libdruntime/gcc/sections/elf_shared.d b/libphobos/libdruntime/gcc/sections/elf_shared.d
new file mode 100644 (file)
index 0000000..f70c232
--- /dev/null
@@ -0,0 +1,978 @@
+// ELF-specific support for sections with shared libraries.
+// Copyright (C) 2019 Free Software Foundation, Inc.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+module gcc.sections.elf_shared;
+
+version (CRuntime_Glibc) enum SharedELF = true;
+else version (CRuntime_Musl) enum SharedELF = true;
+else version (FreeBSD) enum SharedELF = true;
+else version (NetBSD) enum SharedELF = true;
+else version (DragonFlyBSD) enum SharedELF = true;
+else version (CRuntime_UClibc) enum SharedELF = true;
+else enum SharedELF = false;
+static if (SharedELF):
+
+// debug = PRINTF;
+import core.memory;
+import core.stdc.config;
+import core.stdc.stdio;
+import core.stdc.stdlib : calloc, exit, free, malloc, EXIT_FAILURE;
+import core.stdc.string : strlen;
+version (linux)
+{
+    import core.sys.linux.dlfcn;
+    import core.sys.linux.elf;
+    import core.sys.linux.link;
+}
+else version (FreeBSD)
+{
+    import core.sys.freebsd.dlfcn;
+    import core.sys.freebsd.sys.elf;
+    import core.sys.freebsd.sys.link_elf;
+}
+else version (NetBSD)
+{
+    import core.sys.netbsd.dlfcn;
+    import core.sys.netbsd.sys.elf;
+    import core.sys.netbsd.sys.link_elf;
+}
+else version (DragonFlyBSD)
+{
+    import core.sys.dragonflybsd.dlfcn;
+    import core.sys.dragonflybsd.sys.elf;
+    import core.sys.dragonflybsd.sys.link_elf;
+}
+else
+{
+    static assert(0, "unimplemented");
+}
+import core.sys.posix.pthread;
+import rt.deh;
+import rt.dmain2;
+import rt.minfo;
+import rt.util.container.array;
+import rt.util.container.hashtab;
+
+/****
+ * Asserts the specified condition, independent from -release, by abort()ing.
+ * Regular assertions throw an AssertError and thus require an initialized
+ * GC, which isn't the case (yet or anymore) for the startup/shutdown code in
+ * this module (called by CRT ctors/dtors etc.).
+ */
+private void safeAssert(bool condition, scope string msg, size_t line = __LINE__) @nogc nothrow @safe
+{
+    import core.internal.abort;
+    condition || abort(msg, __FILE__, line);
+}
+
+alias DSO SectionGroup;
+struct DSO
+{
+    static int opApply(scope int delegate(ref DSO) dg)
+    {
+        foreach (dso; _loadedDSOs)
+        {
+            if (auto res = dg(*dso))
+                return res;
+        }
+        return 0;
+    }
+
+    static int opApplyReverse(scope int delegate(ref DSO) dg)
+    {
+        foreach_reverse (dso; _loadedDSOs)
+        {
+            if (auto res = dg(*dso))
+                return res;
+        }
+        return 0;
+    }
+
+    @property immutable(ModuleInfo*)[] modules() const nothrow @nogc
+    {
+        return _moduleGroup.modules;
+    }
+
+    @property ref inout(ModuleGroup) moduleGroup() inout nothrow @nogc
+    {
+        return _moduleGroup;
+    }
+
+    @property immutable(FuncTable)[] ehTables() const nothrow @nogc
+    {
+        return null;
+    }
+
+    @property inout(void[])[] gcRanges() inout nothrow @nogc
+    {
+        return _gcRanges[];
+    }
+
+private:
+
+    invariant()
+    {
+        safeAssert(_moduleGroup.modules.length > 0, "No modules for DSO.");
+        safeAssert(_tlsMod || !_tlsSize, "Inconsistent TLS fields for DSO.");
+    }
+
+    ModuleGroup _moduleGroup;
+    Array!(void[]) _gcRanges;
+    size_t _tlsMod;
+    size_t _tlsSize;
+
+    version (Shared)
+    {
+        Array!(void[]) _codeSegments; // array of code segments
+        Array!(DSO*) _deps; // D libraries needed by this DSO
+        void* _handle; // corresponding handle
+    }
+
+    // get the TLS range for the executing thread
+    void[] tlsRange() const nothrow @nogc
+    {
+        return getTLSRange(_tlsMod, _tlsSize);
+    }
+}
+
+/****
+ * Boolean flag set to true while the runtime is initialized.
+ */
+__gshared bool _isRuntimeInitialized;
+
+
+version (FreeBSD) private __gshared void* dummy_ref;
+version (DragonFlyBSD) private __gshared void* dummy_ref;
+version (NetBSD) private __gshared void* dummy_ref;
+
+/****
+ * Gets called on program startup just before GC is initialized.
+ */
+void initSections() nothrow @nogc
+{
+    _isRuntimeInitialized = true;
+    // reference symbol to support weak linkage
+    version (FreeBSD) dummy_ref = &_d_dso_registry;
+    version (DragonFlyBSD) dummy_ref = &_d_dso_registry;
+    version (NetBSD) dummy_ref = &_d_dso_registry;
+}
+
+
+/***
+ * Gets called on program shutdown just after GC is terminated.
+ */
+void finiSections() nothrow @nogc
+{
+    _isRuntimeInitialized = false;
+}
+
+alias ScanDG = void delegate(void* pbeg, void* pend) nothrow;
+
+version (Shared)
+{
+    /***
+     * Called once per thread; returns array of thread local storage ranges
+     */
+    Array!(ThreadDSO)* initTLSRanges() @nogc nothrow
+    {
+        return &_loadedDSOs();
+    }
+
+    void finiTLSRanges(Array!(ThreadDSO)* tdsos) @nogc nothrow
+    {
+        // Nothing to do here. tdsos used to point to the _loadedDSOs instance
+        // in the dying thread's TLS segment and as such is not valid anymore.
+        // The memory for the array contents was already reclaimed in
+        // cleanupLoadedLibraries().
+    }
+
+    void scanTLSRanges(Array!(ThreadDSO)* tdsos, scope ScanDG dg) nothrow
+    {
+        foreach (ref tdso; *tdsos)
+            dg(tdso._tlsRange.ptr, tdso._tlsRange.ptr + tdso._tlsRange.length);
+    }
+
+    // interface for core.thread to inherit loaded libraries
+    void* pinLoadedLibraries() nothrow @nogc
+    {
+        auto res = cast(Array!(ThreadDSO)*)calloc(1, Array!(ThreadDSO).sizeof);
+        res.length = _loadedDSOs.length;
+        foreach (i, ref tdso; _loadedDSOs)
+        {
+            (*res)[i] = tdso;
+            if (tdso._addCnt)
+            {
+                // Increment the dlopen ref for explicitly loaded libraries to pin them.
+                const success = .dlopen(linkMapForHandle(tdso._pdso._handle).l_name, RTLD_LAZY) !is null;
+                safeAssert(success, "Failed to increment dlopen ref.");
+                (*res)[i]._addCnt = 1; // new array takes over the additional ref count
+            }
+        }
+        return res;
+    }
+
+    void unpinLoadedLibraries(void* p) nothrow @nogc
+    {
+        auto pary = cast(Array!(ThreadDSO)*)p;
+        // In case something failed we need to undo the pinning.
+        foreach (ref tdso; *pary)
+        {
+            if (tdso._addCnt)
+            {
+                auto handle = tdso._pdso._handle;
+                safeAssert(handle !is null, "Invalid library handle.");
+                .dlclose(handle);
+            }
+        }
+        pary.reset();
+        .free(pary);
+    }
+
+    // Called before TLS ctors are ran, copy over the loaded libraries
+    // of the parent thread.
+    void inheritLoadedLibraries(void* p) nothrow @nogc
+    {
+        safeAssert(_loadedDSOs.empty, "DSOs have already been registered for this thread.");
+        _loadedDSOs.swap(*cast(Array!(ThreadDSO)*)p);
+        .free(p);
+        foreach (ref dso; _loadedDSOs)
+        {
+            // the copied _tlsRange corresponds to parent thread
+            dso.updateTLSRange();
+        }
+    }
+
+    // Called after all TLS dtors ran, decrements all remaining dlopen refs.
+    void cleanupLoadedLibraries() nothrow @nogc
+    {
+        foreach (ref tdso; _loadedDSOs)
+        {
+            if (tdso._addCnt == 0) continue;
+
+            auto handle = tdso._pdso._handle;
+            safeAssert(handle !is null, "Invalid DSO handle.");
+            for (; tdso._addCnt > 0; --tdso._addCnt)
+                .dlclose(handle);
+        }
+
+        // Free the memory for the array contents.
+        _loadedDSOs.reset();
+    }
+}
+else
+{
+    /***
+     * Called once per thread; returns array of thread local storage ranges
+     */
+    Array!(void[])* initTLSRanges() nothrow @nogc
+    {
+        return &_tlsRanges();
+    }
+
+    void finiTLSRanges(Array!(void[])* rngs) nothrow @nogc
+    {
+        rngs.reset();
+    }
+
+    void scanTLSRanges(Array!(void[])* rngs, scope ScanDG dg) nothrow
+    {
+        foreach (rng; *rngs)
+            dg(rng.ptr, rng.ptr + rng.length);
+    }
+}
+
+private:
+
+version (Shared)
+{
+    /*
+     * Array of thread local DSO metadata for all libraries loaded and
+     * initialized in this thread.
+     *
+     * Note:
+     *     A newly spawned thread will inherit these libraries.
+     * Note:
+     *     We use an array here to preserve the order of
+     *     initialization.  If that became a performance issue, we
+     *     could use a hash table and enumerate the DSOs during
+     *     loading so that the hash table values could be sorted when
+     *     necessary.
+     */
+    struct ThreadDSO
+    {
+        DSO* _pdso;
+        static if (_pdso.sizeof == 8) uint _refCnt, _addCnt;
+        else static if (_pdso.sizeof == 4) ushort _refCnt, _addCnt;
+        else static assert(0, "unimplemented");
+        void[] _tlsRange;
+        alias _pdso this;
+        // update the _tlsRange for the executing thread
+        void updateTLSRange() nothrow @nogc
+        {
+            _tlsRange = _pdso.tlsRange();
+        }
+    }
+    @property ref Array!(ThreadDSO) _loadedDSOs() @nogc nothrow { static Array!(ThreadDSO) x; return x; }
+
+    /*
+     * Set to true during rt_loadLibrary/rt_unloadLibrary calls.
+     */
+    bool _rtLoading;
+
+    /*
+     * Hash table to map link_map* to corresponding DSO*.
+     * The hash table is protected by a Mutex.
+     */
+    __gshared pthread_mutex_t _handleToDSOMutex;
+    @property ref HashTab!(void*, DSO*) _handleToDSO() @nogc nothrow { __gshared HashTab!(void*, DSO*) x; return x; }
+
+    /*
+     * Section in executable that contains copy relocations.
+     * Might be null when druntime is dynamically loaded by a C host.
+     */
+    __gshared const(void)[] _copyRelocSection;
+}
+else
+{
+    /*
+     * Static DSOs loaded by the runtime linker. This includes the
+     * executable. These can't be unloaded.
+     */
+    @property ref Array!(DSO*) _loadedDSOs() @nogc nothrow { __gshared Array!(DSO*) x; return x; }
+
+    /*
+     * Thread local array that contains TLS memory ranges for each
+     * library initialized in this thread.
+     */
+    @property ref Array!(void[]) _tlsRanges() @nogc nothrow { static Array!(void[]) x; return x; }
+
+    enum _rtLoading = false;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Compiler to runtime interface.
+///////////////////////////////////////////////////////////////////////////////
+
+/*
+ * This data structure is generated by the compiler, and then passed to
+ * _d_dso_registry().
+ */
+struct CompilerDSOData
+{
+    size_t _version;                                       // currently 1
+    void** _slot;                                          // can be used to store runtime data
+    immutable(object.ModuleInfo*)* _minfo_beg, _minfo_end; // array of modules in this object file
+}
+
+T[] toRange(T)(T* beg, T* end) { return beg[0 .. end - beg]; }
+
+/* For each shared library and executable, the compiler generates code that
+ * sets up CompilerDSOData and calls _d_dso_registry().
+ * A pointer to that code is inserted into both the .ctors and .dtors
+ * segment so it gets called by the loader on startup and shutdown.
+ */
+extern(C) void _d_dso_registry(CompilerDSOData* data)
+{
+    // only one supported currently
+    safeAssert(data._version >= 1, "Incompatible compiler-generated DSO data version.");
+
+    // no backlink => register
+    if (*data._slot is null)
+    {
+        immutable firstDSO = _loadedDSOs.empty;
+        if (firstDSO) initLocks();
+
+        DSO* pdso = cast(DSO*).calloc(1, DSO.sizeof);
+        assert(typeid(DSO).initializer().ptr is null);
+        *data._slot = pdso; // store backlink in library record
+
+        pdso._moduleGroup = ModuleGroup(toRange(data._minfo_beg, data._minfo_end));
+
+        dl_phdr_info info = void;
+        const headerFound = findDSOInfoForAddr(data._slot, &info);
+        safeAssert(headerFound, "Failed to find image header.");
+
+        scanSegments(info, pdso);
+
+        version (Shared)
+        {
+            auto handle = handleForAddr(data._slot);
+
+            getDependencies(info, pdso._deps);
+            pdso._handle = handle;
+            setDSOForHandle(pdso, pdso._handle);
+
+            if (!_rtLoading)
+            {
+                /* This DSO was not loaded by rt_loadLibrary which
+                 * happens for all dependencies of an executable or
+                 * the first dlopen call from a C program.
+                 * In this case we add the DSO to the _loadedDSOs of this
+                 * thread with a refCnt of 1 and call the TlsCtors.
+                 */
+                immutable ushort refCnt = 1, addCnt = 0;
+                _loadedDSOs.insertBack(ThreadDSO(pdso, refCnt, addCnt, pdso.tlsRange()));
+            }
+        }
+        else
+        {
+            foreach (p; _loadedDSOs)
+                safeAssert(p !is pdso, "DSO already registered.");
+            _loadedDSOs.insertBack(pdso);
+            _tlsRanges.insertBack(pdso.tlsRange());
+        }
+
+        // don't initialize modules before rt_init was called (see Bugzilla 11378)
+        if (_isRuntimeInitialized)
+        {
+            registerGCRanges(pdso);
+            // rt_loadLibrary will run tls ctors, so do this only for dlopen
+            immutable runTlsCtors = !_rtLoading;
+            runModuleConstructors(pdso, runTlsCtors);
+        }
+    }
+    // has backlink => unregister
+    else
+    {
+        DSO* pdso = cast(DSO*)*data._slot;
+        *data._slot = null;
+
+        // don't finalizes modules after rt_term was called (see Bugzilla 11378)
+        if (_isRuntimeInitialized)
+        {
+            // rt_unloadLibrary already ran tls dtors, so do this only for dlclose
+            immutable runTlsDtors = !_rtLoading;
+            runModuleDestructors(pdso, runTlsDtors);
+            unregisterGCRanges(pdso);
+            // run finalizers after module dtors (same order as in rt_term)
+            version (Shared) runFinalizers(pdso);
+        }
+
+        version (Shared)
+        {
+            if (!_rtLoading)
+            {
+                /* This DSO was not unloaded by rt_unloadLibrary so we
+                 * have to remove it from _loadedDSOs here.
+                 */
+                foreach (i, ref tdso; _loadedDSOs)
+                {
+                    if (tdso._pdso == pdso)
+                    {
+                        _loadedDSOs.remove(i);
+                        break;
+                    }
+                }
+            }
+
+            unsetDSOForHandle(pdso, pdso._handle);
+        }
+        else
+        {
+            // static DSOs are unloaded in reverse order
+            safeAssert(pdso == _loadedDSOs.back, "DSO being unregistered isn't current last one.");
+            _loadedDSOs.popBack();
+        }
+
+        freeDSO(pdso);
+
+        // last DSO being unloaded => shutdown registry
+        if (_loadedDSOs.empty)
+        {
+            version (Shared)
+            {
+                safeAssert(_handleToDSO.empty, "_handleToDSO not in sync with _loadedDSOs.");
+                _handleToDSO.reset();
+            }
+            finiLocks();
+        }
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Dynamic loading
+///////////////////////////////////////////////////////////////////////////////
+
+// Shared D libraries are only supported when linking against a shared druntime library.
+
+version (Shared)
+{
+    ThreadDSO* findThreadDSO(DSO* pdso) nothrow @nogc
+    {
+        foreach (ref tdata; _loadedDSOs)
+            if (tdata._pdso == pdso) return &tdata;
+        return null;
+    }
+
+    void incThreadRef(DSO* pdso, bool incAdd)
+    {
+        if (auto tdata = findThreadDSO(pdso)) // already initialized
+        {
+            if (incAdd && ++tdata._addCnt > 1) return;
+            ++tdata._refCnt;
+        }
+        else
+        {
+            foreach (dep; pdso._deps)
+                incThreadRef(dep, false);
+            immutable ushort refCnt = 1, addCnt = incAdd ? 1 : 0;
+            _loadedDSOs.insertBack(ThreadDSO(pdso, refCnt, addCnt, pdso.tlsRange()));
+            pdso._moduleGroup.runTlsCtors();
+        }
+    }
+
+    void decThreadRef(DSO* pdso, bool decAdd)
+    {
+        auto tdata = findThreadDSO(pdso);
+        safeAssert(tdata !is null, "Failed to find thread DSO.");
+        safeAssert(!decAdd || tdata._addCnt > 0, "Mismatching rt_unloadLibrary call.");
+
+        if (decAdd && --tdata._addCnt > 0) return;
+        if (--tdata._refCnt > 0) return;
+
+        pdso._moduleGroup.runTlsDtors();
+        foreach (i, ref td; _loadedDSOs)
+            if (td._pdso == pdso) _loadedDSOs.remove(i);
+        foreach (dep; pdso._deps)
+            decThreadRef(dep, false);
+    }
+
+    extern(C) void* rt_loadLibrary(const char* name)
+    {
+        immutable save = _rtLoading;
+        _rtLoading = true;
+        scope (exit) _rtLoading = save;
+
+        auto handle = .dlopen(name, RTLD_LAZY);
+        if (handle is null) return null;
+
+        // if it's a D library
+        if (auto pdso = dsoForHandle(handle))
+            incThreadRef(pdso, true);
+        return handle;
+    }
+
+    extern(C) int rt_unloadLibrary(void* handle)
+    {
+        if (handle is null) return false;
+
+        immutable save = _rtLoading;
+        _rtLoading = true;
+        scope (exit) _rtLoading = save;
+
+        // if it's a D library
+        if (auto pdso = dsoForHandle(handle))
+            decThreadRef(pdso, true);
+        return .dlclose(handle) == 0;
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Helper functions
+///////////////////////////////////////////////////////////////////////////////
+
+void initLocks() nothrow @nogc
+{
+    version (Shared)
+        !pthread_mutex_init(&_handleToDSOMutex, null) || assert(0);
+}
+
+void finiLocks() nothrow @nogc
+{
+    version (Shared)
+        !pthread_mutex_destroy(&_handleToDSOMutex) || assert(0);
+}
+
+void runModuleConstructors(DSO* pdso, bool runTlsCtors)
+{
+    pdso._moduleGroup.sortCtors();
+    pdso._moduleGroup.runCtors();
+    if (runTlsCtors) pdso._moduleGroup.runTlsCtors();
+}
+
+void runModuleDestructors(DSO* pdso, bool runTlsDtors)
+{
+    if (runTlsDtors) pdso._moduleGroup.runTlsDtors();
+    pdso._moduleGroup.runDtors();
+}
+
+void registerGCRanges(DSO* pdso) nothrow @nogc
+{
+    foreach (rng; pdso._gcRanges)
+        GC.addRange(rng.ptr, rng.length);
+}
+
+void unregisterGCRanges(DSO* pdso) nothrow @nogc
+{
+    foreach (rng; pdso._gcRanges)
+        GC.removeRange(rng.ptr);
+}
+
+version (Shared) void runFinalizers(DSO* pdso)
+{
+    foreach (seg; pdso._codeSegments)
+        GC.runFinalizers(seg);
+}
+
+void freeDSO(DSO* pdso) nothrow @nogc
+{
+    pdso._gcRanges.reset();
+    version (Shared)
+    {
+        pdso._codeSegments.reset();
+        pdso._deps.reset();
+        pdso._handle = null;
+    }
+    .free(pdso);
+}
+
+version (Shared)
+{
+@nogc nothrow:
+    link_map* linkMapForHandle(void* handle)
+    {
+        link_map* map;
+        const success = dlinfo(handle, RTLD_DI_LINKMAP, &map) == 0;
+        safeAssert(success, "Failed to get DSO info.");
+        return map;
+    }
+
+     link_map* exeLinkMap(link_map* map)
+     {
+         safeAssert(map !is null, "Invalid link_map.");
+         while (map.l_prev !is null)
+             map = map.l_prev;
+         return map;
+     }
+
+    DSO* dsoForHandle(void* handle)
+    {
+        DSO* pdso;
+        !pthread_mutex_lock(&_handleToDSOMutex) || assert(0);
+        if (auto ppdso = handle in _handleToDSO)
+            pdso = *ppdso;
+        !pthread_mutex_unlock(&_handleToDSOMutex) || assert(0);
+        return pdso;
+    }
+
+    void setDSOForHandle(DSO* pdso, void* handle)
+    {
+        !pthread_mutex_lock(&_handleToDSOMutex) || assert(0);
+        safeAssert(handle !in _handleToDSO, "DSO already registered.");
+        _handleToDSO[handle] = pdso;
+        !pthread_mutex_unlock(&_handleToDSOMutex) || assert(0);
+    }
+
+    void unsetDSOForHandle(DSO* pdso, void* handle)
+    {
+        !pthread_mutex_lock(&_handleToDSOMutex) || assert(0);
+        safeAssert(_handleToDSO[handle] == pdso, "Handle doesn't match registered DSO.");
+        _handleToDSO.remove(handle);
+        !pthread_mutex_unlock(&_handleToDSOMutex) || assert(0);
+    }
+
+    void getDependencies(in ref dl_phdr_info info, ref Array!(DSO*) deps)
+    {
+        // get the entries of the .dynamic section
+        ElfW!"Dyn"[] dyns;
+        foreach (ref phdr; info.dlpi_phdr[0 .. info.dlpi_phnum])
+        {
+            if (phdr.p_type == PT_DYNAMIC)
+            {
+                auto p = cast(ElfW!"Dyn"*)(info.dlpi_addr + (phdr.p_vaddr & ~(size_t.sizeof - 1)));
+                dyns = p[0 .. phdr.p_memsz / ElfW!"Dyn".sizeof];
+                break;
+            }
+        }
+        // find the string table which contains the sonames
+        const(char)* strtab;
+        foreach (dyn; dyns)
+        {
+            if (dyn.d_tag == DT_STRTAB)
+            {
+                version (CRuntime_Musl)
+                    strtab = cast(const(char)*)(info.dlpi_addr + dyn.d_un.d_ptr); // relocate
+                else version (linux)
+                    strtab = cast(const(char)*)dyn.d_un.d_ptr;
+                else version (FreeBSD)
+                    strtab = cast(const(char)*)(info.dlpi_addr + dyn.d_un.d_ptr); // relocate
+                else version (NetBSD)
+                    strtab = cast(const(char)*)(info.dlpi_addr + dyn.d_un.d_ptr); // relocate
+                else version (DragonFlyBSD)
+                    strtab = cast(const(char)*)(info.dlpi_addr + dyn.d_un.d_ptr); // relocate
+                else
+                    static assert(0, "unimplemented");
+                break;
+            }
+        }
+        foreach (dyn; dyns)
+        {
+            immutable tag = dyn.d_tag;
+            if (!(tag == DT_NEEDED || tag == DT_AUXILIARY || tag == DT_FILTER))
+                continue;
+
+            // soname of the dependency
+            auto name = strtab + dyn.d_un.d_val;
+            // get handle without loading the library
+            auto handle = handleForName(name);
+            // the runtime linker has already loaded all dependencies
+            safeAssert(handle !is null, "Failed to get library handle.");
+            // if it's a D library
+            if (auto pdso = dsoForHandle(handle))
+                deps.insertBack(pdso); // append it to the dependencies
+        }
+    }
+
+    void* handleForName(const char* name)
+    {
+        auto handle = .dlopen(name, RTLD_NOLOAD | RTLD_LAZY);
+        if (handle !is null) .dlclose(handle); // drop reference count
+        return handle;
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Elf program header iteration
+///////////////////////////////////////////////////////////////////////////////
+
+/************
+ * Scan segments in Linux dl_phdr_info struct and store
+ * the TLS and writeable data segments in *pdso.
+ */
+void scanSegments(in ref dl_phdr_info info, DSO* pdso) nothrow @nogc
+{
+    foreach (ref phdr; info.dlpi_phdr[0 .. info.dlpi_phnum])
+    {
+        switch (phdr.p_type)
+        {
+        case PT_LOAD:
+            if (phdr.p_flags & PF_W) // writeable data segment
+            {
+                auto beg = cast(void*)(info.dlpi_addr + (phdr.p_vaddr & ~(size_t.sizeof - 1)));
+                pdso._gcRanges.insertBack(beg[0 .. phdr.p_memsz]);
+            }
+            version (Shared) if (phdr.p_flags & PF_X) // code segment
+            {
+                auto beg = cast(void*)(info.dlpi_addr + (phdr.p_vaddr & ~(size_t.sizeof - 1)));
+                pdso._codeSegments.insertBack(beg[0 .. phdr.p_memsz]);
+            }
+            break;
+
+        case PT_TLS: // TLS segment
+            safeAssert(!pdso._tlsSize, "Multiple TLS segments in image header.");
+            pdso._tlsMod = info.dlpi_tls_modid;
+            pdso._tlsSize = phdr.p_memsz;
+            break;
+
+        default:
+            break;
+        }
+    }
+}
+
+/**************************
+ * Input:
+ *      result  where the output is to be written; dl_phdr_info is an OS struct
+ * Returns:
+ *      true if found, and *result is filled in
+ * References:
+ *      http://linux.die.net/man/3/dl_iterate_phdr
+ */
+bool findDSOInfoForAddr(in void* addr, dl_phdr_info* result=null) nothrow @nogc
+{
+    version (linux)       enum IterateManually = true;
+    else version (NetBSD) enum IterateManually = true;
+    else                  enum IterateManually = false;
+
+    static if (IterateManually)
+    {
+        static struct DG { const(void)* addr; dl_phdr_info* result; }
+
+        extern(C) int callback(dl_phdr_info* info, size_t sz, void* arg) nothrow @nogc
+        {
+            auto p = cast(DG*)arg;
+            if (findSegmentForAddr(*info, p.addr))
+            {
+                if (p.result !is null) *p.result = *info;
+                return 1; // break;
+            }
+            return 0; // continue iteration
+        }
+
+        auto dg = DG(addr, result);
+
+        /* OS function that walks through the list of an application's shared objects and
+         * calls 'callback' once for each object, until either all shared objects
+         * have been processed or 'callback' returns a nonzero value.
+         */
+        return dl_iterate_phdr(&callback, &dg) != 0;
+    }
+    else version (FreeBSD)
+    {
+        return !!_rtld_addr_phdr(addr, result);
+    }
+    else version (DragonFlyBSD)
+    {
+        return !!_rtld_addr_phdr(addr, result);
+    }
+    else
+        static assert(0, "unimplemented");
+}
+
+/*********************************
+ * Determine if 'addr' lies within shared object 'info'.
+ * If so, return true and fill in 'result' with the corresponding ELF program header.
+ */
+bool findSegmentForAddr(in ref dl_phdr_info info, in void* addr, ElfW!"Phdr"* result=null) nothrow @nogc
+{
+    if (addr < cast(void*)info.dlpi_addr) // less than base address of object means quick reject
+        return false;
+
+    foreach (ref phdr; info.dlpi_phdr[0 .. info.dlpi_phnum])
+    {
+        auto beg = cast(void*)(info.dlpi_addr + phdr.p_vaddr);
+        if (cast(size_t)(addr - beg) < phdr.p_memsz)
+        {
+            if (result !is null) *result = phdr;
+            return true;
+        }
+    }
+    return false;
+}
+
+version (linux) import core.sys.linux.errno : program_invocation_name;
+// should be in core.sys.freebsd.stdlib
+version (FreeBSD) extern(C) const(char)* getprogname() nothrow @nogc;
+version (DragonFlyBSD) extern(C) const(char)* getprogname() nothrow @nogc;
+version (NetBSD) extern(C) const(char)* getprogname() nothrow @nogc;
+
+@property const(char)* progname() nothrow @nogc
+{
+    version (linux) return program_invocation_name;
+    version (FreeBSD) return getprogname();
+    version (DragonFlyBSD) return getprogname();
+    version (NetBSD) return getprogname();
+}
+
+const(char)[] dsoName(const char* dlpi_name) nothrow @nogc
+{
+    // the main executable doesn't have a name in its dlpi_name field
+    const char* p = dlpi_name[0] != 0 ? dlpi_name : progname;
+    return p[0 .. strlen(p)];
+}
+
+/**************************
+ * Input:
+ *      addr  an internal address of a DSO
+ * Returns:
+ *      the dlopen handle for that DSO or null if addr is not within a loaded DSO
+ */
+version (Shared) void* handleForAddr(void* addr) nothrow @nogc
+{
+    Dl_info info = void;
+    if (dladdr(addr, &info) != 0)
+        return handleForName(info.dli_fname);
+    return null;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// TLS module helper
+///////////////////////////////////////////////////////////////////////////////
+
+
+/*
+ * Returns: the TLS memory range for a given module and the calling
+ * thread or null if that module has no TLS.
+ *
+ * Note: This will cause the TLS memory to be eagerly allocated.
+ */
+struct tls_index
+{
+    version (CRuntime_Glibc)
+    {
+        // For x86_64, fields are of type uint64_t, this is important for x32
+        // where tls_index would otherwise have the wrong size.
+        // See https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/x86_64/dl-tls.h
+        version (X86_64)
+        {
+            ulong ti_module;
+            ulong ti_offset;
+        }
+        else
+        {
+            c_ulong ti_module;
+            c_ulong ti_offset;
+        }
+    }
+    else
+    {
+        size_t ti_module;
+        size_t ti_offset;
+    }
+}
+
+extern(C) void* __tls_get_addr(tls_index* ti) nothrow @nogc;
+
+/* The dynamic thread vector (DTV) pointers may point 0x8000 past the start of
+ * each TLS block. This is at least true for PowerPC and Mips platforms.
+ * See: https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/powerpc/dl-tls.h;h=f7cf6f96ebfb505abfd2f02be0ad0e833107c0cd;hb=HEAD#l34
+ *      https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/mips/dl-tls.h;h=93a6dc050cb144b9f68b96fb3199c60f5b1fcd18;hb=HEAD#l32
+ *      https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/riscv/dl-tls.h;h=ab2d860314de94c18812bc894ff6b3f55368f20f;hb=HEAD#l32
+ */
+version (X86)
+    enum TLS_DTV_OFFSET = 0x0;
+else version (X86_64)
+    enum TLS_DTV_OFFSET = 0x0;
+else version (ARM)
+    enum TLS_DTV_OFFSET = 0x0;
+else version (AArch64)
+    enum TLS_DTV_OFFSET = 0x0;
+else version (RISCV32)
+    enum TLS_DTV_OFFSET = 0x800;
+else version (RISCV64)
+    enum TLS_DTV_OFFSET = 0x800;
+else version (HPPA)
+    enum TLS_DTV_OFFSET = 0x0;
+else version (SPARC)
+    enum TLS_DTV_OFFSET = 0x0;
+else version (SPARC64)
+    enum TLS_DTV_OFFSET = 0x0;
+else version (PPC)
+    enum TLS_DTV_OFFSET = 0x8000;
+else version (PPC64)
+    enum TLS_DTV_OFFSET = 0x8000;
+else version (MIPS32)
+    enum TLS_DTV_OFFSET = 0x8000;
+else version (MIPS64)
+    enum TLS_DTV_OFFSET = 0x8000;
+else
+    static assert( false, "Platform not supported." );
+
+void[] getTLSRange(size_t mod, size_t sz) nothrow @nogc
+{
+    if (mod == 0)
+        return null;
+
+    // base offset
+    auto ti = tls_index(mod, 0);
+    return (__tls_get_addr(&ti)-TLS_DTV_OFFSET)[0 .. sz];
+}
diff --git a/libphobos/libdruntime/gcc/sections/osx.d b/libphobos/libdruntime/gcc/sections/osx.d
new file mode 100644 (file)
index 0000000..55caee4
--- /dev/null
@@ -0,0 +1,284 @@
+// OSX-specific support for sections.
+// Copyright (C) 2019 Free Software Foundation, Inc.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+module gcc.sections.osx;
+
+version (OSX):
+
+// debug = PRINTF;
+import core.stdc.stdio;
+import core.stdc.string, core.stdc.stdlib;
+import core.sys.posix.pthread;
+import core.sys.darwin.mach.dyld;
+import core.sys.darwin.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 nothrow @nogc
+    {
+        return _moduleGroup.modules;
+    }
+
+    @property ref inout(ModuleGroup) moduleGroup() inout nothrow @nogc
+    {
+        return _moduleGroup;
+    }
+
+    @property inout(void[])[] gcRanges() inout nothrow @nogc
+    {
+        return _gcRanges[];
+    }
+
+    @property immutable(FuncTable)[] ehTables() const nothrow @nogc
+    {
+        return _ehTables[];
+    }
+
+private:
+    immutable(FuncTable)[] _ehTables;
+    ModuleGroup _moduleGroup;
+    Array!(void[]) _gcRanges;
+    immutable(void)[][2] _tlsImage;
+}
+
+/****
+ * 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() nothrow @nogc
+{
+    pthread_key_create(&_tlsKey, null);
+    _dyld_register_func_for_add_image(&sections_osx_onAddImage);
+    _isRuntimeInitialized = true;
+}
+
+/***
+ * Gets called on program shutdown just after GC is terminated.
+ */
+void finiSections() nothrow @nogc
+{
+    _sections._gcRanges.reset();
+    pthread_key_delete(_tlsKey);
+    _isRuntimeInitialized = false;
+}
+
+void[]* initTLSRanges() nothrow @nogc
+{
+    return &getTLSBlock();
+}
+
+void finiTLSRanges(void[]* rng) nothrow @nogc
+{
+    .free(rng.ptr);
+    .free(rng);
+}
+
+void scanTLSRanges(void[]* rng, scope void delegate(void* pbeg, void* pend) nothrow dg) nothrow
+{
+    dg(rng.ptr, rng.ptr + rng.length);
+}
+
+// NOTE: The Mach-O object file format does not allow for thread local
+//       storage declarations. So instead we roll our own by putting tls
+//       into the __tls_data and the __tlscoal_nt sections.
+//
+//       This function is called by the code emitted by the compiler.  It
+//       is expected to translate an address into the TLS static data to
+//       the corresponding address in the TLS dynamic per-thread data.
+
+// NB: the compiler mangles this function as '___tls_get_addr' even though it is extern(D)
+extern(D) void* ___tls_get_addr( void* p )
+{
+    immutable off = tlsOffset(p);
+    auto tls = getTLSBlockAlloc();
+    assert(off < tls.length);
+    return tls.ptr + off;
+}
+
+private:
+
+__gshared pthread_key_t _tlsKey;
+
+size_t tlsOffset(void* p)
+in
+{
+    assert(_sections._tlsImage[0].ptr !is null ||
+           _sections._tlsImage[1].ptr !is null);
+}
+body
+{
+    // NOTE: p is an address in the TLS static data emitted by the
+    //       compiler.  If it isn't, something is disastrously wrong.
+    immutable off0 = cast(size_t)(p - _sections._tlsImage[0].ptr);
+    if (off0 < _sections._tlsImage[0].length)
+    {
+        return off0;
+    }
+    immutable off1 = cast(size_t)(p - _sections._tlsImage[1].ptr);
+    if (off1 < _sections._tlsImage[1].length)
+    {
+        size_t sz = (_sections._tlsImage[0].length + 15) & ~cast(size_t)15;
+        return sz + off1;
+    }
+    assert(0);
+}
+
+ref void[] getTLSBlock() nothrow @nogc
+{
+    auto pary = cast(void[]*)pthread_getspecific(_tlsKey);
+    if (pary is null)
+    {
+        pary = cast(void[]*).calloc(1, (void[]).sizeof);
+        if (pthread_setspecific(_tlsKey, pary) != 0)
+        {
+            import core.stdc.stdio;
+            perror("pthread_setspecific failed with");
+            assert(0);
+        }
+    }
+    return *pary;
+}
+
+ref void[] getTLSBlockAlloc()
+{
+    auto pary = &getTLSBlock();
+    if (!pary.length)
+    {
+        auto imgs = _sections._tlsImage;
+        immutable sz0 = (imgs[0].length + 15) & ~cast(size_t)15;
+        immutable sz2 = sz0 + imgs[1].length;
+        auto p = .malloc(sz2);
+        memcpy(p, imgs[0].ptr, imgs[0].length);
+        memcpy(p + sz0, imgs[1].ptr, imgs[1].length);
+        *pary = p[0 .. sz2];
+    }
+    return *pary;
+}
+
+__gshared SectionGroup _sections;
+
+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];
+    }
+
+    auto tlssect = getSection(h, slide, "__DATA", "__tls_data");
+    if (tlssect != null)
+    {
+        debug(PRINTF) printf("  tls_data %p %p\n", tlssect.ptr, tlssect.ptr + tlssect.length);
+        _sections._tlsImage[0] = (cast(immutable(void)*)tlssect.ptr)[0 .. tlssect.length];
+    }
+
+    auto tlssect2 = getSection(h, slide, "__DATA", "__tlscoal_nt");
+    if (tlssect2 != null)
+    {
+        debug(PRINTF) printf("  tlscoal_nt %p %p\n", tlssect2.ptr, tlssect2.ptr + tlssect2.length);
+        _sections._tlsImage[1] = (cast(immutable(void)*)tlssect2.ptr)[0 .. tlssect2.length];
+    }
+}
+
+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)
+{
+    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");
+
+    if (sect !is null && sect.size > 0)
+        return (cast(ubyte*)sect.addr + slide)[0 .. cast(size_t)sect.size];
+    return null;
+}
diff --git a/libphobos/libdruntime/gcc/sections/package.d b/libphobos/libdruntime/gcc/sections/package.d
new file mode 100644 (file)
index 0000000..07617ea
--- /dev/null
@@ -0,0 +1,48 @@
+// Run-time support for retrieving platform-specific sections.
+// Copyright (C) 2019 Free Software Foundation, Inc.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+module gcc.sections;
+
+version (CRuntime_Glibc)
+    public import gcc.sections.elf_shared;
+else version (CRuntime_Musl)
+    public import gcc.sections.elf_shared;
+else version (CRuntime_UClibc)
+    public import gcc.sections.elf_shared;
+else version (FreeBSD)
+    public import gcc.sections.elf_shared;
+else version (NetBSD)
+    public import gcc.sections.elf_shared;
+else version (DragonFlyBSD)
+    public import gcc.sections.elf_shared;
+else version (Solaris)
+    public import gcc.sections.solaris;
+else version (OSX)
+    public import gcc.sections.osx;
+else version (CRuntime_DigitalMars)
+    public import gcc.sections.win32;
+else version (CRuntime_Microsoft)
+    public import gcc.sections.win64;
+else version (CRuntime_Bionic)
+    public import gcc.sections.android;
+else
+    static assert(0, "unimplemented");
diff --git a/libphobos/libdruntime/gcc/sections/solaris.d b/libphobos/libdruntime/gcc/sections/solaris.d
new file mode 100644 (file)
index 0000000..e66325b
--- /dev/null
@@ -0,0 +1,126 @@
+// Solaris-specific support for sections.
+// Copyright (C) 2019 Free Software Foundation, Inc.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+module gcc.sections.solaris;
+
+version (Solaris):
+
+// debug = PRINTF;
+debug(PRINTF) import core.stdc.stdio;
+import core.stdc.stdlib : malloc, free;
+import rt.deh, rt.minfo;
+
+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 nothrow @nogc
+    {
+        return _moduleGroup.modules;
+    }
+
+    @property ref inout(ModuleGroup) moduleGroup() inout nothrow @nogc
+    {
+        return _moduleGroup;
+    }
+
+    @property immutable(FuncTable)[] ehTables() const nothrow @nogc
+    {
+        auto pbeg = cast(immutable(FuncTable)*)&__start_deh;
+        auto pend = cast(immutable(FuncTable)*)&__stop_deh;
+        return pbeg[0 .. pend - pbeg];
+    }
+
+    @property inout(void[])[] gcRanges() inout nothrow @nogc
+    {
+        return _gcRanges[];
+    }
+
+private:
+    ModuleGroup _moduleGroup;
+    void[][1] _gcRanges;
+}
+
+void initSections() nothrow @nogc
+{
+    auto mbeg = cast(immutable ModuleInfo**)&__start_minfo;
+    auto mend = cast(immutable ModuleInfo**)&__stop_minfo;
+    _sections.moduleGroup = ModuleGroup(mbeg[0 .. mend - mbeg]);
+
+    auto pbeg = cast(void*)&__dso_handle;
+    auto pend = cast(void*)&_end;
+    _sections._gcRanges[0] = pbeg[0 .. pend - pbeg];
+}
+
+void finiSections() nothrow @nogc
+{
+}
+
+void[] initTLSRanges() nothrow @nogc
+{
+    auto pbeg = cast(void*)&_tlsstart;
+    auto pend = cast(void*)&_tlsend;
+    return pbeg[0 .. pend - pbeg];
+}
+
+void finiTLSRanges(void[] rng) nothrow @nogc
+{
+}
+
+void scanTLSRanges(void[] rng, scope void delegate(void* pbeg, void* pend) nothrow dg) nothrow
+{
+    dg(rng.ptr, rng.ptr + rng.length);
+}
+
+private:
+
+__gshared SectionGroup _sections;
+
+extern(C)
+{
+    /* Symbols created by the compiler/linker and inserted into the
+     * object file that 'bracket' sections.
+     */
+    extern __gshared
+    {
+        void* __start_deh;
+        void* __stop_deh;
+        void* __start_minfo;
+        void* __stop_minfo;
+        int __dso_handle;
+        int _end;
+    }
+
+    extern
+    {
+        void* _tlsstart;
+        void* _tlsend;
+    }
+}
diff --git a/libphobos/libdruntime/gcc/sections/win32.d b/libphobos/libdruntime/gcc/sections/win32.d
new file mode 100644 (file)
index 0000000..4b76ca8
--- /dev/null
@@ -0,0 +1,183 @@
+// Win32-specific support for sections.
+// Copyright (C) 2019 Free Software Foundation, Inc.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+module gcc.sections.win32;
+
+version (CRuntime_DigitalMars):
+
+// debug = PRINTF;
+debug(PRINTF) import core.stdc.stdio;
+import rt.minfo;
+import core.stdc.stdlib : malloc, free;
+
+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 nothrow @nogc
+    {
+        return _moduleGroup.modules;
+    }
+
+    @property ref inout(ModuleGroup) moduleGroup() inout nothrow @nogc
+    {
+        return _moduleGroup;
+    }
+
+    @property inout(void[])[] gcRanges() inout nothrow @nogc
+    {
+        return _gcRanges[];
+    }
+
+private:
+    ModuleGroup _moduleGroup;
+    void[][] _gcRanges;
+}
+
+shared(bool) conservative;
+
+void initSections() nothrow @nogc
+{
+    _sections._moduleGroup = ModuleGroup(getModuleInfos());
+
+    import rt.sections;
+    conservative = !scanDataSegPrecisely();
+
+    if (conservative)
+    {
+        _sections._gcRanges = (cast(void[]*) malloc(2 * (void[]).sizeof))[0..2];
+
+        auto databeg = cast(void*)&_xi_a;
+        auto dataend = cast(void*)_moduleinfo_array.ptr;
+        _sections._gcRanges[0] = databeg[0 .. dataend - databeg];
+
+        // skip module info and CONST segment
+        auto bssbeg = cast(void*)&_edata;
+        auto bssend = cast(void*)&_end;
+        _sections._gcRanges[1] = bssbeg[0 .. bssend - bssbeg];
+    }
+    else
+    {
+        size_t count = &_DPend - &_DPbegin;
+        auto ranges = cast(void[]*) malloc(count * (void[]).sizeof);
+        size_t r = 0;
+        void* prev = null;
+        for (size_t i = 0; i < count; i++)
+        {
+            void* addr = (&_DPbegin)[i];
+            if (prev + (void*).sizeof == addr)
+                ranges[r-1] = ranges[r-1].ptr[0 .. ranges[r-1].length + (void*).sizeof];
+            else
+                ranges[r++] = (cast(void**)addr)[0..1];
+            prev = addr;
+        }
+        _sections._gcRanges = ranges[0..r];
+    }
+}
+
+void finiSections() nothrow @nogc
+{
+    free(_sections._gcRanges.ptr);
+}
+
+void[] initTLSRanges() nothrow @nogc
+{
+    auto pbeg = cast(void*)&_tlsstart;
+    auto pend = cast(void*)&_tlsend;
+    return pbeg[0 .. pend - pbeg];
+}
+
+void finiTLSRanges(void[] rng) nothrow @nogc
+{
+}
+
+void scanTLSRanges(void[] rng, scope void delegate(void* pbeg, void* pend) nothrow dg) nothrow
+{
+    if (conservative)
+    {
+        dg(rng.ptr, rng.ptr + rng.length);
+    }
+    else
+    {
+        for (auto p = &_TPbegin; p < &_TPend; )
+        {
+            uint beg = *p++;
+            uint end = beg + cast(uint)((void*).sizeof);
+            while (p < &_TPend && *p == end)
+            {
+                end += (void*).sizeof;
+                p++;
+            }
+            dg(rng.ptr + beg, rng.ptr + end);
+        }
+    }
+}
+
+private:
+
+__gshared SectionGroup _sections;
+
+// Windows: this gets initialized by minit.asm
+extern(C) __gshared immutable(ModuleInfo*)[] _moduleinfo_array;
+extern(C) void _minit() nothrow @nogc;
+
+immutable(ModuleInfo*)[] getModuleInfos() nothrow @nogc
+out (result)
+{
+    foreach (m; result)
+        assert(m !is null);
+}
+body
+{
+    // _minit directly alters the global _moduleinfo_array
+    _minit();
+    return _moduleinfo_array;
+}
+
+extern(C)
+{
+    extern __gshared
+    {
+        int _xi_a;      // &_xi_a just happens to be start of data segment
+        int _edata;     // &_edata is start of BSS segment
+        int _end;       // &_end is past end of BSS
+
+        void* _DPbegin; // first entry in the array of pointers addresses
+        void* _DPend;   // &_DPend points after last entry of array
+        uint _TPbegin;  // first entry in the array of TLS offsets of pointers
+        uint _TPend;    // &_DPend points after last entry of array
+    }
+
+    extern
+    {
+        int _tlsstart;
+        int _tlsend;
+    }
+}
diff --git a/libphobos/libdruntime/gcc/sections/win64.d b/libphobos/libdruntime/gcc/sections/win64.d
new file mode 100644 (file)
index 0000000..b98c352
--- /dev/null
@@ -0,0 +1,321 @@
+// Win64-specific support for sections.
+// Copyright (C) 2019 Free Software Foundation, Inc.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+module gcc.sections.win64;
+
+version (CRuntime_Microsoft):
+
+// debug = PRINTF;
+debug(PRINTF) import core.stdc.stdio;
+import core.stdc.stdlib : malloc, free;
+import rt.deh, rt.minfo;
+
+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 nothrow @nogc
+    {
+        return _moduleGroup.modules;
+    }
+
+    @property ref inout(ModuleGroup) moduleGroup() inout nothrow @nogc
+    {
+        return _moduleGroup;
+    }
+
+    version (Win64)
+    @property immutable(FuncTable)[] ehTables() const nothrow @nogc
+    {
+        auto pbeg = cast(immutable(FuncTable)*)&_deh_beg;
+        auto pend = cast(immutable(FuncTable)*)&_deh_end;
+        return pbeg[0 .. pend - pbeg];
+    }
+
+    @property inout(void[])[] gcRanges() inout nothrow @nogc
+    {
+        return _gcRanges[];
+    }
+
+private:
+    ModuleGroup _moduleGroup;
+    void[][] _gcRanges;
+}
+
+shared(bool) conservative;
+
+void initSections() nothrow @nogc
+{
+    _sections._moduleGroup = ModuleGroup(getModuleInfos());
+
+    // the ".data" image section includes both object file sections ".data" and ".bss"
+    void[] dataSection = findImageSection(".data");
+    debug(PRINTF) printf("found .data section: [%p,+%llx]\n", dataSection.ptr,
+                         cast(ulong)dataSection.length);
+
+    import rt.sections;
+    conservative = !scanDataSegPrecisely();
+
+    if (conservative)
+    {
+        _sections._gcRanges = (cast(void[]*) malloc((void[]).sizeof))[0..1];
+        _sections._gcRanges[0] = dataSection;
+    }
+    else
+    {
+        size_t count = &_DP_end - &_DP_beg;
+        auto ranges = cast(void[]*) malloc(count * (void[]).sizeof);
+        size_t r = 0;
+        void* prev = null;
+        for (size_t i = 0; i < count; i++)
+        {
+            auto off = (&_DP_beg)[i];
+            if (off == 0) // skip zero entries added by incremental linking
+                continue; // assumes there is no D-pointer at the very beginning of .data
+            void* addr = dataSection.ptr + off;
+            debug(PRINTF) printf("  scan %p\n", addr);
+            // combine consecutive pointers into single range
+            if (prev + (void*).sizeof == addr)
+                ranges[r-1] = ranges[r-1].ptr[0 .. ranges[r-1].length + (void*).sizeof];
+            else
+                ranges[r++] = (cast(void**)addr)[0..1];
+            prev = addr;
+        }
+        _sections._gcRanges = ranges[0..r];
+    }
+}
+
+void finiSections() nothrow @nogc
+{
+    .free(cast(void*)_sections.modules.ptr);
+    .free(_sections._gcRanges.ptr);
+}
+
+void[] initTLSRanges() nothrow @nogc
+{
+    void* pbeg;
+    void* pend;
+    // with VS2017 15.3.1, the linker no longer puts TLS segments into a
+    //  separate image section. That way _tls_start and _tls_end no
+    //  longer generate offsets into .tls, but DATA.
+    // Use the TEB entry to find the start of TLS instead and read the
+    //  length from the TLS directory
+    version (D_InlineAsm_X86)
+    {
+        asm @nogc nothrow
+        {
+            mov EAX, _tls_index;
+            mov ECX, FS:[0x2C];     // _tls_array
+            mov EAX, [ECX+4*EAX];
+            mov pbeg, EAX;
+            add EAX, [_tls_used+4]; // end
+            sub EAX, [_tls_used+0]; // start
+            mov pend, EAX;
+        }
+    }
+    else version (D_InlineAsm_X86_64)
+    {
+        asm @nogc nothrow
+        {
+            xor RAX, RAX;
+            mov EAX, _tls_index;
+            mov RCX, 0x58;
+            mov RCX, GS:[RCX];      // _tls_array (immediate value causes fixup)
+            mov RAX, [RCX+8*RAX];
+            mov pbeg, RAX;
+            add RAX, [_tls_used+8]; // end
+            sub RAX, [_tls_used+0]; // start
+            mov pend, RAX;
+        }
+    }
+    else
+        static assert(false, "Architecture not supported.");
+
+    return pbeg[0 .. pend - pbeg];
+}
+
+void finiTLSRanges(void[] rng) nothrow @nogc
+{
+}
+
+void scanTLSRanges(void[] rng, scope void delegate(void* pbeg, void* pend) nothrow dg) nothrow
+{
+    if (conservative)
+    {
+        dg(rng.ptr, rng.ptr + rng.length);
+    }
+    else
+    {
+        for (auto p = &_TP_beg; p < &_TP_end; )
+        {
+            uint beg = *p++;
+            uint end = beg + cast(uint)((void*).sizeof);
+            while (p < &_TP_end && *p == end)
+            {
+                end += (void*).sizeof;
+                p++;
+            }
+            dg(rng.ptr + beg, rng.ptr + end);
+        }
+    }
+}
+
+private:
+__gshared SectionGroup _sections;
+
+extern(C)
+{
+    extern __gshared void* _minfo_beg;
+    extern __gshared void* _minfo_end;
+}
+
+immutable(ModuleInfo*)[] getModuleInfos() nothrow @nogc
+out (result)
+{
+    foreach (m; result)
+        assert(m !is null);
+}
+body
+{
+    auto m = (cast(immutable(ModuleInfo*)*)&_minfo_beg)[1 .. &_minfo_end - &_minfo_beg];
+    /* Because of alignment inserted by the linker, various null pointers
+     * are there. We need to filter them out.
+     */
+    auto p = m.ptr;
+    auto pend = m.ptr + m.length;
+
+    // count non-null pointers
+    size_t cnt;
+    for (; p < pend; ++p)
+    {
+        if (*p !is null) ++cnt;
+    }
+
+    auto result = (cast(immutable(ModuleInfo)**).malloc(cnt * size_t.sizeof))[0 .. cnt];
+
+    p = m.ptr;
+    cnt = 0;
+    for (; p < pend; ++p)
+        if (*p !is null) result[cnt++] = *p;
+
+    return cast(immutable)result;
+}
+
+extern(C)
+{
+    /* Symbols created by the compiler/linker and inserted into the
+     * object file that 'bracket' sections.
+     */
+    extern __gshared
+    {
+        void* __ImageBase;
+
+        void* _deh_beg;
+        void* _deh_end;
+
+        uint _DP_beg;
+        uint _DP_end;
+        uint _TP_beg;
+        uint _TP_end;
+
+        void*[2] _tls_used; // start, end
+        int _tls_index;
+    }
+}
+
+/////////////////////////////////////////////////////////////////////
+
+enum IMAGE_DOS_SIGNATURE = 0x5A4D;      // MZ
+
+struct IMAGE_DOS_HEADER // DOS .EXE header
+{
+    ushort   e_magic;    // Magic number
+    ushort[29] e_res2;   // Reserved ushorts
+    int      e_lfanew;   // File address of new exe header
+}
+
+struct IMAGE_FILE_HEADER
+{
+    ushort Machine;
+    ushort NumberOfSections;
+    uint   TimeDateStamp;
+    uint   PointerToSymbolTable;
+    uint   NumberOfSymbols;
+    ushort SizeOfOptionalHeader;
+    ushort Characteristics;
+}
+
+struct IMAGE_NT_HEADERS
+{
+    uint Signature;
+    IMAGE_FILE_HEADER FileHeader;
+    // optional header follows
+}
+
+struct IMAGE_SECTION_HEADER
+{
+    char[8] Name = 0;
+    union {
+        uint   PhysicalAddress;
+        uint   VirtualSize;
+    }
+    uint   VirtualAddress;
+    uint   SizeOfRawData;
+    uint   PointerToRawData;
+    uint   PointerToRelocations;
+    uint   PointerToLinenumbers;
+    ushort NumberOfRelocations;
+    ushort NumberOfLinenumbers;
+    uint   Characteristics;
+}
+
+bool compareSectionName(ref IMAGE_SECTION_HEADER section, string name) nothrow @nogc
+{
+    if (name[] != section.Name[0 .. name.length])
+        return false;
+    return name.length == 8 || section.Name[name.length] == 0;
+}
+
+void[] findImageSection(string name) nothrow @nogc
+{
+    if (name.length > 8) // section name from string table not supported
+        return null;
+    IMAGE_DOS_HEADER* doshdr = cast(IMAGE_DOS_HEADER*) &__ImageBase;
+    if (doshdr.e_magic != IMAGE_DOS_SIGNATURE)
+        return null;
+
+    auto nthdr = cast(IMAGE_NT_HEADERS*)(cast(void*)doshdr + doshdr.e_lfanew);
+    auto sections = cast(IMAGE_SECTION_HEADER*)(cast(void*)nthdr + IMAGE_NT_HEADERS.sizeof + nthdr.FileHeader.SizeOfOptionalHeader);
+    for (ushort i = 0; i < nthdr.FileHeader.NumberOfSections; i++)
+        if (compareSectionName (sections[i], name))
+            return (cast(void*)&__ImageBase + sections[i].VirtualAddress)[0 .. sections[i].VirtualSize];
+
+    return null;
+}
diff --git a/libphobos/libdruntime/rt/bss_section.c b/libphobos/libdruntime/rt/bss_section.c
deleted file mode 100644 (file)
index b00f40d..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-/**
- * This module is used to detect copy relocated ModuleInfos (located in .bss section).
- *
- * Copyright: Copyright Martin Nowak 2014-.
- * License:   $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
- * Authors:   Martin Nowak
- * Source: $(DRUNTIMESRC src/rt/_bss_section.c)
- */
-
-/* These symbols are defined in the linker script and bracket the
- * .bss, .lbss, .lrodata and .ldata sections.
- */
-#if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__)
-// Need to use weak linkage to workaround a bug in ld.bfd (Bugzilla 13025).
-extern int __attribute__((weak)) __bss_start, _end;
-
-__attribute__ ((visibility ("hidden"))) void* rt_get_bss_start();
-__attribute__ ((visibility ("hidden"))) void* rt_get_end();
-void* rt_get_bss_start() { return (void*)&__bss_start; }
-void* rt_get_end() { return (void*)&_end; }
-#endif
index 53357f681907e95dd1d8b878271abbdfac6f27a6..6009a79abc5d1d1384c75d1e13d0bfa97d53fc99 100644 (file)
@@ -8,6 +8,9 @@
  * Source: $(DRUNTIMESRC src/rt/_sections.d)
  */
 
+/* NOTE: This file has been patched from the original DMD distribution to
+ * work with the GDC compiler.
+ */
 module rt.sections;
 
 version (OSX)
@@ -19,7 +22,9 @@ else version (TVOS)
 else version (WatchOS)
     version = Darwin;
 
-version (CRuntime_Glibc)
+version (GNU)
+    public import gcc.sections;
+else version (CRuntime_Glibc)
     public import rt.sections_elf_shared;
 else version (FreeBSD)
     public import rt.sections_elf_shared;
diff --git a/libphobos/libdruntime/rt/sections_android.d b/libphobos/libdruntime/rt/sections_android.d
deleted file mode 100644 (file)
index 16c5465..0000000
+++ /dev/null
@@ -1,188 +0,0 @@
-/**
- * Written in the D programming language.
- * This module provides bionic-specific support for sections.
- *
- * Copyright: Copyright Martin Nowak 2012-2013.
- * License:   $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
- * Authors:   Martin Nowak
- * Source: $(DRUNTIMESRC src/rt/_sections_android.d)
- */
-
-module rt.sections_android;
-
-version (CRuntime_Bionic):
-
-// debug = PRINTF;
-debug(PRINTF) import core.stdc.stdio;
-import core.stdc.stdlib : malloc, free;
-import rt.deh, rt.minfo;
-import core.sys.posix.pthread;
-import core.stdc.stdlib : calloc;
-import core.stdc.string : memcpy;
-
-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 nothrow @nogc
-    {
-        return _moduleGroup.modules;
-    }
-
-    @property ref inout(ModuleGroup) moduleGroup() inout nothrow @nogc
-    {
-        return _moduleGroup;
-    }
-
-    @property immutable(FuncTable)[] ehTables() const nothrow @nogc
-    {
-        auto pbeg = cast(immutable(FuncTable)*)&__start_deh;
-        auto pend = cast(immutable(FuncTable)*)&__stop_deh;
-        return pbeg[0 .. pend - pbeg];
-    }
-
-    @property inout(void[])[] gcRanges() inout nothrow @nogc
-    {
-        return _gcRanges[];
-    }
-
-private:
-    ModuleGroup _moduleGroup;
-    void[][1] _gcRanges;
-}
-
-void initSections() nothrow @nogc
-{
-    pthread_key_create(&_tlsKey, null);
-
-    auto mbeg = cast(immutable ModuleInfo**)&__start_minfo;
-    auto mend = cast(immutable ModuleInfo**)&__stop_minfo;
-    _sections.moduleGroup = ModuleGroup(mbeg[0 .. mend - mbeg]);
-
-    auto pbeg = cast(void*)&_tlsend;
-    auto pend = cast(void*)&__bss_end__;
-    _sections._gcRanges[0] = pbeg[0 .. pend - pbeg];
-}
-
-void finiSections() nothrow @nogc
-{
-    pthread_key_delete(_tlsKey);
-}
-
-void[]* initTLSRanges() nothrow @nogc
-{
-    return &getTLSBlock();
-}
-
-void finiTLSRanges(void[]* rng) nothrow @nogc
-{
-    .free(rng.ptr);
-    .free(rng);
-}
-
-void scanTLSRanges(void[]* rng, scope void delegate(void* pbeg, void* pend) nothrow dg) nothrow
-{
-    dg(rng.ptr, rng.ptr + rng.length);
-}
-
-/* NOTE: The Bionic C library ignores thread-local data stored in the normal
- *       .tbss/.tdata ELF sections, which are marked with the SHF_TLS/STT_TLS
- *       flags.  So instead we roll our own by keeping TLS data in the
- *       .tdata/.tbss sections but removing the SHF_TLS/STT_TLS flags, and
- *       access the TLS data using this function and the _tlsstart/_tlsend
- *       symbols as delimiters.
- *
- *       This function is called by the code emitted by the compiler.  It
- *       is expected to translate an address in the TLS static data to
- *       the corresponding address in the TLS dynamic per-thread data.
- */
-
-version (X86)
-{
-    // NB: the compiler mangles this function as '___tls_get_addr'
-    // even though it is extern(D)
-    extern(D) void* ___tls_get_addr( void* p ) nothrow @nogc
-    {
-        debug(PRINTF) printf("  ___tls_get_addr input - %p\n", p);
-        immutable offset = cast(size_t)(p - cast(void*)&_tlsstart);
-        auto tls = getTLSBlockAlloc();
-        assert(offset < tls.length);
-        return tls.ptr + offset;
-    }
-}
-else version (ARM)
-{
-    extern(C) void* __tls_get_addr( void** p ) nothrow @nogc
-    {
-        debug(PRINTF) printf("  __tls_get_addr input - %p\n", *p);
-        immutable offset = cast(size_t)(*p - cast(void*)&_tlsstart);
-        auto tls = getTLSBlockAlloc();
-        assert(offset < tls.length);
-        return tls.ptr + offset;
-    }
-}
-else
-    static assert( false, "Android architecture not supported." );
-
-private:
-
-__gshared pthread_key_t _tlsKey;
-
-ref void[] getTLSBlock() nothrow @nogc
-{
-    auto pary = cast(void[]*)pthread_getspecific(_tlsKey);
-    if (pary is null)
-    {
-        pary = cast(void[]*).calloc(1, (void[]).sizeof);
-        if (pthread_setspecific(_tlsKey, pary) != 0)
-        {
-            import core.stdc.stdio;
-            perror("pthread_setspecific failed with");
-            assert(0);
-        }
-    }
-    return *pary;
-}
-
-ref void[] getTLSBlockAlloc() nothrow @nogc
-{
-    auto pary = &getTLSBlock();
-    if (!pary.length)
-    {
-        auto pbeg = cast(void*)&_tlsstart;
-        auto pend = cast(void*)&_tlsend;
-        auto p = .malloc(pend - pbeg);
-        memcpy(p, pbeg, pend - pbeg);
-        *pary = p[0 .. pend - pbeg];
-    }
-    return *pary;
-}
-
-__gshared SectionGroup _sections;
-
-extern(C)
-{
-    /* Symbols created by the compiler/linker and inserted into the
-     * object file that 'bracket' sections.
-     */
-    extern __gshared
-    {
-        void* __start_deh;
-        void* __stop_deh;
-        void* __start_minfo;
-        void* __stop_minfo;
-
-        size_t __bss_end__;
-
-        void* _tlsstart;
-        void* _tlsend;
-    }
-}
diff --git a/libphobos/libdruntime/rt/sections_elf_shared.d b/libphobos/libdruntime/rt/sections_elf_shared.d
deleted file mode 100644 (file)
index d4e1ff0..0000000
+++ /dev/null
@@ -1,1026 +0,0 @@
-/**
- * Written in the D programming language.
- * This module provides ELF-specific support for sections with shared libraries.
- *
- * Copyright: Copyright Martin Nowak 2012-2013.
- * License:   $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
- * Authors:   Martin Nowak
- * Source: $(DRUNTIMESRC src/rt/_sections_linux.d)
- */
-
-module rt.sections_elf_shared;
-
-version (CRuntime_Glibc) enum SharedELF = true;
-else version (FreeBSD) enum SharedELF = true;
-else version (NetBSD) enum SharedELF = true;
-else enum SharedELF = false;
-static if (SharedELF):
-
-// debug = PRINTF;
-import core.memory;
-import core.stdc.config;
-import core.stdc.stdio;
-import core.stdc.stdlib : calloc, exit, free, malloc, EXIT_FAILURE;
-import core.stdc.string : strlen;
-version (linux)
-{
-    import core.sys.linux.dlfcn;
-    import core.sys.linux.elf;
-    import core.sys.linux.link;
-}
-else version (FreeBSD)
-{
-    import core.sys.freebsd.dlfcn;
-    import core.sys.freebsd.sys.elf;
-    import core.sys.freebsd.sys.link_elf;
-}
-else version (NetBSD)
-{
-    import core.sys.netbsd.dlfcn;
-    import core.sys.netbsd.sys.elf;
-    import core.sys.netbsd.sys.link_elf;
-}
-else
-{
-    static assert(0, "unimplemented");
-}
-import core.sys.posix.pthread;
-import rt.deh;
-import rt.dmain2;
-import rt.minfo;
-import rt.util.container.array;
-import rt.util.container.hashtab;
-
-alias DSO SectionGroup;
-struct DSO
-{
-    static int opApply(scope int delegate(ref DSO) dg)
-    {
-        foreach (dso; _loadedDSOs)
-        {
-            if (auto res = dg(*dso))
-                return res;
-        }
-        return 0;
-    }
-
-    static int opApplyReverse(scope int delegate(ref DSO) dg)
-    {
-        foreach_reverse (dso; _loadedDSOs)
-        {
-            if (auto res = dg(*dso))
-                return res;
-        }
-        return 0;
-    }
-
-    @property immutable(ModuleInfo*)[] modules() const nothrow @nogc
-    {
-        return _moduleGroup.modules;
-    }
-
-    @property ref inout(ModuleGroup) moduleGroup() inout nothrow @nogc
-    {
-        return _moduleGroup;
-    }
-
-    @property immutable(FuncTable)[] ehTables() const nothrow @nogc
-    {
-        return null;
-    }
-
-    @property inout(void[])[] gcRanges() inout nothrow @nogc
-    {
-        return _gcRanges[];
-    }
-
-private:
-
-    invariant()
-    {
-        assert(_moduleGroup.modules.length);
-        assert(_tlsMod || !_tlsSize);
-    }
-
-    ModuleGroup _moduleGroup;
-    Array!(void[]) _gcRanges;
-    size_t _tlsMod;
-    size_t _tlsSize;
-
-    version (Shared)
-    {
-        Array!(void[]) _codeSegments; // array of code segments
-        Array!(DSO*) _deps; // D libraries needed by this DSO
-        void* _handle; // corresponding handle
-    }
-}
-
-/****
- * Boolean flag set to true while the runtime is initialized.
- */
-__gshared bool _isRuntimeInitialized;
-
-
-version (FreeBSD) private __gshared void* dummy_ref;
-version (NetBSD) private __gshared void* dummy_ref;
-
-/****
- * Gets called on program startup just before GC is initialized.
- */
-void initSections() nothrow @nogc
-{
-    _isRuntimeInitialized = true;
-    // reference symbol to support weak linkage
-    version (FreeBSD) dummy_ref = &_d_dso_registry;
-    version (NetBSD) dummy_ref = &_d_dso_registry;
-}
-
-
-/***
- * Gets called on program shutdown just after GC is terminated.
- */
-void finiSections() nothrow @nogc
-{
-    _isRuntimeInitialized = false;
-}
-
-alias ScanDG = void delegate(void* pbeg, void* pend) nothrow;
-
-version (Shared)
-{
-    /***
-     * Called once per thread; returns array of thread local storage ranges
-     */
-    Array!(ThreadDSO)* initTLSRanges() @nogc nothrow
-    {
-        return &_loadedDSOs;
-    }
-
-    void finiTLSRanges(Array!(ThreadDSO)* tdsos) @nogc nothrow
-    {
-        // Nothing to do here. tdsos used to point to the _loadedDSOs instance
-        // in the dying thread's TLS segment and as such is not valid anymore.
-        // The memory for the array contents was already reclaimed in
-        // cleanupLoadedLibraries().
-    }
-
-    void scanTLSRanges(Array!(ThreadDSO)* tdsos, scope ScanDG dg) nothrow
-    {
-        foreach (ref tdso; *tdsos)
-            dg(tdso._tlsRange.ptr, tdso._tlsRange.ptr + tdso._tlsRange.length);
-    }
-
-    // interface for core.thread to inherit loaded libraries
-    void* pinLoadedLibraries() nothrow @nogc
-    {
-        auto res = cast(Array!(ThreadDSO)*)calloc(1, Array!(ThreadDSO).sizeof);
-        res.length = _loadedDSOs.length;
-        foreach (i, ref tdso; _loadedDSOs)
-        {
-            (*res)[i] = tdso;
-            if (tdso._addCnt)
-            {
-                // Increment the dlopen ref for explicitly loaded libraries to pin them.
-                .dlopen(linkMapForHandle(tdso._pdso._handle).l_name, RTLD_LAZY) !is null || assert(0);
-                (*res)[i]._addCnt = 1; // new array takes over the additional ref count
-            }
-        }
-        return res;
-    }
-
-    void unpinLoadedLibraries(void* p) nothrow @nogc
-    {
-        auto pary = cast(Array!(ThreadDSO)*)p;
-        // In case something failed we need to undo the pinning.
-        foreach (ref tdso; *pary)
-        {
-            if (tdso._addCnt)
-            {
-                auto handle = tdso._pdso._handle;
-                handle !is null || assert(0);
-                .dlclose(handle);
-            }
-        }
-        pary.reset();
-        .free(pary);
-    }
-
-    // Called before TLS ctors are ran, copy over the loaded libraries
-    // of the parent thread.
-    void inheritLoadedLibraries(void* p) nothrow @nogc
-    {
-        assert(_loadedDSOs.empty);
-        _loadedDSOs.swap(*cast(Array!(ThreadDSO)*)p);
-        .free(p);
-        foreach (ref dso; _loadedDSOs)
-        {
-            // the copied _tlsRange corresponds to parent thread
-            dso.updateTLSRange();
-        }
-    }
-
-    // Called after all TLS dtors ran, decrements all remaining dlopen refs.
-    void cleanupLoadedLibraries() nothrow @nogc
-    {
-        foreach (ref tdso; _loadedDSOs)
-        {
-            if (tdso._addCnt == 0) continue;
-
-            auto handle = tdso._pdso._handle;
-            handle !is null || assert(0);
-            for (; tdso._addCnt > 0; --tdso._addCnt)
-                .dlclose(handle);
-        }
-
-        // Free the memory for the array contents.
-        _loadedDSOs.reset();
-    }
-}
-else
-{
-    /***
-     * Called once per thread; returns array of thread local storage ranges
-     */
-    Array!(void[])* initTLSRanges() nothrow @nogc
-    {
-        return &_tlsRanges;
-    }
-
-    void finiTLSRanges(Array!(void[])* rngs) nothrow @nogc
-    {
-        rngs.reset();
-    }
-
-    void scanTLSRanges(Array!(void[])* rngs, scope ScanDG dg) nothrow
-    {
-        foreach (rng; *rngs)
-            dg(rng.ptr, rng.ptr + rng.length);
-    }
-}
-
-private:
-
-// start of linked list for ModuleInfo references
-version (FreeBSD) deprecated extern (C) __gshared void* _Dmodule_ref;
-version (NetBSD) deprecated extern (C) __gshared void* _Dmodule_ref;
-
-version (Shared)
-{
-    /*
-     * Array of thread local DSO metadata for all libraries loaded and
-     * initialized in this thread.
-     *
-     * Note:
-     *     A newly spawned thread will inherit these libraries.
-     * Note:
-     *     We use an array here to preserve the order of
-     *     initialization.  If that became a performance issue, we
-     *     could use a hash table and enumerate the DSOs during
-     *     loading so that the hash table values could be sorted when
-     *     necessary.
-     */
-    struct ThreadDSO
-    {
-        DSO* _pdso;
-        static if (_pdso.sizeof == 8) uint _refCnt, _addCnt;
-        else static if (_pdso.sizeof == 4) ushort _refCnt, _addCnt;
-        else static assert(0, "unimplemented");
-        void[] _tlsRange;
-        alias _pdso this;
-        // update the _tlsRange for the executing thread
-        void updateTLSRange() nothrow @nogc
-        {
-            _tlsRange = getTLSRange(_pdso._tlsMod, _pdso._tlsSize);
-        }
-    }
-    Array!(ThreadDSO) _loadedDSOs;
-
-    /*
-     * Set to true during rt_loadLibrary/rt_unloadLibrary calls.
-     */
-    bool _rtLoading;
-
-    /*
-     * Hash table to map link_map* to corresponding DSO*.
-     * The hash table is protected by a Mutex.
-     */
-    __gshared pthread_mutex_t _handleToDSOMutex;
-    __gshared HashTab!(void*, DSO*) _handleToDSO;
-
-    /*
-     * Section in executable that contains copy relocations.
-     * Might be null when druntime is dynamically loaded by a C host.
-     */
-    __gshared const(void)[] _copyRelocSection;
-}
-else
-{
-    /*
-     * Static DSOs loaded by the runtime linker. This includes the
-     * executable. These can't be unloaded.
-     */
-    __gshared Array!(DSO*) _loadedDSOs;
-
-    /*
-     * Thread local array that contains TLS memory ranges for each
-     * library initialized in this thread.
-     */
-    Array!(void[]) _tlsRanges;
-
-    enum _rtLoading = false;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Compiler to runtime interface.
-///////////////////////////////////////////////////////////////////////////////
-
-import gcc.config;
-
-/*
- * This data structure is generated by the compiler, and then passed to
- * _d_dso_registry().
- */
-struct CompilerDSOData
-{
-    size_t _version;                                       // currently 1
-    void** _slot;                                          // can be used to store runtime data
-    immutable(object.ModuleInfo*)* _minfo_beg, _minfo_end; // array of modules in this object file
-}
-
-T[] toRange(T)(T* beg, T* end) { return beg[0 .. end - beg]; }
-
-/* For each shared library and executable, the compiler generates code that
- * sets up CompilerDSOData and calls _d_dso_registry().
- * A pointer to that code is inserted into both the .ctors and .dtors
- * segment so it gets called by the loader on startup and shutdown.
- */
-extern(C) void _d_dso_registry(CompilerDSOData* data)
-{
-    // only one supported currently
-    data._version >= 1 || assert(0, "corrupt DSO data version");
-
-    // no backlink => register
-    if (*data._slot is null)
-    {
-        immutable firstDSO = _loadedDSOs.empty;
-        if (firstDSO) initLocks();
-
-        DSO* pdso = cast(DSO*).calloc(1, DSO.sizeof);
-        assert(typeid(DSO).initializer().ptr is null);
-        *data._slot = pdso; // store backlink in library record
-
-        pdso._moduleGroup = ModuleGroup(toRange(data._minfo_beg, data._minfo_end));
-
-        dl_phdr_info info = void;
-        findDSOInfoForAddr(data._slot, &info) || assert(0);
-
-        scanSegments(info, pdso);
-
-        version (Shared)
-        {
-            auto handle = handleForAddr(data._slot);
-
-            if (firstDSO)
-            {
-                /// Assert that the first loaded DSO is druntime itself. Use a
-                /// local druntime symbol (rt_get_bss_start) to get the handle.
-                assert(handleForAddr(data._slot) == handleForAddr(&rt_get_bss_start));
-                _copyRelocSection = getCopyRelocSection();
-            }
-            checkModuleCollisions(info, pdso._moduleGroup.modules, _copyRelocSection);
-
-            getDependencies(info, pdso._deps);
-            pdso._handle = handle;
-            setDSOForHandle(pdso, pdso._handle);
-
-            if (!_rtLoading)
-            {
-                /* This DSO was not loaded by rt_loadLibrary which
-                 * happens for all dependencies of an executable or
-                 * the first dlopen call from a C program.
-                 * In this case we add the DSO to the _loadedDSOs of this
-                 * thread with a refCnt of 1 and call the TlsCtors.
-                 */
-                immutable ushort refCnt = 1, addCnt = 0;
-                auto tlsRng = getTLSRange(pdso._tlsMod, pdso._tlsSize);
-                _loadedDSOs.insertBack(ThreadDSO(pdso, refCnt, addCnt, tlsRng));
-            }
-        }
-        else
-        {
-            foreach (p; _loadedDSOs) assert(p !is pdso);
-            _loadedDSOs.insertBack(pdso);
-            _tlsRanges.insertBack(getTLSRange(pdso._tlsMod, pdso._tlsSize));
-        }
-
-        // don't initialize modules before rt_init was called (see Bugzilla 11378)
-        if (_isRuntimeInitialized)
-        {
-            registerGCRanges(pdso);
-            // rt_loadLibrary will run tls ctors, so do this only for dlopen
-            immutable runTlsCtors = !_rtLoading;
-            runModuleConstructors(pdso, runTlsCtors);
-        }
-    }
-    // has backlink => unregister
-    else
-    {
-        DSO* pdso = cast(DSO*)*data._slot;
-        *data._slot = null;
-
-        // don't finalizes modules after rt_term was called (see Bugzilla 11378)
-        if (_isRuntimeInitialized)
-        {
-            // rt_unloadLibrary already ran tls dtors, so do this only for dlclose
-            immutable runTlsDtors = !_rtLoading;
-            runModuleDestructors(pdso, runTlsDtors);
-            unregisterGCRanges(pdso);
-            // run finalizers after module dtors (same order as in rt_term)
-            version (Shared) runFinalizers(pdso);
-        }
-
-        version (Shared)
-        {
-            if (!_rtLoading)
-            {
-                /* This DSO was not unloaded by rt_unloadLibrary so we
-                 * have to remove it from _loadedDSOs here.
-                 */
-                foreach (i, ref tdso; _loadedDSOs)
-                {
-                    if (tdso._pdso == pdso)
-                    {
-                        _loadedDSOs.remove(i);
-                        break;
-                    }
-                }
-            }
-
-            unsetDSOForHandle(pdso, pdso._handle);
-            pdso._handle = null;
-        }
-        else
-        {
-            // static DSOs are unloaded in reverse order
-            assert(pdso._tlsSize == _tlsRanges.back.length);
-            _tlsRanges.popBack();
-            assert(pdso == _loadedDSOs.back);
-            _loadedDSOs.popBack();
-        }
-
-        freeDSO(pdso);
-
-        if (_loadedDSOs.empty) finiLocks(); // last DSO
-    }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// dynamic loading
-///////////////////////////////////////////////////////////////////////////////
-
-// Shared D libraries are only supported when linking against a shared druntime library.
-
-version (Shared)
-{
-    ThreadDSO* findThreadDSO(DSO* pdso) nothrow @nogc
-    {
-        foreach (ref tdata; _loadedDSOs)
-            if (tdata._pdso == pdso) return &tdata;
-        return null;
-    }
-
-    void incThreadRef(DSO* pdso, bool incAdd)
-    {
-        if (auto tdata = findThreadDSO(pdso)) // already initialized
-        {
-            if (incAdd && ++tdata._addCnt > 1) return;
-            ++tdata._refCnt;
-        }
-        else
-        {
-            foreach (dep; pdso._deps)
-                incThreadRef(dep, false);
-            immutable ushort refCnt = 1, addCnt = incAdd ? 1 : 0;
-            auto tlsRng = getTLSRange(pdso._tlsMod, pdso._tlsSize);
-            _loadedDSOs.insertBack(ThreadDSO(pdso, refCnt, addCnt, tlsRng));
-            pdso._moduleGroup.runTlsCtors();
-        }
-    }
-
-    void decThreadRef(DSO* pdso, bool decAdd)
-    {
-        auto tdata = findThreadDSO(pdso);
-        tdata !is null || assert(0);
-        !decAdd || tdata._addCnt > 0 || assert(0, "Mismatching rt_unloadLibrary call.");
-
-        if (decAdd && --tdata._addCnt > 0) return;
-        if (--tdata._refCnt > 0) return;
-
-        pdso._moduleGroup.runTlsDtors();
-        foreach (i, ref td; _loadedDSOs)
-            if (td._pdso == pdso) _loadedDSOs.remove(i);
-        foreach (dep; pdso._deps)
-            decThreadRef(dep, false);
-    }
-
-    extern(C) void* rt_loadLibrary(const char* name)
-    {
-        immutable save = _rtLoading;
-        _rtLoading = true;
-        scope (exit) _rtLoading = save;
-
-        auto handle = .dlopen(name, RTLD_LAZY);
-        if (handle is null) return null;
-
-        // if it's a D library
-        if (auto pdso = dsoForHandle(handle))
-            incThreadRef(pdso, true);
-        return handle;
-    }
-
-    extern(C) int rt_unloadLibrary(void* handle)
-    {
-        if (handle is null) return false;
-
-        immutable save = _rtLoading;
-        _rtLoading = true;
-        scope (exit) _rtLoading = save;
-
-        // if it's a D library
-        if (auto pdso = dsoForHandle(handle))
-            decThreadRef(pdso, true);
-        return .dlclose(handle) == 0;
-    }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// helper functions
-///////////////////////////////////////////////////////////////////////////////
-
-void initLocks() nothrow @nogc
-{
-    version (Shared)
-        !pthread_mutex_init(&_handleToDSOMutex, null) || assert(0);
-}
-
-void finiLocks() nothrow @nogc
-{
-    version (Shared)
-        !pthread_mutex_destroy(&_handleToDSOMutex) || assert(0);
-}
-
-void runModuleConstructors(DSO* pdso, bool runTlsCtors)
-{
-    pdso._moduleGroup.sortCtors();
-    pdso._moduleGroup.runCtors();
-    if (runTlsCtors) pdso._moduleGroup.runTlsCtors();
-}
-
-void runModuleDestructors(DSO* pdso, bool runTlsDtors)
-{
-    if (runTlsDtors) pdso._moduleGroup.runTlsDtors();
-    pdso._moduleGroup.runDtors();
-}
-
-void registerGCRanges(DSO* pdso) nothrow @nogc
-{
-    foreach (rng; pdso._gcRanges)
-        GC.addRange(rng.ptr, rng.length);
-}
-
-void unregisterGCRanges(DSO* pdso) nothrow @nogc
-{
-    foreach (rng; pdso._gcRanges)
-        GC.removeRange(rng.ptr);
-}
-
-version (Shared) void runFinalizers(DSO* pdso)
-{
-    foreach (seg; pdso._codeSegments)
-        GC.runFinalizers(seg);
-}
-
-void freeDSO(DSO* pdso) nothrow @nogc
-{
-    pdso._gcRanges.reset();
-    version (Shared) pdso._codeSegments.reset();
-    .free(pdso);
-}
-
-version (Shared)
-{
-@nogc nothrow:
-    link_map* linkMapForHandle(void* handle) nothrow @nogc
-    {
-        link_map* map;
-        dlinfo(handle, RTLD_DI_LINKMAP, &map) == 0 || assert(0);
-        return map;
-    }
-
-     link_map* exeLinkMap(link_map* map) nothrow @nogc
-     {
-         assert(map);
-         while (map.l_prev !is null)
-             map = map.l_prev;
-         return map;
-     }
-
-    DSO* dsoForHandle(void* handle) nothrow @nogc
-    {
-        DSO* pdso;
-        !pthread_mutex_lock(&_handleToDSOMutex) || assert(0);
-        if (auto ppdso = handle in _handleToDSO)
-            pdso = *ppdso;
-        !pthread_mutex_unlock(&_handleToDSOMutex) || assert(0);
-        return pdso;
-    }
-
-    void setDSOForHandle(DSO* pdso, void* handle) nothrow @nogc
-    {
-        !pthread_mutex_lock(&_handleToDSOMutex) || assert(0);
-        assert(handle !in _handleToDSO);
-        _handleToDSO[handle] = pdso;
-        !pthread_mutex_unlock(&_handleToDSOMutex) || assert(0);
-    }
-
-    void unsetDSOForHandle(DSO* pdso, void* handle) nothrow @nogc
-    {
-        !pthread_mutex_lock(&_handleToDSOMutex) || assert(0);
-        assert(_handleToDSO[handle] == pdso);
-        _handleToDSO.remove(handle);
-        !pthread_mutex_unlock(&_handleToDSOMutex) || assert(0);
-    }
-
-    void getDependencies(in ref dl_phdr_info info, ref Array!(DSO*) deps) nothrow @nogc
-    {
-        // get the entries of the .dynamic section
-        ElfW!"Dyn"[] dyns;
-        foreach (ref phdr; info.dlpi_phdr[0 .. info.dlpi_phnum])
-        {
-            if (phdr.p_type == PT_DYNAMIC)
-            {
-                auto p = cast(ElfW!"Dyn"*)(info.dlpi_addr + (phdr.p_vaddr & ~(size_t.sizeof - 1)));
-                dyns = p[0 .. phdr.p_memsz / ElfW!"Dyn".sizeof];
-                break;
-            }
-        }
-        // find the string table which contains the sonames
-        const(char)* strtab;
-        foreach (dyn; dyns)
-        {
-            if (dyn.d_tag == DT_STRTAB)
-            {
-                version (linux)
-                    strtab = cast(const(char)*)dyn.d_un.d_ptr;
-                else version (FreeBSD)
-                    strtab = cast(const(char)*)(info.dlpi_addr + dyn.d_un.d_ptr); // relocate
-                else version (NetBSD)
-                    strtab = cast(const(char)*)(info.dlpi_addr + dyn.d_un.d_ptr); // relocate
-                else
-                    static assert(0, "unimplemented");
-                break;
-            }
-        }
-        foreach (dyn; dyns)
-        {
-            immutable tag = dyn.d_tag;
-            if (!(tag == DT_NEEDED || tag == DT_AUXILIARY || tag == DT_FILTER))
-                continue;
-
-            // soname of the dependency
-            auto name = strtab + dyn.d_un.d_val;
-            // get handle without loading the library
-            auto handle = handleForName(name);
-            // the runtime linker has already loaded all dependencies
-            if (handle is null) assert(0);
-            // if it's a D library
-            if (auto pdso = dsoForHandle(handle))
-                deps.insertBack(pdso); // append it to the dependencies
-        }
-    }
-
-    void* handleForName(const char* name) nothrow @nogc
-    {
-        auto handle = .dlopen(name, RTLD_NOLOAD | RTLD_LAZY);
-        if (handle !is null) .dlclose(handle); // drop reference count
-        return handle;
-    }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Elf program header iteration
-///////////////////////////////////////////////////////////////////////////////
-
-/************
- * Scan segments in Linux dl_phdr_info struct and store
- * the TLS and writeable data segments in *pdso.
- */
-void scanSegments(in ref dl_phdr_info info, DSO* pdso) nothrow @nogc
-{
-    foreach (ref phdr; info.dlpi_phdr[0 .. info.dlpi_phnum])
-    {
-        switch (phdr.p_type)
-        {
-        case PT_LOAD:
-            if (phdr.p_flags & PF_W) // writeable data segment
-            {
-                auto beg = cast(void*)(info.dlpi_addr + (phdr.p_vaddr & ~(size_t.sizeof - 1)));
-                pdso._gcRanges.insertBack(beg[0 .. phdr.p_memsz]);
-            }
-            version (Shared) if (phdr.p_flags & PF_X) // code segment
-            {
-                auto beg = cast(void*)(info.dlpi_addr + (phdr.p_vaddr & ~(size_t.sizeof - 1)));
-                pdso._codeSegments.insertBack(beg[0 .. phdr.p_memsz]);
-            }
-            break;
-
-        case PT_TLS: // TLS segment
-            assert(!pdso._tlsSize); // is unique per DSO
-            pdso._tlsMod = info.dlpi_tls_modid;
-            pdso._tlsSize = phdr.p_memsz;
-            break;
-
-        default:
-            break;
-        }
-    }
-}
-
-/**************************
- * Input:
- *      result  where the output is to be written; dl_phdr_info is a Linux struct
- * Returns:
- *      true if found, and *result is filled in
- * References:
- *      http://linux.die.net/man/3/dl_iterate_phdr
- */
-version (linux) bool findDSOInfoForAddr(in void* addr, dl_phdr_info* result=null) nothrow @nogc
-{
-    static struct DG { const(void)* addr; dl_phdr_info* result; }
-
-    extern(C) int callback(dl_phdr_info* info, size_t sz, void* arg) nothrow @nogc
-    {
-        auto p = cast(DG*)arg;
-        if (findSegmentForAddr(*info, p.addr))
-        {
-            if (p.result !is null) *p.result = *info;
-            return 1; // break;
-        }
-        return 0; // continue iteration
-    }
-
-    auto dg = DG(addr, result);
-
-    /* Linux function that walks through the list of an application's shared objects and
-     * calls 'callback' once for each object, until either all shared objects
-     * have been processed or 'callback' returns a nonzero value.
-     */
-    return dl_iterate_phdr(&callback, &dg) != 0;
-}
-else version (FreeBSD) bool findDSOInfoForAddr(in void* addr, dl_phdr_info* result=null) nothrow @nogc
-{
-    return !!_rtld_addr_phdr(addr, result);
-}
-else version (NetBSD) bool findDSOInfoForAddr(in void* addr, dl_phdr_info* result=null) nothrow @nogc
-{
-    static struct DG { const(void)* addr; dl_phdr_info* result; }
-
-    extern(C) int callback(dl_phdr_info* info, size_t sz, void* arg) nothrow @nogc
-    {
-        auto p = cast(DG*)arg;
-        if (findSegmentForAddr(*info, p.addr))
-        {
-            if (p.result !is null) *p.result = *info;
-            return 1; // break;
-        }
-        return 0; // continue iteration
-    }
-    auto dg = DG(addr, result);
-    return dl_iterate_phdr(&callback, &dg) != 0;
-}
-
-/*********************************
- * Determine if 'addr' lies within shared object 'info'.
- * If so, return true and fill in 'result' with the corresponding ELF program header.
- */
-bool findSegmentForAddr(in ref dl_phdr_info info, in void* addr, ElfW!"Phdr"* result=null) nothrow @nogc
-{
-    if (addr < cast(void*)info.dlpi_addr) // less than base address of object means quick reject
-        return false;
-
-    foreach (ref phdr; info.dlpi_phdr[0 .. info.dlpi_phnum])
-    {
-        auto beg = cast(void*)(info.dlpi_addr + phdr.p_vaddr);
-        if (cast(size_t)(addr - beg) < phdr.p_memsz)
-        {
-            if (result !is null) *result = phdr;
-            return true;
-        }
-    }
-    return false;
-}
-
-version (linux) import core.sys.linux.errno : program_invocation_name;
-// should be in core.sys.freebsd.stdlib
-version (FreeBSD) extern(C) const(char)* getprogname() nothrow @nogc;
-version (NetBSD) extern(C) const(char)* getprogname() nothrow @nogc;
-
-@property const(char)* progname() nothrow @nogc
-{
-    version (linux) return program_invocation_name;
-    version (FreeBSD) return getprogname();
-    version (NetBSD) return getprogname();
-}
-
-const(char)[] dsoName(const char* dlpi_name) nothrow @nogc
-{
-    // the main executable doesn't have a name in its dlpi_name field
-    const char* p = dlpi_name[0] != 0 ? dlpi_name : progname;
-    return p[0 .. strlen(p)];
-}
-
-extern(C)
-{
-    void* rt_get_bss_start() @nogc nothrow;
-    void* rt_get_end() @nogc nothrow;
-}
-
-/// get the BSS section of the executable to check for copy relocations
-const(void)[] getCopyRelocSection() nothrow @nogc
-{
-    auto bss_start = rt_get_bss_start();
-    auto bss_end = rt_get_end();
-    immutable bss_size = bss_end - bss_start;
-
-    /**
-       Check whether __bss_start/_end both lie within the executable DSO.same DSO.
-
-       When a C host program dynamically loads druntime, i.e. it isn't linked
-       against, __bss_start/_end might be defined in different DSOs, b/c the
-       linker creates those symbols only when they are used.
-       But as there are no copy relocations when dynamically loading a shared
-       library, we can simply return a null bss range in that case.
-    */
-    if (bss_size <= 0)
-        return null;
-
-    version (linux)
-        enum ElfW!"Addr" exeBaseAddr = 0;
-    else version (FreeBSD)
-        enum ElfW!"Addr" exeBaseAddr = 0;
-    else version (NetBSD)
-        enum ElfW!"Addr" exeBaseAddr = 0;
-
-    dl_phdr_info info = void;
-    findDSOInfoForAddr(bss_start, &info) || assert(0);
-    if (info.dlpi_addr != exeBaseAddr)
-        return null;
-    findDSOInfoForAddr(bss_end - 1, &info) || assert(0);
-    if (info.dlpi_addr != exeBaseAddr)
-        return null;
-
-    return bss_start[0 .. bss_size];
-}
-
-/**
- * Check for module collisions. A module in a shared library collides
- * with an existing module if it's ModuleInfo is interposed (search
- * symbol interposition) by another DSO.  Therefor two modules with the
- * same name do not collide if their DSOs are in separate symbol resolution
- * chains.
- */
-void checkModuleCollisions(in ref dl_phdr_info info, in immutable(ModuleInfo)*[] modules,
-                           in void[] copyRelocSection) nothrow @nogc
-in { assert(modules.length); }
-body
-{
-    immutable(ModuleInfo)* conflicting;
-
-    foreach (m; modules)
-    {
-        auto addr = cast(const(void*))m;
-        if (cast(size_t)(addr - copyRelocSection.ptr) < copyRelocSection.length)
-        {
-            // Module is in .bss of the exe because it was copy relocated
-        }
-        else if (!findSegmentForAddr(info, addr))
-        {
-            // Module is in another DSO
-            conflicting = m;
-            break;
-        }
-    }
-
-    if (conflicting !is null)
-    {
-        dl_phdr_info other=void;
-        findDSOInfoForAddr(conflicting, &other) || assert(0);
-
-        auto modname = conflicting.name;
-        auto loading = dsoName(info.dlpi_name);
-        auto existing = dsoName(other.dlpi_name);
-        fprintf(stderr, "Fatal Error while loading '%.*s':\n\tThe module '%.*s' is already defined in '%.*s'.\n",
-                cast(int)loading.length, loading.ptr,
-                cast(int)modname.length, modname.ptr,
-                cast(int)existing.length, existing.ptr);
-        import core.stdc.stdlib : _Exit;
-        _Exit(1);
-    }
-}
-
-/**************************
- * Input:
- *      addr  an internal address of a DSO
- * Returns:
- *      the dlopen handle for that DSO or null if addr is not within a loaded DSO
- */
-version (Shared) void* handleForAddr(void* addr) nothrow @nogc
-{
-    Dl_info info = void;
-    if (dladdr(addr, &info) != 0)
-        return handleForName(info.dli_fname);
-    return null;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// TLS module helper
-///////////////////////////////////////////////////////////////////////////////
-
-
-/*
- * Returns: the TLS memory range for a given module and the calling
- * thread or null if that module has no TLS.
- *
- * Note: This will cause the TLS memory to be eagerly allocated.
- */
-struct tls_index
-{
-    version (CRuntime_Glibc)
-    {
-        // For x86_64, fields are of type uint64_t, this is important for x32
-        // where tls_index would otherwise have the wrong size.
-        // See https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/x86_64/dl-tls.h
-        version (X86_64)
-        {
-            ulong ti_module;
-            ulong ti_offset;
-        }
-        else
-        {
-            c_ulong ti_module;
-            c_ulong ti_offset;
-        }
-    }
-    else
-    {
-        size_t ti_module;
-        size_t ti_offset;
-    }
-}
-
-extern(C) void* __tls_get_addr(tls_index* ti) nothrow @nogc;
-
-/* The dynamic thread vector (DTV) pointers may point 0x8000 past the start of
- * each TLS block. This is at least true for PowerPC and Mips platforms.
- * See: https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/powerpc/dl-tls.h;h=f7cf6f96ebfb505abfd2f02be0ad0e833107c0cd;hb=HEAD#l34
- *      https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/mips/dl-tls.h;h=93a6dc050cb144b9f68b96fb3199c60f5b1fcd18;hb=HEAD#l32
- *      https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/riscv/dl-tls.h;h=ab2d860314de94c18812bc894ff6b3f55368f20f;hb=HEAD#l32
- */
-version (X86)
-    enum TLS_DTV_OFFSET = 0x0;
-else version (X86_64)
-    enum TLS_DTV_OFFSET = 0x0;
-else version (ARM)
-    enum TLS_DTV_OFFSET = 0x0;
-else version (AArch64)
-    enum TLS_DTV_OFFSET = 0x0;
-else version (RISCV32)
-    enum TLS_DTV_OFFSET = 0x800;
-else version (RISCV64)
-    enum TLS_DTV_OFFSET = 0x800;
-else version (HPPA)
-    enum TLS_DTV_OFFSET = 0x0;
-else version (SPARC)
-    enum TLS_DTV_OFFSET = 0x0;
-else version (SPARC64)
-    enum TLS_DTV_OFFSET = 0x0;
-else version (PPC)
-    enum TLS_DTV_OFFSET = 0x8000;
-else version (PPC64)
-    enum TLS_DTV_OFFSET = 0x8000;
-else version (MIPS32)
-    enum TLS_DTV_OFFSET = 0x8000;
-else version (MIPS64)
-    enum TLS_DTV_OFFSET = 0x8000;
-else
-    static assert( false, "Platform not supported." );
-
-void[] getTLSRange(size_t mod, size_t sz) nothrow @nogc
-{
-    if (mod == 0)
-        return null;
-
-    // base offset
-    auto ti = tls_index(mod, 0);
-    return (__tls_get_addr(&ti)-TLS_DTV_OFFSET)[0 .. sz];
-}
diff --git a/libphobos/libdruntime/rt/sections_osx.d b/libphobos/libdruntime/rt/sections_osx.d
deleted file mode 100644 (file)
index 4bea140..0000000
+++ /dev/null
@@ -1,277 +0,0 @@
-/**
- * Written in the D programming language.
- * This module provides OSX-specific support for sections.
- *
- * Copyright: Copyright Digital Mars 2008 - 2012.
- * 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)
- */
-
-module rt.sections_osx;
-
-version (OSX):
-
-// debug = PRINTF;
-import core.stdc.stdio;
-import core.stdc.string, core.stdc.stdlib;
-import core.sys.posix.pthread;
-import core.sys.darwin.mach.dyld;
-import core.sys.darwin.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;
-    immutable(void)[][2] _tlsImage;
-}
-
-/****
- * 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()
-{
-    pthread_key_create(&_tlsKey, null);
-    _dyld_register_func_for_add_image(&sections_osx_onAddImage);
-    _isRuntimeInitialized = true;
-}
-
-/***
- * Gets called on program shutdown just after GC is terminated.
- */
-void finiSections()
-{
-    _sections._gcRanges.reset();
-    pthread_key_delete(_tlsKey);
-    _isRuntimeInitialized = false;
-}
-
-void[]* initTLSRanges()
-{
-    return &getTLSBlock();
-}
-
-void finiTLSRanges(void[]* rng)
-{
-    .free(rng.ptr);
-    .free(rng);
-}
-
-void scanTLSRanges(void[]* rng, scope void delegate(void* pbeg, void* pend) nothrow dg) nothrow
-{
-    dg(rng.ptr, rng.ptr + rng.length);
-}
-
-// NOTE: The Mach-O object file format does not allow for thread local
-//       storage declarations. So instead we roll our own by putting tls
-//       into the __tls_data and the __tlscoal_nt sections.
-//
-//       This function is called by the code emitted by the compiler.  It
-//       is expected to translate an address into the TLS static data to
-//       the corresponding address in the TLS dynamic per-thread data.
-
-// NB: the compiler mangles this function as '___tls_get_addr' even though it is extern(D)
-extern(D) void* ___tls_get_addr( void* p )
-{
-    immutable off = tlsOffset(p);
-    auto tls = getTLSBlockAlloc();
-    assert(off < tls.length);
-    return tls.ptr + off;
-}
-
-private:
-
-__gshared pthread_key_t _tlsKey;
-
-size_t tlsOffset(void* p)
-in
-{
-    assert(_sections._tlsImage[0].ptr !is null ||
-           _sections._tlsImage[1].ptr !is null);
-}
-body
-{
-    // NOTE: p is an address in the TLS static data emitted by the
-    //       compiler.  If it isn't, something is disastrously wrong.
-    immutable off0 = cast(size_t)(p - _sections._tlsImage[0].ptr);
-    if (off0 < _sections._tlsImage[0].length)
-    {
-        return off0;
-    }
-    immutable off1 = cast(size_t)(p - _sections._tlsImage[1].ptr);
-    if (off1 < _sections._tlsImage[1].length)
-    {
-        size_t sz = (_sections._tlsImage[0].length + 15) & ~cast(size_t)15;
-        return sz + off1;
-    }
-    assert(0);
-}
-
-ref void[] getTLSBlock()
-{
-    auto pary = cast(void[]*)pthread_getspecific(_tlsKey);
-    if (pary is null)
-    {
-        pary = cast(void[]*).calloc(1, (void[]).sizeof);
-        if (pthread_setspecific(_tlsKey, pary) != 0)
-        {
-            import core.stdc.stdio;
-            perror("pthread_setspecific failed with");
-            assert(0);
-        }
-    }
-    return *pary;
-}
-
-ref void[] getTLSBlockAlloc()
-{
-    auto pary = &getTLSBlock();
-    if (!pary.length)
-    {
-        auto imgs = _sections._tlsImage;
-        immutable sz0 = (imgs[0].length + 15) & ~cast(size_t)15;
-        immutable sz2 = sz0 + imgs[1].length;
-        auto p = .malloc(sz2);
-        memcpy(p, imgs[0].ptr, imgs[0].length);
-        memcpy(p + sz0, imgs[1].ptr, imgs[1].length);
-        *pary = p[0 .. sz2];
-    }
-    return *pary;
-}
-
-
-__gshared SectionGroup _sections;
-
-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];
-    }
-
-    auto tlssect = getSection(h, slide, "__DATA", "__tls_data");
-    if (tlssect != null)
-    {
-        debug(PRINTF) printf("  tls_data %p %p\n", tlssect.ptr, tlssect.ptr + tlssect.length);
-        _sections._tlsImage[0] = (cast(immutable(void)*)tlssect.ptr)[0 .. tlssect.length];
-    }
-
-    auto tlssect2 = getSection(h, slide, "__DATA", "__tlscoal_nt");
-    if (tlssect2 != null)
-    {
-        debug(PRINTF) printf("  tlscoal_nt %p %p\n", tlssect2.ptr, tlssect2.ptr + tlssect2.length);
-        _sections._tlsImage[1] = (cast(immutable(void)*)tlssect2.ptr)[0 .. tlssect2.length];
-    }
-}
-
-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)
-{
-    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");
-
-    if (sect !is null && sect.size > 0)
-        return (cast(ubyte*)sect.addr + slide)[0 .. cast(size_t)sect.size];
-    return null;
-}
diff --git a/libphobos/libdruntime/rt/sections_solaris.d b/libphobos/libdruntime/rt/sections_solaris.d
deleted file mode 100644 (file)
index 75a4394..0000000
+++ /dev/null
@@ -1,114 +0,0 @@
-/**
- * Written in the D programming language.
- * This module provides Solaris-specific support for sections.
- *
- * Copyright: Copyright Martin Nowak 2012-2013.
- * License:   $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
- * Authors:   Martin Nowak
- * Source: $(DRUNTIMESRC src/rt/_sections_solaris.d)
- */
-
-module rt.sections_solaris;
-
-version (Solaris):
-
-// debug = PRINTF;
-debug(PRINTF) import core.stdc.stdio;
-import core.stdc.stdlib : malloc, free;
-import rt.deh, rt.minfo;
-
-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 nothrow @nogc
-    {
-        return _moduleGroup.modules;
-    }
-
-    @property ref inout(ModuleGroup) moduleGroup() inout nothrow @nogc
-    {
-        return _moduleGroup;
-    }
-
-    @property immutable(FuncTable)[] ehTables() const nothrow @nogc
-    {
-        auto pbeg = cast(immutable(FuncTable)*)&__start_deh;
-        auto pend = cast(immutable(FuncTable)*)&__stop_deh;
-        return pbeg[0 .. pend - pbeg];
-    }
-
-    @property inout(void[])[] gcRanges() inout nothrow @nogc
-    {
-        return _gcRanges[];
-    }
-
-private:
-    ModuleGroup _moduleGroup;
-    void[][1] _gcRanges;
-}
-
-void initSections() nothrow @nogc
-{
-    auto mbeg = cast(immutable ModuleInfo**)&__start_minfo;
-    auto mend = cast(immutable ModuleInfo**)&__stop_minfo;
-    _sections.moduleGroup = ModuleGroup(mbeg[0 .. mend - mbeg]);
-
-    auto pbeg = cast(void*)&__dso_handle;
-    auto pend = cast(void*)&_end;
-    _sections._gcRanges[0] = pbeg[0 .. pend - pbeg];
-}
-
-void finiSections() nothrow @nogc
-{
-}
-
-void[] initTLSRanges() nothrow @nogc
-{
-    auto pbeg = cast(void*)&_tlsstart;
-    auto pend = cast(void*)&_tlsend;
-    return pbeg[0 .. pend - pbeg];
-}
-
-void finiTLSRanges(void[] rng) nothrow @nogc
-{
-}
-
-void scanTLSRanges(void[] rng, scope void delegate(void* pbeg, void* pend) nothrow dg) nothrow
-{
-    dg(rng.ptr, rng.ptr + rng.length);
-}
-
-private:
-
-__gshared SectionGroup _sections;
-
-extern(C)
-{
-    /* Symbols created by the compiler/linker and inserted into the
-     * object file that 'bracket' sections.
-     */
-    extern __gshared
-    {
-        void* __start_deh;
-        void* __stop_deh;
-        void* __start_minfo;
-        void* __stop_minfo;
-        int __dso_handle;
-        int _end;
-    }
-
-    extern
-    {
-        void* _tlsstart;
-        void* _tlsend;
-    }
-}
diff --git a/libphobos/libdruntime/rt/sections_win32.d b/libphobos/libdruntime/rt/sections_win32.d
deleted file mode 100644 (file)
index 14d91ba..0000000
+++ /dev/null
@@ -1,173 +0,0 @@
-/**
- * Written in the D programming language.
- * This module provides Win32-specific support for sections.
- *
- * Copyright: Copyright Digital Mars 2008 - 2012.
- * 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_win32.d)
- */
-
-module rt.sections_win32;
-
-version (CRuntime_DigitalMars):
-
-// debug = PRINTF;
-debug(PRINTF) import core.stdc.stdio;
-import rt.minfo;
-import core.stdc.stdlib : malloc, free;
-
-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 nothrow @nogc
-    {
-        return _moduleGroup.modules;
-    }
-
-    @property ref inout(ModuleGroup) moduleGroup() inout nothrow @nogc
-    {
-        return _moduleGroup;
-    }
-
-    @property inout(void[])[] gcRanges() inout nothrow @nogc
-    {
-        return _gcRanges[];
-    }
-
-private:
-    ModuleGroup _moduleGroup;
-    void[][] _gcRanges;
-}
-
-shared(bool) conservative;
-
-void initSections() nothrow @nogc
-{
-    _sections._moduleGroup = ModuleGroup(getModuleInfos());
-
-    import rt.sections;
-    conservative = !scanDataSegPrecisely();
-
-    if (conservative)
-    {
-        _sections._gcRanges = (cast(void[]*) malloc(2 * (void[]).sizeof))[0..2];
-
-        auto databeg = cast(void*)&_xi_a;
-        auto dataend = cast(void*)_moduleinfo_array.ptr;
-        _sections._gcRanges[0] = databeg[0 .. dataend - databeg];
-
-        // skip module info and CONST segment
-        auto bssbeg = cast(void*)&_edata;
-        auto bssend = cast(void*)&_end;
-        _sections._gcRanges[1] = bssbeg[0 .. bssend - bssbeg];
-    }
-    else
-    {
-        size_t count = &_DPend - &_DPbegin;
-        auto ranges = cast(void[]*) malloc(count * (void[]).sizeof);
-        size_t r = 0;
-        void* prev = null;
-        for (size_t i = 0; i < count; i++)
-        {
-            void* addr = (&_DPbegin)[i];
-            if (prev + (void*).sizeof == addr)
-                ranges[r-1] = ranges[r-1].ptr[0 .. ranges[r-1].length + (void*).sizeof];
-            else
-                ranges[r++] = (cast(void**)addr)[0..1];
-            prev = addr;
-        }
-        _sections._gcRanges = ranges[0..r];
-    }
-}
-
-void finiSections() nothrow @nogc
-{
-    free(_sections._gcRanges.ptr);
-}
-
-void[] initTLSRanges() nothrow @nogc
-{
-    auto pbeg = cast(void*)&_tlsstart;
-    auto pend = cast(void*)&_tlsend;
-    return pbeg[0 .. pend - pbeg];
-}
-
-void finiTLSRanges(void[] rng) nothrow @nogc
-{
-}
-
-void scanTLSRanges(void[] rng, scope void delegate(void* pbeg, void* pend) nothrow dg) nothrow
-{
-    if (conservative)
-    {
-        dg(rng.ptr, rng.ptr + rng.length);
-    }
-    else
-    {
-        for (auto p = &_TPbegin; p < &_TPend; )
-        {
-            uint beg = *p++;
-            uint end = beg + cast(uint)((void*).sizeof);
-            while (p < &_TPend && *p == end)
-            {
-                end += (void*).sizeof;
-                p++;
-            }
-            dg(rng.ptr + beg, rng.ptr + end);
-        }
-    }
-}
-
-private:
-
-__gshared SectionGroup _sections;
-
-// Windows: this gets initialized by minit.asm
-extern(C) __gshared immutable(ModuleInfo*)[] _moduleinfo_array;
-extern(C) void _minit() nothrow @nogc;
-
-immutable(ModuleInfo*)[] getModuleInfos() nothrow @nogc
-out (result)
-{
-    foreach (m; result)
-        assert(m !is null);
-}
-body
-{
-    // _minit directly alters the global _moduleinfo_array
-    _minit();
-    return _moduleinfo_array;
-}
-
-extern(C)
-{
-    extern __gshared
-    {
-        int _xi_a;      // &_xi_a just happens to be start of data segment
-        int _edata;     // &_edata is start of BSS segment
-        int _end;       // &_end is past end of BSS
-
-        void* _DPbegin; // first entry in the array of pointers addresses
-        void* _DPend;   // &_DPend points after last entry of array
-        uint _TPbegin;  // first entry in the array of TLS offsets of pointers
-        uint _TPend;    // &_DPend points after last entry of array
-    }
-
-    extern
-    {
-        int _tlsstart;
-        int _tlsend;
-    }
-}
diff --git a/libphobos/libdruntime/rt/sections_win64.d b/libphobos/libdruntime/rt/sections_win64.d
deleted file mode 100644 (file)
index 346be3b..0000000
+++ /dev/null
@@ -1,311 +0,0 @@
-/**
- * Written in the D programming language.
- * This module provides Win32-specific support for sections.
- *
- * Copyright: Copyright Digital Mars 2008 - 2012.
- * 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_win64.d)
- */
-
-module rt.sections_win64;
-
-version (CRuntime_Microsoft):
-
-// debug = PRINTF;
-debug(PRINTF) import core.stdc.stdio;
-import core.stdc.stdlib : malloc, free;
-import rt.deh, rt.minfo;
-
-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 nothrow @nogc
-    {
-        return _moduleGroup.modules;
-    }
-
-    @property ref inout(ModuleGroup) moduleGroup() inout nothrow @nogc
-    {
-        return _moduleGroup;
-    }
-
-    version (Win64)
-    @property immutable(FuncTable)[] ehTables() const nothrow @nogc
-    {
-        auto pbeg = cast(immutable(FuncTable)*)&_deh_beg;
-        auto pend = cast(immutable(FuncTable)*)&_deh_end;
-        return pbeg[0 .. pend - pbeg];
-    }
-
-    @property inout(void[])[] gcRanges() inout nothrow @nogc
-    {
-        return _gcRanges[];
-    }
-
-private:
-    ModuleGroup _moduleGroup;
-    void[][] _gcRanges;
-}
-
-shared(bool) conservative;
-
-void initSections() nothrow @nogc
-{
-    _sections._moduleGroup = ModuleGroup(getModuleInfos());
-
-    // the ".data" image section includes both object file sections ".data" and ".bss"
-    void[] dataSection = findImageSection(".data");
-    debug(PRINTF) printf("found .data section: [%p,+%llx]\n", dataSection.ptr,
-                         cast(ulong)dataSection.length);
-
-    import rt.sections;
-    conservative = !scanDataSegPrecisely();
-
-    if (conservative)
-    {
-        _sections._gcRanges = (cast(void[]*) malloc((void[]).sizeof))[0..1];
-        _sections._gcRanges[0] = dataSection;
-    }
-    else
-    {
-        size_t count = &_DP_end - &_DP_beg;
-        auto ranges = cast(void[]*) malloc(count * (void[]).sizeof);
-        size_t r = 0;
-        void* prev = null;
-        for (size_t i = 0; i < count; i++)
-        {
-            auto off = (&_DP_beg)[i];
-            if (off == 0) // skip zero entries added by incremental linking
-                continue; // assumes there is no D-pointer at the very beginning of .data
-            void* addr = dataSection.ptr + off;
-            debug(PRINTF) printf("  scan %p\n", addr);
-            // combine consecutive pointers into single range
-            if (prev + (void*).sizeof == addr)
-                ranges[r-1] = ranges[r-1].ptr[0 .. ranges[r-1].length + (void*).sizeof];
-            else
-                ranges[r++] = (cast(void**)addr)[0..1];
-            prev = addr;
-        }
-        _sections._gcRanges = ranges[0..r];
-    }
-}
-
-void finiSections() nothrow @nogc
-{
-    .free(cast(void*)_sections.modules.ptr);
-    .free(_sections._gcRanges.ptr);
-}
-
-void[] initTLSRanges() nothrow @nogc
-{
-    void* pbeg;
-    void* pend;
-    // with VS2017 15.3.1, the linker no longer puts TLS segments into a
-    //  separate image section. That way _tls_start and _tls_end no
-    //  longer generate offsets into .tls, but DATA.
-    // Use the TEB entry to find the start of TLS instead and read the
-    //  length from the TLS directory
-    version (D_InlineAsm_X86)
-    {
-        asm @nogc nothrow
-        {
-            mov EAX, _tls_index;
-            mov ECX, FS:[0x2C];     // _tls_array
-            mov EAX, [ECX+4*EAX];
-            mov pbeg, EAX;
-            add EAX, [_tls_used+4]; // end
-            sub EAX, [_tls_used+0]; // start
-            mov pend, EAX;
-        }
-    }
-    else version (D_InlineAsm_X86_64)
-    {
-        asm @nogc nothrow
-        {
-            xor RAX, RAX;
-            mov EAX, _tls_index;
-            mov RCX, 0x58;
-            mov RCX, GS:[RCX];      // _tls_array (immediate value causes fixup)
-            mov RAX, [RCX+8*RAX];
-            mov pbeg, RAX;
-            add RAX, [_tls_used+8]; // end
-            sub RAX, [_tls_used+0]; // start
-            mov pend, RAX;
-        }
-    }
-    else
-        static assert(false, "Architecture not supported.");
-
-    return pbeg[0 .. pend - pbeg];
-}
-
-void finiTLSRanges(void[] rng) nothrow @nogc
-{
-}
-
-void scanTLSRanges(void[] rng, scope void delegate(void* pbeg, void* pend) nothrow dg) nothrow
-{
-    if (conservative)
-    {
-        dg(rng.ptr, rng.ptr + rng.length);
-    }
-    else
-    {
-        for (auto p = &_TP_beg; p < &_TP_end; )
-        {
-            uint beg = *p++;
-            uint end = beg + cast(uint)((void*).sizeof);
-            while (p < &_TP_end && *p == end)
-            {
-                end += (void*).sizeof;
-                p++;
-            }
-            dg(rng.ptr + beg, rng.ptr + end);
-        }
-    }
-}
-
-private:
-__gshared SectionGroup _sections;
-
-extern(C)
-{
-    extern __gshared void* _minfo_beg;
-    extern __gshared void* _minfo_end;
-}
-
-immutable(ModuleInfo*)[] getModuleInfos() nothrow @nogc
-out (result)
-{
-    foreach (m; result)
-        assert(m !is null);
-}
-body
-{
-    auto m = (cast(immutable(ModuleInfo*)*)&_minfo_beg)[1 .. &_minfo_end - &_minfo_beg];
-    /* Because of alignment inserted by the linker, various null pointers
-     * are there. We need to filter them out.
-     */
-    auto p = m.ptr;
-    auto pend = m.ptr + m.length;
-
-    // count non-null pointers
-    size_t cnt;
-    for (; p < pend; ++p)
-    {
-        if (*p !is null) ++cnt;
-    }
-
-    auto result = (cast(immutable(ModuleInfo)**).malloc(cnt * size_t.sizeof))[0 .. cnt];
-
-    p = m.ptr;
-    cnt = 0;
-    for (; p < pend; ++p)
-        if (*p !is null) result[cnt++] = *p;
-
-    return cast(immutable)result;
-}
-
-extern(C)
-{
-    /* Symbols created by the compiler/linker and inserted into the
-     * object file that 'bracket' sections.
-     */
-    extern __gshared
-    {
-        void* __ImageBase;
-
-        void* _deh_beg;
-        void* _deh_end;
-
-        uint _DP_beg;
-        uint _DP_end;
-        uint _TP_beg;
-        uint _TP_end;
-
-        void*[2] _tls_used; // start, end
-        int _tls_index;
-    }
-}
-
-/////////////////////////////////////////////////////////////////////
-
-enum IMAGE_DOS_SIGNATURE = 0x5A4D;      // MZ
-
-struct IMAGE_DOS_HEADER // DOS .EXE header
-{
-    ushort   e_magic;    // Magic number
-    ushort[29] e_res2;   // Reserved ushorts
-    int      e_lfanew;   // File address of new exe header
-}
-
-struct IMAGE_FILE_HEADER
-{
-    ushort Machine;
-    ushort NumberOfSections;
-    uint   TimeDateStamp;
-    uint   PointerToSymbolTable;
-    uint   NumberOfSymbols;
-    ushort SizeOfOptionalHeader;
-    ushort Characteristics;
-}
-
-struct IMAGE_NT_HEADERS
-{
-    uint Signature;
-    IMAGE_FILE_HEADER FileHeader;
-    // optional header follows
-}
-
-struct IMAGE_SECTION_HEADER
-{
-    char[8] Name;
-    union {
-        uint   PhysicalAddress;
-        uint   VirtualSize;
-    }
-    uint   VirtualAddress;
-    uint   SizeOfRawData;
-    uint   PointerToRawData;
-    uint   PointerToRelocations;
-    uint   PointerToLinenumbers;
-    ushort NumberOfRelocations;
-    ushort NumberOfLinenumbers;
-    uint   Characteristics;
-}
-
-bool compareSectionName(ref IMAGE_SECTION_HEADER section, string name) nothrow @nogc
-{
-    if (name[] != section.Name[0 .. name.length])
-        return false;
-    return name.length == 8 || section.Name[name.length] == 0;
-}
-
-void[] findImageSection(string name) nothrow @nogc
-{
-    if (name.length > 8) // section name from string table not supported
-        return null;
-    IMAGE_DOS_HEADER* doshdr = cast(IMAGE_DOS_HEADER*) &__ImageBase;
-    if (doshdr.e_magic != IMAGE_DOS_SIGNATURE)
-        return null;
-
-    auto nthdr = cast(IMAGE_NT_HEADERS*)(cast(void*)doshdr + doshdr.e_lfanew);
-    auto sections = cast(IMAGE_SECTION_HEADER*)(cast(void*)nthdr + IMAGE_NT_HEADERS.sizeof + nthdr.FileHeader.SizeOfOptionalHeader);
-    for (ushort i = 0; i < nthdr.FileHeader.NumberOfSections; i++)
-        if (compareSectionName (sections[i], name))
-            return (cast(void*)&__ImageBase + sections[i].VirtualAddress)[0 .. sections[i].VirtualSize];
-
-    return null;
-}