public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc(refs/users/ibuclaw/heads/darwin)] libphobos: Checkpoint in darwin runtime support
@ 2021-04-19 18:05 Iain Buclaw
  0 siblings, 0 replies; 15+ messages in thread
From: Iain Buclaw @ 2021-04-19 18:05 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:69e0e9381323209a3dbda01527a90e71786ed31c

commit 69e0e9381323209a3dbda01527a90e71786ed31c
Author: Iain Buclaw <ibuclaw@gdcproject.org>
Date:   Sun Nov 29 14:44:28 2020 +0100

    libphobos: Checkpoint in darwin runtime support

Diff:
---
 libphobos/testsuite/lib/libphobos.exp | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/libphobos/testsuite/lib/libphobos.exp b/libphobos/testsuite/lib/libphobos.exp
index 3be2092b12e..ad323d761b9 100644
--- a/libphobos/testsuite/lib/libphobos.exp
+++ b/libphobos/testsuite/lib/libphobos.exp
@@ -90,6 +90,10 @@ proc libphobos-dg-test { prog do_what extra_tool_flags } {
 }
 
 proc libphobos-dg-prune { system text } {
+
+    # Ignore warnings from cctools.
+    regsub -all "(^|\n)clang: warning: argument unused during compilation:\[^\n\]*" $text "" text
+
     return $text
 }


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [gcc(refs/users/ibuclaw/heads/darwin)] libphobos: Checkpoint in darwin runtime support
@ 2021-09-17 14:33 Iain Buclaw
  0 siblings, 0 replies; 15+ messages in thread
From: Iain Buclaw @ 2021-09-17 14:33 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:0f2f68c1be64b0b5fa2e26345effe8337a94c17c

commit 0f2f68c1be64b0b5fa2e26345effe8337a94c17c
Author: Iain Buclaw <ibuclaw@gdcproject.org>
Date:   Sun Nov 29 14:44:28 2020 +0100

    libphobos: Checkpoint in darwin runtime support

Diff:
---
 libphobos/testsuite/lib/libphobos.exp | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/libphobos/testsuite/lib/libphobos.exp b/libphobos/testsuite/lib/libphobos.exp
index 3be2092b12e..ad323d761b9 100644
--- a/libphobos/testsuite/lib/libphobos.exp
+++ b/libphobos/testsuite/lib/libphobos.exp
@@ -90,6 +90,10 @@ proc libphobos-dg-test { prog do_what extra_tool_flags } {
 }
 
 proc libphobos-dg-prune { system text } {
+
+    # Ignore warnings from cctools.
+    regsub -all "(^|\n)clang: warning: argument unused during compilation:\[^\n\]*" $text "" text
+
     return $text
 }


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [gcc(refs/users/ibuclaw/heads/darwin)] libphobos: Checkpoint in darwin runtime support
@ 2021-04-10 17:00 Iain Buclaw
  0 siblings, 0 replies; 15+ messages in thread
From: Iain Buclaw @ 2021-04-10 17:00 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:c4a997f78b409eed36eb6ca476b5c3ceaefacf21

commit c4a997f78b409eed36eb6ca476b5c3ceaefacf21
Author: Iain Buclaw <ibuclaw@gdcproject.org>
Date:   Sun Nov 29 14:44:28 2020 +0100

    libphobos: Checkpoint in darwin runtime support

Diff:
---
 libphobos/configure                              | 22 ++++++++++++++++++----
 libphobos/libdruntime/config/x86/switchcontext.S |  8 ++++++++
 libphobos/libdruntime/gcc/deh.d                  |  5 -----
 libphobos/libdruntime/gcc/sections/common.d      |  2 +-
 libphobos/m4/druntime/os.m4                      | 22 ++++++++++++++++++----
 libphobos/testsuite/lib/libphobos.exp            |  4 ++++
 6 files changed, 49 insertions(+), 14 deletions(-)

diff --git a/libphobos/configure b/libphobos/configure
index fe7cd9c11ff..bbdcb409562 100755
--- a/libphobos/configure
+++ b/libphobos/configure
@@ -14422,6 +14422,8 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
 
 
+
+
   ac_ext=c
 ac_cpp='$CPP $CPPFLAGS'
 ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -14430,17 +14432,29 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for minfo section bracketing" >&5
 $as_echo_n "checking for minfo section bracketing... " >&6; }
+  case "$druntime_cv_target_os" in
+      darwin*)
+	section="__DATA,__minfodata"
+	start="section\$start\$__DATA\$__minfodata"
+	stop="section\$end\$__DATA\$__minfodata"
+	;;
+      *)
+	section="minfo"
+	start="__start_minfo"
+	stop="__stop_minfo"
+	;;
+  esac
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
-    void* module_info_ptr __attribute__((section ("minfo")));
-    extern void* __start_minfo __attribute__((visibility ("hidden")));
-    extern void* __stop_minfo __attribute__((visibility ("hidden")));
+    void* module_info_ptr __attribute__((section ("$section")));
+    extern void* start_minfo __asm__("$start") __attribute__((visibility ("hidden")));
+    extern void* stop_minfo __asm__("$stop") __attribute__((visibility ("hidden")));
 
     int main()
     {
         // Never run, just to prevent compiler from optimizing access
-        return &__start_minfo == &__stop_minfo;
+        return (int)(&stop_minfo - &start_minfo);
     }
 
 _ACEOF
diff --git a/libphobos/libdruntime/config/x86/switchcontext.S b/libphobos/libdruntime/config/x86/switchcontext.S
index 82420c6159c..8af3f5488ba 100644
--- a/libphobos/libdruntime/config/x86/switchcontext.S
+++ b/libphobos/libdruntime/config/x86/switchcontext.S
@@ -33,7 +33,9 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 
     .text
     .globl CSYM(fiber_switchContext)
+#if defined(__ELF__)
     .type CSYM(fiber_switchContext), @function
+#endif
     .align 16
 CSYM(fiber_switchContext):
     .cfi_startproc
@@ -61,13 +63,17 @@ CSYM(fiber_switchContext):
     // 'return' to complete switch
     ret
     .cfi_endproc
+#if defined(__ELF__)
     .size CSYM(fiber_switchContext),.-CSYM(fiber_switchContext)
+#endif
 
 #elif defined(__x86_64__) && !defined(__ILP32__) && !defined(__CET__)
 
     .text
     .globl CSYM(fiber_switchContext)
+#if defined(__ELF__)
     .type CSYM(fiber_switchContext), @function
+#endif
     .align 16
 CSYM(fiber_switchContext):
     .cfi_startproc
@@ -96,6 +102,8 @@ CSYM(fiber_switchContext):
     // 'return' to complete switch
     ret
     .cfi_endproc
+#if defined(__ELF__)
    .size CSYM(fiber_switchContext),.-CSYM(fiber_switchContext)
+#endif
 
 #endif
diff --git a/libphobos/libdruntime/gcc/deh.d b/libphobos/libdruntime/gcc/deh.d
index 2e679320c38..8df5ac63d81 100644
--- a/libphobos/libdruntime/gcc/deh.d
+++ b/libphobos/libdruntime/gcc/deh.d
@@ -34,11 +34,6 @@ extern(C)
 {
     int _d_isbaseof(ClassInfo, ClassInfo);
     void _d_createTrace(Object, void*);
-
-    // Not used in GDC but declaration required by rt/sections.d
-    struct FuncTable
-    {
-    }
 }
 
 /**
diff --git a/libphobos/libdruntime/gcc/sections/common.d b/libphobos/libdruntime/gcc/sections/common.d
index 85fdc0efd48..411f58ac548 100644
--- a/libphobos/libdruntime/gcc/sections/common.d
+++ b/libphobos/libdruntime/gcc/sections/common.d
@@ -1,5 +1,5 @@
 // Contains various utility functions used by the runtime implementation.
-// Copyright (C) 2019-2021 Free Software Foundation, Inc.
+// Copyright (C) 2021 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
diff --git a/libphobos/m4/druntime/os.m4 b/libphobos/m4/druntime/os.m4
index ed93e30f1e9..351558dbcda 100644
--- a/libphobos/m4/druntime/os.m4
+++ b/libphobos/m4/druntime/os.m4
@@ -149,17 +149,31 @@ AC_DEFUN([DRUNTIME_OS_ARM_EABI_UNWINDER],
 # substitute DCFG_MINFO_BRACKETING.
 AC_DEFUN([DRUNTIME_OS_MINFO_BRACKETING],
 [
+  AC_REQUIRE([DRUNTIME_OS_DETECT])
+
   AC_LANG_PUSH([C])
   AC_MSG_CHECKING([for minfo section bracketing])
+  case "$druntime_cv_target_os" in
+      darwin*)
+	section="__DATA,__minfodata"
+	start="section\$start\$__DATA\$__minfodata"
+	stop="section\$end\$__DATA\$__minfodata"
+	;;
+      *)
+	section="minfo"
+	start="__start_minfo"
+	stop="__stop_minfo"
+	;;
+  esac
   AC_LINK_IFELSE([AC_LANG_SOURCE([
-    void* module_info_ptr __attribute__((section ("minfo")));
-    extern void* __start_minfo __attribute__((visibility ("hidden")));
-    extern void* __stop_minfo __attribute__((visibility ("hidden")));
+    void* module_info_ptr __attribute__((section ("$section")));
+    extern void* start_minfo __asm__("$start") __attribute__((visibility ("hidden")));
+    extern void* stop_minfo __asm__("$stop") __attribute__((visibility ("hidden")));
 
     int main()
     {
         // Never run, just to prevent compiler from optimizing access
-        return &__start_minfo == &__stop_minfo;
+        return (int)(&stop_minfo - &start_minfo);
     }
   ])],
     [AC_MSG_RESULT([yes])
diff --git a/libphobos/testsuite/lib/libphobos.exp b/libphobos/testsuite/lib/libphobos.exp
index 3be2092b12e..ad323d761b9 100644
--- a/libphobos/testsuite/lib/libphobos.exp
+++ b/libphobos/testsuite/lib/libphobos.exp
@@ -90,6 +90,10 @@ proc libphobos-dg-test { prog do_what extra_tool_flags } {
 }
 
 proc libphobos-dg-prune { system text } {
+
+    # Ignore warnings from cctools.
+    regsub -all "(^|\n)clang: warning: argument unused during compilation:\[^\n\]*" $text "" text
+
     return $text
 }


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [gcc(refs/users/ibuclaw/heads/darwin)] libphobos: Checkpoint in darwin runtime support
@ 2021-04-10 15:04 Iain Buclaw
  0 siblings, 0 replies; 15+ messages in thread
From: Iain Buclaw @ 2021-04-10 15:04 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:fb65d306947685b2492f7ba6622936575d638842

commit fb65d306947685b2492f7ba6622936575d638842
Author: Iain Buclaw <ibuclaw@gdcproject.org>
Date:   Sun Nov 29 14:44:28 2020 +0100

    libphobos: Checkpoint in darwin runtime support

Diff:
---
 libphobos/configure                              | 22 ++++++++++++++++++----
 libphobos/libdruntime/config/x86/switchcontext.S |  8 ++++++++
 libphobos/libdruntime/gcc/deh.d                  |  5 -----
 libphobos/libdruntime/gcc/sections/common.d      |  2 +-
 libphobos/m4/druntime/os.m4                      | 22 ++++++++++++++++++----
 libphobos/testsuite/lib/libphobos.exp            |  4 ++++
 6 files changed, 49 insertions(+), 14 deletions(-)

diff --git a/libphobos/configure b/libphobos/configure
index fe7cd9c11ff..bbdcb409562 100755
--- a/libphobos/configure
+++ b/libphobos/configure
@@ -14422,6 +14422,8 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
 
 
+
+
   ac_ext=c
 ac_cpp='$CPP $CPPFLAGS'
 ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -14430,17 +14432,29 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for minfo section bracketing" >&5
 $as_echo_n "checking for minfo section bracketing... " >&6; }
+  case "$druntime_cv_target_os" in
+      darwin*)
+	section="__DATA,__minfodata"
+	start="section\$start\$__DATA\$__minfodata"
+	stop="section\$end\$__DATA\$__minfodata"
+	;;
+      *)
+	section="minfo"
+	start="__start_minfo"
+	stop="__stop_minfo"
+	;;
+  esac
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
-    void* module_info_ptr __attribute__((section ("minfo")));
-    extern void* __start_minfo __attribute__((visibility ("hidden")));
-    extern void* __stop_minfo __attribute__((visibility ("hidden")));
+    void* module_info_ptr __attribute__((section ("$section")));
+    extern void* start_minfo __asm__("$start") __attribute__((visibility ("hidden")));
+    extern void* stop_minfo __asm__("$stop") __attribute__((visibility ("hidden")));
 
     int main()
     {
         // Never run, just to prevent compiler from optimizing access
-        return &__start_minfo == &__stop_minfo;
+        return (int)(&stop_minfo - &start_minfo);
     }
 
 _ACEOF
diff --git a/libphobos/libdruntime/config/x86/switchcontext.S b/libphobos/libdruntime/config/x86/switchcontext.S
index 82420c6159c..8af3f5488ba 100644
--- a/libphobos/libdruntime/config/x86/switchcontext.S
+++ b/libphobos/libdruntime/config/x86/switchcontext.S
@@ -33,7 +33,9 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 
     .text
     .globl CSYM(fiber_switchContext)
+#if defined(__ELF__)
     .type CSYM(fiber_switchContext), @function
+#endif
     .align 16
 CSYM(fiber_switchContext):
     .cfi_startproc
@@ -61,13 +63,17 @@ CSYM(fiber_switchContext):
     // 'return' to complete switch
     ret
     .cfi_endproc
+#if defined(__ELF__)
     .size CSYM(fiber_switchContext),.-CSYM(fiber_switchContext)
+#endif
 
 #elif defined(__x86_64__) && !defined(__ILP32__) && !defined(__CET__)
 
     .text
     .globl CSYM(fiber_switchContext)
+#if defined(__ELF__)
     .type CSYM(fiber_switchContext), @function
+#endif
     .align 16
 CSYM(fiber_switchContext):
     .cfi_startproc
@@ -96,6 +102,8 @@ CSYM(fiber_switchContext):
     // 'return' to complete switch
     ret
     .cfi_endproc
+#if defined(__ELF__)
    .size CSYM(fiber_switchContext),.-CSYM(fiber_switchContext)
+#endif
 
 #endif
diff --git a/libphobos/libdruntime/gcc/deh.d b/libphobos/libdruntime/gcc/deh.d
index 2e679320c38..8df5ac63d81 100644
--- a/libphobos/libdruntime/gcc/deh.d
+++ b/libphobos/libdruntime/gcc/deh.d
@@ -34,11 +34,6 @@ extern(C)
 {
     int _d_isbaseof(ClassInfo, ClassInfo);
     void _d_createTrace(Object, void*);
-
-    // Not used in GDC but declaration required by rt/sections.d
-    struct FuncTable
-    {
-    }
 }
 
 /**
diff --git a/libphobos/libdruntime/gcc/sections/common.d b/libphobos/libdruntime/gcc/sections/common.d
index 85fdc0efd48..411f58ac548 100644
--- a/libphobos/libdruntime/gcc/sections/common.d
+++ b/libphobos/libdruntime/gcc/sections/common.d
@@ -1,5 +1,5 @@
 // Contains various utility functions used by the runtime implementation.
-// Copyright (C) 2019-2021 Free Software Foundation, Inc.
+// Copyright (C) 2021 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
diff --git a/libphobos/m4/druntime/os.m4 b/libphobos/m4/druntime/os.m4
index ed93e30f1e9..351558dbcda 100644
--- a/libphobos/m4/druntime/os.m4
+++ b/libphobos/m4/druntime/os.m4
@@ -149,17 +149,31 @@ AC_DEFUN([DRUNTIME_OS_ARM_EABI_UNWINDER],
 # substitute DCFG_MINFO_BRACKETING.
 AC_DEFUN([DRUNTIME_OS_MINFO_BRACKETING],
 [
+  AC_REQUIRE([DRUNTIME_OS_DETECT])
+
   AC_LANG_PUSH([C])
   AC_MSG_CHECKING([for minfo section bracketing])
+  case "$druntime_cv_target_os" in
+      darwin*)
+	section="__DATA,__minfodata"
+	start="section\$start\$__DATA\$__minfodata"
+	stop="section\$end\$__DATA\$__minfodata"
+	;;
+      *)
+	section="minfo"
+	start="__start_minfo"
+	stop="__stop_minfo"
+	;;
+  esac
   AC_LINK_IFELSE([AC_LANG_SOURCE([
-    void* module_info_ptr __attribute__((section ("minfo")));
-    extern void* __start_minfo __attribute__((visibility ("hidden")));
-    extern void* __stop_minfo __attribute__((visibility ("hidden")));
+    void* module_info_ptr __attribute__((section ("$section")));
+    extern void* start_minfo __asm__("$start") __attribute__((visibility ("hidden")));
+    extern void* stop_minfo __asm__("$stop") __attribute__((visibility ("hidden")));
 
     int main()
     {
         // Never run, just to prevent compiler from optimizing access
-        return &__start_minfo == &__stop_minfo;
+        return (int)(&stop_minfo - &start_minfo);
     }
   ])],
     [AC_MSG_RESULT([yes])
diff --git a/libphobos/testsuite/lib/libphobos.exp b/libphobos/testsuite/lib/libphobos.exp
index 3be2092b12e..ad323d761b9 100644
--- a/libphobos/testsuite/lib/libphobos.exp
+++ b/libphobos/testsuite/lib/libphobos.exp
@@ -90,6 +90,10 @@ proc libphobos-dg-test { prog do_what extra_tool_flags } {
 }
 
 proc libphobos-dg-prune { system text } {
+
+    # Ignore warnings from cctools.
+    regsub -all "(^|\n)clang: warning: argument unused during compilation:\[^\n\]*" $text "" text
+
     return $text
 }


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [gcc(refs/users/ibuclaw/heads/darwin)] libphobos: Checkpoint in darwin runtime support
@ 2021-03-14 22:00 Iain Buclaw
  0 siblings, 0 replies; 15+ messages in thread
From: Iain Buclaw @ 2021-03-14 22:00 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:266258f38e3ac2af31c739e195239e91deaa9a84

commit 266258f38e3ac2af31c739e195239e91deaa9a84
Author: Iain Buclaw <ibuclaw@gdcproject.org>
Date:   Sun Nov 29 14:44:28 2020 +0100

    libphobos: Checkpoint in darwin runtime support

Diff:
---
 libphobos/configure                                |  22 +-
 libphobos/libdruntime/Makefile.am                  |  16 +-
 libphobos/libdruntime/Makefile.in                  |  24 +-
 libphobos/libdruntime/config/x86/switchcontext.S   |   8 +
 libphobos/libdruntime/gcc/deh.d                    |   5 -
 libphobos/libdruntime/gcc/sections/android.d       |   7 -
 libphobos/libdruntime/gcc/sections/common.d        |  48 ++++
 libphobos/libdruntime/gcc/sections/elf_shared.d    |  11 -
 libphobos/libdruntime/gcc/sections/osx.d           | 279 +++++++++++----------
 libphobos/libdruntime/gcc/sections/win64.d         |   8 -
 libphobos/m4/druntime/os.m4                        |  22 +-
 libphobos/testsuite/lib/libphobos.exp              |   4 +
 .../testsuite/libphobos.druntime/druntime.exp      |   2 +-
 libphobos/testsuite/libphobos.phobos/phobos.exp    |   2 +-
 14 files changed, 262 insertions(+), 196 deletions(-)

diff --git a/libphobos/configure b/libphobos/configure
index c940a404be4..5c243430ec1 100755
--- a/libphobos/configure
+++ b/libphobos/configure
@@ -14373,6 +14373,8 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
 
 
+
+
   ac_ext=c
 ac_cpp='$CPP $CPPFLAGS'
 ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -14381,17 +14383,29 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for minfo section bracketing" >&5
 $as_echo_n "checking for minfo section bracketing... " >&6; }
+  case "$druntime_cv_target_os" in
+      darwin*)
+	section="__DATA,__minfodata"
+	start="section\$start\$__DATA\$__minfodata"
+	stop="section\$end\$__DATA\$__minfodata"
+	;;
+      *)
+	section="minfo"
+	start="__start_minfo"
+	stop="__stop_minfo"
+	;;
+  esac
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
-    void* module_info_ptr __attribute__((section ("minfo")));
-    extern void* __start_minfo __attribute__((visibility ("hidden")));
-    extern void* __stop_minfo __attribute__((visibility ("hidden")));
+    void* module_info_ptr __attribute__((section ("$section")));
+    extern void* start_minfo __asm__("$start") __attribute__((visibility ("hidden")));
+    extern void* stop_minfo __asm__("$stop") __attribute__((visibility ("hidden")));
 
     int main()
     {
         // Never run, just to prevent compiler from optimizing access
-        return &__start_minfo == &__stop_minfo;
+        return (int)(&stop_minfo - &start_minfo);
     }
 
 _ACEOF
diff --git a/libphobos/libdruntime/Makefile.am b/libphobos/libdruntime/Makefile.am
index 945271e028f..c332d1787df 100644
--- a/libphobos/libdruntime/Makefile.am
+++ b/libphobos/libdruntime/Makefile.am
@@ -186,14 +186,14 @@ DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \
 	gc/gcinterface.d gc/impl/conservative/gc.d gc/impl/manual/gc.d gc/os.d \
 	gc/pooltable.d gc/proxy.d gcc/attribute.d gcc/backtrace.d \
 	gcc/builtins.d gcc/deh.d gcc/emutls.d gcc/gthread.d \
-	gcc/sections/android.d gcc/sections/elf_shared.d gcc/sections/osx.d \
-	gcc/sections/package.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 \
+	gcc/sections/android.d gcc/sections/common.d gcc/sections/elf_shared.d \
+	gcc/sections/osx.d gcc/sections/package.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/util/array.d rt/util/container/array.d \
 	rt/util/container/common.d rt/util/container/hashtab.d \
 	rt/util/container/treap.d rt/util/random.d rt/util/typeinfo.d \
diff --git a/libphobos/libdruntime/Makefile.in b/libphobos/libdruntime/Makefile.in
index 06c02961c86..23c161f96d0 100644
--- a/libphobos/libdruntime/Makefile.in
+++ b/libphobos/libdruntime/Makefile.in
@@ -211,9 +211,10 @@ am__objects_1 = core/atomic.lo core/attribute.lo core/bitop.lo \
 	gc/impl/conservative/gc.lo gc/impl/manual/gc.lo gc/os.lo \
 	gc/pooltable.lo gc/proxy.lo gcc/attribute.lo gcc/backtrace.lo \
 	gcc/builtins.lo gcc/deh.lo gcc/emutls.lo gcc/gthread.lo \
-	gcc/sections/android.lo gcc/sections/elf_shared.lo \
-	gcc/sections/osx.lo gcc/sections/package.lo \
-	gcc/sections/win32.lo gcc/sections/win64.lo gcc/unwind/arm.lo \
+	gcc/sections/android.lo gcc/sections/common.lo \
+	gcc/sections/elf_shared.lo gcc/sections/osx.lo \
+	gcc/sections/package.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 \
@@ -812,14 +813,14 @@ DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \
 	gc/gcinterface.d gc/impl/conservative/gc.d gc/impl/manual/gc.d gc/os.d \
 	gc/pooltable.d gc/proxy.d gcc/attribute.d gcc/backtrace.d \
 	gcc/builtins.d gcc/deh.d gcc/emutls.d gcc/gthread.d \
-	gcc/sections/android.d gcc/sections/elf_shared.d gcc/sections/osx.d \
-	gcc/sections/package.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 \
+	gcc/sections/android.d gcc/sections/common.d gcc/sections/elf_shared.d \
+	gcc/sections/osx.d gcc/sections/package.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/util/array.d rt/util/container/array.d \
 	rt/util/container/common.d rt/util/container/hashtab.d \
 	rt/util/container/treap.d rt/util/random.d rt/util/typeinfo.d \
@@ -1210,6 +1211,7 @@ gcc/sections/$(am__dirstamp):
 	@$(MKDIR_P) gcc/sections
 	@: > gcc/sections/$(am__dirstamp)
 gcc/sections/android.lo: gcc/sections/$(am__dirstamp)
+gcc/sections/common.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)
diff --git a/libphobos/libdruntime/config/x86/switchcontext.S b/libphobos/libdruntime/config/x86/switchcontext.S
index 82420c6159c..8af3f5488ba 100644
--- a/libphobos/libdruntime/config/x86/switchcontext.S
+++ b/libphobos/libdruntime/config/x86/switchcontext.S
@@ -33,7 +33,9 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 
     .text
     .globl CSYM(fiber_switchContext)
+#if defined(__ELF__)
     .type CSYM(fiber_switchContext), @function
+#endif
     .align 16
 CSYM(fiber_switchContext):
     .cfi_startproc
@@ -61,13 +63,17 @@ CSYM(fiber_switchContext):
     // 'return' to complete switch
     ret
     .cfi_endproc
+#if defined(__ELF__)
     .size CSYM(fiber_switchContext),.-CSYM(fiber_switchContext)
+#endif
 
 #elif defined(__x86_64__) && !defined(__ILP32__) && !defined(__CET__)
 
     .text
     .globl CSYM(fiber_switchContext)
+#if defined(__ELF__)
     .type CSYM(fiber_switchContext), @function
+#endif
     .align 16
 CSYM(fiber_switchContext):
     .cfi_startproc
@@ -96,6 +102,8 @@ CSYM(fiber_switchContext):
     // 'return' to complete switch
     ret
     .cfi_endproc
+#if defined(__ELF__)
    .size CSYM(fiber_switchContext),.-CSYM(fiber_switchContext)
+#endif
 
 #endif
diff --git a/libphobos/libdruntime/gcc/deh.d b/libphobos/libdruntime/gcc/deh.d
index c747b5132d1..7b44f2288dc 100644
--- a/libphobos/libdruntime/gcc/deh.d
+++ b/libphobos/libdruntime/gcc/deh.d
@@ -34,11 +34,6 @@ extern(C)
 {
     int _d_isbaseof(ClassInfo, ClassInfo);
     void _d_createTrace(Object, void*);
-
-    // Not used in GDC but declaration required by rt/sections.d
-    struct FuncTable
-    {
-    }
 }
 
 /**
diff --git a/libphobos/libdruntime/gcc/sections/android.d b/libphobos/libdruntime/gcc/sections/android.d
index 4af26b42ffc..56dff4ec861 100644
--- a/libphobos/libdruntime/gcc/sections/android.d
+++ b/libphobos/libdruntime/gcc/sections/android.d
@@ -54,13 +54,6 @@ struct SectionGroup
         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[];
diff --git a/libphobos/libdruntime/gcc/sections/common.d b/libphobos/libdruntime/gcc/sections/common.d
new file mode 100644
index 00000000000..b2d2322347d
--- /dev/null
+++ b/libphobos/libdruntime/gcc/sections/common.d
@@ -0,0 +1,48 @@
+// Common support routines 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.common;
+
+/****
+ * 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.).
+ */
+void safeAssert(bool condition, scope string msg, size_t line = __LINE__) @nogc nothrow @safe
+{
+    import core.internal.abort;
+    condition || abort(msg, __FILE__, line);
+}
+
+/****
+ * 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]; }
diff --git a/libphobos/libdruntime/gcc/sections/elf_shared.d b/libphobos/libdruntime/gcc/sections/elf_shared.d
index 5b0fad9543b..d73708dc6d3 100644
--- a/libphobos/libdruntime/gcc/sections/elf_shared.d
+++ b/libphobos/libdruntime/gcc/sections/elf_shared.d
@@ -134,11 +134,6 @@ struct DSO
         return _moduleGroup;
     }
 
-    @property immutable(FuncTable)[] ehTables() const nothrow @nogc
-    {
-        return null;
-    }
-
     @property inout(void[])[] gcRanges() inout nothrow @nogc
     {
         return _gcRanges[];
@@ -403,12 +398,6 @@ version (Shared)
      */
     __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
 {
diff --git a/libphobos/libdruntime/gcc/sections/osx.d b/libphobos/libdruntime/gcc/sections/osx.d
index 3e3db70e4b8..2f807bb98e0 100644
--- a/libphobos/libdruntime/gcc/sections/osx.d
+++ b/libphobos/libdruntime/gcc/sections/osx.d
@@ -24,25 +24,38 @@ 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 gcc.sections.common;
+
+import core.stdc.stdlib;
 import core.sys.darwin.mach.dyld;
 import core.sys.darwin.mach.getsect;
-import rt.deh, rt.minfo;
+import rt.minfo;
 import rt.util.container.array;
 
-struct SectionGroup
+version (GNU_EMUTLS)
+    import gcc.emutls;
+
+alias DSO SectionGroup;
+struct DSO
 {
-    static int opApply(scope int delegate(ref SectionGroup) dg)
+    static int opApply(scope int delegate(ref DSO) dg)
     {
-        return dg(_sections);
+        foreach (dso; _loadedDSOs)
+        {
+            if (auto res = dg(*dso))
+                return res;
+        }
+        return 0;
     }
 
-    static int opApplyReverse(scope int delegate(ref SectionGroup) dg)
+    static int opApplyReverse(scope int delegate(ref DSO) dg)
     {
-        return dg(_sections);
+        foreach_reverse (dso; _loadedDSOs)
+        {
+            if (auto res = dg(*dso))
+                return res;
+        }
+        return 0;
     }
 
     @property immutable(ModuleInfo*)[] modules() const nothrow @nogc
@@ -60,16 +73,9 @@ struct SectionGroup
         return _gcRanges[];
     }
 
-    @property immutable(FuncTable)[] ehTables() const nothrow @nogc
-    {
-        return _ehTables[];
-    }
-
 private:
-    immutable(FuncTable)[] _ehTables;
     ModuleGroup _moduleGroup;
     Array!(void[]) _gcRanges;
-    immutable(void)[][2] _tlsImage;
 }
 
 /****
@@ -82,8 +88,6 @@ __gshared bool _isRuntimeInitialized;
  */
 void initSections() nothrow @nogc
 {
-    pthread_key_create(&_tlsKey, null);
-    _dyld_register_func_for_add_image(&sections_osx_onAddImage);
     _isRuntimeInitialized = true;
 }
 
@@ -92,160 +96,161 @@ void initSections() nothrow @nogc
  */
 void finiSections() nothrow @nogc
 {
-    _sections._gcRanges.reset();
-    pthread_key_delete(_tlsKey);
     _isRuntimeInitialized = false;
 }
 
 void[]* initTLSRanges() nothrow @nogc
 {
-    return &getTLSBlock();
+    return null;
 }
 
 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);
+    version (GNU_EMUTLS)
+        _d_emutls_scan(dg);
+    else
+        static assert(0, "Native TLS unimplemented");
 }
 
-// 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 )
+version (Shared)
 {
-    immutable off = tlsOffset(p);
-    auto tls = getTLSBlockAlloc();
-    assert(off < tls.length);
-    return tls.ptr + off;
-}
-
-private:
+    // interface for core.thread to inherit loaded libraries
+    void* pinLoadedLibraries() nothrow @nogc
+    {
+        return null;
+    }
 
-__gshared pthread_key_t _tlsKey;
+    void unpinLoadedLibraries(void* p) nothrow @nogc
+    {
+    }
 
-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)
+    // Called before TLS ctors are ran, copy over the loaded libraries
+    // of the parent thread.
+    void inheritLoadedLibraries(void* p) nothrow @nogc
     {
-        return off0;
     }
-    immutable off1 = cast(size_t)(p - _sections._tlsImage[1].ptr);
-    if (off1 < _sections._tlsImage[1].length)
+
+    // Called after all TLS dtors ran, decrements all remaining dlopen refs.
+    void cleanupLoadedLibraries() nothrow @nogc
     {
-        size_t sz = (_sections._tlsImage[0].length + 15) & ~cast(size_t)15;
-        return sz + off1;
     }
-    assert(0);
 }
 
-ref void[] getTLSBlock() nothrow @nogc
+private:
+
+/*
+ * Static DSOs loaded by the runtime linker. This includes the
+ * executable. These can't be unloaded.
+ */
+@property ref Array!(DSO*) _loadedDSOs() @nogc nothrow
 {
-    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;
+    __gshared Array!(DSO*) x;
+    return x;
 }
 
-ref void[] getTLSBlockAlloc()
+/*
+ * Set to true during rt_loadLibrary/rt_unloadLibrary calls.
+ */
+enum _rtLoading = false;
+
+struct MachHeader
 {
-    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;
+    const(mach_header)* header; // the mach header of the image
+    intptr_t slide;             // virtural memory address slide amount
 }
 
-__gshared SectionGroup _sections;
+///////////////////////////////////////////////////////////////////////////////
+// Compiler to runtime interface.
+///////////////////////////////////////////////////////////////////////////////
 
-extern (C) void sections_osx_onAddImage(in mach_header* h, intptr_t slide)
+/* 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)
 {
-    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]);
-    }
+    // only one supported currently
+    safeAssert(data._version >= 1, "Incompatible compiler-generated DSO data version.");
 
-    auto minfosect = getSection(h, slide, "__DATA", "__minfodata");
-    if (minfosect != null)
+    // no backlink => register
+    if (*data._slot is 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)
+        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));
+
+        MachHeader info = void;
+        const headerFound = findDSOHeaderForAddr(data._slot, &info);
+        safeAssert(headerFound, "Failed to find image header.");
+
+        foreach (e; dataSegs)
         {
-            fprintf(stderr, "Shared libraries are not yet supported on OSX.\n");
+            auto sect = getSection(info.header, info.slide,
+                                   e.seg.ptr, e.sect.ptr);
+            if (sect != null)
+                pdso._gcRanges.insertBack((cast(void*)sect.ptr)[0 .. sect.length]);
         }
 
-        debug(PRINTF) printf("  minfodata\n");
-        auto p = cast(immutable(ModuleInfo*)*)minfosect.ptr;
-        immutable len = minfosect.length / (*p).sizeof;
-
-        _sections._moduleGroup = ModuleGroup(p[0 .. len]);
+        foreach (p; _loadedDSOs)
+            safeAssert(p !is pdso, "DSO already registered.");
+        _loadedDSOs.insertBack(pdso);
     }
-
-    auto ehsect = getSection(h, slide, "__DATA", "__deh_eh");
-    if (ehsect != null)
+    // has backlink => unregister
+    else
     {
-        debug(PRINTF) printf("  deh_eh\n");
-        auto p = cast(immutable(FuncTable)*)ehsect.ptr;
-        immutable len = ehsect.length / (*p).sizeof;
+        DSO* pdso = cast(DSO*)*data._slot;
+        *data._slot = null;
 
-        _sections._ehTables = p[0 .. len];
-    }
+        // static DSOs are unloaded in reverse order
+        safeAssert(pdso == _loadedDSOs.back, "DSO being unregistered isn't current last one.");
+        _loadedDSOs.popBack();
 
-    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];
+        pdso._gcRanges.reset();
+        .free(pdso);
+
+        // last DSO being unloaded => shutdown registry
+        if (_loadedDSOs.empty)
+        {
+            version (GNU_EMUTLS)
+                _d_emutls_destroy();
+        }
     }
+}
+
+/**************************
+ * Input:
+ *      result where the output is to be written
+ * Returns:
+ *      true if found, and *result is filled in
+ */
 
-    auto tlssect2 = getSection(h, slide, "__DATA", "__tlscoal_nt");
-    if (tlssect2 != null)
+bool findDSOHeaderForAddr(in void* addr, MachHeader* result)
+{
+    foreach (i; 0 .. _dyld_image_count())
     {
-        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];
+        const header = _dyld_get_image_header(i);
+        const slide = _dyld_get_image_vmaddr_slide(i);
+        const section = getSection(header, slide, SEG_DATA, SECT_DATA);
+
+        // less than base address of section means quick reject
+        if (!section.length || addr < section.ptr)
+           continue;
+
+        if (addr < section.ptr + section.length)
+        {
+            result.header = header;
+            result.slide = slide;
+            return true;
+        }
     }
+    return false;
 }
 
 struct SegRef
@@ -258,25 +263,27 @@ static immutable SegRef[] dataSegs = [{SEG_DATA, SECT_DATA},
                                       {SEG_DATA, SECT_BSS},
                                       {SEG_DATA, SECT_COMMON}];
 
+/**
+ * Returns the section for the named section in the named segment
+ * for the mach_header pointer passed, or null if not found.
+ */
 ubyte[] getSection(in mach_header* header, intptr_t slide,
                    in char* segmentName, in char* sectionName)
 {
-    version (X86)
+    version (D_LP64)
     {
-        assert(header.magic == MH_MAGIC);
-        auto sect = getsectbynamefromheader(header,
+        assert(header.magic == MH_MAGIC_64);
+        auto sect = getsectbynamefromheader_64(cast(mach_header_64*)header,
                                             segmentName,
                                             sectionName);
     }
-    else version (X86_64)
+    else
     {
-        assert(header.magic == MH_MAGIC_64);
-        auto sect = getsectbynamefromheader_64(cast(mach_header_64*)header,
+        assert(header.magic == MH_MAGIC);
+        auto sect = getsectbynamefromheader(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];
diff --git a/libphobos/libdruntime/gcc/sections/win64.d b/libphobos/libdruntime/gcc/sections/win64.d
index 357940ba821..512693c071d 100644
--- a/libphobos/libdruntime/gcc/sections/win64.d
+++ b/libphobos/libdruntime/gcc/sections/win64.d
@@ -51,14 +51,6 @@ struct SectionGroup
         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[];
diff --git a/libphobos/m4/druntime/os.m4 b/libphobos/m4/druntime/os.m4
index ed93e30f1e9..351558dbcda 100644
--- a/libphobos/m4/druntime/os.m4
+++ b/libphobos/m4/druntime/os.m4
@@ -149,17 +149,31 @@ AC_DEFUN([DRUNTIME_OS_ARM_EABI_UNWINDER],
 # substitute DCFG_MINFO_BRACKETING.
 AC_DEFUN([DRUNTIME_OS_MINFO_BRACKETING],
 [
+  AC_REQUIRE([DRUNTIME_OS_DETECT])
+
   AC_LANG_PUSH([C])
   AC_MSG_CHECKING([for minfo section bracketing])
+  case "$druntime_cv_target_os" in
+      darwin*)
+	section="__DATA,__minfodata"
+	start="section\$start\$__DATA\$__minfodata"
+	stop="section\$end\$__DATA\$__minfodata"
+	;;
+      *)
+	section="minfo"
+	start="__start_minfo"
+	stop="__stop_minfo"
+	;;
+  esac
   AC_LINK_IFELSE([AC_LANG_SOURCE([
-    void* module_info_ptr __attribute__((section ("minfo")));
-    extern void* __start_minfo __attribute__((visibility ("hidden")));
-    extern void* __stop_minfo __attribute__((visibility ("hidden")));
+    void* module_info_ptr __attribute__((section ("$section")));
+    extern void* start_minfo __asm__("$start") __attribute__((visibility ("hidden")));
+    extern void* stop_minfo __asm__("$stop") __attribute__((visibility ("hidden")));
 
     int main()
     {
         // Never run, just to prevent compiler from optimizing access
-        return &__start_minfo == &__stop_minfo;
+        return (int)(&stop_minfo - &start_minfo);
     }
   ])],
     [AC_MSG_RESULT([yes])
diff --git a/libphobos/testsuite/lib/libphobos.exp b/libphobos/testsuite/lib/libphobos.exp
index 3be2092b12e..ad323d761b9 100644
--- a/libphobos/testsuite/lib/libphobos.exp
+++ b/libphobos/testsuite/lib/libphobos.exp
@@ -90,6 +90,10 @@ proc libphobos-dg-test { prog do_what extra_tool_flags } {
 }
 
 proc libphobos-dg-prune { system text } {
+
+    # Ignore warnings from cctools.
+    regsub -all "(^|\n)clang: warning: argument unused during compilation:\[^\n\]*" $text "" text
+
     return $text
 }
 
diff --git a/libphobos/testsuite/libphobos.druntime/druntime.exp b/libphobos/testsuite/libphobos.druntime/druntime.exp
index 2f3a36f73cf..df01fcc8a23 100644
--- a/libphobos/testsuite/libphobos.druntime/druntime.exp
+++ b/libphobos/testsuite/libphobos.druntime/druntime.exp
@@ -15,7 +15,7 @@
 # <http://www.gnu.org/licenses/>.
 
 # Immediately exit if we can't run target executables.
-if { ![isnative] || ![is-effective-target static] } {
+if { ![isnative] } {
     return
 }
 
diff --git a/libphobos/testsuite/libphobos.phobos/phobos.exp b/libphobos/testsuite/libphobos.phobos/phobos.exp
index 0975ab1f801..770e5769e3c 100644
--- a/libphobos/testsuite/libphobos.phobos/phobos.exp
+++ b/libphobos/testsuite/libphobos.phobos/phobos.exp
@@ -15,7 +15,7 @@
 # <http://www.gnu.org/licenses/>.
 
 # Immediately exit if we can't run target executables.
-if { ![isnative] || ![is-effective-target static] } {
+if { ![isnative] } {
     return
 }


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [gcc(refs/users/ibuclaw/heads/darwin)] libphobos: Checkpoint in darwin runtime support
@ 2021-03-07 17:01 Iain Buclaw
  0 siblings, 0 replies; 15+ messages in thread
From: Iain Buclaw @ 2021-03-07 17:01 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:0ddfb769aaf3ac23950f43950da6739f290b65cd

commit 0ddfb769aaf3ac23950f43950da6739f290b65cd
Author: Iain Buclaw <ibuclaw@gdcproject.org>
Date:   Sun Nov 29 14:44:28 2020 +0100

    libphobos: Checkpoint in darwin runtime support

Diff:
---
 libphobos/configure                                |  22 +-
 libphobos/libdruntime/Makefile.am                  |  16 +-
 libphobos/libdruntime/Makefile.in                  |  24 +-
 libphobos/libdruntime/config/x86/switchcontext.S   |   8 +
 libphobos/libdruntime/gcc/deh.d                    |   5 -
 libphobos/libdruntime/gcc/sections/android.d       |   7 -
 libphobos/libdruntime/gcc/sections/common.d        |  48 ++++
 libphobos/libdruntime/gcc/sections/elf_shared.d    |  11 -
 libphobos/libdruntime/gcc/sections/osx.d           | 279 +++++++++++----------
 libphobos/libdruntime/gcc/sections/win64.d         |   8 -
 libphobos/m4/druntime/os.m4                        |  22 +-
 libphobos/testsuite/lib/libphobos.exp              |   4 +
 .../testsuite/libphobos.druntime/druntime.exp      |   2 +-
 libphobos/testsuite/libphobos.phobos/phobos.exp    |   2 +-
 14 files changed, 262 insertions(+), 196 deletions(-)

diff --git a/libphobos/configure b/libphobos/configure
index c940a404be4..5c243430ec1 100755
--- a/libphobos/configure
+++ b/libphobos/configure
@@ -14373,6 +14373,8 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
 
 
+
+
   ac_ext=c
 ac_cpp='$CPP $CPPFLAGS'
 ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -14381,17 +14383,29 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for minfo section bracketing" >&5
 $as_echo_n "checking for minfo section bracketing... " >&6; }
+  case "$druntime_cv_target_os" in
+      darwin*)
+	section="__DATA,__minfodata"
+	start="section\$start\$__DATA\$__minfodata"
+	stop="section\$end\$__DATA\$__minfodata"
+	;;
+      *)
+	section="minfo"
+	start="__start_minfo"
+	stop="__stop_minfo"
+	;;
+  esac
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
-    void* module_info_ptr __attribute__((section ("minfo")));
-    extern void* __start_minfo __attribute__((visibility ("hidden")));
-    extern void* __stop_minfo __attribute__((visibility ("hidden")));
+    void* module_info_ptr __attribute__((section ("$section")));
+    extern void* start_minfo __asm__("$start") __attribute__((visibility ("hidden")));
+    extern void* stop_minfo __asm__("$stop") __attribute__((visibility ("hidden")));
 
     int main()
     {
         // Never run, just to prevent compiler from optimizing access
-        return &__start_minfo == &__stop_minfo;
+        return (int)(&stop_minfo - &start_minfo);
     }
 
 _ACEOF
diff --git a/libphobos/libdruntime/Makefile.am b/libphobos/libdruntime/Makefile.am
index 945271e028f..c332d1787df 100644
--- a/libphobos/libdruntime/Makefile.am
+++ b/libphobos/libdruntime/Makefile.am
@@ -186,14 +186,14 @@ DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \
 	gc/gcinterface.d gc/impl/conservative/gc.d gc/impl/manual/gc.d gc/os.d \
 	gc/pooltable.d gc/proxy.d gcc/attribute.d gcc/backtrace.d \
 	gcc/builtins.d gcc/deh.d gcc/emutls.d gcc/gthread.d \
-	gcc/sections/android.d gcc/sections/elf_shared.d gcc/sections/osx.d \
-	gcc/sections/package.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 \
+	gcc/sections/android.d gcc/sections/common.d gcc/sections/elf_shared.d \
+	gcc/sections/osx.d gcc/sections/package.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/util/array.d rt/util/container/array.d \
 	rt/util/container/common.d rt/util/container/hashtab.d \
 	rt/util/container/treap.d rt/util/random.d rt/util/typeinfo.d \
diff --git a/libphobos/libdruntime/Makefile.in b/libphobos/libdruntime/Makefile.in
index 06c02961c86..23c161f96d0 100644
--- a/libphobos/libdruntime/Makefile.in
+++ b/libphobos/libdruntime/Makefile.in
@@ -211,9 +211,10 @@ am__objects_1 = core/atomic.lo core/attribute.lo core/bitop.lo \
 	gc/impl/conservative/gc.lo gc/impl/manual/gc.lo gc/os.lo \
 	gc/pooltable.lo gc/proxy.lo gcc/attribute.lo gcc/backtrace.lo \
 	gcc/builtins.lo gcc/deh.lo gcc/emutls.lo gcc/gthread.lo \
-	gcc/sections/android.lo gcc/sections/elf_shared.lo \
-	gcc/sections/osx.lo gcc/sections/package.lo \
-	gcc/sections/win32.lo gcc/sections/win64.lo gcc/unwind/arm.lo \
+	gcc/sections/android.lo gcc/sections/common.lo \
+	gcc/sections/elf_shared.lo gcc/sections/osx.lo \
+	gcc/sections/package.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 \
@@ -812,14 +813,14 @@ DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \
 	gc/gcinterface.d gc/impl/conservative/gc.d gc/impl/manual/gc.d gc/os.d \
 	gc/pooltable.d gc/proxy.d gcc/attribute.d gcc/backtrace.d \
 	gcc/builtins.d gcc/deh.d gcc/emutls.d gcc/gthread.d \
-	gcc/sections/android.d gcc/sections/elf_shared.d gcc/sections/osx.d \
-	gcc/sections/package.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 \
+	gcc/sections/android.d gcc/sections/common.d gcc/sections/elf_shared.d \
+	gcc/sections/osx.d gcc/sections/package.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/util/array.d rt/util/container/array.d \
 	rt/util/container/common.d rt/util/container/hashtab.d \
 	rt/util/container/treap.d rt/util/random.d rt/util/typeinfo.d \
@@ -1210,6 +1211,7 @@ gcc/sections/$(am__dirstamp):
 	@$(MKDIR_P) gcc/sections
 	@: > gcc/sections/$(am__dirstamp)
 gcc/sections/android.lo: gcc/sections/$(am__dirstamp)
+gcc/sections/common.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)
diff --git a/libphobos/libdruntime/config/x86/switchcontext.S b/libphobos/libdruntime/config/x86/switchcontext.S
index 82420c6159c..8af3f5488ba 100644
--- a/libphobos/libdruntime/config/x86/switchcontext.S
+++ b/libphobos/libdruntime/config/x86/switchcontext.S
@@ -33,7 +33,9 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 
     .text
     .globl CSYM(fiber_switchContext)
+#if defined(__ELF__)
     .type CSYM(fiber_switchContext), @function
+#endif
     .align 16
 CSYM(fiber_switchContext):
     .cfi_startproc
@@ -61,13 +63,17 @@ CSYM(fiber_switchContext):
     // 'return' to complete switch
     ret
     .cfi_endproc
+#if defined(__ELF__)
     .size CSYM(fiber_switchContext),.-CSYM(fiber_switchContext)
+#endif
 
 #elif defined(__x86_64__) && !defined(__ILP32__) && !defined(__CET__)
 
     .text
     .globl CSYM(fiber_switchContext)
+#if defined(__ELF__)
     .type CSYM(fiber_switchContext), @function
+#endif
     .align 16
 CSYM(fiber_switchContext):
     .cfi_startproc
@@ -96,6 +102,8 @@ CSYM(fiber_switchContext):
     // 'return' to complete switch
     ret
     .cfi_endproc
+#if defined(__ELF__)
    .size CSYM(fiber_switchContext),.-CSYM(fiber_switchContext)
+#endif
 
 #endif
diff --git a/libphobos/libdruntime/gcc/deh.d b/libphobos/libdruntime/gcc/deh.d
index c747b5132d1..7b44f2288dc 100644
--- a/libphobos/libdruntime/gcc/deh.d
+++ b/libphobos/libdruntime/gcc/deh.d
@@ -34,11 +34,6 @@ extern(C)
 {
     int _d_isbaseof(ClassInfo, ClassInfo);
     void _d_createTrace(Object, void*);
-
-    // Not used in GDC but declaration required by rt/sections.d
-    struct FuncTable
-    {
-    }
 }
 
 /**
diff --git a/libphobos/libdruntime/gcc/sections/android.d b/libphobos/libdruntime/gcc/sections/android.d
index 4af26b42ffc..56dff4ec861 100644
--- a/libphobos/libdruntime/gcc/sections/android.d
+++ b/libphobos/libdruntime/gcc/sections/android.d
@@ -54,13 +54,6 @@ struct SectionGroup
         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[];
diff --git a/libphobos/libdruntime/gcc/sections/common.d b/libphobos/libdruntime/gcc/sections/common.d
new file mode 100644
index 00000000000..b2d2322347d
--- /dev/null
+++ b/libphobos/libdruntime/gcc/sections/common.d
@@ -0,0 +1,48 @@
+// Common support routines 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.common;
+
+/****
+ * 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.).
+ */
+void safeAssert(bool condition, scope string msg, size_t line = __LINE__) @nogc nothrow @safe
+{
+    import core.internal.abort;
+    condition || abort(msg, __FILE__, line);
+}
+
+/****
+ * 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]; }
diff --git a/libphobos/libdruntime/gcc/sections/elf_shared.d b/libphobos/libdruntime/gcc/sections/elf_shared.d
index 5b0fad9543b..d73708dc6d3 100644
--- a/libphobos/libdruntime/gcc/sections/elf_shared.d
+++ b/libphobos/libdruntime/gcc/sections/elf_shared.d
@@ -134,11 +134,6 @@ struct DSO
         return _moduleGroup;
     }
 
-    @property immutable(FuncTable)[] ehTables() const nothrow @nogc
-    {
-        return null;
-    }
-
     @property inout(void[])[] gcRanges() inout nothrow @nogc
     {
         return _gcRanges[];
@@ -403,12 +398,6 @@ version (Shared)
      */
     __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
 {
diff --git a/libphobos/libdruntime/gcc/sections/osx.d b/libphobos/libdruntime/gcc/sections/osx.d
index 3e3db70e4b8..2f807bb98e0 100644
--- a/libphobos/libdruntime/gcc/sections/osx.d
+++ b/libphobos/libdruntime/gcc/sections/osx.d
@@ -24,25 +24,38 @@ 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 gcc.sections.common;
+
+import core.stdc.stdlib;
 import core.sys.darwin.mach.dyld;
 import core.sys.darwin.mach.getsect;
-import rt.deh, rt.minfo;
+import rt.minfo;
 import rt.util.container.array;
 
-struct SectionGroup
+version (GNU_EMUTLS)
+    import gcc.emutls;
+
+alias DSO SectionGroup;
+struct DSO
 {
-    static int opApply(scope int delegate(ref SectionGroup) dg)
+    static int opApply(scope int delegate(ref DSO) dg)
     {
-        return dg(_sections);
+        foreach (dso; _loadedDSOs)
+        {
+            if (auto res = dg(*dso))
+                return res;
+        }
+        return 0;
     }
 
-    static int opApplyReverse(scope int delegate(ref SectionGroup) dg)
+    static int opApplyReverse(scope int delegate(ref DSO) dg)
     {
-        return dg(_sections);
+        foreach_reverse (dso; _loadedDSOs)
+        {
+            if (auto res = dg(*dso))
+                return res;
+        }
+        return 0;
     }
 
     @property immutable(ModuleInfo*)[] modules() const nothrow @nogc
@@ -60,16 +73,9 @@ struct SectionGroup
         return _gcRanges[];
     }
 
-    @property immutable(FuncTable)[] ehTables() const nothrow @nogc
-    {
-        return _ehTables[];
-    }
-
 private:
-    immutable(FuncTable)[] _ehTables;
     ModuleGroup _moduleGroup;
     Array!(void[]) _gcRanges;
-    immutable(void)[][2] _tlsImage;
 }
 
 /****
@@ -82,8 +88,6 @@ __gshared bool _isRuntimeInitialized;
  */
 void initSections() nothrow @nogc
 {
-    pthread_key_create(&_tlsKey, null);
-    _dyld_register_func_for_add_image(&sections_osx_onAddImage);
     _isRuntimeInitialized = true;
 }
 
@@ -92,160 +96,161 @@ void initSections() nothrow @nogc
  */
 void finiSections() nothrow @nogc
 {
-    _sections._gcRanges.reset();
-    pthread_key_delete(_tlsKey);
     _isRuntimeInitialized = false;
 }
 
 void[]* initTLSRanges() nothrow @nogc
 {
-    return &getTLSBlock();
+    return null;
 }
 
 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);
+    version (GNU_EMUTLS)
+        _d_emutls_scan(dg);
+    else
+        static assert(0, "Native TLS unimplemented");
 }
 
-// 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 )
+version (Shared)
 {
-    immutable off = tlsOffset(p);
-    auto tls = getTLSBlockAlloc();
-    assert(off < tls.length);
-    return tls.ptr + off;
-}
-
-private:
+    // interface for core.thread to inherit loaded libraries
+    void* pinLoadedLibraries() nothrow @nogc
+    {
+        return null;
+    }
 
-__gshared pthread_key_t _tlsKey;
+    void unpinLoadedLibraries(void* p) nothrow @nogc
+    {
+    }
 
-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)
+    // Called before TLS ctors are ran, copy over the loaded libraries
+    // of the parent thread.
+    void inheritLoadedLibraries(void* p) nothrow @nogc
     {
-        return off0;
     }
-    immutable off1 = cast(size_t)(p - _sections._tlsImage[1].ptr);
-    if (off1 < _sections._tlsImage[1].length)
+
+    // Called after all TLS dtors ran, decrements all remaining dlopen refs.
+    void cleanupLoadedLibraries() nothrow @nogc
     {
-        size_t sz = (_sections._tlsImage[0].length + 15) & ~cast(size_t)15;
-        return sz + off1;
     }
-    assert(0);
 }
 
-ref void[] getTLSBlock() nothrow @nogc
+private:
+
+/*
+ * Static DSOs loaded by the runtime linker. This includes the
+ * executable. These can't be unloaded.
+ */
+@property ref Array!(DSO*) _loadedDSOs() @nogc nothrow
 {
-    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;
+    __gshared Array!(DSO*) x;
+    return x;
 }
 
-ref void[] getTLSBlockAlloc()
+/*
+ * Set to true during rt_loadLibrary/rt_unloadLibrary calls.
+ */
+enum _rtLoading = false;
+
+struct MachHeader
 {
-    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;
+    const(mach_header)* header; // the mach header of the image
+    intptr_t slide;             // virtural memory address slide amount
 }
 
-__gshared SectionGroup _sections;
+///////////////////////////////////////////////////////////////////////////////
+// Compiler to runtime interface.
+///////////////////////////////////////////////////////////////////////////////
 
-extern (C) void sections_osx_onAddImage(in mach_header* h, intptr_t slide)
+/* 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)
 {
-    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]);
-    }
+    // only one supported currently
+    safeAssert(data._version >= 1, "Incompatible compiler-generated DSO data version.");
 
-    auto minfosect = getSection(h, slide, "__DATA", "__minfodata");
-    if (minfosect != null)
+    // no backlink => register
+    if (*data._slot is 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)
+        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));
+
+        MachHeader info = void;
+        const headerFound = findDSOHeaderForAddr(data._slot, &info);
+        safeAssert(headerFound, "Failed to find image header.");
+
+        foreach (e; dataSegs)
         {
-            fprintf(stderr, "Shared libraries are not yet supported on OSX.\n");
+            auto sect = getSection(info.header, info.slide,
+                                   e.seg.ptr, e.sect.ptr);
+            if (sect != null)
+                pdso._gcRanges.insertBack((cast(void*)sect.ptr)[0 .. sect.length]);
         }
 
-        debug(PRINTF) printf("  minfodata\n");
-        auto p = cast(immutable(ModuleInfo*)*)minfosect.ptr;
-        immutable len = minfosect.length / (*p).sizeof;
-
-        _sections._moduleGroup = ModuleGroup(p[0 .. len]);
+        foreach (p; _loadedDSOs)
+            safeAssert(p !is pdso, "DSO already registered.");
+        _loadedDSOs.insertBack(pdso);
     }
-
-    auto ehsect = getSection(h, slide, "__DATA", "__deh_eh");
-    if (ehsect != null)
+    // has backlink => unregister
+    else
     {
-        debug(PRINTF) printf("  deh_eh\n");
-        auto p = cast(immutable(FuncTable)*)ehsect.ptr;
-        immutable len = ehsect.length / (*p).sizeof;
+        DSO* pdso = cast(DSO*)*data._slot;
+        *data._slot = null;
 
-        _sections._ehTables = p[0 .. len];
-    }
+        // static DSOs are unloaded in reverse order
+        safeAssert(pdso == _loadedDSOs.back, "DSO being unregistered isn't current last one.");
+        _loadedDSOs.popBack();
 
-    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];
+        pdso._gcRanges.reset();
+        .free(pdso);
+
+        // last DSO being unloaded => shutdown registry
+        if (_loadedDSOs.empty)
+        {
+            version (GNU_EMUTLS)
+                _d_emutls_destroy();
+        }
     }
+}
+
+/**************************
+ * Input:
+ *      result where the output is to be written
+ * Returns:
+ *      true if found, and *result is filled in
+ */
 
-    auto tlssect2 = getSection(h, slide, "__DATA", "__tlscoal_nt");
-    if (tlssect2 != null)
+bool findDSOHeaderForAddr(in void* addr, MachHeader* result)
+{
+    foreach (i; 0 .. _dyld_image_count())
     {
-        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];
+        const header = _dyld_get_image_header(i);
+        const slide = _dyld_get_image_vmaddr_slide(i);
+        const section = getSection(header, slide, SEG_DATA, SECT_DATA);
+
+        // less than base address of section means quick reject
+        if (!section.length || addr < section.ptr)
+           continue;
+
+        if (addr < section.ptr + section.length)
+        {
+            result.header = header;
+            result.slide = slide;
+            return true;
+        }
     }
+    return false;
 }
 
 struct SegRef
@@ -258,25 +263,27 @@ static immutable SegRef[] dataSegs = [{SEG_DATA, SECT_DATA},
                                       {SEG_DATA, SECT_BSS},
                                       {SEG_DATA, SECT_COMMON}];
 
+/**
+ * Returns the section for the named section in the named segment
+ * for the mach_header pointer passed, or null if not found.
+ */
 ubyte[] getSection(in mach_header* header, intptr_t slide,
                    in char* segmentName, in char* sectionName)
 {
-    version (X86)
+    version (D_LP64)
     {
-        assert(header.magic == MH_MAGIC);
-        auto sect = getsectbynamefromheader(header,
+        assert(header.magic == MH_MAGIC_64);
+        auto sect = getsectbynamefromheader_64(cast(mach_header_64*)header,
                                             segmentName,
                                             sectionName);
     }
-    else version (X86_64)
+    else
     {
-        assert(header.magic == MH_MAGIC_64);
-        auto sect = getsectbynamefromheader_64(cast(mach_header_64*)header,
+        assert(header.magic == MH_MAGIC);
+        auto sect = getsectbynamefromheader(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];
diff --git a/libphobos/libdruntime/gcc/sections/win64.d b/libphobos/libdruntime/gcc/sections/win64.d
index 357940ba821..512693c071d 100644
--- a/libphobos/libdruntime/gcc/sections/win64.d
+++ b/libphobos/libdruntime/gcc/sections/win64.d
@@ -51,14 +51,6 @@ struct SectionGroup
         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[];
diff --git a/libphobos/m4/druntime/os.m4 b/libphobos/m4/druntime/os.m4
index ed93e30f1e9..351558dbcda 100644
--- a/libphobos/m4/druntime/os.m4
+++ b/libphobos/m4/druntime/os.m4
@@ -149,17 +149,31 @@ AC_DEFUN([DRUNTIME_OS_ARM_EABI_UNWINDER],
 # substitute DCFG_MINFO_BRACKETING.
 AC_DEFUN([DRUNTIME_OS_MINFO_BRACKETING],
 [
+  AC_REQUIRE([DRUNTIME_OS_DETECT])
+
   AC_LANG_PUSH([C])
   AC_MSG_CHECKING([for minfo section bracketing])
+  case "$druntime_cv_target_os" in
+      darwin*)
+	section="__DATA,__minfodata"
+	start="section\$start\$__DATA\$__minfodata"
+	stop="section\$end\$__DATA\$__minfodata"
+	;;
+      *)
+	section="minfo"
+	start="__start_minfo"
+	stop="__stop_minfo"
+	;;
+  esac
   AC_LINK_IFELSE([AC_LANG_SOURCE([
-    void* module_info_ptr __attribute__((section ("minfo")));
-    extern void* __start_minfo __attribute__((visibility ("hidden")));
-    extern void* __stop_minfo __attribute__((visibility ("hidden")));
+    void* module_info_ptr __attribute__((section ("$section")));
+    extern void* start_minfo __asm__("$start") __attribute__((visibility ("hidden")));
+    extern void* stop_minfo __asm__("$stop") __attribute__((visibility ("hidden")));
 
     int main()
     {
         // Never run, just to prevent compiler from optimizing access
-        return &__start_minfo == &__stop_minfo;
+        return (int)(&stop_minfo - &start_minfo);
     }
   ])],
     [AC_MSG_RESULT([yes])
diff --git a/libphobos/testsuite/lib/libphobos.exp b/libphobos/testsuite/lib/libphobos.exp
index 3be2092b12e..ad323d761b9 100644
--- a/libphobos/testsuite/lib/libphobos.exp
+++ b/libphobos/testsuite/lib/libphobos.exp
@@ -90,6 +90,10 @@ proc libphobos-dg-test { prog do_what extra_tool_flags } {
 }
 
 proc libphobos-dg-prune { system text } {
+
+    # Ignore warnings from cctools.
+    regsub -all "(^|\n)clang: warning: argument unused during compilation:\[^\n\]*" $text "" text
+
     return $text
 }
 
diff --git a/libphobos/testsuite/libphobos.druntime/druntime.exp b/libphobos/testsuite/libphobos.druntime/druntime.exp
index 2f3a36f73cf..df01fcc8a23 100644
--- a/libphobos/testsuite/libphobos.druntime/druntime.exp
+++ b/libphobos/testsuite/libphobos.druntime/druntime.exp
@@ -15,7 +15,7 @@
 # <http://www.gnu.org/licenses/>.
 
 # Immediately exit if we can't run target executables.
-if { ![isnative] || ![is-effective-target static] } {
+if { ![isnative] } {
     return
 }
 
diff --git a/libphobos/testsuite/libphobos.phobos/phobos.exp b/libphobos/testsuite/libphobos.phobos/phobos.exp
index 0975ab1f801..770e5769e3c 100644
--- a/libphobos/testsuite/libphobos.phobos/phobos.exp
+++ b/libphobos/testsuite/libphobos.phobos/phobos.exp
@@ -15,7 +15,7 @@
 # <http://www.gnu.org/licenses/>.
 
 # Immediately exit if we can't run target executables.
-if { ![isnative] || ![is-effective-target static] } {
+if { ![isnative] } {
     return
 }


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [gcc(refs/users/ibuclaw/heads/darwin)] libphobos: Checkpoint in darwin runtime support
@ 2021-01-30 19:08 Iain Buclaw
  0 siblings, 0 replies; 15+ messages in thread
From: Iain Buclaw @ 2021-01-30 19:08 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:3e7f1342edfaf64a0aecfa50b7fad999b0810d54

commit 3e7f1342edfaf64a0aecfa50b7fad999b0810d54
Author: Iain Buclaw <ibuclaw@gdcproject.org>
Date:   Sun Nov 29 14:44:28 2020 +0100

    libphobos: Checkpoint in darwin runtime support

Diff:
---
 libphobos/configure                                |  22 +-
 libphobos/libdruntime/Makefile.am                  |  23 +-
 libphobos/libdruntime/Makefile.in                  |  31 +--
 libphobos/libdruntime/config/x86/switchcontext.S   |   8 +
 libphobos/libdruntime/gcc/deh.d                    |   5 -
 libphobos/libdruntime/gcc/sections/android.d       |   7 -
 libphobos/libdruntime/gcc/sections/common.d        |  48 ++++
 libphobos/libdruntime/gcc/sections/elf_shared.d    |  11 -
 libphobos/libdruntime/gcc/sections/osx.d           | 279 +++++++++++----------
 libphobos/libdruntime/gcc/sections/win64.d         |   8 -
 libphobos/m4/druntime/os.m4                        |  22 +-
 libphobos/testsuite/lib/libphobos.exp              |   4 +
 .../testsuite/libphobos.druntime/druntime.exp      |   2 +-
 libphobos/testsuite/libphobos.phobos/phobos.exp    |   2 +-
 14 files changed, 270 insertions(+), 202 deletions(-)

diff --git a/libphobos/configure b/libphobos/configure
index c940a404be4..5c243430ec1 100755
--- a/libphobos/configure
+++ b/libphobos/configure
@@ -14373,6 +14373,8 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
 
 
+
+
   ac_ext=c
 ac_cpp='$CPP $CPPFLAGS'
 ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -14381,17 +14383,29 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for minfo section bracketing" >&5
 $as_echo_n "checking for minfo section bracketing... " >&6; }
+  case "$druntime_cv_target_os" in
+      darwin*)
+	section="__DATA,__minfodata"
+	start="section\$start\$__DATA\$__minfodata"
+	stop="section\$end\$__DATA\$__minfodata"
+	;;
+      *)
+	section="minfo"
+	start="__start_minfo"
+	stop="__stop_minfo"
+	;;
+  esac
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
-    void* module_info_ptr __attribute__((section ("minfo")));
-    extern void* __start_minfo __attribute__((visibility ("hidden")));
-    extern void* __stop_minfo __attribute__((visibility ("hidden")));
+    void* module_info_ptr __attribute__((section ("$section")));
+    extern void* start_minfo __asm__("$start") __attribute__((visibility ("hidden")));
+    extern void* stop_minfo __asm__("$stop") __attribute__((visibility ("hidden")));
 
     int main()
     {
         // Never run, just to prevent compiler from optimizing access
-        return &__start_minfo == &__stop_minfo;
+        return (int)(&stop_minfo - &start_minfo);
     }
 
 _ACEOF
diff --git a/libphobos/libdruntime/Makefile.am b/libphobos/libdruntime/Makefile.am
index 57de872862b..6402f26b1b8 100644
--- a/libphobos/libdruntime/Makefile.am
+++ b/libphobos/libdruntime/Makefile.am
@@ -185,17 +185,18 @@ DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \
 	gc/impl/conservative/gc.d gc/impl/manual/gc.d gc/os.d gc/pooltable.d \
 	gc/proxy.d gcc/attribute.d gcc/backtrace.d gcc/builtins.d gcc/deh.d \
 	gcc/emutls.d gcc/gthread.d gcc/sections/android.d \
-	gcc/sections/elf_shared.d gcc/sections/osx.d gcc/sections/package.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/util/array.d rt/util/container/array.d rt/util/container/common.d \
-	rt/util/container/hashtab.d rt/util/container/treap.d rt/util/random.d \
-	rt/util/typeinfo.d rt/util/utf.d
+	gcc/sections/common.d gcc/sections/elf_shared.d gcc/sections/osx.d \
+	gcc/sections/package.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/util/array.d rt/util/container/array.d \
+	rt/util/container/common.d rt/util/container/hashtab.d \
+	rt/util/container/treap.d rt/util/random.d rt/util/typeinfo.d \
+	rt/util/utf.d
 
 DRUNTIME_DSOURCES_STDCXX = core/stdcpp/exception.d \
 	core/stdcpp/typeinfo.d
diff --git a/libphobos/libdruntime/Makefile.in b/libphobos/libdruntime/Makefile.in
index e1b0a851b67..c82a6e75060 100644
--- a/libphobos/libdruntime/Makefile.in
+++ b/libphobos/libdruntime/Makefile.in
@@ -210,9 +210,10 @@ am__objects_1 = core/atomic.lo core/attribute.lo core/bitop.lo \
 	gc/impl/conservative/gc.lo gc/impl/manual/gc.lo gc/os.lo \
 	gc/pooltable.lo gc/proxy.lo gcc/attribute.lo gcc/backtrace.lo \
 	gcc/builtins.lo gcc/deh.lo gcc/emutls.lo gcc/gthread.lo \
-	gcc/sections/android.lo gcc/sections/elf_shared.lo \
-	gcc/sections/osx.lo gcc/sections/package.lo \
-	gcc/sections/win32.lo gcc/sections/win64.lo gcc/unwind/arm.lo \
+	gcc/sections/android.lo gcc/sections/common.lo \
+	gcc/sections/elf_shared.lo gcc/sections/osx.lo \
+	gcc/sections/package.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 \
@@ -803,17 +804,18 @@ DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \
 	gc/impl/conservative/gc.d gc/impl/manual/gc.d gc/os.d gc/pooltable.d \
 	gc/proxy.d gcc/attribute.d gcc/backtrace.d gcc/builtins.d gcc/deh.d \
 	gcc/emutls.d gcc/gthread.d gcc/sections/android.d \
-	gcc/sections/elf_shared.d gcc/sections/osx.d gcc/sections/package.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/util/array.d rt/util/container/array.d rt/util/container/common.d \
-	rt/util/container/hashtab.d rt/util/container/treap.d rt/util/random.d \
-	rt/util/typeinfo.d rt/util/utf.d
+	gcc/sections/common.d gcc/sections/elf_shared.d gcc/sections/osx.d \
+	gcc/sections/package.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/util/array.d rt/util/container/array.d \
+	rt/util/container/common.d rt/util/container/hashtab.d \
+	rt/util/container/treap.d rt/util/random.d rt/util/typeinfo.d \
+	rt/util/utf.d
 
 DRUNTIME_DSOURCES_STDCXX = core/stdcpp/exception.d \
 	core/stdcpp/typeinfo.d
@@ -1192,6 +1194,7 @@ gcc/sections/$(am__dirstamp):
 	@$(MKDIR_P) gcc/sections
 	@: > gcc/sections/$(am__dirstamp)
 gcc/sections/android.lo: gcc/sections/$(am__dirstamp)
+gcc/sections/common.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)
diff --git a/libphobos/libdruntime/config/x86/switchcontext.S b/libphobos/libdruntime/config/x86/switchcontext.S
index 82420c6159c..8af3f5488ba 100644
--- a/libphobos/libdruntime/config/x86/switchcontext.S
+++ b/libphobos/libdruntime/config/x86/switchcontext.S
@@ -33,7 +33,9 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 
     .text
     .globl CSYM(fiber_switchContext)
+#if defined(__ELF__)
     .type CSYM(fiber_switchContext), @function
+#endif
     .align 16
 CSYM(fiber_switchContext):
     .cfi_startproc
@@ -61,13 +63,17 @@ CSYM(fiber_switchContext):
     // 'return' to complete switch
     ret
     .cfi_endproc
+#if defined(__ELF__)
     .size CSYM(fiber_switchContext),.-CSYM(fiber_switchContext)
+#endif
 
 #elif defined(__x86_64__) && !defined(__ILP32__) && !defined(__CET__)
 
     .text
     .globl CSYM(fiber_switchContext)
+#if defined(__ELF__)
     .type CSYM(fiber_switchContext), @function
+#endif
     .align 16
 CSYM(fiber_switchContext):
     .cfi_startproc
@@ -96,6 +102,8 @@ CSYM(fiber_switchContext):
     // 'return' to complete switch
     ret
     .cfi_endproc
+#if defined(__ELF__)
    .size CSYM(fiber_switchContext),.-CSYM(fiber_switchContext)
+#endif
 
 #endif
diff --git a/libphobos/libdruntime/gcc/deh.d b/libphobos/libdruntime/gcc/deh.d
index c747b5132d1..7b44f2288dc 100644
--- a/libphobos/libdruntime/gcc/deh.d
+++ b/libphobos/libdruntime/gcc/deh.d
@@ -34,11 +34,6 @@ extern(C)
 {
     int _d_isbaseof(ClassInfo, ClassInfo);
     void _d_createTrace(Object, void*);
-
-    // Not used in GDC but declaration required by rt/sections.d
-    struct FuncTable
-    {
-    }
 }
 
 /**
diff --git a/libphobos/libdruntime/gcc/sections/android.d b/libphobos/libdruntime/gcc/sections/android.d
index 4af26b42ffc..56dff4ec861 100644
--- a/libphobos/libdruntime/gcc/sections/android.d
+++ b/libphobos/libdruntime/gcc/sections/android.d
@@ -54,13 +54,6 @@ struct SectionGroup
         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[];
diff --git a/libphobos/libdruntime/gcc/sections/common.d b/libphobos/libdruntime/gcc/sections/common.d
new file mode 100644
index 00000000000..b2d2322347d
--- /dev/null
+++ b/libphobos/libdruntime/gcc/sections/common.d
@@ -0,0 +1,48 @@
+// Common support routines 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.common;
+
+/****
+ * 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.).
+ */
+void safeAssert(bool condition, scope string msg, size_t line = __LINE__) @nogc nothrow @safe
+{
+    import core.internal.abort;
+    condition || abort(msg, __FILE__, line);
+}
+
+/****
+ * 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]; }
diff --git a/libphobos/libdruntime/gcc/sections/elf_shared.d b/libphobos/libdruntime/gcc/sections/elf_shared.d
index 5b0fad9543b..d73708dc6d3 100644
--- a/libphobos/libdruntime/gcc/sections/elf_shared.d
+++ b/libphobos/libdruntime/gcc/sections/elf_shared.d
@@ -134,11 +134,6 @@ struct DSO
         return _moduleGroup;
     }
 
-    @property immutable(FuncTable)[] ehTables() const nothrow @nogc
-    {
-        return null;
-    }
-
     @property inout(void[])[] gcRanges() inout nothrow @nogc
     {
         return _gcRanges[];
@@ -403,12 +398,6 @@ version (Shared)
      */
     __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
 {
diff --git a/libphobos/libdruntime/gcc/sections/osx.d b/libphobos/libdruntime/gcc/sections/osx.d
index 3e3db70e4b8..2f807bb98e0 100644
--- a/libphobos/libdruntime/gcc/sections/osx.d
+++ b/libphobos/libdruntime/gcc/sections/osx.d
@@ -24,25 +24,38 @@ 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 gcc.sections.common;
+
+import core.stdc.stdlib;
 import core.sys.darwin.mach.dyld;
 import core.sys.darwin.mach.getsect;
-import rt.deh, rt.minfo;
+import rt.minfo;
 import rt.util.container.array;
 
-struct SectionGroup
+version (GNU_EMUTLS)
+    import gcc.emutls;
+
+alias DSO SectionGroup;
+struct DSO
 {
-    static int opApply(scope int delegate(ref SectionGroup) dg)
+    static int opApply(scope int delegate(ref DSO) dg)
     {
-        return dg(_sections);
+        foreach (dso; _loadedDSOs)
+        {
+            if (auto res = dg(*dso))
+                return res;
+        }
+        return 0;
     }
 
-    static int opApplyReverse(scope int delegate(ref SectionGroup) dg)
+    static int opApplyReverse(scope int delegate(ref DSO) dg)
     {
-        return dg(_sections);
+        foreach_reverse (dso; _loadedDSOs)
+        {
+            if (auto res = dg(*dso))
+                return res;
+        }
+        return 0;
     }
 
     @property immutable(ModuleInfo*)[] modules() const nothrow @nogc
@@ -60,16 +73,9 @@ struct SectionGroup
         return _gcRanges[];
     }
 
-    @property immutable(FuncTable)[] ehTables() const nothrow @nogc
-    {
-        return _ehTables[];
-    }
-
 private:
-    immutable(FuncTable)[] _ehTables;
     ModuleGroup _moduleGroup;
     Array!(void[]) _gcRanges;
-    immutable(void)[][2] _tlsImage;
 }
 
 /****
@@ -82,8 +88,6 @@ __gshared bool _isRuntimeInitialized;
  */
 void initSections() nothrow @nogc
 {
-    pthread_key_create(&_tlsKey, null);
-    _dyld_register_func_for_add_image(&sections_osx_onAddImage);
     _isRuntimeInitialized = true;
 }
 
@@ -92,160 +96,161 @@ void initSections() nothrow @nogc
  */
 void finiSections() nothrow @nogc
 {
-    _sections._gcRanges.reset();
-    pthread_key_delete(_tlsKey);
     _isRuntimeInitialized = false;
 }
 
 void[]* initTLSRanges() nothrow @nogc
 {
-    return &getTLSBlock();
+    return null;
 }
 
 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);
+    version (GNU_EMUTLS)
+        _d_emutls_scan(dg);
+    else
+        static assert(0, "Native TLS unimplemented");
 }
 
-// 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 )
+version (Shared)
 {
-    immutable off = tlsOffset(p);
-    auto tls = getTLSBlockAlloc();
-    assert(off < tls.length);
-    return tls.ptr + off;
-}
-
-private:
+    // interface for core.thread to inherit loaded libraries
+    void* pinLoadedLibraries() nothrow @nogc
+    {
+        return null;
+    }
 
-__gshared pthread_key_t _tlsKey;
+    void unpinLoadedLibraries(void* p) nothrow @nogc
+    {
+    }
 
-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)
+    // Called before TLS ctors are ran, copy over the loaded libraries
+    // of the parent thread.
+    void inheritLoadedLibraries(void* p) nothrow @nogc
     {
-        return off0;
     }
-    immutable off1 = cast(size_t)(p - _sections._tlsImage[1].ptr);
-    if (off1 < _sections._tlsImage[1].length)
+
+    // Called after all TLS dtors ran, decrements all remaining dlopen refs.
+    void cleanupLoadedLibraries() nothrow @nogc
     {
-        size_t sz = (_sections._tlsImage[0].length + 15) & ~cast(size_t)15;
-        return sz + off1;
     }
-    assert(0);
 }
 
-ref void[] getTLSBlock() nothrow @nogc
+private:
+
+/*
+ * Static DSOs loaded by the runtime linker. This includes the
+ * executable. These can't be unloaded.
+ */
+@property ref Array!(DSO*) _loadedDSOs() @nogc nothrow
 {
-    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;
+    __gshared Array!(DSO*) x;
+    return x;
 }
 
-ref void[] getTLSBlockAlloc()
+/*
+ * Set to true during rt_loadLibrary/rt_unloadLibrary calls.
+ */
+enum _rtLoading = false;
+
+struct MachHeader
 {
-    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;
+    const(mach_header)* header; // the mach header of the image
+    intptr_t slide;             // virtural memory address slide amount
 }
 
-__gshared SectionGroup _sections;
+///////////////////////////////////////////////////////////////////////////////
+// Compiler to runtime interface.
+///////////////////////////////////////////////////////////////////////////////
 
-extern (C) void sections_osx_onAddImage(in mach_header* h, intptr_t slide)
+/* 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)
 {
-    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]);
-    }
+    // only one supported currently
+    safeAssert(data._version >= 1, "Incompatible compiler-generated DSO data version.");
 
-    auto minfosect = getSection(h, slide, "__DATA", "__minfodata");
-    if (minfosect != null)
+    // no backlink => register
+    if (*data._slot is 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)
+        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));
+
+        MachHeader info = void;
+        const headerFound = findDSOHeaderForAddr(data._slot, &info);
+        safeAssert(headerFound, "Failed to find image header.");
+
+        foreach (e; dataSegs)
         {
-            fprintf(stderr, "Shared libraries are not yet supported on OSX.\n");
+            auto sect = getSection(info.header, info.slide,
+                                   e.seg.ptr, e.sect.ptr);
+            if (sect != null)
+                pdso._gcRanges.insertBack((cast(void*)sect.ptr)[0 .. sect.length]);
         }
 
-        debug(PRINTF) printf("  minfodata\n");
-        auto p = cast(immutable(ModuleInfo*)*)minfosect.ptr;
-        immutable len = minfosect.length / (*p).sizeof;
-
-        _sections._moduleGroup = ModuleGroup(p[0 .. len]);
+        foreach (p; _loadedDSOs)
+            safeAssert(p !is pdso, "DSO already registered.");
+        _loadedDSOs.insertBack(pdso);
     }
-
-    auto ehsect = getSection(h, slide, "__DATA", "__deh_eh");
-    if (ehsect != null)
+    // has backlink => unregister
+    else
     {
-        debug(PRINTF) printf("  deh_eh\n");
-        auto p = cast(immutable(FuncTable)*)ehsect.ptr;
-        immutable len = ehsect.length / (*p).sizeof;
+        DSO* pdso = cast(DSO*)*data._slot;
+        *data._slot = null;
 
-        _sections._ehTables = p[0 .. len];
-    }
+        // static DSOs are unloaded in reverse order
+        safeAssert(pdso == _loadedDSOs.back, "DSO being unregistered isn't current last one.");
+        _loadedDSOs.popBack();
 
-    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];
+        pdso._gcRanges.reset();
+        .free(pdso);
+
+        // last DSO being unloaded => shutdown registry
+        if (_loadedDSOs.empty)
+        {
+            version (GNU_EMUTLS)
+                _d_emutls_destroy();
+        }
     }
+}
+
+/**************************
+ * Input:
+ *      result where the output is to be written
+ * Returns:
+ *      true if found, and *result is filled in
+ */
 
-    auto tlssect2 = getSection(h, slide, "__DATA", "__tlscoal_nt");
-    if (tlssect2 != null)
+bool findDSOHeaderForAddr(in void* addr, MachHeader* result)
+{
+    foreach (i; 0 .. _dyld_image_count())
     {
-        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];
+        const header = _dyld_get_image_header(i);
+        const slide = _dyld_get_image_vmaddr_slide(i);
+        const section = getSection(header, slide, SEG_DATA, SECT_DATA);
+
+        // less than base address of section means quick reject
+        if (!section.length || addr < section.ptr)
+           continue;
+
+        if (addr < section.ptr + section.length)
+        {
+            result.header = header;
+            result.slide = slide;
+            return true;
+        }
     }
+    return false;
 }
 
 struct SegRef
@@ -258,25 +263,27 @@ static immutable SegRef[] dataSegs = [{SEG_DATA, SECT_DATA},
                                       {SEG_DATA, SECT_BSS},
                                       {SEG_DATA, SECT_COMMON}];
 
+/**
+ * Returns the section for the named section in the named segment
+ * for the mach_header pointer passed, or null if not found.
+ */
 ubyte[] getSection(in mach_header* header, intptr_t slide,
                    in char* segmentName, in char* sectionName)
 {
-    version (X86)
+    version (D_LP64)
     {
-        assert(header.magic == MH_MAGIC);
-        auto sect = getsectbynamefromheader(header,
+        assert(header.magic == MH_MAGIC_64);
+        auto sect = getsectbynamefromheader_64(cast(mach_header_64*)header,
                                             segmentName,
                                             sectionName);
     }
-    else version (X86_64)
+    else
     {
-        assert(header.magic == MH_MAGIC_64);
-        auto sect = getsectbynamefromheader_64(cast(mach_header_64*)header,
+        assert(header.magic == MH_MAGIC);
+        auto sect = getsectbynamefromheader(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];
diff --git a/libphobos/libdruntime/gcc/sections/win64.d b/libphobos/libdruntime/gcc/sections/win64.d
index 357940ba821..512693c071d 100644
--- a/libphobos/libdruntime/gcc/sections/win64.d
+++ b/libphobos/libdruntime/gcc/sections/win64.d
@@ -51,14 +51,6 @@ struct SectionGroup
         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[];
diff --git a/libphobos/m4/druntime/os.m4 b/libphobos/m4/druntime/os.m4
index ed93e30f1e9..351558dbcda 100644
--- a/libphobos/m4/druntime/os.m4
+++ b/libphobos/m4/druntime/os.m4
@@ -149,17 +149,31 @@ AC_DEFUN([DRUNTIME_OS_ARM_EABI_UNWINDER],
 # substitute DCFG_MINFO_BRACKETING.
 AC_DEFUN([DRUNTIME_OS_MINFO_BRACKETING],
 [
+  AC_REQUIRE([DRUNTIME_OS_DETECT])
+
   AC_LANG_PUSH([C])
   AC_MSG_CHECKING([for minfo section bracketing])
+  case "$druntime_cv_target_os" in
+      darwin*)
+	section="__DATA,__minfodata"
+	start="section\$start\$__DATA\$__minfodata"
+	stop="section\$end\$__DATA\$__minfodata"
+	;;
+      *)
+	section="minfo"
+	start="__start_minfo"
+	stop="__stop_minfo"
+	;;
+  esac
   AC_LINK_IFELSE([AC_LANG_SOURCE([
-    void* module_info_ptr __attribute__((section ("minfo")));
-    extern void* __start_minfo __attribute__((visibility ("hidden")));
-    extern void* __stop_minfo __attribute__((visibility ("hidden")));
+    void* module_info_ptr __attribute__((section ("$section")));
+    extern void* start_minfo __asm__("$start") __attribute__((visibility ("hidden")));
+    extern void* stop_minfo __asm__("$stop") __attribute__((visibility ("hidden")));
 
     int main()
     {
         // Never run, just to prevent compiler from optimizing access
-        return &__start_minfo == &__stop_minfo;
+        return (int)(&stop_minfo - &start_minfo);
     }
   ])],
     [AC_MSG_RESULT([yes])
diff --git a/libphobos/testsuite/lib/libphobos.exp b/libphobos/testsuite/lib/libphobos.exp
index 3be2092b12e..ad323d761b9 100644
--- a/libphobos/testsuite/lib/libphobos.exp
+++ b/libphobos/testsuite/lib/libphobos.exp
@@ -90,6 +90,10 @@ proc libphobos-dg-test { prog do_what extra_tool_flags } {
 }
 
 proc libphobos-dg-prune { system text } {
+
+    # Ignore warnings from cctools.
+    regsub -all "(^|\n)clang: warning: argument unused during compilation:\[^\n\]*" $text "" text
+
     return $text
 }
 
diff --git a/libphobos/testsuite/libphobos.druntime/druntime.exp b/libphobos/testsuite/libphobos.druntime/druntime.exp
index 2f3a36f73cf..df01fcc8a23 100644
--- a/libphobos/testsuite/libphobos.druntime/druntime.exp
+++ b/libphobos/testsuite/libphobos.druntime/druntime.exp
@@ -15,7 +15,7 @@
 # <http://www.gnu.org/licenses/>.
 
 # Immediately exit if we can't run target executables.
-if { ![isnative] || ![is-effective-target static] } {
+if { ![isnative] } {
     return
 }
 
diff --git a/libphobos/testsuite/libphobos.phobos/phobos.exp b/libphobos/testsuite/libphobos.phobos/phobos.exp
index 0975ab1f801..770e5769e3c 100644
--- a/libphobos/testsuite/libphobos.phobos/phobos.exp
+++ b/libphobos/testsuite/libphobos.phobos/phobos.exp
@@ -15,7 +15,7 @@
 # <http://www.gnu.org/licenses/>.
 
 # Immediately exit if we can't run target executables.
-if { ![isnative] || ![is-effective-target static] } {
+if { ![isnative] } {
     return
 }


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [gcc(refs/users/ibuclaw/heads/darwin)] libphobos: Checkpoint in darwin runtime support
@ 2021-01-28 17:31 Iain Buclaw
  0 siblings, 0 replies; 15+ messages in thread
From: Iain Buclaw @ 2021-01-28 17:31 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:4864fdba0a990a9e8052b3111f23531e2958487f

commit 4864fdba0a990a9e8052b3111f23531e2958487f
Author: Iain Buclaw <ibuclaw@gdcproject.org>
Date:   Sun Nov 29 14:44:28 2020 +0100

    libphobos: Checkpoint in darwin runtime support

Diff:
---
 libphobos/configure                                |  22 +-
 libphobos/libdruntime/Makefile.am                  |  23 +-
 libphobos/libdruntime/Makefile.in                  |  31 +--
 libphobos/libdruntime/config/x86/switchcontext.S   |   8 +
 libphobos/libdruntime/gcc/deh.d                    |   5 -
 libphobos/libdruntime/gcc/sections/android.d       |   7 -
 libphobos/libdruntime/gcc/sections/common.d        |  48 ++++
 libphobos/libdruntime/gcc/sections/elf_shared.d    |  11 -
 libphobos/libdruntime/gcc/sections/osx.d           | 279 +++++++++++----------
 libphobos/libdruntime/gcc/sections/win64.d         |   8 -
 libphobos/m4/druntime/os.m4                        |  22 +-
 libphobos/testsuite/lib/libphobos.exp              |   4 +
 .../testsuite/libphobos.druntime/druntime.exp      |   2 +-
 libphobos/testsuite/libphobos.phobos/phobos.exp    |   2 +-
 14 files changed, 270 insertions(+), 202 deletions(-)

diff --git a/libphobos/configure b/libphobos/configure
index c940a404be4..5c243430ec1 100755
--- a/libphobos/configure
+++ b/libphobos/configure
@@ -14373,6 +14373,8 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
 
 
+
+
   ac_ext=c
 ac_cpp='$CPP $CPPFLAGS'
 ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -14381,17 +14383,29 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for minfo section bracketing" >&5
 $as_echo_n "checking for minfo section bracketing... " >&6; }
+  case "$druntime_cv_target_os" in
+      darwin*)
+	section="__DATA,__minfodata"
+	start="section\$start\$__DATA\$__minfodata"
+	stop="section\$end\$__DATA\$__minfodata"
+	;;
+      *)
+	section="minfo"
+	start="__start_minfo"
+	stop="__stop_minfo"
+	;;
+  esac
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
-    void* module_info_ptr __attribute__((section ("minfo")));
-    extern void* __start_minfo __attribute__((visibility ("hidden")));
-    extern void* __stop_minfo __attribute__((visibility ("hidden")));
+    void* module_info_ptr __attribute__((section ("$section")));
+    extern void* start_minfo __asm__("$start") __attribute__((visibility ("hidden")));
+    extern void* stop_minfo __asm__("$stop") __attribute__((visibility ("hidden")));
 
     int main()
     {
         // Never run, just to prevent compiler from optimizing access
-        return &__start_minfo == &__stop_minfo;
+        return (int)(&stop_minfo - &start_minfo);
     }
 
 _ACEOF
diff --git a/libphobos/libdruntime/Makefile.am b/libphobos/libdruntime/Makefile.am
index 57de872862b..6402f26b1b8 100644
--- a/libphobos/libdruntime/Makefile.am
+++ b/libphobos/libdruntime/Makefile.am
@@ -185,17 +185,18 @@ DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \
 	gc/impl/conservative/gc.d gc/impl/manual/gc.d gc/os.d gc/pooltable.d \
 	gc/proxy.d gcc/attribute.d gcc/backtrace.d gcc/builtins.d gcc/deh.d \
 	gcc/emutls.d gcc/gthread.d gcc/sections/android.d \
-	gcc/sections/elf_shared.d gcc/sections/osx.d gcc/sections/package.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/util/array.d rt/util/container/array.d rt/util/container/common.d \
-	rt/util/container/hashtab.d rt/util/container/treap.d rt/util/random.d \
-	rt/util/typeinfo.d rt/util/utf.d
+	gcc/sections/common.d gcc/sections/elf_shared.d gcc/sections/osx.d \
+	gcc/sections/package.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/util/array.d rt/util/container/array.d \
+	rt/util/container/common.d rt/util/container/hashtab.d \
+	rt/util/container/treap.d rt/util/random.d rt/util/typeinfo.d \
+	rt/util/utf.d
 
 DRUNTIME_DSOURCES_STDCXX = core/stdcpp/exception.d \
 	core/stdcpp/typeinfo.d
diff --git a/libphobos/libdruntime/Makefile.in b/libphobos/libdruntime/Makefile.in
index e1b0a851b67..c82a6e75060 100644
--- a/libphobos/libdruntime/Makefile.in
+++ b/libphobos/libdruntime/Makefile.in
@@ -210,9 +210,10 @@ am__objects_1 = core/atomic.lo core/attribute.lo core/bitop.lo \
 	gc/impl/conservative/gc.lo gc/impl/manual/gc.lo gc/os.lo \
 	gc/pooltable.lo gc/proxy.lo gcc/attribute.lo gcc/backtrace.lo \
 	gcc/builtins.lo gcc/deh.lo gcc/emutls.lo gcc/gthread.lo \
-	gcc/sections/android.lo gcc/sections/elf_shared.lo \
-	gcc/sections/osx.lo gcc/sections/package.lo \
-	gcc/sections/win32.lo gcc/sections/win64.lo gcc/unwind/arm.lo \
+	gcc/sections/android.lo gcc/sections/common.lo \
+	gcc/sections/elf_shared.lo gcc/sections/osx.lo \
+	gcc/sections/package.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 \
@@ -803,17 +804,18 @@ DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \
 	gc/impl/conservative/gc.d gc/impl/manual/gc.d gc/os.d gc/pooltable.d \
 	gc/proxy.d gcc/attribute.d gcc/backtrace.d gcc/builtins.d gcc/deh.d \
 	gcc/emutls.d gcc/gthread.d gcc/sections/android.d \
-	gcc/sections/elf_shared.d gcc/sections/osx.d gcc/sections/package.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/util/array.d rt/util/container/array.d rt/util/container/common.d \
-	rt/util/container/hashtab.d rt/util/container/treap.d rt/util/random.d \
-	rt/util/typeinfo.d rt/util/utf.d
+	gcc/sections/common.d gcc/sections/elf_shared.d gcc/sections/osx.d \
+	gcc/sections/package.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/util/array.d rt/util/container/array.d \
+	rt/util/container/common.d rt/util/container/hashtab.d \
+	rt/util/container/treap.d rt/util/random.d rt/util/typeinfo.d \
+	rt/util/utf.d
 
 DRUNTIME_DSOURCES_STDCXX = core/stdcpp/exception.d \
 	core/stdcpp/typeinfo.d
@@ -1192,6 +1194,7 @@ gcc/sections/$(am__dirstamp):
 	@$(MKDIR_P) gcc/sections
 	@: > gcc/sections/$(am__dirstamp)
 gcc/sections/android.lo: gcc/sections/$(am__dirstamp)
+gcc/sections/common.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)
diff --git a/libphobos/libdruntime/config/x86/switchcontext.S b/libphobos/libdruntime/config/x86/switchcontext.S
index 82420c6159c..8af3f5488ba 100644
--- a/libphobos/libdruntime/config/x86/switchcontext.S
+++ b/libphobos/libdruntime/config/x86/switchcontext.S
@@ -33,7 +33,9 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 
     .text
     .globl CSYM(fiber_switchContext)
+#if defined(__ELF__)
     .type CSYM(fiber_switchContext), @function
+#endif
     .align 16
 CSYM(fiber_switchContext):
     .cfi_startproc
@@ -61,13 +63,17 @@ CSYM(fiber_switchContext):
     // 'return' to complete switch
     ret
     .cfi_endproc
+#if defined(__ELF__)
     .size CSYM(fiber_switchContext),.-CSYM(fiber_switchContext)
+#endif
 
 #elif defined(__x86_64__) && !defined(__ILP32__) && !defined(__CET__)
 
     .text
     .globl CSYM(fiber_switchContext)
+#if defined(__ELF__)
     .type CSYM(fiber_switchContext), @function
+#endif
     .align 16
 CSYM(fiber_switchContext):
     .cfi_startproc
@@ -96,6 +102,8 @@ CSYM(fiber_switchContext):
     // 'return' to complete switch
     ret
     .cfi_endproc
+#if defined(__ELF__)
    .size CSYM(fiber_switchContext),.-CSYM(fiber_switchContext)
+#endif
 
 #endif
diff --git a/libphobos/libdruntime/gcc/deh.d b/libphobos/libdruntime/gcc/deh.d
index c747b5132d1..7b44f2288dc 100644
--- a/libphobos/libdruntime/gcc/deh.d
+++ b/libphobos/libdruntime/gcc/deh.d
@@ -34,11 +34,6 @@ extern(C)
 {
     int _d_isbaseof(ClassInfo, ClassInfo);
     void _d_createTrace(Object, void*);
-
-    // Not used in GDC but declaration required by rt/sections.d
-    struct FuncTable
-    {
-    }
 }
 
 /**
diff --git a/libphobos/libdruntime/gcc/sections/android.d b/libphobos/libdruntime/gcc/sections/android.d
index 4af26b42ffc..56dff4ec861 100644
--- a/libphobos/libdruntime/gcc/sections/android.d
+++ b/libphobos/libdruntime/gcc/sections/android.d
@@ -54,13 +54,6 @@ struct SectionGroup
         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[];
diff --git a/libphobos/libdruntime/gcc/sections/common.d b/libphobos/libdruntime/gcc/sections/common.d
new file mode 100644
index 00000000000..b2d2322347d
--- /dev/null
+++ b/libphobos/libdruntime/gcc/sections/common.d
@@ -0,0 +1,48 @@
+// Common support routines 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.common;
+
+/****
+ * 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.).
+ */
+void safeAssert(bool condition, scope string msg, size_t line = __LINE__) @nogc nothrow @safe
+{
+    import core.internal.abort;
+    condition || abort(msg, __FILE__, line);
+}
+
+/****
+ * 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]; }
diff --git a/libphobos/libdruntime/gcc/sections/elf_shared.d b/libphobos/libdruntime/gcc/sections/elf_shared.d
index 5b0fad9543b..d73708dc6d3 100644
--- a/libphobos/libdruntime/gcc/sections/elf_shared.d
+++ b/libphobos/libdruntime/gcc/sections/elf_shared.d
@@ -134,11 +134,6 @@ struct DSO
         return _moduleGroup;
     }
 
-    @property immutable(FuncTable)[] ehTables() const nothrow @nogc
-    {
-        return null;
-    }
-
     @property inout(void[])[] gcRanges() inout nothrow @nogc
     {
         return _gcRanges[];
@@ -403,12 +398,6 @@ version (Shared)
      */
     __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
 {
diff --git a/libphobos/libdruntime/gcc/sections/osx.d b/libphobos/libdruntime/gcc/sections/osx.d
index 3e3db70e4b8..2f807bb98e0 100644
--- a/libphobos/libdruntime/gcc/sections/osx.d
+++ b/libphobos/libdruntime/gcc/sections/osx.d
@@ -24,25 +24,38 @@ 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 gcc.sections.common;
+
+import core.stdc.stdlib;
 import core.sys.darwin.mach.dyld;
 import core.sys.darwin.mach.getsect;
-import rt.deh, rt.minfo;
+import rt.minfo;
 import rt.util.container.array;
 
-struct SectionGroup
+version (GNU_EMUTLS)
+    import gcc.emutls;
+
+alias DSO SectionGroup;
+struct DSO
 {
-    static int opApply(scope int delegate(ref SectionGroup) dg)
+    static int opApply(scope int delegate(ref DSO) dg)
     {
-        return dg(_sections);
+        foreach (dso; _loadedDSOs)
+        {
+            if (auto res = dg(*dso))
+                return res;
+        }
+        return 0;
     }
 
-    static int opApplyReverse(scope int delegate(ref SectionGroup) dg)
+    static int opApplyReverse(scope int delegate(ref DSO) dg)
     {
-        return dg(_sections);
+        foreach_reverse (dso; _loadedDSOs)
+        {
+            if (auto res = dg(*dso))
+                return res;
+        }
+        return 0;
     }
 
     @property immutable(ModuleInfo*)[] modules() const nothrow @nogc
@@ -60,16 +73,9 @@ struct SectionGroup
         return _gcRanges[];
     }
 
-    @property immutable(FuncTable)[] ehTables() const nothrow @nogc
-    {
-        return _ehTables[];
-    }
-
 private:
-    immutable(FuncTable)[] _ehTables;
     ModuleGroup _moduleGroup;
     Array!(void[]) _gcRanges;
-    immutable(void)[][2] _tlsImage;
 }
 
 /****
@@ -82,8 +88,6 @@ __gshared bool _isRuntimeInitialized;
  */
 void initSections() nothrow @nogc
 {
-    pthread_key_create(&_tlsKey, null);
-    _dyld_register_func_for_add_image(&sections_osx_onAddImage);
     _isRuntimeInitialized = true;
 }
 
@@ -92,160 +96,161 @@ void initSections() nothrow @nogc
  */
 void finiSections() nothrow @nogc
 {
-    _sections._gcRanges.reset();
-    pthread_key_delete(_tlsKey);
     _isRuntimeInitialized = false;
 }
 
 void[]* initTLSRanges() nothrow @nogc
 {
-    return &getTLSBlock();
+    return null;
 }
 
 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);
+    version (GNU_EMUTLS)
+        _d_emutls_scan(dg);
+    else
+        static assert(0, "Native TLS unimplemented");
 }
 
-// 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 )
+version (Shared)
 {
-    immutable off = tlsOffset(p);
-    auto tls = getTLSBlockAlloc();
-    assert(off < tls.length);
-    return tls.ptr + off;
-}
-
-private:
+    // interface for core.thread to inherit loaded libraries
+    void* pinLoadedLibraries() nothrow @nogc
+    {
+        return null;
+    }
 
-__gshared pthread_key_t _tlsKey;
+    void unpinLoadedLibraries(void* p) nothrow @nogc
+    {
+    }
 
-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)
+    // Called before TLS ctors are ran, copy over the loaded libraries
+    // of the parent thread.
+    void inheritLoadedLibraries(void* p) nothrow @nogc
     {
-        return off0;
     }
-    immutable off1 = cast(size_t)(p - _sections._tlsImage[1].ptr);
-    if (off1 < _sections._tlsImage[1].length)
+
+    // Called after all TLS dtors ran, decrements all remaining dlopen refs.
+    void cleanupLoadedLibraries() nothrow @nogc
     {
-        size_t sz = (_sections._tlsImage[0].length + 15) & ~cast(size_t)15;
-        return sz + off1;
     }
-    assert(0);
 }
 
-ref void[] getTLSBlock() nothrow @nogc
+private:
+
+/*
+ * Static DSOs loaded by the runtime linker. This includes the
+ * executable. These can't be unloaded.
+ */
+@property ref Array!(DSO*) _loadedDSOs() @nogc nothrow
 {
-    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;
+    __gshared Array!(DSO*) x;
+    return x;
 }
 
-ref void[] getTLSBlockAlloc()
+/*
+ * Set to true during rt_loadLibrary/rt_unloadLibrary calls.
+ */
+enum _rtLoading = false;
+
+struct MachHeader
 {
-    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;
+    const(mach_header)* header; // the mach header of the image
+    intptr_t slide;             // virtural memory address slide amount
 }
 
-__gshared SectionGroup _sections;
+///////////////////////////////////////////////////////////////////////////////
+// Compiler to runtime interface.
+///////////////////////////////////////////////////////////////////////////////
 
-extern (C) void sections_osx_onAddImage(in mach_header* h, intptr_t slide)
+/* 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)
 {
-    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]);
-    }
+    // only one supported currently
+    safeAssert(data._version >= 1, "Incompatible compiler-generated DSO data version.");
 
-    auto minfosect = getSection(h, slide, "__DATA", "__minfodata");
-    if (minfosect != null)
+    // no backlink => register
+    if (*data._slot is 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)
+        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));
+
+        MachHeader info = void;
+        const headerFound = findDSOHeaderForAddr(data._slot, &info);
+        safeAssert(headerFound, "Failed to find image header.");
+
+        foreach (e; dataSegs)
         {
-            fprintf(stderr, "Shared libraries are not yet supported on OSX.\n");
+            auto sect = getSection(info.header, info.slide,
+                                   e.seg.ptr, e.sect.ptr);
+            if (sect != null)
+                pdso._gcRanges.insertBack((cast(void*)sect.ptr)[0 .. sect.length]);
         }
 
-        debug(PRINTF) printf("  minfodata\n");
-        auto p = cast(immutable(ModuleInfo*)*)minfosect.ptr;
-        immutable len = minfosect.length / (*p).sizeof;
-
-        _sections._moduleGroup = ModuleGroup(p[0 .. len]);
+        foreach (p; _loadedDSOs)
+            safeAssert(p !is pdso, "DSO already registered.");
+        _loadedDSOs.insertBack(pdso);
     }
-
-    auto ehsect = getSection(h, slide, "__DATA", "__deh_eh");
-    if (ehsect != null)
+    // has backlink => unregister
+    else
     {
-        debug(PRINTF) printf("  deh_eh\n");
-        auto p = cast(immutable(FuncTable)*)ehsect.ptr;
-        immutable len = ehsect.length / (*p).sizeof;
+        DSO* pdso = cast(DSO*)*data._slot;
+        *data._slot = null;
 
-        _sections._ehTables = p[0 .. len];
-    }
+        // static DSOs are unloaded in reverse order
+        safeAssert(pdso == _loadedDSOs.back, "DSO being unregistered isn't current last one.");
+        _loadedDSOs.popBack();
 
-    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];
+        pdso._gcRanges.reset();
+        .free(pdso);
+
+        // last DSO being unloaded => shutdown registry
+        if (_loadedDSOs.empty)
+        {
+            version (GNU_EMUTLS)
+                _d_emutls_destroy();
+        }
     }
+}
+
+/**************************
+ * Input:
+ *      result where the output is to be written
+ * Returns:
+ *      true if found, and *result is filled in
+ */
 
-    auto tlssect2 = getSection(h, slide, "__DATA", "__tlscoal_nt");
-    if (tlssect2 != null)
+bool findDSOHeaderForAddr(in void* addr, MachHeader* result)
+{
+    foreach (i; 0 .. _dyld_image_count())
     {
-        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];
+        const header = _dyld_get_image_header(i);
+        const slide = _dyld_get_image_vmaddr_slide(i);
+        const section = getSection(header, slide, SEG_DATA, SECT_DATA);
+
+        // less than base address of section means quick reject
+        if (!section.length || addr < section.ptr)
+           continue;
+
+        if (addr < section.ptr + section.length)
+        {
+            result.header = header;
+            result.slide = slide;
+            return true;
+        }
     }
+    return false;
 }
 
 struct SegRef
@@ -258,25 +263,27 @@ static immutable SegRef[] dataSegs = [{SEG_DATA, SECT_DATA},
                                       {SEG_DATA, SECT_BSS},
                                       {SEG_DATA, SECT_COMMON}];
 
+/**
+ * Returns the section for the named section in the named segment
+ * for the mach_header pointer passed, or null if not found.
+ */
 ubyte[] getSection(in mach_header* header, intptr_t slide,
                    in char* segmentName, in char* sectionName)
 {
-    version (X86)
+    version (D_LP64)
     {
-        assert(header.magic == MH_MAGIC);
-        auto sect = getsectbynamefromheader(header,
+        assert(header.magic == MH_MAGIC_64);
+        auto sect = getsectbynamefromheader_64(cast(mach_header_64*)header,
                                             segmentName,
                                             sectionName);
     }
-    else version (X86_64)
+    else
     {
-        assert(header.magic == MH_MAGIC_64);
-        auto sect = getsectbynamefromheader_64(cast(mach_header_64*)header,
+        assert(header.magic == MH_MAGIC);
+        auto sect = getsectbynamefromheader(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];
diff --git a/libphobos/libdruntime/gcc/sections/win64.d b/libphobos/libdruntime/gcc/sections/win64.d
index 357940ba821..512693c071d 100644
--- a/libphobos/libdruntime/gcc/sections/win64.d
+++ b/libphobos/libdruntime/gcc/sections/win64.d
@@ -51,14 +51,6 @@ struct SectionGroup
         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[];
diff --git a/libphobos/m4/druntime/os.m4 b/libphobos/m4/druntime/os.m4
index ed93e30f1e9..351558dbcda 100644
--- a/libphobos/m4/druntime/os.m4
+++ b/libphobos/m4/druntime/os.m4
@@ -149,17 +149,31 @@ AC_DEFUN([DRUNTIME_OS_ARM_EABI_UNWINDER],
 # substitute DCFG_MINFO_BRACKETING.
 AC_DEFUN([DRUNTIME_OS_MINFO_BRACKETING],
 [
+  AC_REQUIRE([DRUNTIME_OS_DETECT])
+
   AC_LANG_PUSH([C])
   AC_MSG_CHECKING([for minfo section bracketing])
+  case "$druntime_cv_target_os" in
+      darwin*)
+	section="__DATA,__minfodata"
+	start="section\$start\$__DATA\$__minfodata"
+	stop="section\$end\$__DATA\$__minfodata"
+	;;
+      *)
+	section="minfo"
+	start="__start_minfo"
+	stop="__stop_minfo"
+	;;
+  esac
   AC_LINK_IFELSE([AC_LANG_SOURCE([
-    void* module_info_ptr __attribute__((section ("minfo")));
-    extern void* __start_minfo __attribute__((visibility ("hidden")));
-    extern void* __stop_minfo __attribute__((visibility ("hidden")));
+    void* module_info_ptr __attribute__((section ("$section")));
+    extern void* start_minfo __asm__("$start") __attribute__((visibility ("hidden")));
+    extern void* stop_minfo __asm__("$stop") __attribute__((visibility ("hidden")));
 
     int main()
     {
         // Never run, just to prevent compiler from optimizing access
-        return &__start_minfo == &__stop_minfo;
+        return (int)(&stop_minfo - &start_minfo);
     }
   ])],
     [AC_MSG_RESULT([yes])
diff --git a/libphobos/testsuite/lib/libphobos.exp b/libphobos/testsuite/lib/libphobos.exp
index 3be2092b12e..ad323d761b9 100644
--- a/libphobos/testsuite/lib/libphobos.exp
+++ b/libphobos/testsuite/lib/libphobos.exp
@@ -90,6 +90,10 @@ proc libphobos-dg-test { prog do_what extra_tool_flags } {
 }
 
 proc libphobos-dg-prune { system text } {
+
+    # Ignore warnings from cctools.
+    regsub -all "(^|\n)clang: warning: argument unused during compilation:\[^\n\]*" $text "" text
+
     return $text
 }
 
diff --git a/libphobos/testsuite/libphobos.druntime/druntime.exp b/libphobos/testsuite/libphobos.druntime/druntime.exp
index 2f3a36f73cf..df01fcc8a23 100644
--- a/libphobos/testsuite/libphobos.druntime/druntime.exp
+++ b/libphobos/testsuite/libphobos.druntime/druntime.exp
@@ -15,7 +15,7 @@
 # <http://www.gnu.org/licenses/>.
 
 # Immediately exit if we can't run target executables.
-if { ![isnative] || ![is-effective-target static] } {
+if { ![isnative] } {
     return
 }
 
diff --git a/libphobos/testsuite/libphobos.phobos/phobos.exp b/libphobos/testsuite/libphobos.phobos/phobos.exp
index 0975ab1f801..770e5769e3c 100644
--- a/libphobos/testsuite/libphobos.phobos/phobos.exp
+++ b/libphobos/testsuite/libphobos.phobos/phobos.exp
@@ -15,7 +15,7 @@
 # <http://www.gnu.org/licenses/>.
 
 # Immediately exit if we can't run target executables.
-if { ![isnative] || ![is-effective-target static] } {
+if { ![isnative] } {
     return
 }


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [gcc(refs/users/ibuclaw/heads/darwin)] libphobos: Checkpoint in darwin runtime support
@ 2021-01-11 11:39 Iain Buclaw
  0 siblings, 0 replies; 15+ messages in thread
From: Iain Buclaw @ 2021-01-11 11:39 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:3f44ca25722ed778aad91204b1b10a3ae0706119

commit 3f44ca25722ed778aad91204b1b10a3ae0706119
Author: Iain Buclaw <ibuclaw@gdcproject.org>
Date:   Sun Nov 29 14:44:28 2020 +0100

    libphobos: Checkpoint in darwin runtime support

Diff:
---
 libphobos/configure                                |  22 +-
 libphobos/libdruntime/Makefile.am                  |  30 +--
 libphobos/libdruntime/Makefile.in                  |  38 +--
 libphobos/libdruntime/config/x86/switchcontext.S   |   8 +
 libphobos/libdruntime/gcc/deh.d                    |   5 -
 libphobos/libdruntime/gcc/sections/android.d       |   7 -
 libphobos/libdruntime/gcc/sections/common.d        |  48 ++++
 libphobos/libdruntime/gcc/sections/elf_shared.d    |  11 -
 libphobos/libdruntime/gcc/sections/osx.d           | 279 +++++++++++----------
 libphobos/libdruntime/gcc/sections/win64.d         |   8 -
 libphobos/m4/druntime/os.m4                        |  22 +-
 libphobos/testsuite/lib/libphobos.exp              |   4 +
 .../testsuite/libphobos.druntime/druntime.exp      |   2 +-
 libphobos/testsuite/libphobos.phobos/phobos.exp    |   2 +-
 14 files changed, 276 insertions(+), 210 deletions(-)

diff --git a/libphobos/configure b/libphobos/configure
index 1c32a552d40..476303dec04 100755
--- a/libphobos/configure
+++ b/libphobos/configure
@@ -14373,6 +14373,8 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
 
 
+
+
   ac_ext=c
 ac_cpp='$CPP $CPPFLAGS'
 ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -14381,17 +14383,29 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for minfo section bracketing" >&5
 $as_echo_n "checking for minfo section bracketing... " >&6; }
+  case "$druntime_cv_target_os" in
+      darwin*)
+	section="__DATA,__minfodata"
+	start="section\$start\$__DATA\$__minfodata"
+	stop="section\$end\$__DATA\$__minfodata"
+	;;
+      *)
+	section="minfo"
+	start="__start_minfo"
+	stop="__stop_minfo"
+	;;
+  esac
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
-    void* module_info_ptr __attribute__((section ("minfo")));
-    extern void* __start_minfo __attribute__((visibility ("hidden")));
-    extern void* __stop_minfo __attribute__((visibility ("hidden")));
+    void* module_info_ptr __attribute__((section ("$section")));
+    extern void* start_minfo __asm__("$start") __attribute__((visibility ("hidden")));
+    extern void* stop_minfo __asm__("$stop") __attribute__((visibility ("hidden")));
 
     int main()
     {
         // Never run, just to prevent compiler from optimizing access
-        return &__start_minfo == &__stop_minfo;
+        return (int)(&stop_minfo - &start_minfo);
     }
 
 _ACEOF
diff --git a/libphobos/libdruntime/Makefile.am b/libphobos/libdruntime/Makefile.am
index 34d3b41df82..81774d92528 100644
--- a/libphobos/libdruntime/Makefile.am
+++ b/libphobos/libdruntime/Makefile.am
@@ -183,21 +183,21 @@ DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \
 	gc/impl/conservative/gc.d gc/impl/manual/gc.d gc/os.d gc/pooltable.d \
 	gc/proxy.d gcc/attribute.d gcc/backtrace.d gcc/builtins.d gcc/deh.d \
 	gcc/emutls.d gcc/gthread.d gcc/sections/android.d \
-	gcc/sections/elf_shared.d gcc/sections/osx.d gcc/sections/package.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 rt/typeinfo/ti_Aint.d \
-	rt/typeinfo/ti_Along.d rt/typeinfo/ti_Areal.d rt/typeinfo/ti_Ashort.d \
-	rt/typeinfo/ti_C.d rt/typeinfo/ti_byte.d rt/typeinfo/ti_cdouble.d \
-	rt/typeinfo/ti_cent.d rt/typeinfo/ti_cfloat.d rt/typeinfo/ti_char.d \
-	rt/typeinfo/ti_creal.d rt/typeinfo/ti_dchar.d \
+	gcc/sections/common.d gcc/sections/elf_shared.d gcc/sections/osx.d \
+	gcc/sections/package.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 \
+	rt/typeinfo/ti_Aint.d rt/typeinfo/ti_Along.d rt/typeinfo/ti_Areal.d \
+	rt/typeinfo/ti_Ashort.d rt/typeinfo/ti_C.d rt/typeinfo/ti_byte.d \
+	rt/typeinfo/ti_cdouble.d rt/typeinfo/ti_cent.d rt/typeinfo/ti_cfloat.d \
+	rt/typeinfo/ti_char.d rt/typeinfo/ti_creal.d rt/typeinfo/ti_dchar.d \
 	rt/typeinfo/ti_delegate.d rt/typeinfo/ti_double.d \
 	rt/typeinfo/ti_float.d rt/typeinfo/ti_idouble.d \
 	rt/typeinfo/ti_ifloat.d rt/typeinfo/ti_int.d rt/typeinfo/ti_ireal.d \
diff --git a/libphobos/libdruntime/Makefile.in b/libphobos/libdruntime/Makefile.in
index 99ee8b92afa..3bf08f52b31 100644
--- a/libphobos/libdruntime/Makefile.in
+++ b/libphobos/libdruntime/Makefile.in
@@ -207,9 +207,10 @@ am__objects_1 = core/atomic.lo core/attribute.lo core/bitop.lo \
 	gc/impl/conservative/gc.lo gc/impl/manual/gc.lo gc/os.lo \
 	gc/pooltable.lo gc/proxy.lo gcc/attribute.lo gcc/backtrace.lo \
 	gcc/builtins.lo gcc/deh.lo gcc/emutls.lo gcc/gthread.lo \
-	gcc/sections/android.lo gcc/sections/elf_shared.lo \
-	gcc/sections/osx.lo gcc/sections/package.lo \
-	gcc/sections/win32.lo gcc/sections/win64.lo gcc/unwind/arm.lo \
+	gcc/sections/android.lo gcc/sections/common.lo \
+	gcc/sections/elf_shared.lo gcc/sections/osx.lo \
+	gcc/sections/package.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 \
@@ -808,21 +809,21 @@ DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \
 	gc/impl/conservative/gc.d gc/impl/manual/gc.d gc/os.d gc/pooltable.d \
 	gc/proxy.d gcc/attribute.d gcc/backtrace.d gcc/builtins.d gcc/deh.d \
 	gcc/emutls.d gcc/gthread.d gcc/sections/android.d \
-	gcc/sections/elf_shared.d gcc/sections/osx.d gcc/sections/package.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 rt/typeinfo/ti_Aint.d \
-	rt/typeinfo/ti_Along.d rt/typeinfo/ti_Areal.d rt/typeinfo/ti_Ashort.d \
-	rt/typeinfo/ti_C.d rt/typeinfo/ti_byte.d rt/typeinfo/ti_cdouble.d \
-	rt/typeinfo/ti_cent.d rt/typeinfo/ti_cfloat.d rt/typeinfo/ti_char.d \
-	rt/typeinfo/ti_creal.d rt/typeinfo/ti_dchar.d \
+	gcc/sections/common.d gcc/sections/elf_shared.d gcc/sections/osx.d \
+	gcc/sections/package.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 \
+	rt/typeinfo/ti_Aint.d rt/typeinfo/ti_Along.d rt/typeinfo/ti_Areal.d \
+	rt/typeinfo/ti_Ashort.d rt/typeinfo/ti_C.d rt/typeinfo/ti_byte.d \
+	rt/typeinfo/ti_cdouble.d rt/typeinfo/ti_cent.d rt/typeinfo/ti_cfloat.d \
+	rt/typeinfo/ti_char.d rt/typeinfo/ti_creal.d rt/typeinfo/ti_dchar.d \
 	rt/typeinfo/ti_delegate.d rt/typeinfo/ti_double.d \
 	rt/typeinfo/ti_float.d rt/typeinfo/ti_idouble.d \
 	rt/typeinfo/ti_ifloat.d rt/typeinfo/ti_int.d rt/typeinfo/ti_ireal.d \
@@ -1195,6 +1196,7 @@ gcc/sections/$(am__dirstamp):
 	@$(MKDIR_P) gcc/sections
 	@: > gcc/sections/$(am__dirstamp)
 gcc/sections/android.lo: gcc/sections/$(am__dirstamp)
+gcc/sections/common.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)
diff --git a/libphobos/libdruntime/config/x86/switchcontext.S b/libphobos/libdruntime/config/x86/switchcontext.S
index 82420c6159c..8af3f5488ba 100644
--- a/libphobos/libdruntime/config/x86/switchcontext.S
+++ b/libphobos/libdruntime/config/x86/switchcontext.S
@@ -33,7 +33,9 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 
     .text
     .globl CSYM(fiber_switchContext)
+#if defined(__ELF__)
     .type CSYM(fiber_switchContext), @function
+#endif
     .align 16
 CSYM(fiber_switchContext):
     .cfi_startproc
@@ -61,13 +63,17 @@ CSYM(fiber_switchContext):
     // 'return' to complete switch
     ret
     .cfi_endproc
+#if defined(__ELF__)
     .size CSYM(fiber_switchContext),.-CSYM(fiber_switchContext)
+#endif
 
 #elif defined(__x86_64__) && !defined(__ILP32__) && !defined(__CET__)
 
     .text
     .globl CSYM(fiber_switchContext)
+#if defined(__ELF__)
     .type CSYM(fiber_switchContext), @function
+#endif
     .align 16
 CSYM(fiber_switchContext):
     .cfi_startproc
@@ -96,6 +102,8 @@ CSYM(fiber_switchContext):
     // 'return' to complete switch
     ret
     .cfi_endproc
+#if defined(__ELF__)
    .size CSYM(fiber_switchContext),.-CSYM(fiber_switchContext)
+#endif
 
 #endif
diff --git a/libphobos/libdruntime/gcc/deh.d b/libphobos/libdruntime/gcc/deh.d
index c747b5132d1..7b44f2288dc 100644
--- a/libphobos/libdruntime/gcc/deh.d
+++ b/libphobos/libdruntime/gcc/deh.d
@@ -34,11 +34,6 @@ extern(C)
 {
     int _d_isbaseof(ClassInfo, ClassInfo);
     void _d_createTrace(Object, void*);
-
-    // Not used in GDC but declaration required by rt/sections.d
-    struct FuncTable
-    {
-    }
 }
 
 /**
diff --git a/libphobos/libdruntime/gcc/sections/android.d b/libphobos/libdruntime/gcc/sections/android.d
index 4af26b42ffc..56dff4ec861 100644
--- a/libphobos/libdruntime/gcc/sections/android.d
+++ b/libphobos/libdruntime/gcc/sections/android.d
@@ -54,13 +54,6 @@ struct SectionGroup
         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[];
diff --git a/libphobos/libdruntime/gcc/sections/common.d b/libphobos/libdruntime/gcc/sections/common.d
new file mode 100644
index 00000000000..b2d2322347d
--- /dev/null
+++ b/libphobos/libdruntime/gcc/sections/common.d
@@ -0,0 +1,48 @@
+// Common support routines 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.common;
+
+/****
+ * 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.).
+ */
+void safeAssert(bool condition, scope string msg, size_t line = __LINE__) @nogc nothrow @safe
+{
+    import core.internal.abort;
+    condition || abort(msg, __FILE__, line);
+}
+
+/****
+ * 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]; }
diff --git a/libphobos/libdruntime/gcc/sections/elf_shared.d b/libphobos/libdruntime/gcc/sections/elf_shared.d
index 9050413b261..9643d36d337 100644
--- a/libphobos/libdruntime/gcc/sections/elf_shared.d
+++ b/libphobos/libdruntime/gcc/sections/elf_shared.d
@@ -132,11 +132,6 @@ struct DSO
         return _moduleGroup;
     }
 
-    @property immutable(FuncTable)[] ehTables() const nothrow @nogc
-    {
-        return null;
-    }
-
     @property inout(void[])[] gcRanges() inout nothrow @nogc
     {
         return _gcRanges[];
@@ -383,12 +378,6 @@ version (Shared)
      */
     __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
 {
diff --git a/libphobos/libdruntime/gcc/sections/osx.d b/libphobos/libdruntime/gcc/sections/osx.d
index 3e3db70e4b8..2f807bb98e0 100644
--- a/libphobos/libdruntime/gcc/sections/osx.d
+++ b/libphobos/libdruntime/gcc/sections/osx.d
@@ -24,25 +24,38 @@ 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 gcc.sections.common;
+
+import core.stdc.stdlib;
 import core.sys.darwin.mach.dyld;
 import core.sys.darwin.mach.getsect;
-import rt.deh, rt.minfo;
+import rt.minfo;
 import rt.util.container.array;
 
-struct SectionGroup
+version (GNU_EMUTLS)
+    import gcc.emutls;
+
+alias DSO SectionGroup;
+struct DSO
 {
-    static int opApply(scope int delegate(ref SectionGroup) dg)
+    static int opApply(scope int delegate(ref DSO) dg)
     {
-        return dg(_sections);
+        foreach (dso; _loadedDSOs)
+        {
+            if (auto res = dg(*dso))
+                return res;
+        }
+        return 0;
     }
 
-    static int opApplyReverse(scope int delegate(ref SectionGroup) dg)
+    static int opApplyReverse(scope int delegate(ref DSO) dg)
     {
-        return dg(_sections);
+        foreach_reverse (dso; _loadedDSOs)
+        {
+            if (auto res = dg(*dso))
+                return res;
+        }
+        return 0;
     }
 
     @property immutable(ModuleInfo*)[] modules() const nothrow @nogc
@@ -60,16 +73,9 @@ struct SectionGroup
         return _gcRanges[];
     }
 
-    @property immutable(FuncTable)[] ehTables() const nothrow @nogc
-    {
-        return _ehTables[];
-    }
-
 private:
-    immutable(FuncTable)[] _ehTables;
     ModuleGroup _moduleGroup;
     Array!(void[]) _gcRanges;
-    immutable(void)[][2] _tlsImage;
 }
 
 /****
@@ -82,8 +88,6 @@ __gshared bool _isRuntimeInitialized;
  */
 void initSections() nothrow @nogc
 {
-    pthread_key_create(&_tlsKey, null);
-    _dyld_register_func_for_add_image(&sections_osx_onAddImage);
     _isRuntimeInitialized = true;
 }
 
@@ -92,160 +96,161 @@ void initSections() nothrow @nogc
  */
 void finiSections() nothrow @nogc
 {
-    _sections._gcRanges.reset();
-    pthread_key_delete(_tlsKey);
     _isRuntimeInitialized = false;
 }
 
 void[]* initTLSRanges() nothrow @nogc
 {
-    return &getTLSBlock();
+    return null;
 }
 
 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);
+    version (GNU_EMUTLS)
+        _d_emutls_scan(dg);
+    else
+        static assert(0, "Native TLS unimplemented");
 }
 
-// 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 )
+version (Shared)
 {
-    immutable off = tlsOffset(p);
-    auto tls = getTLSBlockAlloc();
-    assert(off < tls.length);
-    return tls.ptr + off;
-}
-
-private:
+    // interface for core.thread to inherit loaded libraries
+    void* pinLoadedLibraries() nothrow @nogc
+    {
+        return null;
+    }
 
-__gshared pthread_key_t _tlsKey;
+    void unpinLoadedLibraries(void* p) nothrow @nogc
+    {
+    }
 
-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)
+    // Called before TLS ctors are ran, copy over the loaded libraries
+    // of the parent thread.
+    void inheritLoadedLibraries(void* p) nothrow @nogc
     {
-        return off0;
     }
-    immutable off1 = cast(size_t)(p - _sections._tlsImage[1].ptr);
-    if (off1 < _sections._tlsImage[1].length)
+
+    // Called after all TLS dtors ran, decrements all remaining dlopen refs.
+    void cleanupLoadedLibraries() nothrow @nogc
     {
-        size_t sz = (_sections._tlsImage[0].length + 15) & ~cast(size_t)15;
-        return sz + off1;
     }
-    assert(0);
 }
 
-ref void[] getTLSBlock() nothrow @nogc
+private:
+
+/*
+ * Static DSOs loaded by the runtime linker. This includes the
+ * executable. These can't be unloaded.
+ */
+@property ref Array!(DSO*) _loadedDSOs() @nogc nothrow
 {
-    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;
+    __gshared Array!(DSO*) x;
+    return x;
 }
 
-ref void[] getTLSBlockAlloc()
+/*
+ * Set to true during rt_loadLibrary/rt_unloadLibrary calls.
+ */
+enum _rtLoading = false;
+
+struct MachHeader
 {
-    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;
+    const(mach_header)* header; // the mach header of the image
+    intptr_t slide;             // virtural memory address slide amount
 }
 
-__gshared SectionGroup _sections;
+///////////////////////////////////////////////////////////////////////////////
+// Compiler to runtime interface.
+///////////////////////////////////////////////////////////////////////////////
 
-extern (C) void sections_osx_onAddImage(in mach_header* h, intptr_t slide)
+/* 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)
 {
-    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]);
-    }
+    // only one supported currently
+    safeAssert(data._version >= 1, "Incompatible compiler-generated DSO data version.");
 
-    auto minfosect = getSection(h, slide, "__DATA", "__minfodata");
-    if (minfosect != null)
+    // no backlink => register
+    if (*data._slot is 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)
+        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));
+
+        MachHeader info = void;
+        const headerFound = findDSOHeaderForAddr(data._slot, &info);
+        safeAssert(headerFound, "Failed to find image header.");
+
+        foreach (e; dataSegs)
         {
-            fprintf(stderr, "Shared libraries are not yet supported on OSX.\n");
+            auto sect = getSection(info.header, info.slide,
+                                   e.seg.ptr, e.sect.ptr);
+            if (sect != null)
+                pdso._gcRanges.insertBack((cast(void*)sect.ptr)[0 .. sect.length]);
         }
 
-        debug(PRINTF) printf("  minfodata\n");
-        auto p = cast(immutable(ModuleInfo*)*)minfosect.ptr;
-        immutable len = minfosect.length / (*p).sizeof;
-
-        _sections._moduleGroup = ModuleGroup(p[0 .. len]);
+        foreach (p; _loadedDSOs)
+            safeAssert(p !is pdso, "DSO already registered.");
+        _loadedDSOs.insertBack(pdso);
     }
-
-    auto ehsect = getSection(h, slide, "__DATA", "__deh_eh");
-    if (ehsect != null)
+    // has backlink => unregister
+    else
     {
-        debug(PRINTF) printf("  deh_eh\n");
-        auto p = cast(immutable(FuncTable)*)ehsect.ptr;
-        immutable len = ehsect.length / (*p).sizeof;
+        DSO* pdso = cast(DSO*)*data._slot;
+        *data._slot = null;
 
-        _sections._ehTables = p[0 .. len];
-    }
+        // static DSOs are unloaded in reverse order
+        safeAssert(pdso == _loadedDSOs.back, "DSO being unregistered isn't current last one.");
+        _loadedDSOs.popBack();
 
-    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];
+        pdso._gcRanges.reset();
+        .free(pdso);
+
+        // last DSO being unloaded => shutdown registry
+        if (_loadedDSOs.empty)
+        {
+            version (GNU_EMUTLS)
+                _d_emutls_destroy();
+        }
     }
+}
+
+/**************************
+ * Input:
+ *      result where the output is to be written
+ * Returns:
+ *      true if found, and *result is filled in
+ */
 
-    auto tlssect2 = getSection(h, slide, "__DATA", "__tlscoal_nt");
-    if (tlssect2 != null)
+bool findDSOHeaderForAddr(in void* addr, MachHeader* result)
+{
+    foreach (i; 0 .. _dyld_image_count())
     {
-        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];
+        const header = _dyld_get_image_header(i);
+        const slide = _dyld_get_image_vmaddr_slide(i);
+        const section = getSection(header, slide, SEG_DATA, SECT_DATA);
+
+        // less than base address of section means quick reject
+        if (!section.length || addr < section.ptr)
+           continue;
+
+        if (addr < section.ptr + section.length)
+        {
+            result.header = header;
+            result.slide = slide;
+            return true;
+        }
     }
+    return false;
 }
 
 struct SegRef
@@ -258,25 +263,27 @@ static immutable SegRef[] dataSegs = [{SEG_DATA, SECT_DATA},
                                       {SEG_DATA, SECT_BSS},
                                       {SEG_DATA, SECT_COMMON}];
 
+/**
+ * Returns the section for the named section in the named segment
+ * for the mach_header pointer passed, or null if not found.
+ */
 ubyte[] getSection(in mach_header* header, intptr_t slide,
                    in char* segmentName, in char* sectionName)
 {
-    version (X86)
+    version (D_LP64)
     {
-        assert(header.magic == MH_MAGIC);
-        auto sect = getsectbynamefromheader(header,
+        assert(header.magic == MH_MAGIC_64);
+        auto sect = getsectbynamefromheader_64(cast(mach_header_64*)header,
                                             segmentName,
                                             sectionName);
     }
-    else version (X86_64)
+    else
     {
-        assert(header.magic == MH_MAGIC_64);
-        auto sect = getsectbynamefromheader_64(cast(mach_header_64*)header,
+        assert(header.magic == MH_MAGIC);
+        auto sect = getsectbynamefromheader(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];
diff --git a/libphobos/libdruntime/gcc/sections/win64.d b/libphobos/libdruntime/gcc/sections/win64.d
index 357940ba821..512693c071d 100644
--- a/libphobos/libdruntime/gcc/sections/win64.d
+++ b/libphobos/libdruntime/gcc/sections/win64.d
@@ -51,14 +51,6 @@ struct SectionGroup
         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[];
diff --git a/libphobos/m4/druntime/os.m4 b/libphobos/m4/druntime/os.m4
index ed93e30f1e9..351558dbcda 100644
--- a/libphobos/m4/druntime/os.m4
+++ b/libphobos/m4/druntime/os.m4
@@ -149,17 +149,31 @@ AC_DEFUN([DRUNTIME_OS_ARM_EABI_UNWINDER],
 # substitute DCFG_MINFO_BRACKETING.
 AC_DEFUN([DRUNTIME_OS_MINFO_BRACKETING],
 [
+  AC_REQUIRE([DRUNTIME_OS_DETECT])
+
   AC_LANG_PUSH([C])
   AC_MSG_CHECKING([for minfo section bracketing])
+  case "$druntime_cv_target_os" in
+      darwin*)
+	section="__DATA,__minfodata"
+	start="section\$start\$__DATA\$__minfodata"
+	stop="section\$end\$__DATA\$__minfodata"
+	;;
+      *)
+	section="minfo"
+	start="__start_minfo"
+	stop="__stop_minfo"
+	;;
+  esac
   AC_LINK_IFELSE([AC_LANG_SOURCE([
-    void* module_info_ptr __attribute__((section ("minfo")));
-    extern void* __start_minfo __attribute__((visibility ("hidden")));
-    extern void* __stop_minfo __attribute__((visibility ("hidden")));
+    void* module_info_ptr __attribute__((section ("$section")));
+    extern void* start_minfo __asm__("$start") __attribute__((visibility ("hidden")));
+    extern void* stop_minfo __asm__("$stop") __attribute__((visibility ("hidden")));
 
     int main()
     {
         // Never run, just to prevent compiler from optimizing access
-        return &__start_minfo == &__stop_minfo;
+        return (int)(&stop_minfo - &start_minfo);
     }
   ])],
     [AC_MSG_RESULT([yes])
diff --git a/libphobos/testsuite/lib/libphobos.exp b/libphobos/testsuite/lib/libphobos.exp
index 3be2092b12e..ad323d761b9 100644
--- a/libphobos/testsuite/lib/libphobos.exp
+++ b/libphobos/testsuite/lib/libphobos.exp
@@ -90,6 +90,10 @@ proc libphobos-dg-test { prog do_what extra_tool_flags } {
 }
 
 proc libphobos-dg-prune { system text } {
+
+    # Ignore warnings from cctools.
+    regsub -all "(^|\n)clang: warning: argument unused during compilation:\[^\n\]*" $text "" text
+
     return $text
 }
 
diff --git a/libphobos/testsuite/libphobos.druntime/druntime.exp b/libphobos/testsuite/libphobos.druntime/druntime.exp
index 2f3a36f73cf..df01fcc8a23 100644
--- a/libphobos/testsuite/libphobos.druntime/druntime.exp
+++ b/libphobos/testsuite/libphobos.druntime/druntime.exp
@@ -15,7 +15,7 @@
 # <http://www.gnu.org/licenses/>.
 
 # Immediately exit if we can't run target executables.
-if { ![isnative] || ![is-effective-target static] } {
+if { ![isnative] } {
     return
 }
 
diff --git a/libphobos/testsuite/libphobos.phobos/phobos.exp b/libphobos/testsuite/libphobos.phobos/phobos.exp
index 46dea2bfad0..3c63a42c642 100644
--- a/libphobos/testsuite/libphobos.phobos/phobos.exp
+++ b/libphobos/testsuite/libphobos.phobos/phobos.exp
@@ -15,7 +15,7 @@
 # <http://www.gnu.org/licenses/>.
 
 # Immediately exit if we can't run target executables.
-if { ![isnative] || ![is-effective-target static] } {
+if { ![isnative] } {
     return
 }


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [gcc(refs/users/ibuclaw/heads/darwin)] libphobos: Checkpoint in darwin runtime support
@ 2020-12-22 13:40 Iain Buclaw
  0 siblings, 0 replies; 15+ messages in thread
From: Iain Buclaw @ 2020-12-22 13:40 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:ffd300cc0a8f5b31c0d41eb74dbc26a377d522fd

commit ffd300cc0a8f5b31c0d41eb74dbc26a377d522fd
Author: Iain Buclaw <ibuclaw@gdcproject.org>
Date:   Sun Nov 29 14:44:28 2020 +0100

    libphobos: Checkpoint in darwin runtime support

Diff:
---
 libphobos/configure                                |  22 +-
 libphobos/libdruntime/Makefile.am                  |  30 +--
 libphobos/libdruntime/Makefile.in                  |  38 +--
 libphobos/libdruntime/config/x86/switchcontext.S   |   8 +
 libphobos/libdruntime/gcc/deh.d                    |   5 -
 libphobos/libdruntime/gcc/sections/android.d       |   7 -
 libphobos/libdruntime/gcc/sections/common.d        |  48 ++++
 libphobos/libdruntime/gcc/sections/elf_shared.d    |  11 -
 libphobos/libdruntime/gcc/sections/osx.d           | 279 +++++++++++----------
 libphobos/libdruntime/gcc/sections/win64.d         |   8 -
 libphobos/m4/druntime/os.m4                        |  22 +-
 libphobos/testsuite/lib/libphobos.exp              |   4 +
 .../testsuite/libphobos.druntime/druntime.exp      |   2 +-
 libphobos/testsuite/libphobos.phobos/phobos.exp    |   2 +-
 14 files changed, 276 insertions(+), 210 deletions(-)

diff --git a/libphobos/configure b/libphobos/configure
index a7fb5edb90f..0ec729c9d96 100755
--- a/libphobos/configure
+++ b/libphobos/configure
@@ -14383,6 +14383,8 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
 
 
+
+
   ac_ext=c
 ac_cpp='$CPP $CPPFLAGS'
 ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -14391,17 +14393,29 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for minfo section bracketing" >&5
 $as_echo_n "checking for minfo section bracketing... " >&6; }
+  case "$druntime_cv_target_os" in
+      darwin*)
+	section="__DATA,__minfodata"
+	start="section\$start\$__DATA\$__minfodata"
+	stop="section\$end\$__DATA\$__minfodata"
+	;;
+      *)
+	section="minfo"
+	start="__start_minfo"
+	stop="__stop_minfo"
+	;;
+  esac
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
-    void* module_info_ptr __attribute__((section ("minfo")));
-    extern void* __start_minfo __attribute__((visibility ("hidden")));
-    extern void* __stop_minfo __attribute__((visibility ("hidden")));
+    void* module_info_ptr __attribute__((section ("$section")));
+    extern void* start_minfo __asm__("$start") __attribute__((visibility ("hidden")));
+    extern void* stop_minfo __asm__("$stop") __attribute__((visibility ("hidden")));
 
     int main()
     {
         // Never run, just to prevent compiler from optimizing access
-        return &__start_minfo == &__stop_minfo;
+        return (int)(&stop_minfo - &start_minfo);
     }
 
 _ACEOF
diff --git a/libphobos/libdruntime/Makefile.am b/libphobos/libdruntime/Makefile.am
index 4798bdf777d..1ebc97af39d 100644
--- a/libphobos/libdruntime/Makefile.am
+++ b/libphobos/libdruntime/Makefile.am
@@ -183,21 +183,21 @@ DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \
 	gc/impl/conservative/gc.d gc/impl/manual/gc.d gc/os.d gc/pooltable.d \
 	gc/proxy.d gcc/attribute.d gcc/backtrace.d gcc/builtins.d gcc/deh.d \
 	gcc/emutls.d gcc/gthread.d gcc/sections/android.d \
-	gcc/sections/elf_shared.d gcc/sections/osx.d gcc/sections/package.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 rt/typeinfo/ti_Aint.d \
-	rt/typeinfo/ti_Along.d rt/typeinfo/ti_Areal.d rt/typeinfo/ti_Ashort.d \
-	rt/typeinfo/ti_C.d rt/typeinfo/ti_byte.d rt/typeinfo/ti_cdouble.d \
-	rt/typeinfo/ti_cent.d rt/typeinfo/ti_cfloat.d rt/typeinfo/ti_char.d \
-	rt/typeinfo/ti_creal.d rt/typeinfo/ti_dchar.d \
+	gcc/sections/common.d gcc/sections/elf_shared.d gcc/sections/osx.d \
+	gcc/sections/package.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 \
+	rt/typeinfo/ti_Aint.d rt/typeinfo/ti_Along.d rt/typeinfo/ti_Areal.d \
+	rt/typeinfo/ti_Ashort.d rt/typeinfo/ti_C.d rt/typeinfo/ti_byte.d \
+	rt/typeinfo/ti_cdouble.d rt/typeinfo/ti_cent.d rt/typeinfo/ti_cfloat.d \
+	rt/typeinfo/ti_char.d rt/typeinfo/ti_creal.d rt/typeinfo/ti_dchar.d \
 	rt/typeinfo/ti_delegate.d rt/typeinfo/ti_double.d \
 	rt/typeinfo/ti_float.d rt/typeinfo/ti_idouble.d \
 	rt/typeinfo/ti_ifloat.d rt/typeinfo/ti_int.d rt/typeinfo/ti_ireal.d \
diff --git a/libphobos/libdruntime/Makefile.in b/libphobos/libdruntime/Makefile.in
index 99ee8b92afa..3bf08f52b31 100644
--- a/libphobos/libdruntime/Makefile.in
+++ b/libphobos/libdruntime/Makefile.in
@@ -207,9 +207,10 @@ am__objects_1 = core/atomic.lo core/attribute.lo core/bitop.lo \
 	gc/impl/conservative/gc.lo gc/impl/manual/gc.lo gc/os.lo \
 	gc/pooltable.lo gc/proxy.lo gcc/attribute.lo gcc/backtrace.lo \
 	gcc/builtins.lo gcc/deh.lo gcc/emutls.lo gcc/gthread.lo \
-	gcc/sections/android.lo gcc/sections/elf_shared.lo \
-	gcc/sections/osx.lo gcc/sections/package.lo \
-	gcc/sections/win32.lo gcc/sections/win64.lo gcc/unwind/arm.lo \
+	gcc/sections/android.lo gcc/sections/common.lo \
+	gcc/sections/elf_shared.lo gcc/sections/osx.lo \
+	gcc/sections/package.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 \
@@ -808,21 +809,21 @@ DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \
 	gc/impl/conservative/gc.d gc/impl/manual/gc.d gc/os.d gc/pooltable.d \
 	gc/proxy.d gcc/attribute.d gcc/backtrace.d gcc/builtins.d gcc/deh.d \
 	gcc/emutls.d gcc/gthread.d gcc/sections/android.d \
-	gcc/sections/elf_shared.d gcc/sections/osx.d gcc/sections/package.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 rt/typeinfo/ti_Aint.d \
-	rt/typeinfo/ti_Along.d rt/typeinfo/ti_Areal.d rt/typeinfo/ti_Ashort.d \
-	rt/typeinfo/ti_C.d rt/typeinfo/ti_byte.d rt/typeinfo/ti_cdouble.d \
-	rt/typeinfo/ti_cent.d rt/typeinfo/ti_cfloat.d rt/typeinfo/ti_char.d \
-	rt/typeinfo/ti_creal.d rt/typeinfo/ti_dchar.d \
+	gcc/sections/common.d gcc/sections/elf_shared.d gcc/sections/osx.d \
+	gcc/sections/package.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 \
+	rt/typeinfo/ti_Aint.d rt/typeinfo/ti_Along.d rt/typeinfo/ti_Areal.d \
+	rt/typeinfo/ti_Ashort.d rt/typeinfo/ti_C.d rt/typeinfo/ti_byte.d \
+	rt/typeinfo/ti_cdouble.d rt/typeinfo/ti_cent.d rt/typeinfo/ti_cfloat.d \
+	rt/typeinfo/ti_char.d rt/typeinfo/ti_creal.d rt/typeinfo/ti_dchar.d \
 	rt/typeinfo/ti_delegate.d rt/typeinfo/ti_double.d \
 	rt/typeinfo/ti_float.d rt/typeinfo/ti_idouble.d \
 	rt/typeinfo/ti_ifloat.d rt/typeinfo/ti_int.d rt/typeinfo/ti_ireal.d \
@@ -1195,6 +1196,7 @@ gcc/sections/$(am__dirstamp):
 	@$(MKDIR_P) gcc/sections
 	@: > gcc/sections/$(am__dirstamp)
 gcc/sections/android.lo: gcc/sections/$(am__dirstamp)
+gcc/sections/common.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)
diff --git a/libphobos/libdruntime/config/x86/switchcontext.S b/libphobos/libdruntime/config/x86/switchcontext.S
index f2f8efa218e..66c81f8b37a 100644
--- a/libphobos/libdruntime/config/x86/switchcontext.S
+++ b/libphobos/libdruntime/config/x86/switchcontext.S
@@ -33,7 +33,9 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 
     .text
     .globl CSYM(fiber_switchContext)
+#if defined(__ELF__)
     .type CSYM(fiber_switchContext), @function
+#endif
     .align 16
 CSYM(fiber_switchContext):
     .cfi_startproc
@@ -61,13 +63,17 @@ CSYM(fiber_switchContext):
     // 'return' to complete switch
     ret
     .cfi_endproc
+#if defined(__ELF__)
     .size CSYM(fiber_switchContext),.-CSYM(fiber_switchContext)
+#endif
 
 #elif defined(__x86_64__) && !defined(__ILP32__) && !defined(__CET__)
 
     .text
     .globl CSYM(fiber_switchContext)
+#if defined(__ELF__)
     .type CSYM(fiber_switchContext), @function
+#endif
     .align 16
 CSYM(fiber_switchContext):
     .cfi_startproc
@@ -96,6 +102,8 @@ CSYM(fiber_switchContext):
     // 'return' to complete switch
     ret
     .cfi_endproc
+#if defined(__ELF__)
    .size CSYM(fiber_switchContext),.-CSYM(fiber_switchContext)
+#endif
 
 #endif
diff --git a/libphobos/libdruntime/gcc/deh.d b/libphobos/libdruntime/gcc/deh.d
index 3e78a6c9c0e..bb2035f5155 100644
--- a/libphobos/libdruntime/gcc/deh.d
+++ b/libphobos/libdruntime/gcc/deh.d
@@ -34,11 +34,6 @@ extern(C)
 {
     int _d_isbaseof(ClassInfo, ClassInfo);
     void _d_createTrace(Object, void*);
-
-    // Not used in GDC but declaration required by rt/sections.d
-    struct FuncTable
-    {
-    }
 }
 
 /**
diff --git a/libphobos/libdruntime/gcc/sections/android.d b/libphobos/libdruntime/gcc/sections/android.d
index 2180a0b2514..51f5d24c2cb 100644
--- a/libphobos/libdruntime/gcc/sections/android.d
+++ b/libphobos/libdruntime/gcc/sections/android.d
@@ -54,13 +54,6 @@ struct SectionGroup
         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[];
diff --git a/libphobos/libdruntime/gcc/sections/common.d b/libphobos/libdruntime/gcc/sections/common.d
new file mode 100644
index 00000000000..b2d2322347d
--- /dev/null
+++ b/libphobos/libdruntime/gcc/sections/common.d
@@ -0,0 +1,48 @@
+// Common support routines 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.common;
+
+/****
+ * 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.).
+ */
+void safeAssert(bool condition, scope string msg, size_t line = __LINE__) @nogc nothrow @safe
+{
+    import core.internal.abort;
+    condition || abort(msg, __FILE__, line);
+}
+
+/****
+ * 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]; }
diff --git a/libphobos/libdruntime/gcc/sections/elf_shared.d b/libphobos/libdruntime/gcc/sections/elf_shared.d
index 59e2dd60a1f..3fb1b491f88 100644
--- a/libphobos/libdruntime/gcc/sections/elf_shared.d
+++ b/libphobos/libdruntime/gcc/sections/elf_shared.d
@@ -132,11 +132,6 @@ struct DSO
         return _moduleGroup;
     }
 
-    @property immutable(FuncTable)[] ehTables() const nothrow @nogc
-    {
-        return null;
-    }
-
     @property inout(void[])[] gcRanges() inout nothrow @nogc
     {
         return _gcRanges[];
@@ -383,12 +378,6 @@ version (Shared)
      */
     __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
 {
diff --git a/libphobos/libdruntime/gcc/sections/osx.d b/libphobos/libdruntime/gcc/sections/osx.d
index cb02b452404..6ace2da4a8b 100644
--- a/libphobos/libdruntime/gcc/sections/osx.d
+++ b/libphobos/libdruntime/gcc/sections/osx.d
@@ -24,25 +24,38 @@ 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 gcc.sections.common;
+
+import core.stdc.stdlib;
 import core.sys.darwin.mach.dyld;
 import core.sys.darwin.mach.getsect;
-import rt.deh, rt.minfo;
+import rt.minfo;
 import rt.util.container.array;
 
-struct SectionGroup
+version (GNU_EMUTLS)
+    import gcc.emutls;
+
+alias DSO SectionGroup;
+struct DSO
 {
-    static int opApply(scope int delegate(ref SectionGroup) dg)
+    static int opApply(scope int delegate(ref DSO) dg)
     {
-        return dg(_sections);
+        foreach (dso; _loadedDSOs)
+        {
+            if (auto res = dg(*dso))
+                return res;
+        }
+        return 0;
     }
 
-    static int opApplyReverse(scope int delegate(ref SectionGroup) dg)
+    static int opApplyReverse(scope int delegate(ref DSO) dg)
     {
-        return dg(_sections);
+        foreach_reverse (dso; _loadedDSOs)
+        {
+            if (auto res = dg(*dso))
+                return res;
+        }
+        return 0;
     }
 
     @property immutable(ModuleInfo*)[] modules() const nothrow @nogc
@@ -60,16 +73,9 @@ struct SectionGroup
         return _gcRanges[];
     }
 
-    @property immutable(FuncTable)[] ehTables() const nothrow @nogc
-    {
-        return _ehTables[];
-    }
-
 private:
-    immutable(FuncTable)[] _ehTables;
     ModuleGroup _moduleGroup;
     Array!(void[]) _gcRanges;
-    immutable(void)[][2] _tlsImage;
 }
 
 /****
@@ -82,8 +88,6 @@ __gshared bool _isRuntimeInitialized;
  */
 void initSections() nothrow @nogc
 {
-    pthread_key_create(&_tlsKey, null);
-    _dyld_register_func_for_add_image(&sections_osx_onAddImage);
     _isRuntimeInitialized = true;
 }
 
@@ -92,160 +96,161 @@ void initSections() nothrow @nogc
  */
 void finiSections() nothrow @nogc
 {
-    _sections._gcRanges.reset();
-    pthread_key_delete(_tlsKey);
     _isRuntimeInitialized = false;
 }
 
 void[]* initTLSRanges() nothrow @nogc
 {
-    return &getTLSBlock();
+    return null;
 }
 
 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);
+    version (GNU_EMUTLS)
+        _d_emutls_scan(dg);
+    else
+        static assert(0, "Native TLS unimplemented");
 }
 
-// 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 )
+version (Shared)
 {
-    immutable off = tlsOffset(p);
-    auto tls = getTLSBlockAlloc();
-    assert(off < tls.length);
-    return tls.ptr + off;
-}
-
-private:
+    // interface for core.thread to inherit loaded libraries
+    void* pinLoadedLibraries() nothrow @nogc
+    {
+        return null;
+    }
 
-__gshared pthread_key_t _tlsKey;
+    void unpinLoadedLibraries(void* p) nothrow @nogc
+    {
+    }
 
-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)
+    // Called before TLS ctors are ran, copy over the loaded libraries
+    // of the parent thread.
+    void inheritLoadedLibraries(void* p) nothrow @nogc
     {
-        return off0;
     }
-    immutable off1 = cast(size_t)(p - _sections._tlsImage[1].ptr);
-    if (off1 < _sections._tlsImage[1].length)
+
+    // Called after all TLS dtors ran, decrements all remaining dlopen refs.
+    void cleanupLoadedLibraries() nothrow @nogc
     {
-        size_t sz = (_sections._tlsImage[0].length + 15) & ~cast(size_t)15;
-        return sz + off1;
     }
-    assert(0);
 }
 
-ref void[] getTLSBlock() nothrow @nogc
+private:
+
+/*
+ * Static DSOs loaded by the runtime linker. This includes the
+ * executable. These can't be unloaded.
+ */
+@property ref Array!(DSO*) _loadedDSOs() @nogc nothrow
 {
-    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;
+    __gshared Array!(DSO*) x;
+    return x;
 }
 
-ref void[] getTLSBlockAlloc()
+/*
+ * Set to true during rt_loadLibrary/rt_unloadLibrary calls.
+ */
+enum _rtLoading = false;
+
+struct MachHeader
 {
-    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;
+    const(mach_header)* header; // the mach header of the image
+    intptr_t slide;             // virtural memory address slide amount
 }
 
-__gshared SectionGroup _sections;
+///////////////////////////////////////////////////////////////////////////////
+// Compiler to runtime interface.
+///////////////////////////////////////////////////////////////////////////////
 
-extern (C) void sections_osx_onAddImage(in mach_header* h, intptr_t slide)
+/* 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)
 {
-    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]);
-    }
+    // only one supported currently
+    safeAssert(data._version >= 1, "Incompatible compiler-generated DSO data version.");
 
-    auto minfosect = getSection(h, slide, "__DATA", "__minfodata");
-    if (minfosect != null)
+    // no backlink => register
+    if (*data._slot is 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)
+        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));
+
+        MachHeader info = void;
+        const headerFound = findDSOHeaderForAddr(data._slot, &info);
+        safeAssert(headerFound, "Failed to find image header.");
+
+        foreach (e; dataSegs)
         {
-            fprintf(stderr, "Shared libraries are not yet supported on OSX.\n");
+            auto sect = getSection(info.header, info.slide,
+                                   e.seg.ptr, e.sect.ptr);
+            if (sect != null)
+                pdso._gcRanges.insertBack((cast(void*)sect.ptr)[0 .. sect.length]);
         }
 
-        debug(PRINTF) printf("  minfodata\n");
-        auto p = cast(immutable(ModuleInfo*)*)minfosect.ptr;
-        immutable len = minfosect.length / (*p).sizeof;
-
-        _sections._moduleGroup = ModuleGroup(p[0 .. len]);
+        foreach (p; _loadedDSOs)
+            safeAssert(p !is pdso, "DSO already registered.");
+        _loadedDSOs.insertBack(pdso);
     }
-
-    auto ehsect = getSection(h, slide, "__DATA", "__deh_eh");
-    if (ehsect != null)
+    // has backlink => unregister
+    else
     {
-        debug(PRINTF) printf("  deh_eh\n");
-        auto p = cast(immutable(FuncTable)*)ehsect.ptr;
-        immutable len = ehsect.length / (*p).sizeof;
+        DSO* pdso = cast(DSO*)*data._slot;
+        *data._slot = null;
 
-        _sections._ehTables = p[0 .. len];
-    }
+        // static DSOs are unloaded in reverse order
+        safeAssert(pdso == _loadedDSOs.back, "DSO being unregistered isn't current last one.");
+        _loadedDSOs.popBack();
 
-    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];
+        pdso._gcRanges.reset();
+        .free(pdso);
+
+        // last DSO being unloaded => shutdown registry
+        if (_loadedDSOs.empty)
+        {
+            version (GNU_EMUTLS)
+                _d_emutls_destroy();
+        }
     }
+}
+
+/**************************
+ * Input:
+ *      result where the output is to be written
+ * Returns:
+ *      true if found, and *result is filled in
+ */
 
-    auto tlssect2 = getSection(h, slide, "__DATA", "__tlscoal_nt");
-    if (tlssect2 != null)
+bool findDSOHeaderForAddr(in void* addr, MachHeader* result)
+{
+    foreach (i; 0 .. _dyld_image_count())
     {
-        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];
+        const header = _dyld_get_image_header(i);
+        const slide = _dyld_get_image_vmaddr_slide(i);
+        const section = getSection(header, slide, SEG_DATA, SECT_DATA);
+
+        // less than base address of section means quick reject
+        if (!section.length || addr < section.ptr)
+           continue;
+
+        if (addr < section.ptr + section.length)
+        {
+            result.header = header;
+            result.slide = slide;
+            return true;
+        }
     }
+    return false;
 }
 
 struct SegRef
@@ -258,25 +263,27 @@ static immutable SegRef[] dataSegs = [{SEG_DATA, SECT_DATA},
                                       {SEG_DATA, SECT_BSS},
                                       {SEG_DATA, SECT_COMMON}];
 
+/**
+ * Returns the section for the named section in the named segment
+ * for the mach_header pointer passed, or null if not found.
+ */
 ubyte[] getSection(in mach_header* header, intptr_t slide,
                    in char* segmentName, in char* sectionName)
 {
-    version (X86)
+    version (D_LP64)
     {
-        assert(header.magic == MH_MAGIC);
-        auto sect = getsectbynamefromheader(header,
+        assert(header.magic == MH_MAGIC_64);
+        auto sect = getsectbynamefromheader_64(cast(mach_header_64*)header,
                                             segmentName,
                                             sectionName);
     }
-    else version (X86_64)
+    else
     {
-        assert(header.magic == MH_MAGIC_64);
-        auto sect = getsectbynamefromheader_64(cast(mach_header_64*)header,
+        assert(header.magic == MH_MAGIC);
+        auto sect = getsectbynamefromheader(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];
diff --git a/libphobos/libdruntime/gcc/sections/win64.d b/libphobos/libdruntime/gcc/sections/win64.d
index 1a4ee989cec..8362a6ffa23 100644
--- a/libphobos/libdruntime/gcc/sections/win64.d
+++ b/libphobos/libdruntime/gcc/sections/win64.d
@@ -51,14 +51,6 @@ struct SectionGroup
         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[];
diff --git a/libphobos/m4/druntime/os.m4 b/libphobos/m4/druntime/os.m4
index ed93e30f1e9..351558dbcda 100644
--- a/libphobos/m4/druntime/os.m4
+++ b/libphobos/m4/druntime/os.m4
@@ -149,17 +149,31 @@ AC_DEFUN([DRUNTIME_OS_ARM_EABI_UNWINDER],
 # substitute DCFG_MINFO_BRACKETING.
 AC_DEFUN([DRUNTIME_OS_MINFO_BRACKETING],
 [
+  AC_REQUIRE([DRUNTIME_OS_DETECT])
+
   AC_LANG_PUSH([C])
   AC_MSG_CHECKING([for minfo section bracketing])
+  case "$druntime_cv_target_os" in
+      darwin*)
+	section="__DATA,__minfodata"
+	start="section\$start\$__DATA\$__minfodata"
+	stop="section\$end\$__DATA\$__minfodata"
+	;;
+      *)
+	section="minfo"
+	start="__start_minfo"
+	stop="__stop_minfo"
+	;;
+  esac
   AC_LINK_IFELSE([AC_LANG_SOURCE([
-    void* module_info_ptr __attribute__((section ("minfo")));
-    extern void* __start_minfo __attribute__((visibility ("hidden")));
-    extern void* __stop_minfo __attribute__((visibility ("hidden")));
+    void* module_info_ptr __attribute__((section ("$section")));
+    extern void* start_minfo __asm__("$start") __attribute__((visibility ("hidden")));
+    extern void* stop_minfo __asm__("$stop") __attribute__((visibility ("hidden")));
 
     int main()
     {
         // Never run, just to prevent compiler from optimizing access
-        return &__start_minfo == &__stop_minfo;
+        return (int)(&stop_minfo - &start_minfo);
     }
   ])],
     [AC_MSG_RESULT([yes])
diff --git a/libphobos/testsuite/lib/libphobos.exp b/libphobos/testsuite/lib/libphobos.exp
index 790480bf95c..3b43f0182a7 100644
--- a/libphobos/testsuite/lib/libphobos.exp
+++ b/libphobos/testsuite/lib/libphobos.exp
@@ -90,6 +90,10 @@ proc libphobos-dg-test { prog do_what extra_tool_flags } {
 }
 
 proc libphobos-dg-prune { system text } {
+
+    # Ignore warnings from cctools.
+    regsub -all "(^|\n)clang: warning: argument unused during compilation:\[^\n\]*" $text "" text
+
     return $text
 }
 
diff --git a/libphobos/testsuite/libphobos.druntime/druntime.exp b/libphobos/testsuite/libphobos.druntime/druntime.exp
index 7072ebb1c9f..a157329c916 100644
--- a/libphobos/testsuite/libphobos.druntime/druntime.exp
+++ b/libphobos/testsuite/libphobos.druntime/druntime.exp
@@ -15,7 +15,7 @@
 # <http://www.gnu.org/licenses/>.
 
 # Immediately exit if we can't run target executables.
-if { ![isnative] || ![is-effective-target static] } {
+if { ![isnative] } {
     return
 }
 
diff --git a/libphobos/testsuite/libphobos.phobos/phobos.exp b/libphobos/testsuite/libphobos.phobos/phobos.exp
index aad877c24c2..45c48ce7324 100644
--- a/libphobos/testsuite/libphobos.phobos/phobos.exp
+++ b/libphobos/testsuite/libphobos.phobos/phobos.exp
@@ -15,7 +15,7 @@
 # <http://www.gnu.org/licenses/>.
 
 # Immediately exit if we can't run target executables.
-if { ![isnative] || ![is-effective-target static] } {
+if { ![isnative] } {
     return
 }


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [gcc(refs/users/ibuclaw/heads/darwin)] libphobos: Checkpoint in darwin runtime support
@ 2020-12-09  9:50 Iain Buclaw
  0 siblings, 0 replies; 15+ messages in thread
From: Iain Buclaw @ 2020-12-09  9:50 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:f796c9539cca35b7445bea4ef131a64288cda6cc

commit f796c9539cca35b7445bea4ef131a64288cda6cc
Author: Iain Buclaw <ibuclaw@gdcproject.org>
Date:   Sun Nov 29 14:44:28 2020 +0100

    libphobos: Checkpoint in darwin runtime support

Diff:
---
 libphobos/configure                                |  22 +-
 libphobos/libdruntime/Makefile.am                  |  30 +--
 libphobos/libdruntime/Makefile.in                  |  38 +--
 libphobos/libdruntime/config/x86/switchcontext.S   |   8 +
 libphobos/libdruntime/gcc/deh.d                    |   5 -
 libphobos/libdruntime/gcc/sections/android.d       |   7 -
 libphobos/libdruntime/gcc/sections/common.d        |  48 ++++
 libphobos/libdruntime/gcc/sections/elf_shared.d    |  11 -
 libphobos/libdruntime/gcc/sections/osx.d           | 279 +++++++++++----------
 libphobos/libdruntime/gcc/sections/win64.d         |   8 -
 libphobos/m4/druntime/os.m4                        |  22 +-
 libphobos/testsuite/lib/libphobos.exp              |   4 +
 .../testsuite/libphobos.druntime/druntime.exp      |   2 +-
 libphobos/testsuite/libphobos.phobos/phobos.exp    |   2 +-
 14 files changed, 276 insertions(+), 210 deletions(-)

diff --git a/libphobos/configure b/libphobos/configure
index a7fb5edb90f..0ec729c9d96 100755
--- a/libphobos/configure
+++ b/libphobos/configure
@@ -14383,6 +14383,8 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
 
 
+
+
   ac_ext=c
 ac_cpp='$CPP $CPPFLAGS'
 ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -14391,17 +14393,29 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for minfo section bracketing" >&5
 $as_echo_n "checking for minfo section bracketing... " >&6; }
+  case "$druntime_cv_target_os" in
+      darwin*)
+	section="__DATA,__minfodata"
+	start="section\$start\$__DATA\$__minfodata"
+	stop="section\$end\$__DATA\$__minfodata"
+	;;
+      *)
+	section="minfo"
+	start="__start_minfo"
+	stop="__stop_minfo"
+	;;
+  esac
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
-    void* module_info_ptr __attribute__((section ("minfo")));
-    extern void* __start_minfo __attribute__((visibility ("hidden")));
-    extern void* __stop_minfo __attribute__((visibility ("hidden")));
+    void* module_info_ptr __attribute__((section ("$section")));
+    extern void* start_minfo __asm__("$start") __attribute__((visibility ("hidden")));
+    extern void* stop_minfo __asm__("$stop") __attribute__((visibility ("hidden")));
 
     int main()
     {
         // Never run, just to prevent compiler from optimizing access
-        return &__start_minfo == &__stop_minfo;
+        return (int)(&stop_minfo - &start_minfo);
     }
 
 _ACEOF
diff --git a/libphobos/libdruntime/Makefile.am b/libphobos/libdruntime/Makefile.am
index 4798bdf777d..1ebc97af39d 100644
--- a/libphobos/libdruntime/Makefile.am
+++ b/libphobos/libdruntime/Makefile.am
@@ -183,21 +183,21 @@ DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \
 	gc/impl/conservative/gc.d gc/impl/manual/gc.d gc/os.d gc/pooltable.d \
 	gc/proxy.d gcc/attribute.d gcc/backtrace.d gcc/builtins.d gcc/deh.d \
 	gcc/emutls.d gcc/gthread.d gcc/sections/android.d \
-	gcc/sections/elf_shared.d gcc/sections/osx.d gcc/sections/package.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 rt/typeinfo/ti_Aint.d \
-	rt/typeinfo/ti_Along.d rt/typeinfo/ti_Areal.d rt/typeinfo/ti_Ashort.d \
-	rt/typeinfo/ti_C.d rt/typeinfo/ti_byte.d rt/typeinfo/ti_cdouble.d \
-	rt/typeinfo/ti_cent.d rt/typeinfo/ti_cfloat.d rt/typeinfo/ti_char.d \
-	rt/typeinfo/ti_creal.d rt/typeinfo/ti_dchar.d \
+	gcc/sections/common.d gcc/sections/elf_shared.d gcc/sections/osx.d \
+	gcc/sections/package.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 \
+	rt/typeinfo/ti_Aint.d rt/typeinfo/ti_Along.d rt/typeinfo/ti_Areal.d \
+	rt/typeinfo/ti_Ashort.d rt/typeinfo/ti_C.d rt/typeinfo/ti_byte.d \
+	rt/typeinfo/ti_cdouble.d rt/typeinfo/ti_cent.d rt/typeinfo/ti_cfloat.d \
+	rt/typeinfo/ti_char.d rt/typeinfo/ti_creal.d rt/typeinfo/ti_dchar.d \
 	rt/typeinfo/ti_delegate.d rt/typeinfo/ti_double.d \
 	rt/typeinfo/ti_float.d rt/typeinfo/ti_idouble.d \
 	rt/typeinfo/ti_ifloat.d rt/typeinfo/ti_int.d rt/typeinfo/ti_ireal.d \
diff --git a/libphobos/libdruntime/Makefile.in b/libphobos/libdruntime/Makefile.in
index 99ee8b92afa..3bf08f52b31 100644
--- a/libphobos/libdruntime/Makefile.in
+++ b/libphobos/libdruntime/Makefile.in
@@ -207,9 +207,10 @@ am__objects_1 = core/atomic.lo core/attribute.lo core/bitop.lo \
 	gc/impl/conservative/gc.lo gc/impl/manual/gc.lo gc/os.lo \
 	gc/pooltable.lo gc/proxy.lo gcc/attribute.lo gcc/backtrace.lo \
 	gcc/builtins.lo gcc/deh.lo gcc/emutls.lo gcc/gthread.lo \
-	gcc/sections/android.lo gcc/sections/elf_shared.lo \
-	gcc/sections/osx.lo gcc/sections/package.lo \
-	gcc/sections/win32.lo gcc/sections/win64.lo gcc/unwind/arm.lo \
+	gcc/sections/android.lo gcc/sections/common.lo \
+	gcc/sections/elf_shared.lo gcc/sections/osx.lo \
+	gcc/sections/package.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 \
@@ -808,21 +809,21 @@ DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \
 	gc/impl/conservative/gc.d gc/impl/manual/gc.d gc/os.d gc/pooltable.d \
 	gc/proxy.d gcc/attribute.d gcc/backtrace.d gcc/builtins.d gcc/deh.d \
 	gcc/emutls.d gcc/gthread.d gcc/sections/android.d \
-	gcc/sections/elf_shared.d gcc/sections/osx.d gcc/sections/package.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 rt/typeinfo/ti_Aint.d \
-	rt/typeinfo/ti_Along.d rt/typeinfo/ti_Areal.d rt/typeinfo/ti_Ashort.d \
-	rt/typeinfo/ti_C.d rt/typeinfo/ti_byte.d rt/typeinfo/ti_cdouble.d \
-	rt/typeinfo/ti_cent.d rt/typeinfo/ti_cfloat.d rt/typeinfo/ti_char.d \
-	rt/typeinfo/ti_creal.d rt/typeinfo/ti_dchar.d \
+	gcc/sections/common.d gcc/sections/elf_shared.d gcc/sections/osx.d \
+	gcc/sections/package.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 \
+	rt/typeinfo/ti_Aint.d rt/typeinfo/ti_Along.d rt/typeinfo/ti_Areal.d \
+	rt/typeinfo/ti_Ashort.d rt/typeinfo/ti_C.d rt/typeinfo/ti_byte.d \
+	rt/typeinfo/ti_cdouble.d rt/typeinfo/ti_cent.d rt/typeinfo/ti_cfloat.d \
+	rt/typeinfo/ti_char.d rt/typeinfo/ti_creal.d rt/typeinfo/ti_dchar.d \
 	rt/typeinfo/ti_delegate.d rt/typeinfo/ti_double.d \
 	rt/typeinfo/ti_float.d rt/typeinfo/ti_idouble.d \
 	rt/typeinfo/ti_ifloat.d rt/typeinfo/ti_int.d rt/typeinfo/ti_ireal.d \
@@ -1195,6 +1196,7 @@ gcc/sections/$(am__dirstamp):
 	@$(MKDIR_P) gcc/sections
 	@: > gcc/sections/$(am__dirstamp)
 gcc/sections/android.lo: gcc/sections/$(am__dirstamp)
+gcc/sections/common.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)
diff --git a/libphobos/libdruntime/config/x86/switchcontext.S b/libphobos/libdruntime/config/x86/switchcontext.S
index f2f8efa218e..66c81f8b37a 100644
--- a/libphobos/libdruntime/config/x86/switchcontext.S
+++ b/libphobos/libdruntime/config/x86/switchcontext.S
@@ -33,7 +33,9 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 
     .text
     .globl CSYM(fiber_switchContext)
+#if defined(__ELF__)
     .type CSYM(fiber_switchContext), @function
+#endif
     .align 16
 CSYM(fiber_switchContext):
     .cfi_startproc
@@ -61,13 +63,17 @@ CSYM(fiber_switchContext):
     // 'return' to complete switch
     ret
     .cfi_endproc
+#if defined(__ELF__)
     .size CSYM(fiber_switchContext),.-CSYM(fiber_switchContext)
+#endif
 
 #elif defined(__x86_64__) && !defined(__ILP32__) && !defined(__CET__)
 
     .text
     .globl CSYM(fiber_switchContext)
+#if defined(__ELF__)
     .type CSYM(fiber_switchContext), @function
+#endif
     .align 16
 CSYM(fiber_switchContext):
     .cfi_startproc
@@ -96,6 +102,8 @@ CSYM(fiber_switchContext):
     // 'return' to complete switch
     ret
     .cfi_endproc
+#if defined(__ELF__)
    .size CSYM(fiber_switchContext),.-CSYM(fiber_switchContext)
+#endif
 
 #endif
diff --git a/libphobos/libdruntime/gcc/deh.d b/libphobos/libdruntime/gcc/deh.d
index 3e78a6c9c0e..bb2035f5155 100644
--- a/libphobos/libdruntime/gcc/deh.d
+++ b/libphobos/libdruntime/gcc/deh.d
@@ -34,11 +34,6 @@ extern(C)
 {
     int _d_isbaseof(ClassInfo, ClassInfo);
     void _d_createTrace(Object, void*);
-
-    // Not used in GDC but declaration required by rt/sections.d
-    struct FuncTable
-    {
-    }
 }
 
 /**
diff --git a/libphobos/libdruntime/gcc/sections/android.d b/libphobos/libdruntime/gcc/sections/android.d
index 2180a0b2514..51f5d24c2cb 100644
--- a/libphobos/libdruntime/gcc/sections/android.d
+++ b/libphobos/libdruntime/gcc/sections/android.d
@@ -54,13 +54,6 @@ struct SectionGroup
         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[];
diff --git a/libphobos/libdruntime/gcc/sections/common.d b/libphobos/libdruntime/gcc/sections/common.d
new file mode 100644
index 00000000000..b2d2322347d
--- /dev/null
+++ b/libphobos/libdruntime/gcc/sections/common.d
@@ -0,0 +1,48 @@
+// Common support routines 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.common;
+
+/****
+ * 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.).
+ */
+void safeAssert(bool condition, scope string msg, size_t line = __LINE__) @nogc nothrow @safe
+{
+    import core.internal.abort;
+    condition || abort(msg, __FILE__, line);
+}
+
+/****
+ * 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]; }
diff --git a/libphobos/libdruntime/gcc/sections/elf_shared.d b/libphobos/libdruntime/gcc/sections/elf_shared.d
index 59e2dd60a1f..3fb1b491f88 100644
--- a/libphobos/libdruntime/gcc/sections/elf_shared.d
+++ b/libphobos/libdruntime/gcc/sections/elf_shared.d
@@ -132,11 +132,6 @@ struct DSO
         return _moduleGroup;
     }
 
-    @property immutable(FuncTable)[] ehTables() const nothrow @nogc
-    {
-        return null;
-    }
-
     @property inout(void[])[] gcRanges() inout nothrow @nogc
     {
         return _gcRanges[];
@@ -383,12 +378,6 @@ version (Shared)
      */
     __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
 {
diff --git a/libphobos/libdruntime/gcc/sections/osx.d b/libphobos/libdruntime/gcc/sections/osx.d
index cb02b452404..6ace2da4a8b 100644
--- a/libphobos/libdruntime/gcc/sections/osx.d
+++ b/libphobos/libdruntime/gcc/sections/osx.d
@@ -24,25 +24,38 @@ 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 gcc.sections.common;
+
+import core.stdc.stdlib;
 import core.sys.darwin.mach.dyld;
 import core.sys.darwin.mach.getsect;
-import rt.deh, rt.minfo;
+import rt.minfo;
 import rt.util.container.array;
 
-struct SectionGroup
+version (GNU_EMUTLS)
+    import gcc.emutls;
+
+alias DSO SectionGroup;
+struct DSO
 {
-    static int opApply(scope int delegate(ref SectionGroup) dg)
+    static int opApply(scope int delegate(ref DSO) dg)
     {
-        return dg(_sections);
+        foreach (dso; _loadedDSOs)
+        {
+            if (auto res = dg(*dso))
+                return res;
+        }
+        return 0;
     }
 
-    static int opApplyReverse(scope int delegate(ref SectionGroup) dg)
+    static int opApplyReverse(scope int delegate(ref DSO) dg)
     {
-        return dg(_sections);
+        foreach_reverse (dso; _loadedDSOs)
+        {
+            if (auto res = dg(*dso))
+                return res;
+        }
+        return 0;
     }
 
     @property immutable(ModuleInfo*)[] modules() const nothrow @nogc
@@ -60,16 +73,9 @@ struct SectionGroup
         return _gcRanges[];
     }
 
-    @property immutable(FuncTable)[] ehTables() const nothrow @nogc
-    {
-        return _ehTables[];
-    }
-
 private:
-    immutable(FuncTable)[] _ehTables;
     ModuleGroup _moduleGroup;
     Array!(void[]) _gcRanges;
-    immutable(void)[][2] _tlsImage;
 }
 
 /****
@@ -82,8 +88,6 @@ __gshared bool _isRuntimeInitialized;
  */
 void initSections() nothrow @nogc
 {
-    pthread_key_create(&_tlsKey, null);
-    _dyld_register_func_for_add_image(&sections_osx_onAddImage);
     _isRuntimeInitialized = true;
 }
 
@@ -92,160 +96,161 @@ void initSections() nothrow @nogc
  */
 void finiSections() nothrow @nogc
 {
-    _sections._gcRanges.reset();
-    pthread_key_delete(_tlsKey);
     _isRuntimeInitialized = false;
 }
 
 void[]* initTLSRanges() nothrow @nogc
 {
-    return &getTLSBlock();
+    return null;
 }
 
 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);
+    version (GNU_EMUTLS)
+        _d_emutls_scan(dg);
+    else
+        static assert(0, "Native TLS unimplemented");
 }
 
-// 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 )
+version (Shared)
 {
-    immutable off = tlsOffset(p);
-    auto tls = getTLSBlockAlloc();
-    assert(off < tls.length);
-    return tls.ptr + off;
-}
-
-private:
+    // interface for core.thread to inherit loaded libraries
+    void* pinLoadedLibraries() nothrow @nogc
+    {
+        return null;
+    }
 
-__gshared pthread_key_t _tlsKey;
+    void unpinLoadedLibraries(void* p) nothrow @nogc
+    {
+    }
 
-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)
+    // Called before TLS ctors are ran, copy over the loaded libraries
+    // of the parent thread.
+    void inheritLoadedLibraries(void* p) nothrow @nogc
     {
-        return off0;
     }
-    immutable off1 = cast(size_t)(p - _sections._tlsImage[1].ptr);
-    if (off1 < _sections._tlsImage[1].length)
+
+    // Called after all TLS dtors ran, decrements all remaining dlopen refs.
+    void cleanupLoadedLibraries() nothrow @nogc
     {
-        size_t sz = (_sections._tlsImage[0].length + 15) & ~cast(size_t)15;
-        return sz + off1;
     }
-    assert(0);
 }
 
-ref void[] getTLSBlock() nothrow @nogc
+private:
+
+/*
+ * Static DSOs loaded by the runtime linker. This includes the
+ * executable. These can't be unloaded.
+ */
+@property ref Array!(DSO*) _loadedDSOs() @nogc nothrow
 {
-    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;
+    __gshared Array!(DSO*) x;
+    return x;
 }
 
-ref void[] getTLSBlockAlloc()
+/*
+ * Set to true during rt_loadLibrary/rt_unloadLibrary calls.
+ */
+enum _rtLoading = false;
+
+struct MachHeader
 {
-    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;
+    const(mach_header)* header; // the mach header of the image
+    intptr_t slide;             // virtural memory address slide amount
 }
 
-__gshared SectionGroup _sections;
+///////////////////////////////////////////////////////////////////////////////
+// Compiler to runtime interface.
+///////////////////////////////////////////////////////////////////////////////
 
-extern (C) void sections_osx_onAddImage(in mach_header* h, intptr_t slide)
+/* 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)
 {
-    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]);
-    }
+    // only one supported currently
+    safeAssert(data._version >= 1, "Incompatible compiler-generated DSO data version.");
 
-    auto minfosect = getSection(h, slide, "__DATA", "__minfodata");
-    if (minfosect != null)
+    // no backlink => register
+    if (*data._slot is 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)
+        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));
+
+        MachHeader info = void;
+        const headerFound = findDSOHeaderForAddr(data._slot, &info);
+        safeAssert(headerFound, "Failed to find image header.");
+
+        foreach (e; dataSegs)
         {
-            fprintf(stderr, "Shared libraries are not yet supported on OSX.\n");
+            auto sect = getSection(info.header, info.slide,
+                                   e.seg.ptr, e.sect.ptr);
+            if (sect != null)
+                pdso._gcRanges.insertBack((cast(void*)sect.ptr)[0 .. sect.length]);
         }
 
-        debug(PRINTF) printf("  minfodata\n");
-        auto p = cast(immutable(ModuleInfo*)*)minfosect.ptr;
-        immutable len = minfosect.length / (*p).sizeof;
-
-        _sections._moduleGroup = ModuleGroup(p[0 .. len]);
+        foreach (p; _loadedDSOs)
+            safeAssert(p !is pdso, "DSO already registered.");
+        _loadedDSOs.insertBack(pdso);
     }
-
-    auto ehsect = getSection(h, slide, "__DATA", "__deh_eh");
-    if (ehsect != null)
+    // has backlink => unregister
+    else
     {
-        debug(PRINTF) printf("  deh_eh\n");
-        auto p = cast(immutable(FuncTable)*)ehsect.ptr;
-        immutable len = ehsect.length / (*p).sizeof;
+        DSO* pdso = cast(DSO*)*data._slot;
+        *data._slot = null;
 
-        _sections._ehTables = p[0 .. len];
-    }
+        // static DSOs are unloaded in reverse order
+        safeAssert(pdso == _loadedDSOs.back, "DSO being unregistered isn't current last one.");
+        _loadedDSOs.popBack();
 
-    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];
+        pdso._gcRanges.reset();
+        .free(pdso);
+
+        // last DSO being unloaded => shutdown registry
+        if (_loadedDSOs.empty)
+        {
+            version (GNU_EMUTLS)
+                _d_emutls_destroy();
+        }
     }
+}
+
+/**************************
+ * Input:
+ *      result where the output is to be written
+ * Returns:
+ *      true if found, and *result is filled in
+ */
 
-    auto tlssect2 = getSection(h, slide, "__DATA", "__tlscoal_nt");
-    if (tlssect2 != null)
+bool findDSOHeaderForAddr(in void* addr, MachHeader* result)
+{
+    foreach (i; 0 .. _dyld_image_count())
     {
-        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];
+        const header = _dyld_get_image_header(i);
+        const slide = _dyld_get_image_vmaddr_slide(i);
+        const section = getSection(header, slide, SEG_DATA, SECT_DATA);
+
+        // less than base address of section means quick reject
+        if (!section.length || addr < section.ptr)
+           continue;
+
+        if (addr < section.ptr + section.length)
+        {
+            result.header = header;
+            result.slide = slide;
+            return true;
+        }
     }
+    return false;
 }
 
 struct SegRef
@@ -258,25 +263,27 @@ static immutable SegRef[] dataSegs = [{SEG_DATA, SECT_DATA},
                                       {SEG_DATA, SECT_BSS},
                                       {SEG_DATA, SECT_COMMON}];
 
+/**
+ * Returns the section for the named section in the named segment
+ * for the mach_header pointer passed, or null if not found.
+ */
 ubyte[] getSection(in mach_header* header, intptr_t slide,
                    in char* segmentName, in char* sectionName)
 {
-    version (X86)
+    version (D_LP64)
     {
-        assert(header.magic == MH_MAGIC);
-        auto sect = getsectbynamefromheader(header,
+        assert(header.magic == MH_MAGIC_64);
+        auto sect = getsectbynamefromheader_64(cast(mach_header_64*)header,
                                             segmentName,
                                             sectionName);
     }
-    else version (X86_64)
+    else
     {
-        assert(header.magic == MH_MAGIC_64);
-        auto sect = getsectbynamefromheader_64(cast(mach_header_64*)header,
+        assert(header.magic == MH_MAGIC);
+        auto sect = getsectbynamefromheader(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];
diff --git a/libphobos/libdruntime/gcc/sections/win64.d b/libphobos/libdruntime/gcc/sections/win64.d
index 1a4ee989cec..8362a6ffa23 100644
--- a/libphobos/libdruntime/gcc/sections/win64.d
+++ b/libphobos/libdruntime/gcc/sections/win64.d
@@ -51,14 +51,6 @@ struct SectionGroup
         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[];
diff --git a/libphobos/m4/druntime/os.m4 b/libphobos/m4/druntime/os.m4
index ed93e30f1e9..351558dbcda 100644
--- a/libphobos/m4/druntime/os.m4
+++ b/libphobos/m4/druntime/os.m4
@@ -149,17 +149,31 @@ AC_DEFUN([DRUNTIME_OS_ARM_EABI_UNWINDER],
 # substitute DCFG_MINFO_BRACKETING.
 AC_DEFUN([DRUNTIME_OS_MINFO_BRACKETING],
 [
+  AC_REQUIRE([DRUNTIME_OS_DETECT])
+
   AC_LANG_PUSH([C])
   AC_MSG_CHECKING([for minfo section bracketing])
+  case "$druntime_cv_target_os" in
+      darwin*)
+	section="__DATA,__minfodata"
+	start="section\$start\$__DATA\$__minfodata"
+	stop="section\$end\$__DATA\$__minfodata"
+	;;
+      *)
+	section="minfo"
+	start="__start_minfo"
+	stop="__stop_minfo"
+	;;
+  esac
   AC_LINK_IFELSE([AC_LANG_SOURCE([
-    void* module_info_ptr __attribute__((section ("minfo")));
-    extern void* __start_minfo __attribute__((visibility ("hidden")));
-    extern void* __stop_minfo __attribute__((visibility ("hidden")));
+    void* module_info_ptr __attribute__((section ("$section")));
+    extern void* start_minfo __asm__("$start") __attribute__((visibility ("hidden")));
+    extern void* stop_minfo __asm__("$stop") __attribute__((visibility ("hidden")));
 
     int main()
     {
         // Never run, just to prevent compiler from optimizing access
-        return &__start_minfo == &__stop_minfo;
+        return (int)(&stop_minfo - &start_minfo);
     }
   ])],
     [AC_MSG_RESULT([yes])
diff --git a/libphobos/testsuite/lib/libphobos.exp b/libphobos/testsuite/lib/libphobos.exp
index 790480bf95c..3b43f0182a7 100644
--- a/libphobos/testsuite/lib/libphobos.exp
+++ b/libphobos/testsuite/lib/libphobos.exp
@@ -90,6 +90,10 @@ proc libphobos-dg-test { prog do_what extra_tool_flags } {
 }
 
 proc libphobos-dg-prune { system text } {
+
+    # Ignore warnings from cctools.
+    regsub -all "(^|\n)clang: warning: argument unused during compilation:\[^\n\]*" $text "" text
+
     return $text
 }
 
diff --git a/libphobos/testsuite/libphobos.druntime/druntime.exp b/libphobos/testsuite/libphobos.druntime/druntime.exp
index 7072ebb1c9f..a157329c916 100644
--- a/libphobos/testsuite/libphobos.druntime/druntime.exp
+++ b/libphobos/testsuite/libphobos.druntime/druntime.exp
@@ -15,7 +15,7 @@
 # <http://www.gnu.org/licenses/>.
 
 # Immediately exit if we can't run target executables.
-if { ![isnative] || ![is-effective-target static] } {
+if { ![isnative] } {
     return
 }
 
diff --git a/libphobos/testsuite/libphobos.phobos/phobos.exp b/libphobos/testsuite/libphobos.phobos/phobos.exp
index aad877c24c2..45c48ce7324 100644
--- a/libphobos/testsuite/libphobos.phobos/phobos.exp
+++ b/libphobos/testsuite/libphobos.phobos/phobos.exp
@@ -15,7 +15,7 @@
 # <http://www.gnu.org/licenses/>.
 
 # Immediately exit if we can't run target executables.
-if { ![isnative] || ![is-effective-target static] } {
+if { ![isnative] } {
     return
 }


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [gcc(refs/users/ibuclaw/heads/darwin)] libphobos: Checkpoint in darwin runtime support
@ 2020-12-05 23:47 Iain Buclaw
  0 siblings, 0 replies; 15+ messages in thread
From: Iain Buclaw @ 2020-12-05 23:47 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:64d5fb2102128e39c50e6b80ba20aa3b3513e990

commit 64d5fb2102128e39c50e6b80ba20aa3b3513e990
Author: Iain Buclaw <ibuclaw@gdcproject.org>
Date:   Sun Nov 29 14:44:28 2020 +0100

    libphobos: Checkpoint in darwin runtime support

Diff:
---
 libphobos/configure                                |  22 +-
 libphobos/libdruntime/Makefile.am                  |  30 +--
 libphobos/libdruntime/Makefile.in                  |  38 +--
 libphobos/libdruntime/config/x86/switchcontext.S   |   8 +
 libphobos/libdruntime/gcc/deh.d                    |   5 -
 libphobos/libdruntime/gcc/sections/android.d       |   7 -
 libphobos/libdruntime/gcc/sections/common.d        |  48 ++++
 libphobos/libdruntime/gcc/sections/elf_shared.d    |  11 -
 libphobos/libdruntime/gcc/sections/osx.d           | 279 +++++++++++----------
 libphobos/libdruntime/gcc/sections/win64.d         |   8 -
 libphobos/m4/druntime/os.m4                        |  22 +-
 libphobos/testsuite/lib/libphobos.exp              |   4 +
 .../testsuite/libphobos.druntime/druntime.exp      |   2 +-
 libphobos/testsuite/libphobos.phobos/phobos.exp    |   2 +-
 14 files changed, 276 insertions(+), 210 deletions(-)

diff --git a/libphobos/configure b/libphobos/configure
index a7fb5edb90f..0ec729c9d96 100755
--- a/libphobos/configure
+++ b/libphobos/configure
@@ -14383,6 +14383,8 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
 
 
+
+
   ac_ext=c
 ac_cpp='$CPP $CPPFLAGS'
 ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -14391,17 +14393,29 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for minfo section bracketing" >&5
 $as_echo_n "checking for minfo section bracketing... " >&6; }
+  case "$druntime_cv_target_os" in
+      darwin*)
+	section="__DATA,__minfodata"
+	start="section\$start\$__DATA\$__minfodata"
+	stop="section\$end\$__DATA\$__minfodata"
+	;;
+      *)
+	section="minfo"
+	start="__start_minfo"
+	stop="__stop_minfo"
+	;;
+  esac
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
-    void* module_info_ptr __attribute__((section ("minfo")));
-    extern void* __start_minfo __attribute__((visibility ("hidden")));
-    extern void* __stop_minfo __attribute__((visibility ("hidden")));
+    void* module_info_ptr __attribute__((section ("$section")));
+    extern void* start_minfo __asm__("$start") __attribute__((visibility ("hidden")));
+    extern void* stop_minfo __asm__("$stop") __attribute__((visibility ("hidden")));
 
     int main()
     {
         // Never run, just to prevent compiler from optimizing access
-        return &__start_minfo == &__stop_minfo;
+        return (int)(&stop_minfo - &start_minfo);
     }
 
 _ACEOF
diff --git a/libphobos/libdruntime/Makefile.am b/libphobos/libdruntime/Makefile.am
index 4798bdf777d..1ebc97af39d 100644
--- a/libphobos/libdruntime/Makefile.am
+++ b/libphobos/libdruntime/Makefile.am
@@ -183,21 +183,21 @@ DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \
 	gc/impl/conservative/gc.d gc/impl/manual/gc.d gc/os.d gc/pooltable.d \
 	gc/proxy.d gcc/attribute.d gcc/backtrace.d gcc/builtins.d gcc/deh.d \
 	gcc/emutls.d gcc/gthread.d gcc/sections/android.d \
-	gcc/sections/elf_shared.d gcc/sections/osx.d gcc/sections/package.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 rt/typeinfo/ti_Aint.d \
-	rt/typeinfo/ti_Along.d rt/typeinfo/ti_Areal.d rt/typeinfo/ti_Ashort.d \
-	rt/typeinfo/ti_C.d rt/typeinfo/ti_byte.d rt/typeinfo/ti_cdouble.d \
-	rt/typeinfo/ti_cent.d rt/typeinfo/ti_cfloat.d rt/typeinfo/ti_char.d \
-	rt/typeinfo/ti_creal.d rt/typeinfo/ti_dchar.d \
+	gcc/sections/common.d gcc/sections/elf_shared.d gcc/sections/osx.d \
+	gcc/sections/package.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 \
+	rt/typeinfo/ti_Aint.d rt/typeinfo/ti_Along.d rt/typeinfo/ti_Areal.d \
+	rt/typeinfo/ti_Ashort.d rt/typeinfo/ti_C.d rt/typeinfo/ti_byte.d \
+	rt/typeinfo/ti_cdouble.d rt/typeinfo/ti_cent.d rt/typeinfo/ti_cfloat.d \
+	rt/typeinfo/ti_char.d rt/typeinfo/ti_creal.d rt/typeinfo/ti_dchar.d \
 	rt/typeinfo/ti_delegate.d rt/typeinfo/ti_double.d \
 	rt/typeinfo/ti_float.d rt/typeinfo/ti_idouble.d \
 	rt/typeinfo/ti_ifloat.d rt/typeinfo/ti_int.d rt/typeinfo/ti_ireal.d \
diff --git a/libphobos/libdruntime/Makefile.in b/libphobos/libdruntime/Makefile.in
index 99ee8b92afa..3bf08f52b31 100644
--- a/libphobos/libdruntime/Makefile.in
+++ b/libphobos/libdruntime/Makefile.in
@@ -207,9 +207,10 @@ am__objects_1 = core/atomic.lo core/attribute.lo core/bitop.lo \
 	gc/impl/conservative/gc.lo gc/impl/manual/gc.lo gc/os.lo \
 	gc/pooltable.lo gc/proxy.lo gcc/attribute.lo gcc/backtrace.lo \
 	gcc/builtins.lo gcc/deh.lo gcc/emutls.lo gcc/gthread.lo \
-	gcc/sections/android.lo gcc/sections/elf_shared.lo \
-	gcc/sections/osx.lo gcc/sections/package.lo \
-	gcc/sections/win32.lo gcc/sections/win64.lo gcc/unwind/arm.lo \
+	gcc/sections/android.lo gcc/sections/common.lo \
+	gcc/sections/elf_shared.lo gcc/sections/osx.lo \
+	gcc/sections/package.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 \
@@ -808,21 +809,21 @@ DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \
 	gc/impl/conservative/gc.d gc/impl/manual/gc.d gc/os.d gc/pooltable.d \
 	gc/proxy.d gcc/attribute.d gcc/backtrace.d gcc/builtins.d gcc/deh.d \
 	gcc/emutls.d gcc/gthread.d gcc/sections/android.d \
-	gcc/sections/elf_shared.d gcc/sections/osx.d gcc/sections/package.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 rt/typeinfo/ti_Aint.d \
-	rt/typeinfo/ti_Along.d rt/typeinfo/ti_Areal.d rt/typeinfo/ti_Ashort.d \
-	rt/typeinfo/ti_C.d rt/typeinfo/ti_byte.d rt/typeinfo/ti_cdouble.d \
-	rt/typeinfo/ti_cent.d rt/typeinfo/ti_cfloat.d rt/typeinfo/ti_char.d \
-	rt/typeinfo/ti_creal.d rt/typeinfo/ti_dchar.d \
+	gcc/sections/common.d gcc/sections/elf_shared.d gcc/sections/osx.d \
+	gcc/sections/package.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 \
+	rt/typeinfo/ti_Aint.d rt/typeinfo/ti_Along.d rt/typeinfo/ti_Areal.d \
+	rt/typeinfo/ti_Ashort.d rt/typeinfo/ti_C.d rt/typeinfo/ti_byte.d \
+	rt/typeinfo/ti_cdouble.d rt/typeinfo/ti_cent.d rt/typeinfo/ti_cfloat.d \
+	rt/typeinfo/ti_char.d rt/typeinfo/ti_creal.d rt/typeinfo/ti_dchar.d \
 	rt/typeinfo/ti_delegate.d rt/typeinfo/ti_double.d \
 	rt/typeinfo/ti_float.d rt/typeinfo/ti_idouble.d \
 	rt/typeinfo/ti_ifloat.d rt/typeinfo/ti_int.d rt/typeinfo/ti_ireal.d \
@@ -1195,6 +1196,7 @@ gcc/sections/$(am__dirstamp):
 	@$(MKDIR_P) gcc/sections
 	@: > gcc/sections/$(am__dirstamp)
 gcc/sections/android.lo: gcc/sections/$(am__dirstamp)
+gcc/sections/common.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)
diff --git a/libphobos/libdruntime/config/x86/switchcontext.S b/libphobos/libdruntime/config/x86/switchcontext.S
index f2f8efa218e..66c81f8b37a 100644
--- a/libphobos/libdruntime/config/x86/switchcontext.S
+++ b/libphobos/libdruntime/config/x86/switchcontext.S
@@ -33,7 +33,9 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 
     .text
     .globl CSYM(fiber_switchContext)
+#if defined(__ELF__)
     .type CSYM(fiber_switchContext), @function
+#endif
     .align 16
 CSYM(fiber_switchContext):
     .cfi_startproc
@@ -61,13 +63,17 @@ CSYM(fiber_switchContext):
     // 'return' to complete switch
     ret
     .cfi_endproc
+#if defined(__ELF__)
     .size CSYM(fiber_switchContext),.-CSYM(fiber_switchContext)
+#endif
 
 #elif defined(__x86_64__) && !defined(__ILP32__) && !defined(__CET__)
 
     .text
     .globl CSYM(fiber_switchContext)
+#if defined(__ELF__)
     .type CSYM(fiber_switchContext), @function
+#endif
     .align 16
 CSYM(fiber_switchContext):
     .cfi_startproc
@@ -96,6 +102,8 @@ CSYM(fiber_switchContext):
     // 'return' to complete switch
     ret
     .cfi_endproc
+#if defined(__ELF__)
    .size CSYM(fiber_switchContext),.-CSYM(fiber_switchContext)
+#endif
 
 #endif
diff --git a/libphobos/libdruntime/gcc/deh.d b/libphobos/libdruntime/gcc/deh.d
index 3e78a6c9c0e..bb2035f5155 100644
--- a/libphobos/libdruntime/gcc/deh.d
+++ b/libphobos/libdruntime/gcc/deh.d
@@ -34,11 +34,6 @@ extern(C)
 {
     int _d_isbaseof(ClassInfo, ClassInfo);
     void _d_createTrace(Object, void*);
-
-    // Not used in GDC but declaration required by rt/sections.d
-    struct FuncTable
-    {
-    }
 }
 
 /**
diff --git a/libphobos/libdruntime/gcc/sections/android.d b/libphobos/libdruntime/gcc/sections/android.d
index 2180a0b2514..51f5d24c2cb 100644
--- a/libphobos/libdruntime/gcc/sections/android.d
+++ b/libphobos/libdruntime/gcc/sections/android.d
@@ -54,13 +54,6 @@ struct SectionGroup
         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[];
diff --git a/libphobos/libdruntime/gcc/sections/common.d b/libphobos/libdruntime/gcc/sections/common.d
new file mode 100644
index 00000000000..b2d2322347d
--- /dev/null
+++ b/libphobos/libdruntime/gcc/sections/common.d
@@ -0,0 +1,48 @@
+// Common support routines 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.common;
+
+/****
+ * 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.).
+ */
+void safeAssert(bool condition, scope string msg, size_t line = __LINE__) @nogc nothrow @safe
+{
+    import core.internal.abort;
+    condition || abort(msg, __FILE__, line);
+}
+
+/****
+ * 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]; }
diff --git a/libphobos/libdruntime/gcc/sections/elf_shared.d b/libphobos/libdruntime/gcc/sections/elf_shared.d
index 59e2dd60a1f..3fb1b491f88 100644
--- a/libphobos/libdruntime/gcc/sections/elf_shared.d
+++ b/libphobos/libdruntime/gcc/sections/elf_shared.d
@@ -132,11 +132,6 @@ struct DSO
         return _moduleGroup;
     }
 
-    @property immutable(FuncTable)[] ehTables() const nothrow @nogc
-    {
-        return null;
-    }
-
     @property inout(void[])[] gcRanges() inout nothrow @nogc
     {
         return _gcRanges[];
@@ -383,12 +378,6 @@ version (Shared)
      */
     __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
 {
diff --git a/libphobos/libdruntime/gcc/sections/osx.d b/libphobos/libdruntime/gcc/sections/osx.d
index cb02b452404..6ace2da4a8b 100644
--- a/libphobos/libdruntime/gcc/sections/osx.d
+++ b/libphobos/libdruntime/gcc/sections/osx.d
@@ -24,25 +24,38 @@ 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 gcc.sections.common;
+
+import core.stdc.stdlib;
 import core.sys.darwin.mach.dyld;
 import core.sys.darwin.mach.getsect;
-import rt.deh, rt.minfo;
+import rt.minfo;
 import rt.util.container.array;
 
-struct SectionGroup
+version (GNU_EMUTLS)
+    import gcc.emutls;
+
+alias DSO SectionGroup;
+struct DSO
 {
-    static int opApply(scope int delegate(ref SectionGroup) dg)
+    static int opApply(scope int delegate(ref DSO) dg)
     {
-        return dg(_sections);
+        foreach (dso; _loadedDSOs)
+        {
+            if (auto res = dg(*dso))
+                return res;
+        }
+        return 0;
     }
 
-    static int opApplyReverse(scope int delegate(ref SectionGroup) dg)
+    static int opApplyReverse(scope int delegate(ref DSO) dg)
     {
-        return dg(_sections);
+        foreach_reverse (dso; _loadedDSOs)
+        {
+            if (auto res = dg(*dso))
+                return res;
+        }
+        return 0;
     }
 
     @property immutable(ModuleInfo*)[] modules() const nothrow @nogc
@@ -60,16 +73,9 @@ struct SectionGroup
         return _gcRanges[];
     }
 
-    @property immutable(FuncTable)[] ehTables() const nothrow @nogc
-    {
-        return _ehTables[];
-    }
-
 private:
-    immutable(FuncTable)[] _ehTables;
     ModuleGroup _moduleGroup;
     Array!(void[]) _gcRanges;
-    immutable(void)[][2] _tlsImage;
 }
 
 /****
@@ -82,8 +88,6 @@ __gshared bool _isRuntimeInitialized;
  */
 void initSections() nothrow @nogc
 {
-    pthread_key_create(&_tlsKey, null);
-    _dyld_register_func_for_add_image(&sections_osx_onAddImage);
     _isRuntimeInitialized = true;
 }
 
@@ -92,160 +96,161 @@ void initSections() nothrow @nogc
  */
 void finiSections() nothrow @nogc
 {
-    _sections._gcRanges.reset();
-    pthread_key_delete(_tlsKey);
     _isRuntimeInitialized = false;
 }
 
 void[]* initTLSRanges() nothrow @nogc
 {
-    return &getTLSBlock();
+    return null;
 }
 
 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);
+    version (GNU_EMUTLS)
+        _d_emutls_scan(dg);
+    else
+        static assert(0, "Native TLS unimplemented");
 }
 
-// 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 )
+version (Shared)
 {
-    immutable off = tlsOffset(p);
-    auto tls = getTLSBlockAlloc();
-    assert(off < tls.length);
-    return tls.ptr + off;
-}
-
-private:
+    // interface for core.thread to inherit loaded libraries
+    void* pinLoadedLibraries() nothrow @nogc
+    {
+        return null;
+    }
 
-__gshared pthread_key_t _tlsKey;
+    void unpinLoadedLibraries(void* p) nothrow @nogc
+    {
+    }
 
-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)
+    // Called before TLS ctors are ran, copy over the loaded libraries
+    // of the parent thread.
+    void inheritLoadedLibraries(void* p) nothrow @nogc
     {
-        return off0;
     }
-    immutable off1 = cast(size_t)(p - _sections._tlsImage[1].ptr);
-    if (off1 < _sections._tlsImage[1].length)
+
+    // Called after all TLS dtors ran, decrements all remaining dlopen refs.
+    void cleanupLoadedLibraries() nothrow @nogc
     {
-        size_t sz = (_sections._tlsImage[0].length + 15) & ~cast(size_t)15;
-        return sz + off1;
     }
-    assert(0);
 }
 
-ref void[] getTLSBlock() nothrow @nogc
+private:
+
+/*
+ * Static DSOs loaded by the runtime linker. This includes the
+ * executable. These can't be unloaded.
+ */
+@property ref Array!(DSO*) _loadedDSOs() @nogc nothrow
 {
-    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;
+    __gshared Array!(DSO*) x;
+    return x;
 }
 
-ref void[] getTLSBlockAlloc()
+/*
+ * Set to true during rt_loadLibrary/rt_unloadLibrary calls.
+ */
+enum _rtLoading = false;
+
+struct MachHeader
 {
-    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;
+    const(mach_header)* header; // the mach header of the image
+    intptr_t slide;             // virtural memory address slide amount
 }
 
-__gshared SectionGroup _sections;
+///////////////////////////////////////////////////////////////////////////////
+// Compiler to runtime interface.
+///////////////////////////////////////////////////////////////////////////////
 
-extern (C) void sections_osx_onAddImage(in mach_header* h, intptr_t slide)
+/* 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)
 {
-    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]);
-    }
+    // only one supported currently
+    safeAssert(data._version >= 1, "Incompatible compiler-generated DSO data version.");
 
-    auto minfosect = getSection(h, slide, "__DATA", "__minfodata");
-    if (minfosect != null)
+    // no backlink => register
+    if (*data._slot is 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)
+        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));
+
+        MachHeader info = void;
+        const headerFound = findDSOHeaderForAddr(data._slot, &info);
+        safeAssert(headerFound, "Failed to find image header.");
+
+        foreach (e; dataSegs)
         {
-            fprintf(stderr, "Shared libraries are not yet supported on OSX.\n");
+            auto sect = getSection(info.header, info.slide,
+                                   e.seg.ptr, e.sect.ptr);
+            if (sect != null)
+                pdso._gcRanges.insertBack((cast(void*)sect.ptr)[0 .. sect.length]);
         }
 
-        debug(PRINTF) printf("  minfodata\n");
-        auto p = cast(immutable(ModuleInfo*)*)minfosect.ptr;
-        immutable len = minfosect.length / (*p).sizeof;
-
-        _sections._moduleGroup = ModuleGroup(p[0 .. len]);
+        foreach (p; _loadedDSOs)
+            safeAssert(p !is pdso, "DSO already registered.");
+        _loadedDSOs.insertBack(pdso);
     }
-
-    auto ehsect = getSection(h, slide, "__DATA", "__deh_eh");
-    if (ehsect != null)
+    // has backlink => unregister
+    else
     {
-        debug(PRINTF) printf("  deh_eh\n");
-        auto p = cast(immutable(FuncTable)*)ehsect.ptr;
-        immutable len = ehsect.length / (*p).sizeof;
+        DSO* pdso = cast(DSO*)*data._slot;
+        *data._slot = null;
 
-        _sections._ehTables = p[0 .. len];
-    }
+        // static DSOs are unloaded in reverse order
+        safeAssert(pdso == _loadedDSOs.back, "DSO being unregistered isn't current last one.");
+        _loadedDSOs.popBack();
 
-    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];
+        pdso._gcRanges.reset();
+        .free(pdso);
+
+        // last DSO being unloaded => shutdown registry
+        if (_loadedDSOs.empty)
+        {
+            version (GNU_EMUTLS)
+                _d_emutls_destroy();
+        }
     }
+}
+
+/**************************
+ * Input:
+ *      result where the output is to be written
+ * Returns:
+ *      true if found, and *result is filled in
+ */
 
-    auto tlssect2 = getSection(h, slide, "__DATA", "__tlscoal_nt");
-    if (tlssect2 != null)
+bool findDSOHeaderForAddr(in void* addr, MachHeader* result)
+{
+    foreach (i; 0 .. _dyld_image_count())
     {
-        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];
+        const header = _dyld_get_image_header(i);
+        const slide = _dyld_get_image_vmaddr_slide(i);
+        const section = getSection(header, slide, SEG_DATA, SECT_DATA);
+
+        // less than base address of section means quick reject
+        if (!section.length || addr < section.ptr)
+           continue;
+
+        if (addr < section.ptr + section.length)
+        {
+            result.header = header;
+            result.slide = slide;
+            return true;
+        }
     }
+    return false;
 }
 
 struct SegRef
@@ -258,25 +263,27 @@ static immutable SegRef[] dataSegs = [{SEG_DATA, SECT_DATA},
                                       {SEG_DATA, SECT_BSS},
                                       {SEG_DATA, SECT_COMMON}];
 
+/**
+ * Returns the section for the named section in the named segment
+ * for the mach_header pointer passed, or null if not found.
+ */
 ubyte[] getSection(in mach_header* header, intptr_t slide,
                    in char* segmentName, in char* sectionName)
 {
-    version (X86)
+    version (D_LP64)
     {
-        assert(header.magic == MH_MAGIC);
-        auto sect = getsectbynamefromheader(header,
+        assert(header.magic == MH_MAGIC_64);
+        auto sect = getsectbynamefromheader_64(cast(mach_header_64*)header,
                                             segmentName,
                                             sectionName);
     }
-    else version (X86_64)
+    else
     {
-        assert(header.magic == MH_MAGIC_64);
-        auto sect = getsectbynamefromheader_64(cast(mach_header_64*)header,
+        assert(header.magic == MH_MAGIC);
+        auto sect = getsectbynamefromheader(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];
diff --git a/libphobos/libdruntime/gcc/sections/win64.d b/libphobos/libdruntime/gcc/sections/win64.d
index 1a4ee989cec..8362a6ffa23 100644
--- a/libphobos/libdruntime/gcc/sections/win64.d
+++ b/libphobos/libdruntime/gcc/sections/win64.d
@@ -51,14 +51,6 @@ struct SectionGroup
         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[];
diff --git a/libphobos/m4/druntime/os.m4 b/libphobos/m4/druntime/os.m4
index ed93e30f1e9..351558dbcda 100644
--- a/libphobos/m4/druntime/os.m4
+++ b/libphobos/m4/druntime/os.m4
@@ -149,17 +149,31 @@ AC_DEFUN([DRUNTIME_OS_ARM_EABI_UNWINDER],
 # substitute DCFG_MINFO_BRACKETING.
 AC_DEFUN([DRUNTIME_OS_MINFO_BRACKETING],
 [
+  AC_REQUIRE([DRUNTIME_OS_DETECT])
+
   AC_LANG_PUSH([C])
   AC_MSG_CHECKING([for minfo section bracketing])
+  case "$druntime_cv_target_os" in
+      darwin*)
+	section="__DATA,__minfodata"
+	start="section\$start\$__DATA\$__minfodata"
+	stop="section\$end\$__DATA\$__minfodata"
+	;;
+      *)
+	section="minfo"
+	start="__start_minfo"
+	stop="__stop_minfo"
+	;;
+  esac
   AC_LINK_IFELSE([AC_LANG_SOURCE([
-    void* module_info_ptr __attribute__((section ("minfo")));
-    extern void* __start_minfo __attribute__((visibility ("hidden")));
-    extern void* __stop_minfo __attribute__((visibility ("hidden")));
+    void* module_info_ptr __attribute__((section ("$section")));
+    extern void* start_minfo __asm__("$start") __attribute__((visibility ("hidden")));
+    extern void* stop_minfo __asm__("$stop") __attribute__((visibility ("hidden")));
 
     int main()
     {
         // Never run, just to prevent compiler from optimizing access
-        return &__start_minfo == &__stop_minfo;
+        return (int)(&stop_minfo - &start_minfo);
     }
   ])],
     [AC_MSG_RESULT([yes])
diff --git a/libphobos/testsuite/lib/libphobos.exp b/libphobos/testsuite/lib/libphobos.exp
index 790480bf95c..3b43f0182a7 100644
--- a/libphobos/testsuite/lib/libphobos.exp
+++ b/libphobos/testsuite/lib/libphobos.exp
@@ -90,6 +90,10 @@ proc libphobos-dg-test { prog do_what extra_tool_flags } {
 }
 
 proc libphobos-dg-prune { system text } {
+
+    # Ignore warnings from cctools.
+    regsub -all "(^|\n)clang: warning: argument unused during compilation:\[^\n\]*" $text "" text
+
     return $text
 }
 
diff --git a/libphobos/testsuite/libphobos.druntime/druntime.exp b/libphobos/testsuite/libphobos.druntime/druntime.exp
index 7072ebb1c9f..a157329c916 100644
--- a/libphobos/testsuite/libphobos.druntime/druntime.exp
+++ b/libphobos/testsuite/libphobos.druntime/druntime.exp
@@ -15,7 +15,7 @@
 # <http://www.gnu.org/licenses/>.
 
 # Immediately exit if we can't run target executables.
-if { ![isnative] || ![is-effective-target static] } {
+if { ![isnative] } {
     return
 }
 
diff --git a/libphobos/testsuite/libphobos.phobos/phobos.exp b/libphobos/testsuite/libphobos.phobos/phobos.exp
index aad877c24c2..45c48ce7324 100644
--- a/libphobos/testsuite/libphobos.phobos/phobos.exp
+++ b/libphobos/testsuite/libphobos.phobos/phobos.exp
@@ -15,7 +15,7 @@
 # <http://www.gnu.org/licenses/>.
 
 # Immediately exit if we can't run target executables.
-if { ![isnative] || ![is-effective-target static] } {
+if { ![isnative] } {
     return
 }


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [gcc(refs/users/ibuclaw/heads/darwin)] libphobos: Checkpoint in darwin runtime support
@ 2020-12-03 22:57 Iain Buclaw
  0 siblings, 0 replies; 15+ messages in thread
From: Iain Buclaw @ 2020-12-03 22:57 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:c2e08f8a620525ceb38a64ef3bc62e33686fc0ef

commit c2e08f8a620525ceb38a64ef3bc62e33686fc0ef
Author: Iain Buclaw <ibuclaw@gdcproject.org>
Date:   Sun Nov 29 14:44:28 2020 +0100

    libphobos: Checkpoint in darwin runtime support

Diff:
---
 libphobos/configure                                |  30 ++-
 libphobos/libdruntime/Makefile.am                  |  30 +--
 libphobos/libdruntime/Makefile.in                  |  38 +--
 libphobos/libdruntime/config/x86/switchcontext.S   |   8 +
 libphobos/libdruntime/gcc/deh.d                    |   5 -
 libphobos/libdruntime/gcc/sections/android.d       |   7 -
 libphobos/libdruntime/gcc/sections/common.d        |  48 ++++
 libphobos/libdruntime/gcc/sections/elf_shared.d    |  11 -
 libphobos/libdruntime/gcc/sections/osx.d           | 279 +++++++++++----------
 libphobos/libdruntime/gcc/sections/win64.d         |   8 -
 libphobos/m4/druntime/os.m4                        |  22 +-
 libphobos/testsuite/lib/libphobos.exp              |   4 +
 .../testsuite/libphobos.druntime/druntime.exp      |   2 +-
 libphobos/testsuite/libphobos.phobos/phobos.exp    |   2 +-
 14 files changed, 280 insertions(+), 214 deletions(-)

diff --git a/libphobos/configure b/libphobos/configure
index 77a3125cbd6..e86e129fd72 100755
--- a/libphobos/configure
+++ b/libphobos/configure
@@ -10038,7 +10038,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
       if test "$GCC" = yes && test "$with_gnu_ld" = no; then
 	case $host_cpu in
 	hppa*64*)
-	  archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+	  archive_cmds='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
 	  ;;
 	ia64*)
 	  archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
@@ -10050,7 +10050,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
       else
 	case $host_cpu in
 	hppa*64*)
-	  archive_cmds='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+	  archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
 	  ;;
 	ia64*)
 	  archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
@@ -13485,7 +13485,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
       if test "$GCC" = yes && test "$with_gnu_ld" = no; then
 	case $host_cpu in
 	hppa*64*)
-	  archive_cmds_D='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+	  archive_cmds_D='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
 	  ;;
 	ia64*)
 	  archive_cmds_D='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
@@ -13497,7 +13497,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
       else
 	case $host_cpu in
 	hppa*64*)
-	  archive_cmds_D='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+	  archive_cmds_D='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
 	  ;;
 	ia64*)
 	  archive_cmds_D='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
@@ -14381,6 +14381,8 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
 
 
+
+
   ac_ext=c
 ac_cpp='$CPP $CPPFLAGS'
 ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -14389,17 +14391,29 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for minfo section bracketing" >&5
 $as_echo_n "checking for minfo section bracketing... " >&6; }
+  case "$druntime_cv_target_os" in
+      darwin*)
+	section="__DATA,__minfodata"
+	start="section\$start\$__DATA\$__minfodata"
+	stop="section\$end\$__DATA\$__minfodata"
+	;;
+      *)
+	section="minfo"
+	start="__start_minfo"
+	stop="__stop_minfo"
+	;;
+  esac
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
-    void* module_info_ptr __attribute__((section ("minfo")));
-    extern void* __start_minfo __attribute__((visibility ("hidden")));
-    extern void* __stop_minfo __attribute__((visibility ("hidden")));
+    void* module_info_ptr __attribute__((section ("$section")));
+    extern void* start_minfo __asm__("$start") __attribute__((visibility ("hidden")));
+    extern void* stop_minfo __asm__("$stop") __attribute__((visibility ("hidden")));
 
     int main()
     {
         // Never run, just to prevent compiler from optimizing access
-        return &__start_minfo == &__stop_minfo;
+        return (int)(&stop_minfo - &start_minfo);
     }
 
 _ACEOF
diff --git a/libphobos/libdruntime/Makefile.am b/libphobos/libdruntime/Makefile.am
index 4798bdf777d..1ebc97af39d 100644
--- a/libphobos/libdruntime/Makefile.am
+++ b/libphobos/libdruntime/Makefile.am
@@ -183,21 +183,21 @@ DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \
 	gc/impl/conservative/gc.d gc/impl/manual/gc.d gc/os.d gc/pooltable.d \
 	gc/proxy.d gcc/attribute.d gcc/backtrace.d gcc/builtins.d gcc/deh.d \
 	gcc/emutls.d gcc/gthread.d gcc/sections/android.d \
-	gcc/sections/elf_shared.d gcc/sections/osx.d gcc/sections/package.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 rt/typeinfo/ti_Aint.d \
-	rt/typeinfo/ti_Along.d rt/typeinfo/ti_Areal.d rt/typeinfo/ti_Ashort.d \
-	rt/typeinfo/ti_C.d rt/typeinfo/ti_byte.d rt/typeinfo/ti_cdouble.d \
-	rt/typeinfo/ti_cent.d rt/typeinfo/ti_cfloat.d rt/typeinfo/ti_char.d \
-	rt/typeinfo/ti_creal.d rt/typeinfo/ti_dchar.d \
+	gcc/sections/common.d gcc/sections/elf_shared.d gcc/sections/osx.d \
+	gcc/sections/package.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 \
+	rt/typeinfo/ti_Aint.d rt/typeinfo/ti_Along.d rt/typeinfo/ti_Areal.d \
+	rt/typeinfo/ti_Ashort.d rt/typeinfo/ti_C.d rt/typeinfo/ti_byte.d \
+	rt/typeinfo/ti_cdouble.d rt/typeinfo/ti_cent.d rt/typeinfo/ti_cfloat.d \
+	rt/typeinfo/ti_char.d rt/typeinfo/ti_creal.d rt/typeinfo/ti_dchar.d \
 	rt/typeinfo/ti_delegate.d rt/typeinfo/ti_double.d \
 	rt/typeinfo/ti_float.d rt/typeinfo/ti_idouble.d \
 	rt/typeinfo/ti_ifloat.d rt/typeinfo/ti_int.d rt/typeinfo/ti_ireal.d \
diff --git a/libphobos/libdruntime/Makefile.in b/libphobos/libdruntime/Makefile.in
index 99ee8b92afa..3bf08f52b31 100644
--- a/libphobos/libdruntime/Makefile.in
+++ b/libphobos/libdruntime/Makefile.in
@@ -207,9 +207,10 @@ am__objects_1 = core/atomic.lo core/attribute.lo core/bitop.lo \
 	gc/impl/conservative/gc.lo gc/impl/manual/gc.lo gc/os.lo \
 	gc/pooltable.lo gc/proxy.lo gcc/attribute.lo gcc/backtrace.lo \
 	gcc/builtins.lo gcc/deh.lo gcc/emutls.lo gcc/gthread.lo \
-	gcc/sections/android.lo gcc/sections/elf_shared.lo \
-	gcc/sections/osx.lo gcc/sections/package.lo \
-	gcc/sections/win32.lo gcc/sections/win64.lo gcc/unwind/arm.lo \
+	gcc/sections/android.lo gcc/sections/common.lo \
+	gcc/sections/elf_shared.lo gcc/sections/osx.lo \
+	gcc/sections/package.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 \
@@ -808,21 +809,21 @@ DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \
 	gc/impl/conservative/gc.d gc/impl/manual/gc.d gc/os.d gc/pooltable.d \
 	gc/proxy.d gcc/attribute.d gcc/backtrace.d gcc/builtins.d gcc/deh.d \
 	gcc/emutls.d gcc/gthread.d gcc/sections/android.d \
-	gcc/sections/elf_shared.d gcc/sections/osx.d gcc/sections/package.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 rt/typeinfo/ti_Aint.d \
-	rt/typeinfo/ti_Along.d rt/typeinfo/ti_Areal.d rt/typeinfo/ti_Ashort.d \
-	rt/typeinfo/ti_C.d rt/typeinfo/ti_byte.d rt/typeinfo/ti_cdouble.d \
-	rt/typeinfo/ti_cent.d rt/typeinfo/ti_cfloat.d rt/typeinfo/ti_char.d \
-	rt/typeinfo/ti_creal.d rt/typeinfo/ti_dchar.d \
+	gcc/sections/common.d gcc/sections/elf_shared.d gcc/sections/osx.d \
+	gcc/sections/package.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 \
+	rt/typeinfo/ti_Aint.d rt/typeinfo/ti_Along.d rt/typeinfo/ti_Areal.d \
+	rt/typeinfo/ti_Ashort.d rt/typeinfo/ti_C.d rt/typeinfo/ti_byte.d \
+	rt/typeinfo/ti_cdouble.d rt/typeinfo/ti_cent.d rt/typeinfo/ti_cfloat.d \
+	rt/typeinfo/ti_char.d rt/typeinfo/ti_creal.d rt/typeinfo/ti_dchar.d \
 	rt/typeinfo/ti_delegate.d rt/typeinfo/ti_double.d \
 	rt/typeinfo/ti_float.d rt/typeinfo/ti_idouble.d \
 	rt/typeinfo/ti_ifloat.d rt/typeinfo/ti_int.d rt/typeinfo/ti_ireal.d \
@@ -1195,6 +1196,7 @@ gcc/sections/$(am__dirstamp):
 	@$(MKDIR_P) gcc/sections
 	@: > gcc/sections/$(am__dirstamp)
 gcc/sections/android.lo: gcc/sections/$(am__dirstamp)
+gcc/sections/common.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)
diff --git a/libphobos/libdruntime/config/x86/switchcontext.S b/libphobos/libdruntime/config/x86/switchcontext.S
index f2f8efa218e..66c81f8b37a 100644
--- a/libphobos/libdruntime/config/x86/switchcontext.S
+++ b/libphobos/libdruntime/config/x86/switchcontext.S
@@ -33,7 +33,9 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 
     .text
     .globl CSYM(fiber_switchContext)
+#if defined(__ELF__)
     .type CSYM(fiber_switchContext), @function
+#endif
     .align 16
 CSYM(fiber_switchContext):
     .cfi_startproc
@@ -61,13 +63,17 @@ CSYM(fiber_switchContext):
     // 'return' to complete switch
     ret
     .cfi_endproc
+#if defined(__ELF__)
     .size CSYM(fiber_switchContext),.-CSYM(fiber_switchContext)
+#endif
 
 #elif defined(__x86_64__) && !defined(__ILP32__) && !defined(__CET__)
 
     .text
     .globl CSYM(fiber_switchContext)
+#if defined(__ELF__)
     .type CSYM(fiber_switchContext), @function
+#endif
     .align 16
 CSYM(fiber_switchContext):
     .cfi_startproc
@@ -96,6 +102,8 @@ CSYM(fiber_switchContext):
     // 'return' to complete switch
     ret
     .cfi_endproc
+#if defined(__ELF__)
    .size CSYM(fiber_switchContext),.-CSYM(fiber_switchContext)
+#endif
 
 #endif
diff --git a/libphobos/libdruntime/gcc/deh.d b/libphobos/libdruntime/gcc/deh.d
index 3e78a6c9c0e..bb2035f5155 100644
--- a/libphobos/libdruntime/gcc/deh.d
+++ b/libphobos/libdruntime/gcc/deh.d
@@ -34,11 +34,6 @@ extern(C)
 {
     int _d_isbaseof(ClassInfo, ClassInfo);
     void _d_createTrace(Object, void*);
-
-    // Not used in GDC but declaration required by rt/sections.d
-    struct FuncTable
-    {
-    }
 }
 
 /**
diff --git a/libphobos/libdruntime/gcc/sections/android.d b/libphobos/libdruntime/gcc/sections/android.d
index 2180a0b2514..51f5d24c2cb 100644
--- a/libphobos/libdruntime/gcc/sections/android.d
+++ b/libphobos/libdruntime/gcc/sections/android.d
@@ -54,13 +54,6 @@ struct SectionGroup
         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[];
diff --git a/libphobos/libdruntime/gcc/sections/common.d b/libphobos/libdruntime/gcc/sections/common.d
new file mode 100644
index 00000000000..b2d2322347d
--- /dev/null
+++ b/libphobos/libdruntime/gcc/sections/common.d
@@ -0,0 +1,48 @@
+// Common support routines 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.common;
+
+/****
+ * 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.).
+ */
+void safeAssert(bool condition, scope string msg, size_t line = __LINE__) @nogc nothrow @safe
+{
+    import core.internal.abort;
+    condition || abort(msg, __FILE__, line);
+}
+
+/****
+ * 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]; }
diff --git a/libphobos/libdruntime/gcc/sections/elf_shared.d b/libphobos/libdruntime/gcc/sections/elf_shared.d
index 59e2dd60a1f..3fb1b491f88 100644
--- a/libphobos/libdruntime/gcc/sections/elf_shared.d
+++ b/libphobos/libdruntime/gcc/sections/elf_shared.d
@@ -132,11 +132,6 @@ struct DSO
         return _moduleGroup;
     }
 
-    @property immutable(FuncTable)[] ehTables() const nothrow @nogc
-    {
-        return null;
-    }
-
     @property inout(void[])[] gcRanges() inout nothrow @nogc
     {
         return _gcRanges[];
@@ -383,12 +378,6 @@ version (Shared)
      */
     __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
 {
diff --git a/libphobos/libdruntime/gcc/sections/osx.d b/libphobos/libdruntime/gcc/sections/osx.d
index cb02b452404..6ace2da4a8b 100644
--- a/libphobos/libdruntime/gcc/sections/osx.d
+++ b/libphobos/libdruntime/gcc/sections/osx.d
@@ -24,25 +24,38 @@ 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 gcc.sections.common;
+
+import core.stdc.stdlib;
 import core.sys.darwin.mach.dyld;
 import core.sys.darwin.mach.getsect;
-import rt.deh, rt.minfo;
+import rt.minfo;
 import rt.util.container.array;
 
-struct SectionGroup
+version (GNU_EMUTLS)
+    import gcc.emutls;
+
+alias DSO SectionGroup;
+struct DSO
 {
-    static int opApply(scope int delegate(ref SectionGroup) dg)
+    static int opApply(scope int delegate(ref DSO) dg)
     {
-        return dg(_sections);
+        foreach (dso; _loadedDSOs)
+        {
+            if (auto res = dg(*dso))
+                return res;
+        }
+        return 0;
     }
 
-    static int opApplyReverse(scope int delegate(ref SectionGroup) dg)
+    static int opApplyReverse(scope int delegate(ref DSO) dg)
     {
-        return dg(_sections);
+        foreach_reverse (dso; _loadedDSOs)
+        {
+            if (auto res = dg(*dso))
+                return res;
+        }
+        return 0;
     }
 
     @property immutable(ModuleInfo*)[] modules() const nothrow @nogc
@@ -60,16 +73,9 @@ struct SectionGroup
         return _gcRanges[];
     }
 
-    @property immutable(FuncTable)[] ehTables() const nothrow @nogc
-    {
-        return _ehTables[];
-    }
-
 private:
-    immutable(FuncTable)[] _ehTables;
     ModuleGroup _moduleGroup;
     Array!(void[]) _gcRanges;
-    immutable(void)[][2] _tlsImage;
 }
 
 /****
@@ -82,8 +88,6 @@ __gshared bool _isRuntimeInitialized;
  */
 void initSections() nothrow @nogc
 {
-    pthread_key_create(&_tlsKey, null);
-    _dyld_register_func_for_add_image(&sections_osx_onAddImage);
     _isRuntimeInitialized = true;
 }
 
@@ -92,160 +96,161 @@ void initSections() nothrow @nogc
  */
 void finiSections() nothrow @nogc
 {
-    _sections._gcRanges.reset();
-    pthread_key_delete(_tlsKey);
     _isRuntimeInitialized = false;
 }
 
 void[]* initTLSRanges() nothrow @nogc
 {
-    return &getTLSBlock();
+    return null;
 }
 
 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);
+    version (GNU_EMUTLS)
+        _d_emutls_scan(dg);
+    else
+        static assert(0, "Native TLS unimplemented");
 }
 
-// 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 )
+version (Shared)
 {
-    immutable off = tlsOffset(p);
-    auto tls = getTLSBlockAlloc();
-    assert(off < tls.length);
-    return tls.ptr + off;
-}
-
-private:
+    // interface for core.thread to inherit loaded libraries
+    void* pinLoadedLibraries() nothrow @nogc
+    {
+        return null;
+    }
 
-__gshared pthread_key_t _tlsKey;
+    void unpinLoadedLibraries(void* p) nothrow @nogc
+    {
+    }
 
-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)
+    // Called before TLS ctors are ran, copy over the loaded libraries
+    // of the parent thread.
+    void inheritLoadedLibraries(void* p) nothrow @nogc
     {
-        return off0;
     }
-    immutable off1 = cast(size_t)(p - _sections._tlsImage[1].ptr);
-    if (off1 < _sections._tlsImage[1].length)
+
+    // Called after all TLS dtors ran, decrements all remaining dlopen refs.
+    void cleanupLoadedLibraries() nothrow @nogc
     {
-        size_t sz = (_sections._tlsImage[0].length + 15) & ~cast(size_t)15;
-        return sz + off1;
     }
-    assert(0);
 }
 
-ref void[] getTLSBlock() nothrow @nogc
+private:
+
+/*
+ * Static DSOs loaded by the runtime linker. This includes the
+ * executable. These can't be unloaded.
+ */
+@property ref Array!(DSO*) _loadedDSOs() @nogc nothrow
 {
-    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;
+    __gshared Array!(DSO*) x;
+    return x;
 }
 
-ref void[] getTLSBlockAlloc()
+/*
+ * Set to true during rt_loadLibrary/rt_unloadLibrary calls.
+ */
+enum _rtLoading = false;
+
+struct MachHeader
 {
-    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;
+    const(mach_header)* header; // the mach header of the image
+    intptr_t slide;             // virtural memory address slide amount
 }
 
-__gshared SectionGroup _sections;
+///////////////////////////////////////////////////////////////////////////////
+// Compiler to runtime interface.
+///////////////////////////////////////////////////////////////////////////////
 
-extern (C) void sections_osx_onAddImage(in mach_header* h, intptr_t slide)
+/* 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)
 {
-    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]);
-    }
+    // only one supported currently
+    safeAssert(data._version >= 1, "Incompatible compiler-generated DSO data version.");
 
-    auto minfosect = getSection(h, slide, "__DATA", "__minfodata");
-    if (minfosect != null)
+    // no backlink => register
+    if (*data._slot is 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)
+        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));
+
+        MachHeader info = void;
+        const headerFound = findDSOHeaderForAddr(data._slot, &info);
+        safeAssert(headerFound, "Failed to find image header.");
+
+        foreach (e; dataSegs)
         {
-            fprintf(stderr, "Shared libraries are not yet supported on OSX.\n");
+            auto sect = getSection(info.header, info.slide,
+                                   e.seg.ptr, e.sect.ptr);
+            if (sect != null)
+                pdso._gcRanges.insertBack((cast(void*)sect.ptr)[0 .. sect.length]);
         }
 
-        debug(PRINTF) printf("  minfodata\n");
-        auto p = cast(immutable(ModuleInfo*)*)minfosect.ptr;
-        immutable len = minfosect.length / (*p).sizeof;
-
-        _sections._moduleGroup = ModuleGroup(p[0 .. len]);
+        foreach (p; _loadedDSOs)
+            safeAssert(p !is pdso, "DSO already registered.");
+        _loadedDSOs.insertBack(pdso);
     }
-
-    auto ehsect = getSection(h, slide, "__DATA", "__deh_eh");
-    if (ehsect != null)
+    // has backlink => unregister
+    else
     {
-        debug(PRINTF) printf("  deh_eh\n");
-        auto p = cast(immutable(FuncTable)*)ehsect.ptr;
-        immutable len = ehsect.length / (*p).sizeof;
+        DSO* pdso = cast(DSO*)*data._slot;
+        *data._slot = null;
 
-        _sections._ehTables = p[0 .. len];
-    }
+        // static DSOs are unloaded in reverse order
+        safeAssert(pdso == _loadedDSOs.back, "DSO being unregistered isn't current last one.");
+        _loadedDSOs.popBack();
 
-    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];
+        pdso._gcRanges.reset();
+        .free(pdso);
+
+        // last DSO being unloaded => shutdown registry
+        if (_loadedDSOs.empty)
+        {
+            version (GNU_EMUTLS)
+                _d_emutls_destroy();
+        }
     }
+}
+
+/**************************
+ * Input:
+ *      result where the output is to be written
+ * Returns:
+ *      true if found, and *result is filled in
+ */
 
-    auto tlssect2 = getSection(h, slide, "__DATA", "__tlscoal_nt");
-    if (tlssect2 != null)
+bool findDSOHeaderForAddr(in void* addr, MachHeader* result)
+{
+    foreach (i; 0 .. _dyld_image_count())
     {
-        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];
+        const header = _dyld_get_image_header(i);
+        const slide = _dyld_get_image_vmaddr_slide(i);
+        const section = getSection(header, slide, SEG_DATA, SECT_DATA);
+
+        // less than base address of section means quick reject
+        if (!section.length || addr < section.ptr)
+           continue;
+
+        if (addr < section.ptr + section.length)
+        {
+            result.header = header;
+            result.slide = slide;
+            return true;
+        }
     }
+    return false;
 }
 
 struct SegRef
@@ -258,25 +263,27 @@ static immutable SegRef[] dataSegs = [{SEG_DATA, SECT_DATA},
                                       {SEG_DATA, SECT_BSS},
                                       {SEG_DATA, SECT_COMMON}];
 
+/**
+ * Returns the section for the named section in the named segment
+ * for the mach_header pointer passed, or null if not found.
+ */
 ubyte[] getSection(in mach_header* header, intptr_t slide,
                    in char* segmentName, in char* sectionName)
 {
-    version (X86)
+    version (D_LP64)
     {
-        assert(header.magic == MH_MAGIC);
-        auto sect = getsectbynamefromheader(header,
+        assert(header.magic == MH_MAGIC_64);
+        auto sect = getsectbynamefromheader_64(cast(mach_header_64*)header,
                                             segmentName,
                                             sectionName);
     }
-    else version (X86_64)
+    else
     {
-        assert(header.magic == MH_MAGIC_64);
-        auto sect = getsectbynamefromheader_64(cast(mach_header_64*)header,
+        assert(header.magic == MH_MAGIC);
+        auto sect = getsectbynamefromheader(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];
diff --git a/libphobos/libdruntime/gcc/sections/win64.d b/libphobos/libdruntime/gcc/sections/win64.d
index 1a4ee989cec..8362a6ffa23 100644
--- a/libphobos/libdruntime/gcc/sections/win64.d
+++ b/libphobos/libdruntime/gcc/sections/win64.d
@@ -51,14 +51,6 @@ struct SectionGroup
         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[];
diff --git a/libphobos/m4/druntime/os.m4 b/libphobos/m4/druntime/os.m4
index ed93e30f1e9..351558dbcda 100644
--- a/libphobos/m4/druntime/os.m4
+++ b/libphobos/m4/druntime/os.m4
@@ -149,17 +149,31 @@ AC_DEFUN([DRUNTIME_OS_ARM_EABI_UNWINDER],
 # substitute DCFG_MINFO_BRACKETING.
 AC_DEFUN([DRUNTIME_OS_MINFO_BRACKETING],
 [
+  AC_REQUIRE([DRUNTIME_OS_DETECT])
+
   AC_LANG_PUSH([C])
   AC_MSG_CHECKING([for minfo section bracketing])
+  case "$druntime_cv_target_os" in
+      darwin*)
+	section="__DATA,__minfodata"
+	start="section\$start\$__DATA\$__minfodata"
+	stop="section\$end\$__DATA\$__minfodata"
+	;;
+      *)
+	section="minfo"
+	start="__start_minfo"
+	stop="__stop_minfo"
+	;;
+  esac
   AC_LINK_IFELSE([AC_LANG_SOURCE([
-    void* module_info_ptr __attribute__((section ("minfo")));
-    extern void* __start_minfo __attribute__((visibility ("hidden")));
-    extern void* __stop_minfo __attribute__((visibility ("hidden")));
+    void* module_info_ptr __attribute__((section ("$section")));
+    extern void* start_minfo __asm__("$start") __attribute__((visibility ("hidden")));
+    extern void* stop_minfo __asm__("$stop") __attribute__((visibility ("hidden")));
 
     int main()
     {
         // Never run, just to prevent compiler from optimizing access
-        return &__start_minfo == &__stop_minfo;
+        return (int)(&stop_minfo - &start_minfo);
     }
   ])],
     [AC_MSG_RESULT([yes])
diff --git a/libphobos/testsuite/lib/libphobos.exp b/libphobos/testsuite/lib/libphobos.exp
index 790480bf95c..3b43f0182a7 100644
--- a/libphobos/testsuite/lib/libphobos.exp
+++ b/libphobos/testsuite/lib/libphobos.exp
@@ -90,6 +90,10 @@ proc libphobos-dg-test { prog do_what extra_tool_flags } {
 }
 
 proc libphobos-dg-prune { system text } {
+
+    # Ignore warnings from cctools.
+    regsub -all "(^|\n)clang: warning: argument unused during compilation:\[^\n\]*" $text "" text
+
     return $text
 }
 
diff --git a/libphobos/testsuite/libphobos.druntime/druntime.exp b/libphobos/testsuite/libphobos.druntime/druntime.exp
index 7072ebb1c9f..a157329c916 100644
--- a/libphobos/testsuite/libphobos.druntime/druntime.exp
+++ b/libphobos/testsuite/libphobos.druntime/druntime.exp
@@ -15,7 +15,7 @@
 # <http://www.gnu.org/licenses/>.
 
 # Immediately exit if we can't run target executables.
-if { ![isnative] || ![is-effective-target static] } {
+if { ![isnative] } {
     return
 }
 
diff --git a/libphobos/testsuite/libphobos.phobos/phobos.exp b/libphobos/testsuite/libphobos.phobos/phobos.exp
index aad877c24c2..45c48ce7324 100644
--- a/libphobos/testsuite/libphobos.phobos/phobos.exp
+++ b/libphobos/testsuite/libphobos.phobos/phobos.exp
@@ -15,7 +15,7 @@
 # <http://www.gnu.org/licenses/>.
 
 # Immediately exit if we can't run target executables.
-if { ![isnative] || ![is-effective-target static] } {
+if { ![isnative] } {
     return
 }


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [gcc(refs/users/ibuclaw/heads/darwin)] libphobos: Checkpoint in darwin runtime support
@ 2020-11-30 14:38 Iain Buclaw
  0 siblings, 0 replies; 15+ messages in thread
From: Iain Buclaw @ 2020-11-30 14:38 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:53e719ddf791ff35d243df556ae3162404cf95c0

commit 53e719ddf791ff35d243df556ae3162404cf95c0
Author: Iain Buclaw <ibuclaw@gdcproject.org>
Date:   Sun Nov 29 14:44:28 2020 +0100

    libphobos: Checkpoint in darwin runtime support

Diff:
---
 libphobos/configure                                |  30 ++-
 libphobos/libdruntime/Makefile.am                  |  30 +--
 libphobos/libdruntime/Makefile.in                  |  38 +--
 libphobos/libdruntime/config/x86/switchcontext.S   |   8 +
 libphobos/libdruntime/gcc/deh.d                    |   5 -
 libphobos/libdruntime/gcc/sections/android.d       |   7 -
 libphobos/libdruntime/gcc/sections/common.d        |  48 ++++
 libphobos/libdruntime/gcc/sections/elf_shared.d    |  11 -
 libphobos/libdruntime/gcc/sections/osx.d           | 279 +++++++++++----------
 libphobos/libdruntime/gcc/sections/win64.d         |   8 -
 libphobos/m4/druntime/os.m4                        |  22 +-
 libphobos/testsuite/lib/libphobos.exp              |   4 +
 .../testsuite/libphobos.druntime/druntime.exp      |   2 +-
 libphobos/testsuite/libphobos.phobos/phobos.exp    |   2 +-
 14 files changed, 280 insertions(+), 214 deletions(-)

diff --git a/libphobos/configure b/libphobos/configure
index 77a3125cbd6..e86e129fd72 100755
--- a/libphobos/configure
+++ b/libphobos/configure
@@ -10038,7 +10038,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
       if test "$GCC" = yes && test "$with_gnu_ld" = no; then
 	case $host_cpu in
 	hppa*64*)
-	  archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+	  archive_cmds='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
 	  ;;
 	ia64*)
 	  archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
@@ -10050,7 +10050,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
       else
 	case $host_cpu in
 	hppa*64*)
-	  archive_cmds='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+	  archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
 	  ;;
 	ia64*)
 	  archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
@@ -13485,7 +13485,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
       if test "$GCC" = yes && test "$with_gnu_ld" = no; then
 	case $host_cpu in
 	hppa*64*)
-	  archive_cmds_D='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+	  archive_cmds_D='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
 	  ;;
 	ia64*)
 	  archive_cmds_D='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
@@ -13497,7 +13497,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
       else
 	case $host_cpu in
 	hppa*64*)
-	  archive_cmds_D='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+	  archive_cmds_D='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
 	  ;;
 	ia64*)
 	  archive_cmds_D='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
@@ -14381,6 +14381,8 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
 
 
+
+
   ac_ext=c
 ac_cpp='$CPP $CPPFLAGS'
 ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -14389,17 +14391,29 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for minfo section bracketing" >&5
 $as_echo_n "checking for minfo section bracketing... " >&6; }
+  case "$druntime_cv_target_os" in
+      darwin*)
+	section="__DATA,__minfodata"
+	start="section\$start\$__DATA\$__minfodata"
+	stop="section\$end\$__DATA\$__minfodata"
+	;;
+      *)
+	section="minfo"
+	start="__start_minfo"
+	stop="__stop_minfo"
+	;;
+  esac
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
-    void* module_info_ptr __attribute__((section ("minfo")));
-    extern void* __start_minfo __attribute__((visibility ("hidden")));
-    extern void* __stop_minfo __attribute__((visibility ("hidden")));
+    void* module_info_ptr __attribute__((section ("$section")));
+    extern void* start_minfo __asm__("$start") __attribute__((visibility ("hidden")));
+    extern void* stop_minfo __asm__("$stop") __attribute__((visibility ("hidden")));
 
     int main()
     {
         // Never run, just to prevent compiler from optimizing access
-        return &__start_minfo == &__stop_minfo;
+        return (int)(&stop_minfo - &start_minfo);
     }
 
 _ACEOF
diff --git a/libphobos/libdruntime/Makefile.am b/libphobos/libdruntime/Makefile.am
index 4798bdf777d..1ebc97af39d 100644
--- a/libphobos/libdruntime/Makefile.am
+++ b/libphobos/libdruntime/Makefile.am
@@ -183,21 +183,21 @@ DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \
 	gc/impl/conservative/gc.d gc/impl/manual/gc.d gc/os.d gc/pooltable.d \
 	gc/proxy.d gcc/attribute.d gcc/backtrace.d gcc/builtins.d gcc/deh.d \
 	gcc/emutls.d gcc/gthread.d gcc/sections/android.d \
-	gcc/sections/elf_shared.d gcc/sections/osx.d gcc/sections/package.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 rt/typeinfo/ti_Aint.d \
-	rt/typeinfo/ti_Along.d rt/typeinfo/ti_Areal.d rt/typeinfo/ti_Ashort.d \
-	rt/typeinfo/ti_C.d rt/typeinfo/ti_byte.d rt/typeinfo/ti_cdouble.d \
-	rt/typeinfo/ti_cent.d rt/typeinfo/ti_cfloat.d rt/typeinfo/ti_char.d \
-	rt/typeinfo/ti_creal.d rt/typeinfo/ti_dchar.d \
+	gcc/sections/common.d gcc/sections/elf_shared.d gcc/sections/osx.d \
+	gcc/sections/package.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 \
+	rt/typeinfo/ti_Aint.d rt/typeinfo/ti_Along.d rt/typeinfo/ti_Areal.d \
+	rt/typeinfo/ti_Ashort.d rt/typeinfo/ti_C.d rt/typeinfo/ti_byte.d \
+	rt/typeinfo/ti_cdouble.d rt/typeinfo/ti_cent.d rt/typeinfo/ti_cfloat.d \
+	rt/typeinfo/ti_char.d rt/typeinfo/ti_creal.d rt/typeinfo/ti_dchar.d \
 	rt/typeinfo/ti_delegate.d rt/typeinfo/ti_double.d \
 	rt/typeinfo/ti_float.d rt/typeinfo/ti_idouble.d \
 	rt/typeinfo/ti_ifloat.d rt/typeinfo/ti_int.d rt/typeinfo/ti_ireal.d \
diff --git a/libphobos/libdruntime/Makefile.in b/libphobos/libdruntime/Makefile.in
index 99ee8b92afa..3bf08f52b31 100644
--- a/libphobos/libdruntime/Makefile.in
+++ b/libphobos/libdruntime/Makefile.in
@@ -207,9 +207,10 @@ am__objects_1 = core/atomic.lo core/attribute.lo core/bitop.lo \
 	gc/impl/conservative/gc.lo gc/impl/manual/gc.lo gc/os.lo \
 	gc/pooltable.lo gc/proxy.lo gcc/attribute.lo gcc/backtrace.lo \
 	gcc/builtins.lo gcc/deh.lo gcc/emutls.lo gcc/gthread.lo \
-	gcc/sections/android.lo gcc/sections/elf_shared.lo \
-	gcc/sections/osx.lo gcc/sections/package.lo \
-	gcc/sections/win32.lo gcc/sections/win64.lo gcc/unwind/arm.lo \
+	gcc/sections/android.lo gcc/sections/common.lo \
+	gcc/sections/elf_shared.lo gcc/sections/osx.lo \
+	gcc/sections/package.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 \
@@ -808,21 +809,21 @@ DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \
 	gc/impl/conservative/gc.d gc/impl/manual/gc.d gc/os.d gc/pooltable.d \
 	gc/proxy.d gcc/attribute.d gcc/backtrace.d gcc/builtins.d gcc/deh.d \
 	gcc/emutls.d gcc/gthread.d gcc/sections/android.d \
-	gcc/sections/elf_shared.d gcc/sections/osx.d gcc/sections/package.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 rt/typeinfo/ti_Aint.d \
-	rt/typeinfo/ti_Along.d rt/typeinfo/ti_Areal.d rt/typeinfo/ti_Ashort.d \
-	rt/typeinfo/ti_C.d rt/typeinfo/ti_byte.d rt/typeinfo/ti_cdouble.d \
-	rt/typeinfo/ti_cent.d rt/typeinfo/ti_cfloat.d rt/typeinfo/ti_char.d \
-	rt/typeinfo/ti_creal.d rt/typeinfo/ti_dchar.d \
+	gcc/sections/common.d gcc/sections/elf_shared.d gcc/sections/osx.d \
+	gcc/sections/package.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 \
+	rt/typeinfo/ti_Aint.d rt/typeinfo/ti_Along.d rt/typeinfo/ti_Areal.d \
+	rt/typeinfo/ti_Ashort.d rt/typeinfo/ti_C.d rt/typeinfo/ti_byte.d \
+	rt/typeinfo/ti_cdouble.d rt/typeinfo/ti_cent.d rt/typeinfo/ti_cfloat.d \
+	rt/typeinfo/ti_char.d rt/typeinfo/ti_creal.d rt/typeinfo/ti_dchar.d \
 	rt/typeinfo/ti_delegate.d rt/typeinfo/ti_double.d \
 	rt/typeinfo/ti_float.d rt/typeinfo/ti_idouble.d \
 	rt/typeinfo/ti_ifloat.d rt/typeinfo/ti_int.d rt/typeinfo/ti_ireal.d \
@@ -1195,6 +1196,7 @@ gcc/sections/$(am__dirstamp):
 	@$(MKDIR_P) gcc/sections
 	@: > gcc/sections/$(am__dirstamp)
 gcc/sections/android.lo: gcc/sections/$(am__dirstamp)
+gcc/sections/common.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)
diff --git a/libphobos/libdruntime/config/x86/switchcontext.S b/libphobos/libdruntime/config/x86/switchcontext.S
index f2f8efa218e..66c81f8b37a 100644
--- a/libphobos/libdruntime/config/x86/switchcontext.S
+++ b/libphobos/libdruntime/config/x86/switchcontext.S
@@ -33,7 +33,9 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 
     .text
     .globl CSYM(fiber_switchContext)
+#if defined(__ELF__)
     .type CSYM(fiber_switchContext), @function
+#endif
     .align 16
 CSYM(fiber_switchContext):
     .cfi_startproc
@@ -61,13 +63,17 @@ CSYM(fiber_switchContext):
     // 'return' to complete switch
     ret
     .cfi_endproc
+#if defined(__ELF__)
     .size CSYM(fiber_switchContext),.-CSYM(fiber_switchContext)
+#endif
 
 #elif defined(__x86_64__) && !defined(__ILP32__) && !defined(__CET__)
 
     .text
     .globl CSYM(fiber_switchContext)
+#if defined(__ELF__)
     .type CSYM(fiber_switchContext), @function
+#endif
     .align 16
 CSYM(fiber_switchContext):
     .cfi_startproc
@@ -96,6 +102,8 @@ CSYM(fiber_switchContext):
     // 'return' to complete switch
     ret
     .cfi_endproc
+#if defined(__ELF__)
    .size CSYM(fiber_switchContext),.-CSYM(fiber_switchContext)
+#endif
 
 #endif
diff --git a/libphobos/libdruntime/gcc/deh.d b/libphobos/libdruntime/gcc/deh.d
index 3e78a6c9c0e..bb2035f5155 100644
--- a/libphobos/libdruntime/gcc/deh.d
+++ b/libphobos/libdruntime/gcc/deh.d
@@ -34,11 +34,6 @@ extern(C)
 {
     int _d_isbaseof(ClassInfo, ClassInfo);
     void _d_createTrace(Object, void*);
-
-    // Not used in GDC but declaration required by rt/sections.d
-    struct FuncTable
-    {
-    }
 }
 
 /**
diff --git a/libphobos/libdruntime/gcc/sections/android.d b/libphobos/libdruntime/gcc/sections/android.d
index 2180a0b2514..51f5d24c2cb 100644
--- a/libphobos/libdruntime/gcc/sections/android.d
+++ b/libphobos/libdruntime/gcc/sections/android.d
@@ -54,13 +54,6 @@ struct SectionGroup
         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[];
diff --git a/libphobos/libdruntime/gcc/sections/common.d b/libphobos/libdruntime/gcc/sections/common.d
new file mode 100644
index 00000000000..b2d2322347d
--- /dev/null
+++ b/libphobos/libdruntime/gcc/sections/common.d
@@ -0,0 +1,48 @@
+// Common support routines 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.common;
+
+/****
+ * 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.).
+ */
+void safeAssert(bool condition, scope string msg, size_t line = __LINE__) @nogc nothrow @safe
+{
+    import core.internal.abort;
+    condition || abort(msg, __FILE__, line);
+}
+
+/****
+ * 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]; }
diff --git a/libphobos/libdruntime/gcc/sections/elf_shared.d b/libphobos/libdruntime/gcc/sections/elf_shared.d
index 59e2dd60a1f..3fb1b491f88 100644
--- a/libphobos/libdruntime/gcc/sections/elf_shared.d
+++ b/libphobos/libdruntime/gcc/sections/elf_shared.d
@@ -132,11 +132,6 @@ struct DSO
         return _moduleGroup;
     }
 
-    @property immutable(FuncTable)[] ehTables() const nothrow @nogc
-    {
-        return null;
-    }
-
     @property inout(void[])[] gcRanges() inout nothrow @nogc
     {
         return _gcRanges[];
@@ -383,12 +378,6 @@ version (Shared)
      */
     __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
 {
diff --git a/libphobos/libdruntime/gcc/sections/osx.d b/libphobos/libdruntime/gcc/sections/osx.d
index cb02b452404..6ace2da4a8b 100644
--- a/libphobos/libdruntime/gcc/sections/osx.d
+++ b/libphobos/libdruntime/gcc/sections/osx.d
@@ -24,25 +24,38 @@ 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 gcc.sections.common;
+
+import core.stdc.stdlib;
 import core.sys.darwin.mach.dyld;
 import core.sys.darwin.mach.getsect;
-import rt.deh, rt.minfo;
+import rt.minfo;
 import rt.util.container.array;
 
-struct SectionGroup
+version (GNU_EMUTLS)
+    import gcc.emutls;
+
+alias DSO SectionGroup;
+struct DSO
 {
-    static int opApply(scope int delegate(ref SectionGroup) dg)
+    static int opApply(scope int delegate(ref DSO) dg)
     {
-        return dg(_sections);
+        foreach (dso; _loadedDSOs)
+        {
+            if (auto res = dg(*dso))
+                return res;
+        }
+        return 0;
     }
 
-    static int opApplyReverse(scope int delegate(ref SectionGroup) dg)
+    static int opApplyReverse(scope int delegate(ref DSO) dg)
     {
-        return dg(_sections);
+        foreach_reverse (dso; _loadedDSOs)
+        {
+            if (auto res = dg(*dso))
+                return res;
+        }
+        return 0;
     }
 
     @property immutable(ModuleInfo*)[] modules() const nothrow @nogc
@@ -60,16 +73,9 @@ struct SectionGroup
         return _gcRanges[];
     }
 
-    @property immutable(FuncTable)[] ehTables() const nothrow @nogc
-    {
-        return _ehTables[];
-    }
-
 private:
-    immutable(FuncTable)[] _ehTables;
     ModuleGroup _moduleGroup;
     Array!(void[]) _gcRanges;
-    immutable(void)[][2] _tlsImage;
 }
 
 /****
@@ -82,8 +88,6 @@ __gshared bool _isRuntimeInitialized;
  */
 void initSections() nothrow @nogc
 {
-    pthread_key_create(&_tlsKey, null);
-    _dyld_register_func_for_add_image(&sections_osx_onAddImage);
     _isRuntimeInitialized = true;
 }
 
@@ -92,160 +96,161 @@ void initSections() nothrow @nogc
  */
 void finiSections() nothrow @nogc
 {
-    _sections._gcRanges.reset();
-    pthread_key_delete(_tlsKey);
     _isRuntimeInitialized = false;
 }
 
 void[]* initTLSRanges() nothrow @nogc
 {
-    return &getTLSBlock();
+    return null;
 }
 
 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);
+    version (GNU_EMUTLS)
+        _d_emutls_scan(dg);
+    else
+        static assert(0, "Native TLS unimplemented");
 }
 
-// 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 )
+version (Shared)
 {
-    immutable off = tlsOffset(p);
-    auto tls = getTLSBlockAlloc();
-    assert(off < tls.length);
-    return tls.ptr + off;
-}
-
-private:
+    // interface for core.thread to inherit loaded libraries
+    void* pinLoadedLibraries() nothrow @nogc
+    {
+        return null;
+    }
 
-__gshared pthread_key_t _tlsKey;
+    void unpinLoadedLibraries(void* p) nothrow @nogc
+    {
+    }
 
-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)
+    // Called before TLS ctors are ran, copy over the loaded libraries
+    // of the parent thread.
+    void inheritLoadedLibraries(void* p) nothrow @nogc
     {
-        return off0;
     }
-    immutable off1 = cast(size_t)(p - _sections._tlsImage[1].ptr);
-    if (off1 < _sections._tlsImage[1].length)
+
+    // Called after all TLS dtors ran, decrements all remaining dlopen refs.
+    void cleanupLoadedLibraries() nothrow @nogc
     {
-        size_t sz = (_sections._tlsImage[0].length + 15) & ~cast(size_t)15;
-        return sz + off1;
     }
-    assert(0);
 }
 
-ref void[] getTLSBlock() nothrow @nogc
+private:
+
+/*
+ * Static DSOs loaded by the runtime linker. This includes the
+ * executable. These can't be unloaded.
+ */
+@property ref Array!(DSO*) _loadedDSOs() @nogc nothrow
 {
-    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;
+    __gshared Array!(DSO*) x;
+    return x;
 }
 
-ref void[] getTLSBlockAlloc()
+/*
+ * Set to true during rt_loadLibrary/rt_unloadLibrary calls.
+ */
+enum _rtLoading = false;
+
+struct MachHeader
 {
-    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;
+    const(mach_header)* header; // the mach header of the image
+    intptr_t slide;             // virtural memory address slide amount
 }
 
-__gshared SectionGroup _sections;
+///////////////////////////////////////////////////////////////////////////////
+// Compiler to runtime interface.
+///////////////////////////////////////////////////////////////////////////////
 
-extern (C) void sections_osx_onAddImage(in mach_header* h, intptr_t slide)
+/* 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)
 {
-    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]);
-    }
+    // only one supported currently
+    safeAssert(data._version >= 1, "Incompatible compiler-generated DSO data version.");
 
-    auto minfosect = getSection(h, slide, "__DATA", "__minfodata");
-    if (minfosect != null)
+    // no backlink => register
+    if (*data._slot is 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)
+        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));
+
+        MachHeader info = void;
+        const headerFound = findDSOHeaderForAddr(data._slot, &info);
+        safeAssert(headerFound, "Failed to find image header.");
+
+        foreach (e; dataSegs)
         {
-            fprintf(stderr, "Shared libraries are not yet supported on OSX.\n");
+            auto sect = getSection(info.header, info.slide,
+                                   e.seg.ptr, e.sect.ptr);
+            if (sect != null)
+                pdso._gcRanges.insertBack((cast(void*)sect.ptr)[0 .. sect.length]);
         }
 
-        debug(PRINTF) printf("  minfodata\n");
-        auto p = cast(immutable(ModuleInfo*)*)minfosect.ptr;
-        immutable len = minfosect.length / (*p).sizeof;
-
-        _sections._moduleGroup = ModuleGroup(p[0 .. len]);
+        foreach (p; _loadedDSOs)
+            safeAssert(p !is pdso, "DSO already registered.");
+        _loadedDSOs.insertBack(pdso);
     }
-
-    auto ehsect = getSection(h, slide, "__DATA", "__deh_eh");
-    if (ehsect != null)
+    // has backlink => unregister
+    else
     {
-        debug(PRINTF) printf("  deh_eh\n");
-        auto p = cast(immutable(FuncTable)*)ehsect.ptr;
-        immutable len = ehsect.length / (*p).sizeof;
+        DSO* pdso = cast(DSO*)*data._slot;
+        *data._slot = null;
 
-        _sections._ehTables = p[0 .. len];
-    }
+        // static DSOs are unloaded in reverse order
+        safeAssert(pdso == _loadedDSOs.back, "DSO being unregistered isn't current last one.");
+        _loadedDSOs.popBack();
 
-    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];
+        pdso._gcRanges.reset();
+        .free(pdso);
+
+        // last DSO being unloaded => shutdown registry
+        if (_loadedDSOs.empty)
+        {
+            version (GNU_EMUTLS)
+                _d_emutls_destroy();
+        }
     }
+}
+
+/**************************
+ * Input:
+ *      result where the output is to be written
+ * Returns:
+ *      true if found, and *result is filled in
+ */
 
-    auto tlssect2 = getSection(h, slide, "__DATA", "__tlscoal_nt");
-    if (tlssect2 != null)
+bool findDSOHeaderForAddr(in void* addr, MachHeader* result)
+{
+    foreach (i; 0 .. _dyld_image_count())
     {
-        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];
+        const header = _dyld_get_image_header(i);
+        const slide = _dyld_get_image_vmaddr_slide(i);
+        const section = getSection(header, slide, SEG_DATA, SECT_DATA);
+
+        // less than base address of section means quick reject
+        if (!section.length || addr < section.ptr)
+           continue;
+
+        if (addr < section.ptr + section.length)
+        {
+            result.header = header;
+            result.slide = slide;
+            return true;
+        }
     }
+    return false;
 }
 
 struct SegRef
@@ -258,25 +263,27 @@ static immutable SegRef[] dataSegs = [{SEG_DATA, SECT_DATA},
                                       {SEG_DATA, SECT_BSS},
                                       {SEG_DATA, SECT_COMMON}];
 
+/**
+ * Returns the section for the named section in the named segment
+ * for the mach_header pointer passed, or null if not found.
+ */
 ubyte[] getSection(in mach_header* header, intptr_t slide,
                    in char* segmentName, in char* sectionName)
 {
-    version (X86)
+    version (D_LP64)
     {
-        assert(header.magic == MH_MAGIC);
-        auto sect = getsectbynamefromheader(header,
+        assert(header.magic == MH_MAGIC_64);
+        auto sect = getsectbynamefromheader_64(cast(mach_header_64*)header,
                                             segmentName,
                                             sectionName);
     }
-    else version (X86_64)
+    else
     {
-        assert(header.magic == MH_MAGIC_64);
-        auto sect = getsectbynamefromheader_64(cast(mach_header_64*)header,
+        assert(header.magic == MH_MAGIC);
+        auto sect = getsectbynamefromheader(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];
diff --git a/libphobos/libdruntime/gcc/sections/win64.d b/libphobos/libdruntime/gcc/sections/win64.d
index 1a4ee989cec..8362a6ffa23 100644
--- a/libphobos/libdruntime/gcc/sections/win64.d
+++ b/libphobos/libdruntime/gcc/sections/win64.d
@@ -51,14 +51,6 @@ struct SectionGroup
         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[];
diff --git a/libphobos/m4/druntime/os.m4 b/libphobos/m4/druntime/os.m4
index ed93e30f1e9..351558dbcda 100644
--- a/libphobos/m4/druntime/os.m4
+++ b/libphobos/m4/druntime/os.m4
@@ -149,17 +149,31 @@ AC_DEFUN([DRUNTIME_OS_ARM_EABI_UNWINDER],
 # substitute DCFG_MINFO_BRACKETING.
 AC_DEFUN([DRUNTIME_OS_MINFO_BRACKETING],
 [
+  AC_REQUIRE([DRUNTIME_OS_DETECT])
+
   AC_LANG_PUSH([C])
   AC_MSG_CHECKING([for minfo section bracketing])
+  case "$druntime_cv_target_os" in
+      darwin*)
+	section="__DATA,__minfodata"
+	start="section\$start\$__DATA\$__minfodata"
+	stop="section\$end\$__DATA\$__minfodata"
+	;;
+      *)
+	section="minfo"
+	start="__start_minfo"
+	stop="__stop_minfo"
+	;;
+  esac
   AC_LINK_IFELSE([AC_LANG_SOURCE([
-    void* module_info_ptr __attribute__((section ("minfo")));
-    extern void* __start_minfo __attribute__((visibility ("hidden")));
-    extern void* __stop_minfo __attribute__((visibility ("hidden")));
+    void* module_info_ptr __attribute__((section ("$section")));
+    extern void* start_minfo __asm__("$start") __attribute__((visibility ("hidden")));
+    extern void* stop_minfo __asm__("$stop") __attribute__((visibility ("hidden")));
 
     int main()
     {
         // Never run, just to prevent compiler from optimizing access
-        return &__start_minfo == &__stop_minfo;
+        return (int)(&stop_minfo - &start_minfo);
     }
   ])],
     [AC_MSG_RESULT([yes])
diff --git a/libphobos/testsuite/lib/libphobos.exp b/libphobos/testsuite/lib/libphobos.exp
index 790480bf95c..3b43f0182a7 100644
--- a/libphobos/testsuite/lib/libphobos.exp
+++ b/libphobos/testsuite/lib/libphobos.exp
@@ -90,6 +90,10 @@ proc libphobos-dg-test { prog do_what extra_tool_flags } {
 }
 
 proc libphobos-dg-prune { system text } {
+
+    # Ignore warnings from cctools.
+    regsub -all "(^|\n)clang: warning: argument unused during compilation:\[^\n\]*" $text "" text
+
     return $text
 }
 
diff --git a/libphobos/testsuite/libphobos.druntime/druntime.exp b/libphobos/testsuite/libphobos.druntime/druntime.exp
index 7072ebb1c9f..a157329c916 100644
--- a/libphobos/testsuite/libphobos.druntime/druntime.exp
+++ b/libphobos/testsuite/libphobos.druntime/druntime.exp
@@ -15,7 +15,7 @@
 # <http://www.gnu.org/licenses/>.
 
 # Immediately exit if we can't run target executables.
-if { ![isnative] || ![is-effective-target static] } {
+if { ![isnative] } {
     return
 }
 
diff --git a/libphobos/testsuite/libphobos.phobos/phobos.exp b/libphobos/testsuite/libphobos.phobos/phobos.exp
index aad877c24c2..45c48ce7324 100644
--- a/libphobos/testsuite/libphobos.phobos/phobos.exp
+++ b/libphobos/testsuite/libphobos.phobos/phobos.exp
@@ -15,7 +15,7 @@
 # <http://www.gnu.org/licenses/>.
 
 # Immediately exit if we can't run target executables.
-if { ![isnative] || ![is-effective-target static] } {
+if { ![isnative] } {
     return
 }


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [gcc(refs/users/ibuclaw/heads/darwin)] libphobos: Checkpoint in darwin runtime support
@ 2020-11-29 13:45 Iain Buclaw
  0 siblings, 0 replies; 15+ messages in thread
From: Iain Buclaw @ 2020-11-29 13:45 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:9eec2ee9893b784d419926147ccdbfcd36bcbb07

commit 9eec2ee9893b784d419926147ccdbfcd36bcbb07
Author: Iain Buclaw <ibuclaw@gdcproject.org>
Date:   Sun Nov 29 14:44:28 2020 +0100

    libphobos: Checkpoint in darwin runtime support

Diff:
---
 gcc/d/modules.cc                                   |   1 +
 libphobos/configure                                |  22 +-
 libphobos/libdruntime/Makefile.in                  |   1 +
 libphobos/libdruntime/config/x86/switchcontext.S   |   8 +
 libphobos/libdruntime/gcc/deh.d                    |   5 -
 libphobos/libdruntime/gcc/sections/android.d       |   7 -
 libphobos/libdruntime/gcc/sections/common.d        |  48 ++++
 libphobos/libdruntime/gcc/sections/elf_shared.d    |  11 -
 libphobos/libdruntime/gcc/sections/osx.d           | 279 +++++++++++----------
 libphobos/libdruntime/gcc/sections/win64.d         |   8 -
 libphobos/m4/druntime/os.m4                        |  22 +-
 libphobos/testsuite/lib/libphobos.exp              |   4 +
 .../testsuite/libphobos.druntime/druntime.exp      |   2 +-
 libphobos/testsuite/libphobos.phobos/phobos.exp    |   2 +-
 14 files changed, 243 insertions(+), 177 deletions(-)

diff --git a/gcc/d/modules.cc b/gcc/d/modules.cc
index 742a24ff0bb..4e3fda53e7e 100644
--- a/gcc/d/modules.cc
+++ b/gcc/d/modules.cc
@@ -173,6 +173,7 @@ build_internal_fn (tree ident, tree expr)
   TREE_PUBLIC (decl) = 0;
   TREE_USED (decl) = 1;
   DECL_ARTIFICIAL (decl) = 1;
+  DECL_WEAK (decl) = 0;
 
   return decl;
 }
diff --git a/libphobos/configure b/libphobos/configure
index 77a3125cbd6..fb624b6f8e5 100755
--- a/libphobos/configure
+++ b/libphobos/configure
@@ -14381,6 +14381,8 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
 
 
+
+
   ac_ext=c
 ac_cpp='$CPP $CPPFLAGS'
 ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -14389,17 +14391,29 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for minfo section bracketing" >&5
 $as_echo_n "checking for minfo section bracketing... " >&6; }
+  case "$druntime_cv_target_os" in
+      darwin*)
+       section="__DATA,__minfodata"
+       start="section\$start\$__DATA\$__minfodata"
+       stop="section\$end\$__DATA\$__minfodata"
+        ;;
+      *)
+       section="minfo"
+       start="__start_minfo"
+       stop="__stop_minfo"
+       ;;
+  esac
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
-    void* module_info_ptr __attribute__((section ("minfo")));
-    extern void* __start_minfo __attribute__((visibility ("hidden")));
-    extern void* __stop_minfo __attribute__((visibility ("hidden")));
+    void* module_info_ptr __attribute__((section ("$section")));
+    extern void* start_minfo __asm__("$start") __attribute__((visibility ("hidden")));
+    extern void* stop_minfo __asm__("$stop") __attribute__((visibility ("hidden")));
 
     int main()
     {
         // Never run, just to prevent compiler from optimizing access
-        return &__start_minfo == &__stop_minfo;
+        return (int)(&stop_minfo - &start_minfo);
     }
 
 _ACEOF
diff --git a/libphobos/libdruntime/Makefile.in b/libphobos/libdruntime/Makefile.in
index 99ee8b92afa..b14b3c159cf 100644
--- a/libphobos/libdruntime/Makefile.in
+++ b/libphobos/libdruntime/Makefile.in
@@ -1195,6 +1195,7 @@ gcc/sections/$(am__dirstamp):
 	@$(MKDIR_P) gcc/sections
 	@: > gcc/sections/$(am__dirstamp)
 gcc/sections/android.lo: gcc/sections/$(am__dirstamp)
+gcc/sections/common.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)
diff --git a/libphobos/libdruntime/config/x86/switchcontext.S b/libphobos/libdruntime/config/x86/switchcontext.S
index f2f8efa218e..66c81f8b37a 100644
--- a/libphobos/libdruntime/config/x86/switchcontext.S
+++ b/libphobos/libdruntime/config/x86/switchcontext.S
@@ -33,7 +33,9 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 
     .text
     .globl CSYM(fiber_switchContext)
+#if defined(__ELF__)
     .type CSYM(fiber_switchContext), @function
+#endif
     .align 16
 CSYM(fiber_switchContext):
     .cfi_startproc
@@ -61,13 +63,17 @@ CSYM(fiber_switchContext):
     // 'return' to complete switch
     ret
     .cfi_endproc
+#if defined(__ELF__)
     .size CSYM(fiber_switchContext),.-CSYM(fiber_switchContext)
+#endif
 
 #elif defined(__x86_64__) && !defined(__ILP32__) && !defined(__CET__)
 
     .text
     .globl CSYM(fiber_switchContext)
+#if defined(__ELF__)
     .type CSYM(fiber_switchContext), @function
+#endif
     .align 16
 CSYM(fiber_switchContext):
     .cfi_startproc
@@ -96,6 +102,8 @@ CSYM(fiber_switchContext):
     // 'return' to complete switch
     ret
     .cfi_endproc
+#if defined(__ELF__)
    .size CSYM(fiber_switchContext),.-CSYM(fiber_switchContext)
+#endif
 
 #endif
diff --git a/libphobos/libdruntime/gcc/deh.d b/libphobos/libdruntime/gcc/deh.d
index 3e78a6c9c0e..bb2035f5155 100644
--- a/libphobos/libdruntime/gcc/deh.d
+++ b/libphobos/libdruntime/gcc/deh.d
@@ -34,11 +34,6 @@ extern(C)
 {
     int _d_isbaseof(ClassInfo, ClassInfo);
     void _d_createTrace(Object, void*);
-
-    // Not used in GDC but declaration required by rt/sections.d
-    struct FuncTable
-    {
-    }
 }
 
 /**
diff --git a/libphobos/libdruntime/gcc/sections/android.d b/libphobos/libdruntime/gcc/sections/android.d
index 2180a0b2514..51f5d24c2cb 100644
--- a/libphobos/libdruntime/gcc/sections/android.d
+++ b/libphobos/libdruntime/gcc/sections/android.d
@@ -54,13 +54,6 @@ struct SectionGroup
         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[];
diff --git a/libphobos/libdruntime/gcc/sections/common.d b/libphobos/libdruntime/gcc/sections/common.d
new file mode 100644
index 00000000000..b2d2322347d
--- /dev/null
+++ b/libphobos/libdruntime/gcc/sections/common.d
@@ -0,0 +1,48 @@
+// Common support routines 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.common;
+
+/****
+ * 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.).
+ */
+void safeAssert(bool condition, scope string msg, size_t line = __LINE__) @nogc nothrow @safe
+{
+    import core.internal.abort;
+    condition || abort(msg, __FILE__, line);
+}
+
+/****
+ * 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]; }
diff --git a/libphobos/libdruntime/gcc/sections/elf_shared.d b/libphobos/libdruntime/gcc/sections/elf_shared.d
index 59e2dd60a1f..3fb1b491f88 100644
--- a/libphobos/libdruntime/gcc/sections/elf_shared.d
+++ b/libphobos/libdruntime/gcc/sections/elf_shared.d
@@ -132,11 +132,6 @@ struct DSO
         return _moduleGroup;
     }
 
-    @property immutable(FuncTable)[] ehTables() const nothrow @nogc
-    {
-        return null;
-    }
-
     @property inout(void[])[] gcRanges() inout nothrow @nogc
     {
         return _gcRanges[];
@@ -383,12 +378,6 @@ version (Shared)
      */
     __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
 {
diff --git a/libphobos/libdruntime/gcc/sections/osx.d b/libphobos/libdruntime/gcc/sections/osx.d
index cb02b452404..6ace2da4a8b 100644
--- a/libphobos/libdruntime/gcc/sections/osx.d
+++ b/libphobos/libdruntime/gcc/sections/osx.d
@@ -24,25 +24,38 @@ 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 gcc.sections.common;
+
+import core.stdc.stdlib;
 import core.sys.darwin.mach.dyld;
 import core.sys.darwin.mach.getsect;
-import rt.deh, rt.minfo;
+import rt.minfo;
 import rt.util.container.array;
 
-struct SectionGroup
+version (GNU_EMUTLS)
+    import gcc.emutls;
+
+alias DSO SectionGroup;
+struct DSO
 {
-    static int opApply(scope int delegate(ref SectionGroup) dg)
+    static int opApply(scope int delegate(ref DSO) dg)
     {
-        return dg(_sections);
+        foreach (dso; _loadedDSOs)
+        {
+            if (auto res = dg(*dso))
+                return res;
+        }
+        return 0;
     }
 
-    static int opApplyReverse(scope int delegate(ref SectionGroup) dg)
+    static int opApplyReverse(scope int delegate(ref DSO) dg)
     {
-        return dg(_sections);
+        foreach_reverse (dso; _loadedDSOs)
+        {
+            if (auto res = dg(*dso))
+                return res;
+        }
+        return 0;
     }
 
     @property immutable(ModuleInfo*)[] modules() const nothrow @nogc
@@ -60,16 +73,9 @@ struct SectionGroup
         return _gcRanges[];
     }
 
-    @property immutable(FuncTable)[] ehTables() const nothrow @nogc
-    {
-        return _ehTables[];
-    }
-
 private:
-    immutable(FuncTable)[] _ehTables;
     ModuleGroup _moduleGroup;
     Array!(void[]) _gcRanges;
-    immutable(void)[][2] _tlsImage;
 }
 
 /****
@@ -82,8 +88,6 @@ __gshared bool _isRuntimeInitialized;
  */
 void initSections() nothrow @nogc
 {
-    pthread_key_create(&_tlsKey, null);
-    _dyld_register_func_for_add_image(&sections_osx_onAddImage);
     _isRuntimeInitialized = true;
 }
 
@@ -92,160 +96,161 @@ void initSections() nothrow @nogc
  */
 void finiSections() nothrow @nogc
 {
-    _sections._gcRanges.reset();
-    pthread_key_delete(_tlsKey);
     _isRuntimeInitialized = false;
 }
 
 void[]* initTLSRanges() nothrow @nogc
 {
-    return &getTLSBlock();
+    return null;
 }
 
 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);
+    version (GNU_EMUTLS)
+        _d_emutls_scan(dg);
+    else
+        static assert(0, "Native TLS unimplemented");
 }
 
-// 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 )
+version (Shared)
 {
-    immutable off = tlsOffset(p);
-    auto tls = getTLSBlockAlloc();
-    assert(off < tls.length);
-    return tls.ptr + off;
-}
-
-private:
+    // interface for core.thread to inherit loaded libraries
+    void* pinLoadedLibraries() nothrow @nogc
+    {
+        return null;
+    }
 
-__gshared pthread_key_t _tlsKey;
+    void unpinLoadedLibraries(void* p) nothrow @nogc
+    {
+    }
 
-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)
+    // Called before TLS ctors are ran, copy over the loaded libraries
+    // of the parent thread.
+    void inheritLoadedLibraries(void* p) nothrow @nogc
     {
-        return off0;
     }
-    immutable off1 = cast(size_t)(p - _sections._tlsImage[1].ptr);
-    if (off1 < _sections._tlsImage[1].length)
+
+    // Called after all TLS dtors ran, decrements all remaining dlopen refs.
+    void cleanupLoadedLibraries() nothrow @nogc
     {
-        size_t sz = (_sections._tlsImage[0].length + 15) & ~cast(size_t)15;
-        return sz + off1;
     }
-    assert(0);
 }
 
-ref void[] getTLSBlock() nothrow @nogc
+private:
+
+/*
+ * Static DSOs loaded by the runtime linker. This includes the
+ * executable. These can't be unloaded.
+ */
+@property ref Array!(DSO*) _loadedDSOs() @nogc nothrow
 {
-    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;
+    __gshared Array!(DSO*) x;
+    return x;
 }
 
-ref void[] getTLSBlockAlloc()
+/*
+ * Set to true during rt_loadLibrary/rt_unloadLibrary calls.
+ */
+enum _rtLoading = false;
+
+struct MachHeader
 {
-    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;
+    const(mach_header)* header; // the mach header of the image
+    intptr_t slide;             // virtural memory address slide amount
 }
 
-__gshared SectionGroup _sections;
+///////////////////////////////////////////////////////////////////////////////
+// Compiler to runtime interface.
+///////////////////////////////////////////////////////////////////////////////
 
-extern (C) void sections_osx_onAddImage(in mach_header* h, intptr_t slide)
+/* 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)
 {
-    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]);
-    }
+    // only one supported currently
+    safeAssert(data._version >= 1, "Incompatible compiler-generated DSO data version.");
 
-    auto minfosect = getSection(h, slide, "__DATA", "__minfodata");
-    if (minfosect != null)
+    // no backlink => register
+    if (*data._slot is 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)
+        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));
+
+        MachHeader info = void;
+        const headerFound = findDSOHeaderForAddr(data._slot, &info);
+        safeAssert(headerFound, "Failed to find image header.");
+
+        foreach (e; dataSegs)
         {
-            fprintf(stderr, "Shared libraries are not yet supported on OSX.\n");
+            auto sect = getSection(info.header, info.slide,
+                                   e.seg.ptr, e.sect.ptr);
+            if (sect != null)
+                pdso._gcRanges.insertBack((cast(void*)sect.ptr)[0 .. sect.length]);
         }
 
-        debug(PRINTF) printf("  minfodata\n");
-        auto p = cast(immutable(ModuleInfo*)*)minfosect.ptr;
-        immutable len = minfosect.length / (*p).sizeof;
-
-        _sections._moduleGroup = ModuleGroup(p[0 .. len]);
+        foreach (p; _loadedDSOs)
+            safeAssert(p !is pdso, "DSO already registered.");
+        _loadedDSOs.insertBack(pdso);
     }
-
-    auto ehsect = getSection(h, slide, "__DATA", "__deh_eh");
-    if (ehsect != null)
+    // has backlink => unregister
+    else
     {
-        debug(PRINTF) printf("  deh_eh\n");
-        auto p = cast(immutable(FuncTable)*)ehsect.ptr;
-        immutable len = ehsect.length / (*p).sizeof;
+        DSO* pdso = cast(DSO*)*data._slot;
+        *data._slot = null;
 
-        _sections._ehTables = p[0 .. len];
-    }
+        // static DSOs are unloaded in reverse order
+        safeAssert(pdso == _loadedDSOs.back, "DSO being unregistered isn't current last one.");
+        _loadedDSOs.popBack();
 
-    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];
+        pdso._gcRanges.reset();
+        .free(pdso);
+
+        // last DSO being unloaded => shutdown registry
+        if (_loadedDSOs.empty)
+        {
+            version (GNU_EMUTLS)
+                _d_emutls_destroy();
+        }
     }
+}
+
+/**************************
+ * Input:
+ *      result where the output is to be written
+ * Returns:
+ *      true if found, and *result is filled in
+ */
 
-    auto tlssect2 = getSection(h, slide, "__DATA", "__tlscoal_nt");
-    if (tlssect2 != null)
+bool findDSOHeaderForAddr(in void* addr, MachHeader* result)
+{
+    foreach (i; 0 .. _dyld_image_count())
     {
-        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];
+        const header = _dyld_get_image_header(i);
+        const slide = _dyld_get_image_vmaddr_slide(i);
+        const section = getSection(header, slide, SEG_DATA, SECT_DATA);
+
+        // less than base address of section means quick reject
+        if (!section.length || addr < section.ptr)
+           continue;
+
+        if (addr < section.ptr + section.length)
+        {
+            result.header = header;
+            result.slide = slide;
+            return true;
+        }
     }
+    return false;
 }
 
 struct SegRef
@@ -258,25 +263,27 @@ static immutable SegRef[] dataSegs = [{SEG_DATA, SECT_DATA},
                                       {SEG_DATA, SECT_BSS},
                                       {SEG_DATA, SECT_COMMON}];
 
+/**
+ * Returns the section for the named section in the named segment
+ * for the mach_header pointer passed, or null if not found.
+ */
 ubyte[] getSection(in mach_header* header, intptr_t slide,
                    in char* segmentName, in char* sectionName)
 {
-    version (X86)
+    version (D_LP64)
     {
-        assert(header.magic == MH_MAGIC);
-        auto sect = getsectbynamefromheader(header,
+        assert(header.magic == MH_MAGIC_64);
+        auto sect = getsectbynamefromheader_64(cast(mach_header_64*)header,
                                             segmentName,
                                             sectionName);
     }
-    else version (X86_64)
+    else
     {
-        assert(header.magic == MH_MAGIC_64);
-        auto sect = getsectbynamefromheader_64(cast(mach_header_64*)header,
+        assert(header.magic == MH_MAGIC);
+        auto sect = getsectbynamefromheader(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];
diff --git a/libphobos/libdruntime/gcc/sections/win64.d b/libphobos/libdruntime/gcc/sections/win64.d
index 1a4ee989cec..8362a6ffa23 100644
--- a/libphobos/libdruntime/gcc/sections/win64.d
+++ b/libphobos/libdruntime/gcc/sections/win64.d
@@ -51,14 +51,6 @@ struct SectionGroup
         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[];
diff --git a/libphobos/m4/druntime/os.m4 b/libphobos/m4/druntime/os.m4
index ed93e30f1e9..7f90374dbd5 100644
--- a/libphobos/m4/druntime/os.m4
+++ b/libphobos/m4/druntime/os.m4
@@ -149,17 +149,31 @@ AC_DEFUN([DRUNTIME_OS_ARM_EABI_UNWINDER],
 # substitute DCFG_MINFO_BRACKETING.
 AC_DEFUN([DRUNTIME_OS_MINFO_BRACKETING],
 [
+  AC_REQUIRE([DRUNTIME_OS_DETECT])
+
   AC_LANG_PUSH([C])
   AC_MSG_CHECKING([for minfo section bracketing])
+  case "$druntime_cv_target_os" in
+      darwin*)
+       section="__DATA,__minfodata"
+       start="section\$start\$__DATA\$__minfodata"
+       stop="section\$end\$__DATA\$__minfodata"
+        ;;
+      *)
+       section="minfo"
+       start="__start_minfo"
+       stop="__stop_minfo"
+       ;;
+  esac
   AC_LINK_IFELSE([AC_LANG_SOURCE([
-    void* module_info_ptr __attribute__((section ("minfo")));
-    extern void* __start_minfo __attribute__((visibility ("hidden")));
-    extern void* __stop_minfo __attribute__((visibility ("hidden")));
+    void* module_info_ptr __attribute__((section ("$section")));
+    extern void* start_minfo __asm__("$start") __attribute__((visibility ("hidden")));
+    extern void* stop_minfo __asm__("$stop") __attribute__((visibility ("hidden")));
 
     int main()
     {
         // Never run, just to prevent compiler from optimizing access
-        return &__start_minfo == &__stop_minfo;
+        return (int)(&stop_minfo - &start_minfo);
     }
   ])],
     [AC_MSG_RESULT([yes])
diff --git a/libphobos/testsuite/lib/libphobos.exp b/libphobos/testsuite/lib/libphobos.exp
index 790480bf95c..3b43f0182a7 100644
--- a/libphobos/testsuite/lib/libphobos.exp
+++ b/libphobos/testsuite/lib/libphobos.exp
@@ -90,6 +90,10 @@ proc libphobos-dg-test { prog do_what extra_tool_flags } {
 }
 
 proc libphobos-dg-prune { system text } {
+
+    # Ignore warnings from cctools.
+    regsub -all "(^|\n)clang: warning: argument unused during compilation:\[^\n\]*" $text "" text
+
     return $text
 }
 
diff --git a/libphobos/testsuite/libphobos.druntime/druntime.exp b/libphobos/testsuite/libphobos.druntime/druntime.exp
index 7072ebb1c9f..a157329c916 100644
--- a/libphobos/testsuite/libphobos.druntime/druntime.exp
+++ b/libphobos/testsuite/libphobos.druntime/druntime.exp
@@ -15,7 +15,7 @@
 # <http://www.gnu.org/licenses/>.
 
 # Immediately exit if we can't run target executables.
-if { ![isnative] || ![is-effective-target static] } {
+if { ![isnative] } {
     return
 }
 
diff --git a/libphobos/testsuite/libphobos.phobos/phobos.exp b/libphobos/testsuite/libphobos.phobos/phobos.exp
index aad877c24c2..45c48ce7324 100644
--- a/libphobos/testsuite/libphobos.phobos/phobos.exp
+++ b/libphobos/testsuite/libphobos.phobos/phobos.exp
@@ -15,7 +15,7 @@
 # <http://www.gnu.org/licenses/>.
 
 # Immediately exit if we can't run target executables.
-if { ![isnative] || ![is-effective-target static] } {
+if { ![isnative] } {
     return
 }


^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2021-09-17 14:33 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-04-19 18:05 [gcc(refs/users/ibuclaw/heads/darwin)] libphobos: Checkpoint in darwin runtime support Iain Buclaw
  -- strict thread matches above, loose matches on Subject: below --
2021-09-17 14:33 Iain Buclaw
2021-04-10 17:00 Iain Buclaw
2021-04-10 15:04 Iain Buclaw
2021-03-14 22:00 Iain Buclaw
2021-03-07 17:01 Iain Buclaw
2021-01-30 19:08 Iain Buclaw
2021-01-28 17:31 Iain Buclaw
2021-01-11 11:39 Iain Buclaw
2020-12-22 13:40 Iain Buclaw
2020-12-09  9:50 Iain Buclaw
2020-12-05 23:47 Iain Buclaw
2020-12-03 22:57 Iain Buclaw
2020-11-30 14:38 Iain Buclaw
2020-11-29 13:45 Iain Buclaw

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).