public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc(refs/users/iains/heads/d-for-darwin)] libphobos: Align interface of gcc.sections.osx with gcc.sections.elf_shared
@ 2021-10-15 19:33 Iain D Sandoe
  0 siblings, 0 replies; 6+ messages in thread
From: Iain D Sandoe @ 2021-10-15 19:33 UTC (permalink / raw)
  To: gcc-cvs

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

commit b0953941dcd9a7833b42f9a61512959a221fced9
Author: Iain Buclaw <ibuclaw@gdcproject.org>
Date:   Mon Dec 7 01:25:17 2020 +0100

    libphobos: Align interface of gcc.sections.osx with gcc.sections.elf_shared

Diff:
---
 libphobos/libdruntime/core/sys/darwin/execinfo.d | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/libphobos/libdruntime/core/sys/darwin/execinfo.d b/libphobos/libdruntime/core/sys/darwin/execinfo.d
index c929cc2f88d..d9607f392eb 100644
--- a/libphobos/libdruntime/core/sys/darwin/execinfo.d
+++ b/libphobos/libdruntime/core/sys/darwin/execinfo.d
@@ -21,6 +21,11 @@ extern (C):
 nothrow:
 @nogc:
 
-int backtrace(void** buffer, int size);
-char** backtrace_symbols(const(void*)* buffer, int size);
-void backtrace_symbols_fd(const(void*)* buffer, int size, int fd);
+import core.sys.darwin.config;
+
+static if (__traits(getTargetInfo, "osxVersionMin") >= __MAC_10_5)
+{
+    int backtrace(void** buffer, int size);
+    char** backtrace_symbols(const(void*)* buffer, int size);
+    void backtrace_symbols_fd(const(void*)* buffer, int size, int fd);
+}


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

* [gcc(refs/users/iains/heads/d-for-darwin)] libphobos: Align interface of gcc.sections.osx with gcc.sections.elf_shared
@ 2021-10-18 15:54 Iain D Sandoe
  0 siblings, 0 replies; 6+ messages in thread
From: Iain D Sandoe @ 2021-10-18 15:54 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:95652536ebaa11398dd54fcb4f9572923bddaa62

commit 95652536ebaa11398dd54fcb4f9572923bddaa62
Author: Iain Buclaw <ibuclaw@gdcproject.org>
Date:   Mon Dec 7 01:25:17 2020 +0100

    libphobos: Align interface of gcc.sections.osx with gcc.sections.elf_shared

Diff:
---
 libphobos/libdruntime/core/sys/darwin/execinfo.d | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/libphobos/libdruntime/core/sys/darwin/execinfo.d b/libphobos/libdruntime/core/sys/darwin/execinfo.d
index c929cc2f88d..d9607f392eb 100644
--- a/libphobos/libdruntime/core/sys/darwin/execinfo.d
+++ b/libphobos/libdruntime/core/sys/darwin/execinfo.d
@@ -21,6 +21,11 @@ extern (C):
 nothrow:
 @nogc:
 
-int backtrace(void** buffer, int size);
-char** backtrace_symbols(const(void*)* buffer, int size);
-void backtrace_symbols_fd(const(void*)* buffer, int size, int fd);
+import core.sys.darwin.config;
+
+static if (__traits(getTargetInfo, "osxVersionMin") >= __MAC_10_5)
+{
+    int backtrace(void** buffer, int size);
+    char** backtrace_symbols(const(void*)* buffer, int size);
+    void backtrace_symbols_fd(const(void*)* buffer, int size, int fd);
+}


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

* [gcc(refs/users/iains/heads/d-for-darwin)] libphobos: Align interface of gcc.sections.osx with gcc.sections.elf_shared
@ 2021-10-13  8:30 Iain D Sandoe
  0 siblings, 0 replies; 6+ messages in thread
From: Iain D Sandoe @ 2021-10-13  8:30 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:97d81400cd87690d429a2444fb50c75b6d153147

commit 97d81400cd87690d429a2444fb50c75b6d153147
Author: Iain Buclaw <ibuclaw@gdcproject.org>
Date:   Mon Dec 7 01:25:17 2020 +0100

    libphobos: Align interface of gcc.sections.osx with gcc.sections.elf_shared

Diff:
---
 libphobos/libdruntime/core/sys/darwin/execinfo.d | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/libphobos/libdruntime/core/sys/darwin/execinfo.d b/libphobos/libdruntime/core/sys/darwin/execinfo.d
index c929cc2f88d..d9607f392eb 100644
--- a/libphobos/libdruntime/core/sys/darwin/execinfo.d
+++ b/libphobos/libdruntime/core/sys/darwin/execinfo.d
@@ -21,6 +21,11 @@ extern (C):
 nothrow:
 @nogc:
 
-int backtrace(void** buffer, int size);
-char** backtrace_symbols(const(void*)* buffer, int size);
-void backtrace_symbols_fd(const(void*)* buffer, int size, int fd);
+import core.sys.darwin.config;
+
+static if (__traits(getTargetInfo, "osxVersionMin") >= __MAC_10_5)
+{
+    int backtrace(void** buffer, int size);
+    char** backtrace_symbols(const(void*)* buffer, int size);
+    void backtrace_symbols_fd(const(void*)* buffer, int size, int fd);
+}


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

* [gcc(refs/users/iains/heads/d-for-darwin)] libphobos: Align interface of gcc.sections.osx with gcc.sections.elf_shared
@ 2021-10-11 20:35 Iain D Sandoe
  0 siblings, 0 replies; 6+ messages in thread
From: Iain D Sandoe @ 2021-10-11 20:35 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:28c4bfaa1c184b9b661c26c312717b422d70290f

commit 28c4bfaa1c184b9b661c26c312717b422d70290f
Author: Iain Buclaw <ibuclaw@gdcproject.org>
Date:   Mon Dec 7 01:25:17 2020 +0100

    libphobos: Align interface of gcc.sections.osx with gcc.sections.elf_shared

Diff:
---
 libphobos/libdruntime/core/sys/darwin/execinfo.d | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/libphobos/libdruntime/core/sys/darwin/execinfo.d b/libphobos/libdruntime/core/sys/darwin/execinfo.d
index c929cc2f88d..d9607f392eb 100644
--- a/libphobos/libdruntime/core/sys/darwin/execinfo.d
+++ b/libphobos/libdruntime/core/sys/darwin/execinfo.d
@@ -21,6 +21,11 @@ extern (C):
 nothrow:
 @nogc:
 
-int backtrace(void** buffer, int size);
-char** backtrace_symbols(const(void*)* buffer, int size);
-void backtrace_symbols_fd(const(void*)* buffer, int size, int fd);
+import core.sys.darwin.config;
+
+static if (__traits(getTargetInfo, "osxVersionMin") >= __MAC_10_5)
+{
+    int backtrace(void** buffer, int size);
+    char** backtrace_symbols(const(void*)* buffer, int size);
+    void backtrace_symbols_fd(const(void*)* buffer, int size, int fd);
+}


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

* [gcc(refs/users/iains/heads/d-for-darwin)] libphobos: Align interface of gcc.sections.osx with gcc.sections.elf_shared
@ 2020-12-21 20:36 Iain D Sandoe
  0 siblings, 0 replies; 6+ messages in thread
From: Iain D Sandoe @ 2020-12-21 20:36 UTC (permalink / raw)
  To: gcc-cvs

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

commit 9e38b3df1aefae86530ee6726b568af2985be663
Author: Iain Buclaw <ibuclaw@gdcproject.org>
Date:   Mon Dec 7 01:25:17 2020 +0100

    libphobos: Align interface of gcc.sections.osx with gcc.sections.elf_shared

Diff:
---
 libphobos/libdruntime/Makefile.am                |  30 +-
 libphobos/libdruntime/Makefile.in                |  64 +--
 libphobos/libdruntime/core/sys/darwin/execinfo.d |  11 +-
 libphobos/libdruntime/gcc/sections/common.d      |  48 --
 libphobos/libdruntime/gcc/sections/osx.d         | 569 ++++++++++++++++++++---
 5 files changed, 565 insertions(+), 157 deletions(-)

diff --git a/libphobos/libdruntime/Makefile.am b/libphobos/libdruntime/Makefile.am
index 124d5b049d0..722f1edfe09 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/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 \
+	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 3bf08f52b31..d99998d8934 100644
--- a/libphobos/libdruntime/Makefile.in
+++ b/libphobos/libdruntime/Makefile.in
@@ -207,10 +207,9 @@ 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/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/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/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 \
@@ -268,9 +267,10 @@ am__objects_3 = core/sys/posix/aio.lo core/sys/posix/arpa/inet.lo \
 	core/sys/posix/time.lo core/sys/posix/ucontext.lo \
 	core/sys/posix/unistd.lo core/sys/posix/utime.lo
 @DRUNTIME_OS_POSIX_TRUE@am__objects_4 = $(am__objects_3)
-am__objects_5 = core/sys/darwin/crt_externs.lo \
-	core/sys/darwin/dlfcn.lo core/sys/darwin/execinfo.lo \
-	core/sys/darwin/mach/dyld.lo core/sys/darwin/mach/getsect.lo \
+am__objects_5 = core/sys/darwin/config.lo \
+	core/sys/darwin/crt_externs.lo core/sys/darwin/dlfcn.lo \
+	core/sys/darwin/execinfo.lo core/sys/darwin/mach/dyld.lo \
+	core/sys/darwin/mach/getsect.lo \
 	core/sys/darwin/mach/kern_return.lo \
 	core/sys/darwin/mach/loader.lo core/sys/darwin/mach/port.lo \
 	core/sys/darwin/mach/semaphore.lo \
@@ -809,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/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 \
+	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 \
@@ -841,15 +841,15 @@ DRUNTIME_DSOURCES_STDCXX = core/stdcpp/exception.d \
 DRUNTIME_DSOURCES_BIONIC = core/sys/bionic/fcntl.d \
 	core/sys/bionic/string.d core/sys/bionic/unistd.d
 
-DRUNTIME_DSOURCES_DARWIN = core/sys/darwin/crt_externs.d \
-	core/sys/darwin/dlfcn.d core/sys/darwin/execinfo.d \
-	core/sys/darwin/mach/dyld.d core/sys/darwin/mach/getsect.d \
-	core/sys/darwin/mach/kern_return.d core/sys/darwin/mach/loader.d \
-	core/sys/darwin/mach/port.d core/sys/darwin/mach/semaphore.d \
-	core/sys/darwin/mach/thread_act.d core/sys/darwin/netinet/in_.d \
-	core/sys/darwin/pthread.d core/sys/darwin/string.d \
-	core/sys/darwin/sys/cdefs.d core/sys/darwin/sys/event.d \
-	core/sys/darwin/sys/mman.d
+DRUNTIME_DSOURCES_DARWIN = core/sys/darwin/config.d \
+	core/sys/darwin/crt_externs.d core/sys/darwin/dlfcn.d \
+	core/sys/darwin/execinfo.d core/sys/darwin/mach/dyld.d \
+	core/sys/darwin/mach/getsect.d core/sys/darwin/mach/kern_return.d \
+	core/sys/darwin/mach/loader.d core/sys/darwin/mach/port.d \
+	core/sys/darwin/mach/semaphore.d core/sys/darwin/mach/thread_act.d \
+	core/sys/darwin/netinet/in_.d core/sys/darwin/pthread.d \
+	core/sys/darwin/string.d core/sys/darwin/sys/cdefs.d \
+	core/sys/darwin/sys/event.d core/sys/darwin/sys/mman.d
 
 DRUNTIME_DSOURCES_DRAGONFLYBSD = core/sys/dragonflybsd/dlfcn.d \
 	core/sys/dragonflybsd/execinfo.d core/sys/dragonflybsd/netinet/in_.d \
@@ -1196,7 +1196,6 @@ 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)
@@ -1359,6 +1358,7 @@ core/sys/posix/utime.lo: core/sys/posix/$(am__dirstamp)
 core/sys/darwin/$(am__dirstamp):
 	@$(MKDIR_P) core/sys/darwin
 	@: > core/sys/darwin/$(am__dirstamp)
+core/sys/darwin/config.lo: core/sys/darwin/$(am__dirstamp)
 core/sys/darwin/crt_externs.lo: core/sys/darwin/$(am__dirstamp)
 core/sys/darwin/dlfcn.lo: core/sys/darwin/$(am__dirstamp)
 core/sys/darwin/execinfo.lo: core/sys/darwin/$(am__dirstamp)
diff --git a/libphobos/libdruntime/core/sys/darwin/execinfo.d b/libphobos/libdruntime/core/sys/darwin/execinfo.d
index c929cc2f88d..d9607f392eb 100644
--- a/libphobos/libdruntime/core/sys/darwin/execinfo.d
+++ b/libphobos/libdruntime/core/sys/darwin/execinfo.d
@@ -21,6 +21,11 @@ extern (C):
 nothrow:
 @nogc:
 
-int backtrace(void** buffer, int size);
-char** backtrace_symbols(const(void*)* buffer, int size);
-void backtrace_symbols_fd(const(void*)* buffer, int size, int fd);
+import core.sys.darwin.config;
+
+static if (__traits(getTargetInfo, "osxVersionMin") >= __MAC_10_5)
+{
+    int backtrace(void** buffer, int size);
+    char** backtrace_symbols(const(void*)* buffer, int size);
+    void backtrace_symbols_fd(const(void*)* buffer, int size, int fd);
+}
diff --git a/libphobos/libdruntime/gcc/sections/common.d b/libphobos/libdruntime/gcc/sections/common.d
deleted file mode 100644
index b2d2322347d..00000000000
--- a/libphobos/libdruntime/gcc/sections/common.d
+++ /dev/null
@@ -1,48 +0,0 @@
-// 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/osx.d b/libphobos/libdruntime/gcc/sections/osx.d
index 6ace2da4a8b..9ec5b79974e 100644
--- a/libphobos/libdruntime/gcc/sections/osx.d
+++ b/libphobos/libdruntime/gcc/sections/osx.d
@@ -24,17 +24,31 @@ module gcc.sections.osx;
 
 version (OSX):
 
-import gcc.sections.common;
-
+import core.memory;
 import core.stdc.stdlib;
+import core.sys.darwin.dlfcn;
 import core.sys.darwin.mach.dyld;
 import core.sys.darwin.mach.getsect;
+import core.sys.posix.pthread;
 import rt.minfo;
 import rt.util.container.array;
+import rt.util.container.hashtab;
 
 version (GNU_EMUTLS)
     import gcc.emutls;
 
+/****
+ * 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);
+}
+
 alias DSO SectionGroup;
 struct DSO
 {
@@ -74,8 +88,22 @@ struct DSO
     }
 
 private:
+
+    invariant()
+    {
+        safeAssert(_moduleGroup.modules.length > 0, "No modules for DSO.");
+    }
+
+    void** _slot;
     ModuleGroup _moduleGroup;
     Array!(void[]) _gcRanges;
+
+    version (Shared)
+    {
+        Array!(void[]) _codeSegments; // array of code segments
+        Array!(DSO*) _deps; // D libraries needed by this DSO
+        void* _handle; // corresponding handle
+    }
 }
 
 /****
@@ -99,63 +127,185 @@ void finiSections() nothrow @nogc
     _isRuntimeInitialized = false;
 }
 
-void[]* initTLSRanges() nothrow @nogc
-{
-    return null;
-}
+alias ScanDG = void delegate(void* pbeg, void* pend) nothrow;
 
-void finiTLSRanges(void[]* rng) nothrow @nogc
+version (Shared)
 {
-}
+    /***
+     * Called once per thread; returns array of thread local storage ranges
+     */
+    Array!(ThreadDSO)* initTLSRanges() @nogc nothrow
+    {
+        return &_loadedDSOs();
+    }
 
-void scanTLSRanges(void[]* rng, scope void delegate(void* pbeg, void* pend) nothrow dg) nothrow
-{
-    version (GNU_EMUTLS)
-        _d_emutls_scan(dg);
-    else
-        static assert(0, "Native TLS unimplemented");
-}
+    void finiTLSRanges(Array!(ThreadDSO)* tdsos) @nogc nothrow
+    {
+        // Nothing to do here. tdsos used to point to the _loadedDSOs instance
+        // in the dying thread's TLS segment and as such is not valid anymore.
+        // The memory for the array contents was already reclaimed in
+        // cleanupLoadedLibraries().
+    }
+
+    void scanTLSRanges(Array!(ThreadDSO)* tdsos, scope ScanDG dg) nothrow
+    {
+        version (GNU_EMUTLS)
+            _d_emutls_scan(dg);
+        else
+            static assert(0, "Native TLS unimplemented");
+    }
 
-version (Shared)
-{
     // interface for core.thread to inherit loaded libraries
     void* pinLoadedLibraries() nothrow @nogc
     {
-        return null;
+        auto res = cast(Array!(ThreadDSO)*)calloc(1, Array!(ThreadDSO).sizeof);
+        res.length = _loadedDSOs.length;
+        foreach (i, ref tdso; _loadedDSOs)
+        {
+            (*res)[i] = tdso;
+            if (tdso._addCnt)
+            {
+                // Increment the dlopen ref for explicitly loaded libraries to pin them.
+                const success = .dlopen(nameForDSO(tdso._pdso), RTLD_LAZY) !is null;
+                safeAssert(success, "Failed to increment dlopen ref.");
+                (*res)[i]._addCnt = 1; // new array takes over the additional ref count
+            }
+        }
+        return res;
     }
 
     void unpinLoadedLibraries(void* p) nothrow @nogc
     {
+        auto pary = cast(Array!(ThreadDSO)*)p;
+        // In case something failed we need to undo the pinning.
+        foreach (ref tdso; *pary)
+        {
+            if (tdso._addCnt)
+            {
+                auto handle = tdso._pdso._handle;
+                safeAssert(handle !is null, "Invalid library handle.");
+                .dlclose(handle);
+            }
+        }
+        pary.reset();
+        .free(pary);
     }
 
     // Called before TLS ctors are ran, copy over the loaded libraries
     // of the parent thread.
     void inheritLoadedLibraries(void* p) nothrow @nogc
     {
+        safeAssert(_loadedDSOs.empty, "DSOs have already been registered for this thread.");
+        _loadedDSOs.swap(*cast(Array!(ThreadDSO)*)p);
+        .free(p);
     }
 
     // Called after all TLS dtors ran, decrements all remaining dlopen refs.
     void cleanupLoadedLibraries() nothrow @nogc
     {
+        foreach (ref tdso; _loadedDSOs)
+        {
+            if (tdso._addCnt == 0) continue;
+
+            auto handle = tdso._pdso._handle;
+            safeAssert(handle !is null, "Invalid DSO handle.");
+            for (; tdso._addCnt > 0; --tdso._addCnt)
+                .dlclose(handle);
+        }
+
+        // Free the memory for the array contents.
+        _loadedDSOs.reset();
+    }
+}
+else
+{
+    /***
+     * Called once per thread; returns array of thread local storage ranges
+     */
+    Array!(void[])* initTLSRanges() nothrow @nogc
+    {
+        return null;
+    }
+
+    void finiTLSRanges(Array!(void[])* rngs) nothrow @nogc
+    {
+    }
+
+    void scanTLSRanges(Array!(void[])* rngs, scope ScanDG dg) nothrow
+    {
+        version (GNU_EMUTLS)
+            _d_emutls_scan(dg);
+        else
+            static assert(0, "Native TLS unimplemented");
     }
 }
 
 private:
 
-/*
- * Static DSOs loaded by the runtime linker. This includes the
- * executable. These can't be unloaded.
- */
-@property ref Array!(DSO*) _loadedDSOs() @nogc nothrow
+version (Shared)
 {
-    __gshared Array!(DSO*) x;
-    return x;
+    /*
+     * Array of thread local DSO metadata for all libraries loaded and
+     * initialized in this thread.
+     *
+     * Note:
+     *     A newly spawned thread will inherit these libraries.
+     * Note:
+     *     We use an array here to preserve the order of
+     *     initialization.  If that became a performance issue, we
+     *     could use a hash table and enumerate the DSOs during
+     *     loading so that the hash table values could be sorted when
+     *     necessary.
+     */
+    struct ThreadDSO
+    {
+        DSO* _pdso;
+        static if (_pdso.sizeof == 8) uint _refCnt, _addCnt;
+        else static if (_pdso.sizeof == 4) ushort _refCnt, _addCnt;
+        else static assert(0, "unimplemented");
+        alias _pdso this;
+    }
+
+    @property ref Array!(ThreadDSO) _loadedDSOs() @nogc nothrow
+    {
+        static Array!(ThreadDSO) x;
+        return x;
+    }
+
+    /*
+     * Set to true during rt_loadLibrary/rt_unloadLibrary calls.
+     */
+    bool _rtLoading;
+
+    /*
+     * Hash table to map the native handle (as returned by dlopen)
+     * to the corresponding DSO*, protected by a mutex.
+     */
+    __gshared pthread_mutex_t _handleToDSOMutex;
+    @property ref HashTab!(void*, DSO*) _handleToDSO() @nogc nothrow
+    {
+        __gshared HashTab!(void*, DSO*) x;
+        return x;
+    }
 }
+else
+{
+    /*
+     * Static DSOs loaded by the runtime linker. This includes the
+     * executable. These can't be unloaded.
+     */
+    @property ref Array!(DSO*) _loadedDSOs() @nogc nothrow
+    {
+        __gshared Array!(DSO*) x;
+        return x;
+    }
 
-/*
- * Set to true during rt_loadLibrary/rt_unloadLibrary calls.
- */
-enum _rtLoading = false;
+    enum _rtLoading = false;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Compiler to runtime interface.
+///////////////////////////////////////////////////////////////////////////////
 
 struct MachHeader
 {
@@ -163,9 +313,18 @@ struct MachHeader
     intptr_t slide;             // virtural memory address slide amount
 }
 
-///////////////////////////////////////////////////////////////////////////////
-// Compiler to runtime interface.
-///////////////////////////////////////////////////////////////////////////////
+/****
+ * This data structure is generated by the compiler, and then passed to
+ * _d_dso_registry().
+ */
+struct CompilerDSOData
+{
+    size_t _version;                                       // currently 1
+    void** _slot;                                          // can be used to store runtime data
+    immutable(object.ModuleInfo*)* _minfo_beg, _minfo_end; // array of modules in this object file
+}
+
+T[] toRange(T)(T* beg, T* end) { return beg[0 .. end - beg]; }
 
 /* For each shared library and executable, the compiler generates code that
  * sets up CompilerDSOData and calls _d_dso_registry().
@@ -180,27 +339,57 @@ extern(C) void _d_dso_registry(CompilerDSOData* data)
     // no backlink => register
     if (*data._slot is null)
     {
+        immutable firstDSO = _loadedDSOs.empty;
+        if (firstDSO) initLocks();
+
         DSO* pdso = cast(DSO*).calloc(1, DSO.sizeof);
         assert(typeid(DSO).initializer().ptr is null);
+        pdso._slot = data._slot;
         *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);
+        MachHeader header = void;
+        const headerFound = findImageHeaderForAddr(data._slot, header);
         safeAssert(headerFound, "Failed to find image header.");
 
-        foreach (e; dataSegs)
+        scanSegments(header, pdso);
+
+        version (Shared)
+        {
+            auto handle = handleForAddr(data._slot);
+
+            getDependencies(header, pdso._deps);
+            pdso._handle = handle;
+            setDSOForHandle(pdso, pdso._handle);
+
+            if (!_rtLoading)
+            {
+                /* This DSO was not loaded by rt_loadLibrary which
+                 * happens for all dependencies of an executable or
+                 * the first dlopen call from a C program.
+                 * In this case we add the DSO to the _loadedDSOs of this
+                 * thread with a refCnt of 1 and call the TlsCtors.
+                 */
+                immutable ushort refCnt = 1, addCnt = 0;
+                _loadedDSOs.insertBack(ThreadDSO(pdso, refCnt, addCnt));
+            }
+        }
+        else
         {
-            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]);
+            foreach (p; _loadedDSOs)
+                safeAssert(p !is pdso, "DSO already registered.");
+            _loadedDSOs.insertBack(pdso);
         }
 
-        foreach (p; _loadedDSOs)
-            safeAssert(p !is pdso, "DSO already registered.");
-        _loadedDSOs.insertBack(pdso);
+        // don't initialize modules before rt_init was called
+        if (_isRuntimeInitialized)
+        {
+            registerGCRanges(pdso);
+            // rt_loadLibrary will run tls ctors, so do this only for dlopen
+            immutable runTlsCtors = !_rtLoading;
+            runModuleConstructors(pdso, runTlsCtors);
+        }
     }
     // has backlink => unregister
     else
@@ -208,22 +397,274 @@ extern(C) void _d_dso_registry(CompilerDSOData* data)
         DSO* pdso = cast(DSO*)*data._slot;
         *data._slot = null;
 
-        // static DSOs are unloaded in reverse order
-        safeAssert(pdso == _loadedDSOs.back, "DSO being unregistered isn't current last one.");
-        _loadedDSOs.popBack();
+        // don't finalizes modules after rt_term was called (see Bugzilla 11378)
+        if (_isRuntimeInitialized)
+        {
+            // rt_unloadLibrary already ran tls dtors, so do this only for dlclose
+            immutable runTlsDtors = !_rtLoading;
+            runModuleDestructors(pdso, runTlsDtors);
+            unregisterGCRanges(pdso);
+            // run finalizers after module dtors (same order as in rt_term)
+            version (Shared) runFinalizers(pdso);
+        }
+
+        version (Shared)
+        {
+            if (!_rtLoading)
+            {
+                /* This DSO was not unloaded by rt_unloadLibrary so we
+                 * have to remove it from _loadedDSOs here.
+                 */
+                foreach (i, ref tdso; _loadedDSOs)
+                {
+                    if (tdso._pdso == pdso)
+                    {
+                        _loadedDSOs.remove(i);
+                        break;
+                    }
+                }
+            }
+
+            unsetDSOForHandle(pdso, pdso._handle);
+        }
+        else
+        {
+            // static DSOs are unloaded in reverse order
+            safeAssert(pdso == _loadedDSOs.back, "DSO being unregistered isn't current last one.");
+            _loadedDSOs.popBack();
+        }
 
-        pdso._gcRanges.reset();
-        .free(pdso);
+        freeDSO(pdso);
 
         // last DSO being unloaded => shutdown registry
         if (_loadedDSOs.empty)
         {
             version (GNU_EMUTLS)
                 _d_emutls_destroy();
+            version (Shared)
+            {
+                safeAssert(_handleToDSO.empty, "_handleToDSO not in sync with _loadedDSOs.");
+                _handleToDSO.reset();
+            }
+            finiLocks();
         }
     }
 }
 
+///////////////////////////////////////////////////////////////////////////////
+// dynamic loading
+///////////////////////////////////////////////////////////////////////////////
+
+// Shared D libraries are only supported when linking against a shared druntime library.
+
+version (Shared)
+{
+    ThreadDSO* findThreadDSO(DSO* pdso) nothrow @nogc
+    {
+        foreach (ref tdata; _loadedDSOs)
+            if (tdata._pdso == pdso) return &tdata;
+        return null;
+    }
+
+    void incThreadRef(DSO* pdso, bool incAdd)
+    {
+        if (auto tdata = findThreadDSO(pdso)) // already initialized
+        {
+            if (incAdd && ++tdata._addCnt > 1) return;
+            ++tdata._refCnt;
+        }
+        else
+        {
+            foreach (dep; pdso._deps)
+                incThreadRef(dep, false);
+            immutable ushort refCnt = 1, addCnt = incAdd ? 1 : 0;
+            _loadedDSOs.insertBack(ThreadDSO(pdso, refCnt, addCnt));
+            pdso._moduleGroup.runTlsCtors();
+        }
+    }
+
+    void decThreadRef(DSO* pdso, bool decAdd)
+    {
+        auto tdata = findThreadDSO(pdso);
+        safeAssert(tdata !is null, "Failed to find thread DSO.");
+        safeAssert(!decAdd || tdata._addCnt > 0, "Mismatching rt_unloadLibrary call.");
+
+        if (decAdd && --tdata._addCnt > 0) return;
+        if (--tdata._refCnt > 0) return;
+
+        pdso._moduleGroup.runTlsDtors();
+        foreach (i, ref td; _loadedDSOs)
+            if (td._pdso == pdso) _loadedDSOs.remove(i);
+        foreach (dep; pdso._deps)
+            decThreadRef(dep, false);
+    }
+
+    extern(C) void* rt_loadLibrary(const char* name)
+    {
+        immutable save = _rtLoading;
+        _rtLoading = true;
+        scope (exit) _rtLoading = save;
+
+        auto handle = .dlopen(name, RTLD_LAZY);
+        if (handle is null) return null;
+
+        // if it's a D library
+        if (auto pdso = dsoForHandle(handle))
+            incThreadRef(pdso, true);
+        return handle;
+    }
+
+    extern(C) int rt_unloadLibrary(void* handle)
+    {
+        if (handle is null) return false;
+
+        immutable save = _rtLoading;
+        _rtLoading = true;
+        scope (exit) _rtLoading = save;
+
+        // if it's a D library
+        if (auto pdso = dsoForHandle(handle))
+            decThreadRef(pdso, true);
+        return .dlclose(handle) == 0;
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// helper functions
+///////////////////////////////////////////////////////////////////////////////
+
+void initLocks() nothrow @nogc
+{
+    version (Shared)
+        !pthread_mutex_init(&_handleToDSOMutex, null) || assert(0);
+}
+
+void finiLocks() nothrow @nogc
+{
+    version (Shared)
+        !pthread_mutex_destroy(&_handleToDSOMutex) || assert(0);
+}
+
+void runModuleConstructors(DSO* pdso, bool runTlsCtors)
+{
+    pdso._moduleGroup.sortCtors();
+    pdso._moduleGroup.runCtors();
+    if (runTlsCtors) pdso._moduleGroup.runTlsCtors();
+}
+
+void runModuleDestructors(DSO* pdso, bool runTlsDtors)
+{
+    if (runTlsDtors) pdso._moduleGroup.runTlsDtors();
+    pdso._moduleGroup.runDtors();
+}
+
+void registerGCRanges(DSO* pdso) nothrow @nogc
+{
+    foreach (rng; pdso._gcRanges)
+        GC.addRange(rng.ptr, rng.length);
+}
+
+void unregisterGCRanges(DSO* pdso) nothrow @nogc
+{
+    foreach (rng; pdso._gcRanges)
+        GC.removeRange(rng.ptr);
+}
+
+version (Shared) void runFinalizers(DSO* pdso)
+{
+    foreach (seg; pdso._codeSegments)
+        GC.runFinalizers(seg);
+}
+
+void freeDSO(DSO* pdso) nothrow @nogc
+{
+    pdso._gcRanges.reset();
+    version (Shared)
+    {
+        pdso._codeSegments.reset();
+        pdso._deps.reset();
+        pdso._handle = null;
+    }
+    .free(pdso);
+}
+
+version (Shared)
+{
+@nogc nothrow:
+    const(char)* nameForDSO(in DSO* pdso)
+    {
+        Dl_info info = void;
+        const success = dladdr(pdso._slot, &info) != 0;
+        safeAssert(success, "Failed to get DSO info.");
+        return info.dli_fname;
+    }
+
+    DSO* dsoForHandle(void* handle)
+    {
+        DSO* pdso;
+        !pthread_mutex_lock(&_handleToDSOMutex) || assert(0);
+        if (auto ppdso = handle in _handleToDSO)
+            pdso = *ppdso;
+        !pthread_mutex_unlock(&_handleToDSOMutex) || assert(0);
+        return pdso;
+    }
+
+    void setDSOForHandle(DSO* pdso, void* handle)
+    {
+        !pthread_mutex_lock(&_handleToDSOMutex) || assert(0);
+        safeAssert(handle !in _handleToDSO, "DSO already registered.");
+        _handleToDSO[handle] = pdso;
+        !pthread_mutex_unlock(&_handleToDSOMutex) || assert(0);
+    }
+
+    void unsetDSOForHandle(DSO* pdso, void* handle)
+    {
+        !pthread_mutex_lock(&_handleToDSOMutex) || assert(0);
+        safeAssert(_handleToDSO[handle] == pdso, "Handle doesn't match registered DSO.");
+        _handleToDSO.remove(handle);
+        !pthread_mutex_unlock(&_handleToDSOMutex) || assert(0);
+    }
+
+    void getDependencies(in MachHeader info, ref Array!(DSO*) deps)
+    {
+        // FIXME: Not implemented yet.
+    }
+
+    void* handleForName(const char* name)
+    {
+        auto handle = .dlopen(name, RTLD_NOLOAD | RTLD_LAZY);
+        if (handle !is null) .dlclose(handle); // drop reference count
+        return handle;
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Mach-O program header iteration
+///////////////////////////////////////////////////////////////////////////////
+
+/************
+ * Scan segments in the image header and store
+ * the writeable data segments in *pdso.
+ */
+
+void scanSegments(in MachHeader info, DSO* pdso)
+{
+    foreach (e; dataSegs)
+    {
+        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]);
+    }
+
+    version (Shared)
+    {
+        void[] text = getSection(info.header, info.slide, "__TEXT", "__text");
+        if (!text)
+            assert(0, "Failed to get text section.");
+        pdso._codeSegments.insertBack(text);
+    }
+}
+
 /**************************
  * Input:
  *      result where the output is to be written
@@ -231,28 +672,38 @@ extern(C) void _d_dso_registry(CompilerDSOData* data)
  *      true if found, and *result is filled in
  */
 
-bool findDSOHeaderForAddr(in void* addr, MachHeader* result)
+bool findImageHeaderForAddr(in void* addr, out MachHeader result)
 {
+    Dl_info info;
+    if (dladdr(addr, &info) == 0)
+        return false;
+
     foreach (i; 0 .. _dyld_image_count())
     {
-        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)
+        if (info.dli_fbase == _dyld_get_image_header(i))
         {
-            result.header = header;
-            result.slide = slide;
+            result.header = cast(const(mach_header)*)info.dli_fbase;
+            result.slide = _dyld_get_image_vmaddr_slide(i);
             return true;
         }
     }
     return false;
 }
 
+/**************************
+ * Input:
+ *      addr  an internal address of a DSO
+ * Returns:
+ *      the dlopen handle for that DSO or null if addr is not within a loaded DSO
+ */
+version (Shared) void* handleForAddr(void* addr) nothrow @nogc
+{
+    Dl_info info = void;
+    if (dladdr(addr, &info) != 0)
+        return handleForName(info.dli_fname);
+    return null;
+}
+
 struct SegRef
 {
     string seg;


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

* [gcc(refs/users/iains/heads/d-for-darwin)] libphobos: Align interface of gcc.sections.osx with gcc.sections.elf_shared
@ 2020-12-13 17:43 Iain D Sandoe
  0 siblings, 0 replies; 6+ messages in thread
From: Iain D Sandoe @ 2020-12-13 17:43 UTC (permalink / raw)
  To: gcc-cvs

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

commit b07a001e2676d2aac15061c86e24453e21f4cdff
Author: Iain Buclaw <ibuclaw@gdcproject.org>
Date:   Mon Dec 7 01:25:17 2020 +0100

    libphobos: Align interface of gcc.sections.osx with gcc.sections.elf_shared

Diff:
---
 libphobos/libdruntime/Makefile.am                |  30 +-
 libphobos/libdruntime/Makefile.in                |  64 +--
 libphobos/libdruntime/core/sys/darwin/execinfo.d |  11 +-
 libphobos/libdruntime/gcc/sections/common.d      |  48 --
 libphobos/libdruntime/gcc/sections/osx.d         | 569 ++++++++++++++++++++---
 5 files changed, 565 insertions(+), 157 deletions(-)

diff --git a/libphobos/libdruntime/Makefile.am b/libphobos/libdruntime/Makefile.am
index 124d5b049d0..722f1edfe09 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/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 \
+	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 3bf08f52b31..d99998d8934 100644
--- a/libphobos/libdruntime/Makefile.in
+++ b/libphobos/libdruntime/Makefile.in
@@ -207,10 +207,9 @@ 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/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/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/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 \
@@ -268,9 +267,10 @@ am__objects_3 = core/sys/posix/aio.lo core/sys/posix/arpa/inet.lo \
 	core/sys/posix/time.lo core/sys/posix/ucontext.lo \
 	core/sys/posix/unistd.lo core/sys/posix/utime.lo
 @DRUNTIME_OS_POSIX_TRUE@am__objects_4 = $(am__objects_3)
-am__objects_5 = core/sys/darwin/crt_externs.lo \
-	core/sys/darwin/dlfcn.lo core/sys/darwin/execinfo.lo \
-	core/sys/darwin/mach/dyld.lo core/sys/darwin/mach/getsect.lo \
+am__objects_5 = core/sys/darwin/config.lo \
+	core/sys/darwin/crt_externs.lo core/sys/darwin/dlfcn.lo \
+	core/sys/darwin/execinfo.lo core/sys/darwin/mach/dyld.lo \
+	core/sys/darwin/mach/getsect.lo \
 	core/sys/darwin/mach/kern_return.lo \
 	core/sys/darwin/mach/loader.lo core/sys/darwin/mach/port.lo \
 	core/sys/darwin/mach/semaphore.lo \
@@ -809,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/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 \
+	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 \
@@ -841,15 +841,15 @@ DRUNTIME_DSOURCES_STDCXX = core/stdcpp/exception.d \
 DRUNTIME_DSOURCES_BIONIC = core/sys/bionic/fcntl.d \
 	core/sys/bionic/string.d core/sys/bionic/unistd.d
 
-DRUNTIME_DSOURCES_DARWIN = core/sys/darwin/crt_externs.d \
-	core/sys/darwin/dlfcn.d core/sys/darwin/execinfo.d \
-	core/sys/darwin/mach/dyld.d core/sys/darwin/mach/getsect.d \
-	core/sys/darwin/mach/kern_return.d core/sys/darwin/mach/loader.d \
-	core/sys/darwin/mach/port.d core/sys/darwin/mach/semaphore.d \
-	core/sys/darwin/mach/thread_act.d core/sys/darwin/netinet/in_.d \
-	core/sys/darwin/pthread.d core/sys/darwin/string.d \
-	core/sys/darwin/sys/cdefs.d core/sys/darwin/sys/event.d \
-	core/sys/darwin/sys/mman.d
+DRUNTIME_DSOURCES_DARWIN = core/sys/darwin/config.d \
+	core/sys/darwin/crt_externs.d core/sys/darwin/dlfcn.d \
+	core/sys/darwin/execinfo.d core/sys/darwin/mach/dyld.d \
+	core/sys/darwin/mach/getsect.d core/sys/darwin/mach/kern_return.d \
+	core/sys/darwin/mach/loader.d core/sys/darwin/mach/port.d \
+	core/sys/darwin/mach/semaphore.d core/sys/darwin/mach/thread_act.d \
+	core/sys/darwin/netinet/in_.d core/sys/darwin/pthread.d \
+	core/sys/darwin/string.d core/sys/darwin/sys/cdefs.d \
+	core/sys/darwin/sys/event.d core/sys/darwin/sys/mman.d
 
 DRUNTIME_DSOURCES_DRAGONFLYBSD = core/sys/dragonflybsd/dlfcn.d \
 	core/sys/dragonflybsd/execinfo.d core/sys/dragonflybsd/netinet/in_.d \
@@ -1196,7 +1196,6 @@ 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)
@@ -1359,6 +1358,7 @@ core/sys/posix/utime.lo: core/sys/posix/$(am__dirstamp)
 core/sys/darwin/$(am__dirstamp):
 	@$(MKDIR_P) core/sys/darwin
 	@: > core/sys/darwin/$(am__dirstamp)
+core/sys/darwin/config.lo: core/sys/darwin/$(am__dirstamp)
 core/sys/darwin/crt_externs.lo: core/sys/darwin/$(am__dirstamp)
 core/sys/darwin/dlfcn.lo: core/sys/darwin/$(am__dirstamp)
 core/sys/darwin/execinfo.lo: core/sys/darwin/$(am__dirstamp)
diff --git a/libphobos/libdruntime/core/sys/darwin/execinfo.d b/libphobos/libdruntime/core/sys/darwin/execinfo.d
index c929cc2f88d..d9607f392eb 100644
--- a/libphobos/libdruntime/core/sys/darwin/execinfo.d
+++ b/libphobos/libdruntime/core/sys/darwin/execinfo.d
@@ -21,6 +21,11 @@ extern (C):
 nothrow:
 @nogc:
 
-int backtrace(void** buffer, int size);
-char** backtrace_symbols(const(void*)* buffer, int size);
-void backtrace_symbols_fd(const(void*)* buffer, int size, int fd);
+import core.sys.darwin.config;
+
+static if (__traits(getTargetInfo, "osxVersionMin") >= __MAC_10_5)
+{
+    int backtrace(void** buffer, int size);
+    char** backtrace_symbols(const(void*)* buffer, int size);
+    void backtrace_symbols_fd(const(void*)* buffer, int size, int fd);
+}
diff --git a/libphobos/libdruntime/gcc/sections/common.d b/libphobos/libdruntime/gcc/sections/common.d
deleted file mode 100644
index b2d2322347d..00000000000
--- a/libphobos/libdruntime/gcc/sections/common.d
+++ /dev/null
@@ -1,48 +0,0 @@
-// 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/osx.d b/libphobos/libdruntime/gcc/sections/osx.d
index 6ace2da4a8b..9ec5b79974e 100644
--- a/libphobos/libdruntime/gcc/sections/osx.d
+++ b/libphobos/libdruntime/gcc/sections/osx.d
@@ -24,17 +24,31 @@ module gcc.sections.osx;
 
 version (OSX):
 
-import gcc.sections.common;
-
+import core.memory;
 import core.stdc.stdlib;
+import core.sys.darwin.dlfcn;
 import core.sys.darwin.mach.dyld;
 import core.sys.darwin.mach.getsect;
+import core.sys.posix.pthread;
 import rt.minfo;
 import rt.util.container.array;
+import rt.util.container.hashtab;
 
 version (GNU_EMUTLS)
     import gcc.emutls;
 
+/****
+ * 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);
+}
+
 alias DSO SectionGroup;
 struct DSO
 {
@@ -74,8 +88,22 @@ struct DSO
     }
 
 private:
+
+    invariant()
+    {
+        safeAssert(_moduleGroup.modules.length > 0, "No modules for DSO.");
+    }
+
+    void** _slot;
     ModuleGroup _moduleGroup;
     Array!(void[]) _gcRanges;
+
+    version (Shared)
+    {
+        Array!(void[]) _codeSegments; // array of code segments
+        Array!(DSO*) _deps; // D libraries needed by this DSO
+        void* _handle; // corresponding handle
+    }
 }
 
 /****
@@ -99,63 +127,185 @@ void finiSections() nothrow @nogc
     _isRuntimeInitialized = false;
 }
 
-void[]* initTLSRanges() nothrow @nogc
-{
-    return null;
-}
+alias ScanDG = void delegate(void* pbeg, void* pend) nothrow;
 
-void finiTLSRanges(void[]* rng) nothrow @nogc
+version (Shared)
 {
-}
+    /***
+     * Called once per thread; returns array of thread local storage ranges
+     */
+    Array!(ThreadDSO)* initTLSRanges() @nogc nothrow
+    {
+        return &_loadedDSOs();
+    }
 
-void scanTLSRanges(void[]* rng, scope void delegate(void* pbeg, void* pend) nothrow dg) nothrow
-{
-    version (GNU_EMUTLS)
-        _d_emutls_scan(dg);
-    else
-        static assert(0, "Native TLS unimplemented");
-}
+    void finiTLSRanges(Array!(ThreadDSO)* tdsos) @nogc nothrow
+    {
+        // Nothing to do here. tdsos used to point to the _loadedDSOs instance
+        // in the dying thread's TLS segment and as such is not valid anymore.
+        // The memory for the array contents was already reclaimed in
+        // cleanupLoadedLibraries().
+    }
+
+    void scanTLSRanges(Array!(ThreadDSO)* tdsos, scope ScanDG dg) nothrow
+    {
+        version (GNU_EMUTLS)
+            _d_emutls_scan(dg);
+        else
+            static assert(0, "Native TLS unimplemented");
+    }
 
-version (Shared)
-{
     // interface for core.thread to inherit loaded libraries
     void* pinLoadedLibraries() nothrow @nogc
     {
-        return null;
+        auto res = cast(Array!(ThreadDSO)*)calloc(1, Array!(ThreadDSO).sizeof);
+        res.length = _loadedDSOs.length;
+        foreach (i, ref tdso; _loadedDSOs)
+        {
+            (*res)[i] = tdso;
+            if (tdso._addCnt)
+            {
+                // Increment the dlopen ref for explicitly loaded libraries to pin them.
+                const success = .dlopen(nameForDSO(tdso._pdso), RTLD_LAZY) !is null;
+                safeAssert(success, "Failed to increment dlopen ref.");
+                (*res)[i]._addCnt = 1; // new array takes over the additional ref count
+            }
+        }
+        return res;
     }
 
     void unpinLoadedLibraries(void* p) nothrow @nogc
     {
+        auto pary = cast(Array!(ThreadDSO)*)p;
+        // In case something failed we need to undo the pinning.
+        foreach (ref tdso; *pary)
+        {
+            if (tdso._addCnt)
+            {
+                auto handle = tdso._pdso._handle;
+                safeAssert(handle !is null, "Invalid library handle.");
+                .dlclose(handle);
+            }
+        }
+        pary.reset();
+        .free(pary);
     }
 
     // Called before TLS ctors are ran, copy over the loaded libraries
     // of the parent thread.
     void inheritLoadedLibraries(void* p) nothrow @nogc
     {
+        safeAssert(_loadedDSOs.empty, "DSOs have already been registered for this thread.");
+        _loadedDSOs.swap(*cast(Array!(ThreadDSO)*)p);
+        .free(p);
     }
 
     // Called after all TLS dtors ran, decrements all remaining dlopen refs.
     void cleanupLoadedLibraries() nothrow @nogc
     {
+        foreach (ref tdso; _loadedDSOs)
+        {
+            if (tdso._addCnt == 0) continue;
+
+            auto handle = tdso._pdso._handle;
+            safeAssert(handle !is null, "Invalid DSO handle.");
+            for (; tdso._addCnt > 0; --tdso._addCnt)
+                .dlclose(handle);
+        }
+
+        // Free the memory for the array contents.
+        _loadedDSOs.reset();
+    }
+}
+else
+{
+    /***
+     * Called once per thread; returns array of thread local storage ranges
+     */
+    Array!(void[])* initTLSRanges() nothrow @nogc
+    {
+        return null;
+    }
+
+    void finiTLSRanges(Array!(void[])* rngs) nothrow @nogc
+    {
+    }
+
+    void scanTLSRanges(Array!(void[])* rngs, scope ScanDG dg) nothrow
+    {
+        version (GNU_EMUTLS)
+            _d_emutls_scan(dg);
+        else
+            static assert(0, "Native TLS unimplemented");
     }
 }
 
 private:
 
-/*
- * Static DSOs loaded by the runtime linker. This includes the
- * executable. These can't be unloaded.
- */
-@property ref Array!(DSO*) _loadedDSOs() @nogc nothrow
+version (Shared)
 {
-    __gshared Array!(DSO*) x;
-    return x;
+    /*
+     * Array of thread local DSO metadata for all libraries loaded and
+     * initialized in this thread.
+     *
+     * Note:
+     *     A newly spawned thread will inherit these libraries.
+     * Note:
+     *     We use an array here to preserve the order of
+     *     initialization.  If that became a performance issue, we
+     *     could use a hash table and enumerate the DSOs during
+     *     loading so that the hash table values could be sorted when
+     *     necessary.
+     */
+    struct ThreadDSO
+    {
+        DSO* _pdso;
+        static if (_pdso.sizeof == 8) uint _refCnt, _addCnt;
+        else static if (_pdso.sizeof == 4) ushort _refCnt, _addCnt;
+        else static assert(0, "unimplemented");
+        alias _pdso this;
+    }
+
+    @property ref Array!(ThreadDSO) _loadedDSOs() @nogc nothrow
+    {
+        static Array!(ThreadDSO) x;
+        return x;
+    }
+
+    /*
+     * Set to true during rt_loadLibrary/rt_unloadLibrary calls.
+     */
+    bool _rtLoading;
+
+    /*
+     * Hash table to map the native handle (as returned by dlopen)
+     * to the corresponding DSO*, protected by a mutex.
+     */
+    __gshared pthread_mutex_t _handleToDSOMutex;
+    @property ref HashTab!(void*, DSO*) _handleToDSO() @nogc nothrow
+    {
+        __gshared HashTab!(void*, DSO*) x;
+        return x;
+    }
 }
+else
+{
+    /*
+     * Static DSOs loaded by the runtime linker. This includes the
+     * executable. These can't be unloaded.
+     */
+    @property ref Array!(DSO*) _loadedDSOs() @nogc nothrow
+    {
+        __gshared Array!(DSO*) x;
+        return x;
+    }
 
-/*
- * Set to true during rt_loadLibrary/rt_unloadLibrary calls.
- */
-enum _rtLoading = false;
+    enum _rtLoading = false;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Compiler to runtime interface.
+///////////////////////////////////////////////////////////////////////////////
 
 struct MachHeader
 {
@@ -163,9 +313,18 @@ struct MachHeader
     intptr_t slide;             // virtural memory address slide amount
 }
 
-///////////////////////////////////////////////////////////////////////////////
-// Compiler to runtime interface.
-///////////////////////////////////////////////////////////////////////////////
+/****
+ * This data structure is generated by the compiler, and then passed to
+ * _d_dso_registry().
+ */
+struct CompilerDSOData
+{
+    size_t _version;                                       // currently 1
+    void** _slot;                                          // can be used to store runtime data
+    immutable(object.ModuleInfo*)* _minfo_beg, _minfo_end; // array of modules in this object file
+}
+
+T[] toRange(T)(T* beg, T* end) { return beg[0 .. end - beg]; }
 
 /* For each shared library and executable, the compiler generates code that
  * sets up CompilerDSOData and calls _d_dso_registry().
@@ -180,27 +339,57 @@ extern(C) void _d_dso_registry(CompilerDSOData* data)
     // no backlink => register
     if (*data._slot is null)
     {
+        immutable firstDSO = _loadedDSOs.empty;
+        if (firstDSO) initLocks();
+
         DSO* pdso = cast(DSO*).calloc(1, DSO.sizeof);
         assert(typeid(DSO).initializer().ptr is null);
+        pdso._slot = data._slot;
         *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);
+        MachHeader header = void;
+        const headerFound = findImageHeaderForAddr(data._slot, header);
         safeAssert(headerFound, "Failed to find image header.");
 
-        foreach (e; dataSegs)
+        scanSegments(header, pdso);
+
+        version (Shared)
+        {
+            auto handle = handleForAddr(data._slot);
+
+            getDependencies(header, pdso._deps);
+            pdso._handle = handle;
+            setDSOForHandle(pdso, pdso._handle);
+
+            if (!_rtLoading)
+            {
+                /* This DSO was not loaded by rt_loadLibrary which
+                 * happens for all dependencies of an executable or
+                 * the first dlopen call from a C program.
+                 * In this case we add the DSO to the _loadedDSOs of this
+                 * thread with a refCnt of 1 and call the TlsCtors.
+                 */
+                immutable ushort refCnt = 1, addCnt = 0;
+                _loadedDSOs.insertBack(ThreadDSO(pdso, refCnt, addCnt));
+            }
+        }
+        else
         {
-            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]);
+            foreach (p; _loadedDSOs)
+                safeAssert(p !is pdso, "DSO already registered.");
+            _loadedDSOs.insertBack(pdso);
         }
 
-        foreach (p; _loadedDSOs)
-            safeAssert(p !is pdso, "DSO already registered.");
-        _loadedDSOs.insertBack(pdso);
+        // don't initialize modules before rt_init was called
+        if (_isRuntimeInitialized)
+        {
+            registerGCRanges(pdso);
+            // rt_loadLibrary will run tls ctors, so do this only for dlopen
+            immutable runTlsCtors = !_rtLoading;
+            runModuleConstructors(pdso, runTlsCtors);
+        }
     }
     // has backlink => unregister
     else
@@ -208,22 +397,274 @@ extern(C) void _d_dso_registry(CompilerDSOData* data)
         DSO* pdso = cast(DSO*)*data._slot;
         *data._slot = null;
 
-        // static DSOs are unloaded in reverse order
-        safeAssert(pdso == _loadedDSOs.back, "DSO being unregistered isn't current last one.");
-        _loadedDSOs.popBack();
+        // don't finalizes modules after rt_term was called (see Bugzilla 11378)
+        if (_isRuntimeInitialized)
+        {
+            // rt_unloadLibrary already ran tls dtors, so do this only for dlclose
+            immutable runTlsDtors = !_rtLoading;
+            runModuleDestructors(pdso, runTlsDtors);
+            unregisterGCRanges(pdso);
+            // run finalizers after module dtors (same order as in rt_term)
+            version (Shared) runFinalizers(pdso);
+        }
+
+        version (Shared)
+        {
+            if (!_rtLoading)
+            {
+                /* This DSO was not unloaded by rt_unloadLibrary so we
+                 * have to remove it from _loadedDSOs here.
+                 */
+                foreach (i, ref tdso; _loadedDSOs)
+                {
+                    if (tdso._pdso == pdso)
+                    {
+                        _loadedDSOs.remove(i);
+                        break;
+                    }
+                }
+            }
+
+            unsetDSOForHandle(pdso, pdso._handle);
+        }
+        else
+        {
+            // static DSOs are unloaded in reverse order
+            safeAssert(pdso == _loadedDSOs.back, "DSO being unregistered isn't current last one.");
+            _loadedDSOs.popBack();
+        }
 
-        pdso._gcRanges.reset();
-        .free(pdso);
+        freeDSO(pdso);
 
         // last DSO being unloaded => shutdown registry
         if (_loadedDSOs.empty)
         {
             version (GNU_EMUTLS)
                 _d_emutls_destroy();
+            version (Shared)
+            {
+                safeAssert(_handleToDSO.empty, "_handleToDSO not in sync with _loadedDSOs.");
+                _handleToDSO.reset();
+            }
+            finiLocks();
         }
     }
 }
 
+///////////////////////////////////////////////////////////////////////////////
+// dynamic loading
+///////////////////////////////////////////////////////////////////////////////
+
+// Shared D libraries are only supported when linking against a shared druntime library.
+
+version (Shared)
+{
+    ThreadDSO* findThreadDSO(DSO* pdso) nothrow @nogc
+    {
+        foreach (ref tdata; _loadedDSOs)
+            if (tdata._pdso == pdso) return &tdata;
+        return null;
+    }
+
+    void incThreadRef(DSO* pdso, bool incAdd)
+    {
+        if (auto tdata = findThreadDSO(pdso)) // already initialized
+        {
+            if (incAdd && ++tdata._addCnt > 1) return;
+            ++tdata._refCnt;
+        }
+        else
+        {
+            foreach (dep; pdso._deps)
+                incThreadRef(dep, false);
+            immutable ushort refCnt = 1, addCnt = incAdd ? 1 : 0;
+            _loadedDSOs.insertBack(ThreadDSO(pdso, refCnt, addCnt));
+            pdso._moduleGroup.runTlsCtors();
+        }
+    }
+
+    void decThreadRef(DSO* pdso, bool decAdd)
+    {
+        auto tdata = findThreadDSO(pdso);
+        safeAssert(tdata !is null, "Failed to find thread DSO.");
+        safeAssert(!decAdd || tdata._addCnt > 0, "Mismatching rt_unloadLibrary call.");
+
+        if (decAdd && --tdata._addCnt > 0) return;
+        if (--tdata._refCnt > 0) return;
+
+        pdso._moduleGroup.runTlsDtors();
+        foreach (i, ref td; _loadedDSOs)
+            if (td._pdso == pdso) _loadedDSOs.remove(i);
+        foreach (dep; pdso._deps)
+            decThreadRef(dep, false);
+    }
+
+    extern(C) void* rt_loadLibrary(const char* name)
+    {
+        immutable save = _rtLoading;
+        _rtLoading = true;
+        scope (exit) _rtLoading = save;
+
+        auto handle = .dlopen(name, RTLD_LAZY);
+        if (handle is null) return null;
+
+        // if it's a D library
+        if (auto pdso = dsoForHandle(handle))
+            incThreadRef(pdso, true);
+        return handle;
+    }
+
+    extern(C) int rt_unloadLibrary(void* handle)
+    {
+        if (handle is null) return false;
+
+        immutable save = _rtLoading;
+        _rtLoading = true;
+        scope (exit) _rtLoading = save;
+
+        // if it's a D library
+        if (auto pdso = dsoForHandle(handle))
+            decThreadRef(pdso, true);
+        return .dlclose(handle) == 0;
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// helper functions
+///////////////////////////////////////////////////////////////////////////////
+
+void initLocks() nothrow @nogc
+{
+    version (Shared)
+        !pthread_mutex_init(&_handleToDSOMutex, null) || assert(0);
+}
+
+void finiLocks() nothrow @nogc
+{
+    version (Shared)
+        !pthread_mutex_destroy(&_handleToDSOMutex) || assert(0);
+}
+
+void runModuleConstructors(DSO* pdso, bool runTlsCtors)
+{
+    pdso._moduleGroup.sortCtors();
+    pdso._moduleGroup.runCtors();
+    if (runTlsCtors) pdso._moduleGroup.runTlsCtors();
+}
+
+void runModuleDestructors(DSO* pdso, bool runTlsDtors)
+{
+    if (runTlsDtors) pdso._moduleGroup.runTlsDtors();
+    pdso._moduleGroup.runDtors();
+}
+
+void registerGCRanges(DSO* pdso) nothrow @nogc
+{
+    foreach (rng; pdso._gcRanges)
+        GC.addRange(rng.ptr, rng.length);
+}
+
+void unregisterGCRanges(DSO* pdso) nothrow @nogc
+{
+    foreach (rng; pdso._gcRanges)
+        GC.removeRange(rng.ptr);
+}
+
+version (Shared) void runFinalizers(DSO* pdso)
+{
+    foreach (seg; pdso._codeSegments)
+        GC.runFinalizers(seg);
+}
+
+void freeDSO(DSO* pdso) nothrow @nogc
+{
+    pdso._gcRanges.reset();
+    version (Shared)
+    {
+        pdso._codeSegments.reset();
+        pdso._deps.reset();
+        pdso._handle = null;
+    }
+    .free(pdso);
+}
+
+version (Shared)
+{
+@nogc nothrow:
+    const(char)* nameForDSO(in DSO* pdso)
+    {
+        Dl_info info = void;
+        const success = dladdr(pdso._slot, &info) != 0;
+        safeAssert(success, "Failed to get DSO info.");
+        return info.dli_fname;
+    }
+
+    DSO* dsoForHandle(void* handle)
+    {
+        DSO* pdso;
+        !pthread_mutex_lock(&_handleToDSOMutex) || assert(0);
+        if (auto ppdso = handle in _handleToDSO)
+            pdso = *ppdso;
+        !pthread_mutex_unlock(&_handleToDSOMutex) || assert(0);
+        return pdso;
+    }
+
+    void setDSOForHandle(DSO* pdso, void* handle)
+    {
+        !pthread_mutex_lock(&_handleToDSOMutex) || assert(0);
+        safeAssert(handle !in _handleToDSO, "DSO already registered.");
+        _handleToDSO[handle] = pdso;
+        !pthread_mutex_unlock(&_handleToDSOMutex) || assert(0);
+    }
+
+    void unsetDSOForHandle(DSO* pdso, void* handle)
+    {
+        !pthread_mutex_lock(&_handleToDSOMutex) || assert(0);
+        safeAssert(_handleToDSO[handle] == pdso, "Handle doesn't match registered DSO.");
+        _handleToDSO.remove(handle);
+        !pthread_mutex_unlock(&_handleToDSOMutex) || assert(0);
+    }
+
+    void getDependencies(in MachHeader info, ref Array!(DSO*) deps)
+    {
+        // FIXME: Not implemented yet.
+    }
+
+    void* handleForName(const char* name)
+    {
+        auto handle = .dlopen(name, RTLD_NOLOAD | RTLD_LAZY);
+        if (handle !is null) .dlclose(handle); // drop reference count
+        return handle;
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Mach-O program header iteration
+///////////////////////////////////////////////////////////////////////////////
+
+/************
+ * Scan segments in the image header and store
+ * the writeable data segments in *pdso.
+ */
+
+void scanSegments(in MachHeader info, DSO* pdso)
+{
+    foreach (e; dataSegs)
+    {
+        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]);
+    }
+
+    version (Shared)
+    {
+        void[] text = getSection(info.header, info.slide, "__TEXT", "__text");
+        if (!text)
+            assert(0, "Failed to get text section.");
+        pdso._codeSegments.insertBack(text);
+    }
+}
+
 /**************************
  * Input:
  *      result where the output is to be written
@@ -231,28 +672,38 @@ extern(C) void _d_dso_registry(CompilerDSOData* data)
  *      true if found, and *result is filled in
  */
 
-bool findDSOHeaderForAddr(in void* addr, MachHeader* result)
+bool findImageHeaderForAddr(in void* addr, out MachHeader result)
 {
+    Dl_info info;
+    if (dladdr(addr, &info) == 0)
+        return false;
+
     foreach (i; 0 .. _dyld_image_count())
     {
-        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)
+        if (info.dli_fbase == _dyld_get_image_header(i))
         {
-            result.header = header;
-            result.slide = slide;
+            result.header = cast(const(mach_header)*)info.dli_fbase;
+            result.slide = _dyld_get_image_vmaddr_slide(i);
             return true;
         }
     }
     return false;
 }
 
+/**************************
+ * Input:
+ *      addr  an internal address of a DSO
+ * Returns:
+ *      the dlopen handle for that DSO or null if addr is not within a loaded DSO
+ */
+version (Shared) void* handleForAddr(void* addr) nothrow @nogc
+{
+    Dl_info info = void;
+    if (dladdr(addr, &info) != 0)
+        return handleForName(info.dli_fname);
+    return null;
+}
+
 struct SegRef
 {
     string seg;


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

end of thread, other threads:[~2021-10-18 15:54 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-10-15 19:33 [gcc(refs/users/iains/heads/d-for-darwin)] libphobos: Align interface of gcc.sections.osx with gcc.sections.elf_shared Iain D Sandoe
  -- strict thread matches above, loose matches on Subject: below --
2021-10-18 15:54 Iain D Sandoe
2021-10-13  8:30 Iain D Sandoe
2021-10-11 20:35 Iain D Sandoe
2020-12-21 20:36 Iain D Sandoe
2020-12-13 17:43 Iain D Sandoe

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).