diff mbox series

d: Move DSO registry support code from compiler to drtstuff in library (PR100062)

Message ID 20220708130729.3690093-1-ibuclaw@gdcproject.org
State New
Headers show
Series d: Move DSO registry support code from compiler to drtstuff in library (PR100062) | expand

Commit Message

Iain Buclaw July 8, 2022, 1:07 p.m. UTC
Hi,

Currently the DSO support for D runtime is generated by the compiler in
every object, when really it is only required once per shared object.

This patch moves that support logic from the compiler itself to the
library as part of the drtstuff code.  The object files drtbegin.o and
drtend.o are now always linked in.

Bootstrapped and tested on x86_64-linux-gnu/-m32/-mx32, with no
observable regressions.

@Rainer, as you provided the original, would be good to validate this is
fine for Solaris too.

Regards
Iain.

---
	PR d/100062

gcc/ChangeLog:

	* config/darwin-d.cc (TARGET_D_MINFO_START_NAME): Remove.
	(TARGET_D_MINFO_END_NAME): Remove.
	* config/elfos.h (TARGET_D_MINFO_START_NAME): Remove.
	(TARGET_D_MINFO_END_NAME): Remove.
	* config/i386/winnt-d.cc (TARGET_D_MINFO_START_NAME): Remove.
	(TARGET_D_MINFO_END_NAME): Remove.
	* doc/tm.texi: Regenerate.
	* doc/tm.texi.in: Remove hooks for TARGET_D_MINFO_START_NAME and
	TARGET_D_MINFO_END_NAME

gcc/d/ChangeLog:

	* d-target.def (d_minfo_start_name): Remove hook.
	(d_minfo_end_name): Remove hook.
	* modules.cc (compiler_dso_type): Remove.
	(dso_registry_fn): Remove.
	(dso_slot_node): Remove.
	(dso_initialized_node): Remove.
	(start_minfo_node): Remove.
	(stop_minfo_node): Remove.
	(get_compiler_dso_type): Remove.
	(get_dso_registry_fn): Remove.
	(build_dso_cdtor_fn): Remove.
	(build_dso_registry_var): Remove.
	(register_moduleinfo): Don't generate and emit DSO registry code.

gcc/testsuite/ChangeLog:

	* lib/gdc-utils.exp (gdc-convert-args): Handle -nophoboslib.

libphobos/ChangeLog:

	* Makefile.in: Regenerate.
	* configure: Regenerate.
	* configure.ac: Remove substitution of DRTSTUFF_SPEC.
	(DRUNTIME_OS_MINFO_BRACKETING): Rename to...
	(DRUNTIME_OS_NAMED_SECTIONS): ...this.
	* libdruntime/Makefile.am: Always compile $(DRTSTUFF).
	(gcc/drtbegin.o): Compile with gdc.
	(gcc/drtend.o): Likewise.
	* libdruntime/Makefile.in: Regenerate.
	* libdruntime/gcc/config.d.in (OS_Have_Named_Sections): Define.
	* libdruntime/gcc/sections/common.d (CompilerDSOData): Define.
	* libdruntime/gcc/sections/elf.d (CompilerDSOData): Remove.
	* libdruntime/gcc/sections/macho.d (CompilerDSOData): Remove.
	* libdruntime/gcc/sections/pecoff.d (CompilerDSOData): Remove.
	* m4/druntime/os.m4 (DRUNTIME_OS_MINFO_BRACKETING): Remove.
	(DRUNTIME_OS_NAMED_SECTIONS): Define.
	* src/Makefile.in: Regenerate.
	* src/libgphobos.spec.in: Always add drtbegin and drtend to startfile
	and endfile spec.
	* testsuite/Makefile.in: Regenerate.
	* libdruntime/gcc/drtstuff.c: Rename to file to...
	* libdruntime/gcc/drtstuff.d: ...this. Convert source to D, add DSO
	registry code originally generated by the compiler.
---
 gcc/config/darwin-d.cc                      |   6 -
 gcc/config/elfos.h                          |   2 -
 gcc/config/i386/winnt-d.cc                  |   6 -
 gcc/d/d-target.def                          |  17 +-
 gcc/d/modules.cc                            | 202 +-------------------
 gcc/doc/tm.texi                             |  12 --
 gcc/doc/tm.texi.in                          |   4 -
 gcc/testsuite/lib/gdc-utils.exp             |   3 +
 libphobos/Makefile.in                       |   2 +-
 libphobos/configure                         | 119 +++---------
 libphobos/configure.ac                      |  10 +-
 libphobos/libdruntime/Makefile.am           |  16 +-
 libphobos/libdruntime/Makefile.in           |  16 +-
 libphobos/libdruntime/gcc/config.d.in       |   3 +
 libphobos/libdruntime/gcc/drtstuff.c        |  39 ----
 libphobos/libdruntime/gcc/drtstuff.d        | 105 ++++++++++
 libphobos/libdruntime/gcc/sections/common.d |  11 ++
 libphobos/libdruntime/gcc/sections/elf.d    |  11 --
 libphobos/libdruntime/gcc/sections/macho.d  |  11 --
 libphobos/libdruntime/gcc/sections/pecoff.d |  11 --
 libphobos/m4/druntime/os.m4                 |  40 +---
 libphobos/src/Makefile.in                   |   2 +-
 libphobos/src/libgphobos.spec.in            |   6 +-
 libphobos/testsuite/Makefile.in             |   2 +-
 24 files changed, 183 insertions(+), 473 deletions(-)
 delete mode 100644 libphobos/libdruntime/gcc/drtstuff.c
 create mode 100644 libphobos/libdruntime/gcc/drtstuff.d

Comments

Rainer Orth July 11, 2022, 8:58 a.m. UTC | #1
Hi Iain,

> Currently the DSO support for D runtime is generated by the compiler in
> every object, when really it is only required once per shared object.
>
> This patch moves that support logic from the compiler itself to the
> library as part of the drtstuff code.  The object files drtbegin.o and
> drtend.o are now always linked in.
>
> Bootstrapped and tested on x86_64-linux-gnu/-m32/-mx32, with no
> observable regressions.
>
> @Rainer, as you provided the original, would be good to validate this is
> fine for Solaris too.

I did, with mixed success: initially, the patch broke bootstrap on both
i386-pc-solaris2.11 and sparc-sun-solaris2.11 linking libgdruntime.so:

Text relocation remains                        referenced
    against symbol                  offset      in file
__start_minfo                       0x2         gcc/drtbegin.o
_D8drtstuff7dsoSlotPv               0x7         gcc/drtbegin.o
_D8drtstuff7dsoDataS3gcc8sections6common15CompilerDSOData 0x1e          gcc/drtbegin.o
_D8drtstuff7dsoDataS3gcc8sections6common15CompilerDSOData 0x28          gcc/drtbegin.o
__stop_minfo                        0x2c        gcc/drtbegin.o
_D8drtstuff7dsoDataS3gcc8sections6common15CompilerDSOData 0x34          gcc/drtbegin.o
_D8drtstuff7dsoDataS3gcc8sections6common15CompilerDSOData 0x39          gcc/drtbegin.o
_D8drtstuff7dsoDataS3gcc8sections6common15CompilerDSOData 0x7           gcc/drtbegin.o
_d_dso_registry                     0x3e        gcc/drtbegin.o
_d_dso_registry                     0xc         gcc/drtbegin.o
ld: fatal: relocations remain against allocatable but non-writable sections
collect2: error: ld returned 1 exit status
make[5]: *** [Makefile:1943: libgdruntime.la] Error 1

Solaris ld defaults to -z text, and gcc is still non-pic/pie by
default.  The attached patch fixes the issue by building
drtbegin.o/drtend.o as libtool objects.

There are a couple of caveats, though:

* It directs gdc to libdruntime/gcc/.libs instead of libdruntime/gcc.
  I've no idea what happens when configuring with --disable-shared,
  building for targets without PIC support, or on Windows where that
  directory is called _libs instead (I've found no variable to use
  here).

  OTOH, testsuite_flags.in already hardcodes .libs, so this is a
  preexisting problem.

* I haven't checked if the PIC drt*.o files are actually installed,
  otherwise gdc wouldn't be able to create shared objects on Solaris.

* This comment is misleading now that those files are used unconditionally:

# Provide __start_minfo, __stop_minfo if linker doesn't.
DRTSTUFF = gcc/drtbegin.o gcc/drtend.o

At least with this incremental patch, I've been able to successfully
bootstrap and test trunk on i386-pc-solaris2.11 (Solaris 11.3 which
lacks ld support for __start_<section>/__stop_<section) and 11.4 which
has it) and sparc-sun-solaris2.11 (Solaris 11.4 only).

	Rainer
diff mbox series

Patch

diff --git a/gcc/config/darwin-d.cc b/gcc/config/darwin-d.cc
index e983883dba6..358a049212b 100644
--- a/gcc/config/darwin-d.cc
+++ b/gcc/config/darwin-d.cc
@@ -66,10 +66,4 @@  darwin_d_register_target_info (void)
 #undef TARGET_D_MINFO_SECTION
 #define TARGET_D_MINFO_SECTION "__DATA,__minfodata"
 
-#undef TARGET_D_MINFO_START_NAME
-#define TARGET_D_MINFO_START_NAME "*section$start$__DATA$__minfodata"
-
-#undef TARGET_D_MINFO_END_NAME
-#define TARGET_D_MINFO_END_NAME "*section$end$__DATA$__minfodata"
-
 struct gcc_targetdm targetdm = TARGETDM_INITIALIZER;
diff --git a/gcc/config/elfos.h b/gcc/config/elfos.h
index acb376283cf..66a4758f345 100644
--- a/gcc/config/elfos.h
+++ b/gcc/config/elfos.h
@@ -486,5 +486,3 @@  see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 /* ELF support needed only by D front-end.  */
 
 #define TARGET_D_MINFO_SECTION "minfo"
-#define TARGET_D_MINFO_START_NAME "__start_minfo"
-#define TARGET_D_MINFO_END_NAME "__stop_minfo"
diff --git a/gcc/config/i386/winnt-d.cc b/gcc/config/i386/winnt-d.cc
index 3d990a12331..220f464b567 100644
--- a/gcc/config/i386/winnt-d.cc
+++ b/gcc/config/i386/winnt-d.cc
@@ -72,12 +72,6 @@  winnt_d_register_target_info (void)
 #undef TARGET_D_MINFO_SECTION
 #define TARGET_D_MINFO_SECTION "minfo"
 
-#undef TARGET_D_MINFO_START_NAME
-#define TARGET_D_MINFO_START_NAME "__start_minfo"
-
-#undef TARGET_D_MINFO_END_NAME
-#define TARGET_D_MINFO_END_NAME "__stop_minfo"
-
 /* Define TARGET_D_TEMPLATES_ALWAYS_COMDAT for Windows targets.  */
 
 #undef TARGET_D_TEMPLATES_ALWAYS_COMDAT
diff --git a/gcc/d/d-target.def b/gcc/d/d-target.def
index 7805942b91e..c8c6f31a7c4 100644
--- a/gcc/d/d-target.def
+++ b/gcc/d/d-target.def
@@ -66,7 +66,7 @@  the target operating system.",
  void, (void),
  hook_void_void)
 
-/* ModuleInfo section name and brackets.  */
+/* The name of the ModuleInfo section.  */
 DEFHOOKPOD
 (d_minfo_section,
  "Contains the name of the section in which module info references should be\n\
@@ -76,21 +76,6 @@  collect all modules for each loaded shared library and executable.  The\n\
 default value of @code{NULL} disables the use of sections altogether.",
  const char *, NULL)
 
-DEFHOOKPOD
-(d_minfo_start_name,
- "If @code{TARGET_D_MINFO_SECTION} is defined, then this must also be defined\n\
-as the name of the symbol indicating the start address of the module info\n\
-section",
- const char *, NULL)
-
-/* The name of the ModuleInfo section.  */
-DEFHOOKPOD
-(d_minfo_end_name,
- "If @code{TARGET_D_MINFO_SECTION} is defined, then this must also be defined\n\
-as the name of the symbol indicating the end address of the module info\n\
-section",
- const char *, NULL)
-
 /* The "stdcall" convention is really supported on 32-bit x86/Windows only.
    The following hook is a helper to determine whether to apply the attribute
    on declarations with `extern(System)' and `extern(Windows)' linkage.  */
diff --git a/gcc/d/modules.cc b/gcc/d/modules.cc
index edc79122365..456b91632e3 100644
--- a/gcc/d/modules.cc
+++ b/gcc/d/modules.cc
@@ -54,23 +54,8 @@  along with GCC; see the file COPYING3.  If not see
    structure, as well as accessors for the variadic fields.  So we only define
    layout compatible POD_structs for ModuleInfo.  */
 
-/* The internally represented ModuleInfo and CompilerDSO types.  */
+/* The internally represented ModuleInfo type.  */
 static tree moduleinfo_type;
-static tree compiler_dso_type;
-static tree dso_registry_fn;
-
-/* The DSO slot for use by the druntime implementation.  */
-static tree dso_slot_node;
-
-/* For registering and deregistering DSOs with druntime, we have one global
-   constructor and destructor per object that calls _d_dso_registry with the
-   respective DSO record.  To ensure that this is only done once, a
-   `dso_initialized' variable is introduced to guard repeated calls.  */
-static tree dso_initialized_node;
-
-/* The beginning and end of the `minfo' section.  */
-static tree start_minfo_node;
-static tree stop_minfo_node;
 
 /* Record information about module initialization, termination,
    unit testing, and thread local storage in the compilation.  */
@@ -252,154 +237,8 @@  get_moduleinfo_decl (Module *decl)
   return decl->csym;
 }
 
-/* Return the type for CompilerDSOData, create it if it doesn't exist.  */
-
-static tree
-get_compiler_dso_type (void)
-{
-  if (compiler_dso_type)
-    return compiler_dso_type;
-
-  /* Layout of CompilerDSOData is:
-	size_t version;
-	void** slot;
-	ModuleInfo** _minfo_beg;
-	ModuleInfo** _minfo_end;
-	FuncTable* _deh_beg;
-	FuncTable* _deh_end;
-
-     Note, finish_builtin_struct() expects these fields in reverse order.  */
-  tree fields = create_field_decl (ptr_type_node, NULL, 1, 1);
-  tree field = create_field_decl (ptr_type_node, NULL, 1, 1);
-  DECL_CHAIN (field) = fields;
-  fields = field;
-
-  field = create_field_decl (build_pointer_type (get_moduleinfo_type ()),
-			     NULL, 1, 1);
-  DECL_CHAIN (field) = fields;
-  fields = field;
-  field = create_field_decl (build_pointer_type (get_moduleinfo_type ()),
-			     NULL, 1, 1);
-  DECL_CHAIN (field) = fields;
-  fields = field;
-
-  field = create_field_decl (build_pointer_type (ptr_type_node), NULL, 1, 1);
-  DECL_CHAIN (field) = fields;
-  fields = field;
-
-  field = create_field_decl (size_type_node, NULL, 1, 1);
-  DECL_CHAIN (field) = fields;
-  fields = field;
-
-  compiler_dso_type = make_node (RECORD_TYPE);
-  finish_builtin_struct (compiler_dso_type, "CompilerDSOData",
-			 fields, NULL_TREE);
-
-  return compiler_dso_type;
-}
-
-/* Returns the _d_dso_registry FUNCTION_DECL.  */
-
-static tree
-get_dso_registry_fn (void)
-{
-  if (dso_registry_fn)
-    return dso_registry_fn;
-
-  tree dso_type = get_compiler_dso_type ();
-  tree fntype = build_function_type_list (void_type_node,
-					  build_pointer_type (dso_type),
-					  NULL_TREE);
-  dso_registry_fn = build_decl (UNKNOWN_LOCATION, FUNCTION_DECL,
-				get_identifier ("_d_dso_registry"), fntype);
-  TREE_PUBLIC (dso_registry_fn) = 1;
-  DECL_EXTERNAL (dso_registry_fn) = 1;
-
-  return dso_registry_fn;
-}
-
-/* Depending on CTOR_P, builds and emits eiter a constructor or destructor
-   calling _d_dso_registry if `dso_initialized' is `false' in a constructor
-   or `true' in a destructor.  */
-
-static tree
-build_dso_cdtor_fn (bool ctor_p)
-{
-  const char *name = ctor_p ? GDC_PREFIX ("dso_ctor") : GDC_PREFIX ("dso_dtor");
-  tree condition = ctor_p ? boolean_true_node : boolean_false_node;
-
-  /* Declaration of dso_ctor/dso_dtor is:
-
-     extern(C) void dso_{c,d}tor (void)
-     {
-	if (dso_initialized != condition)
-	{
-	    dso_initialized = condition;
-	    CompilerDSOData dso = {1, &dsoSlot, &__start_minfo, &__stop_minfo};
-	    _d_dso_registry (&dso);
-	}
-    }
-   */
-  Visibility visibility;
-  visibility.kind = Visibility::public_;
-  FuncDeclaration *fd = get_internal_fn (get_identifier (name), visibility);
-  tree decl = get_symbol_decl (fd);
-
-  TREE_PUBLIC (decl) = 1;
-  DECL_ARTIFICIAL (decl) = 1;
-  DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
-  DECL_VISIBILITY_SPECIFIED (decl) = 1;
-
-  /* Start laying out the body.  */
-  tree old_context = start_function (fd);
-  rest_of_decl_compilation (decl, 1, 0);
-
-  /* if (dso_initialized != condition).  */
-  tree if_cond = build_boolop (NE_EXPR, dso_initialized_node, condition);
-
-  /* dso_initialized = condition;  */
-  tree expr_list = modify_expr (dso_initialized_node, condition);
-
-  /* CompilerDSOData dso = {1, &dsoSlot, &__start_minfo, &__stop_minfo};  */
-  tree dso_type = get_compiler_dso_type ();
-  tree dso = build_local_temp (dso_type);
-
-  vec <constructor_elt, va_gc> *ve = NULL;
-  CONSTRUCTOR_APPEND_ELT (ve, NULL_TREE, build_integer_cst (1, size_type_node));
-  CONSTRUCTOR_APPEND_ELT (ve, NULL_TREE, build_address (dso_slot_node));
-  CONSTRUCTOR_APPEND_ELT (ve, NULL_TREE, build_address (start_minfo_node));
-  CONSTRUCTOR_APPEND_ELT (ve, NULL_TREE, build_address (stop_minfo_node));
-
-  tree assign_expr = modify_expr (dso, build_struct_literal (dso_type, ve));
-  expr_list = compound_expr (expr_list, assign_expr);
-
-  /* _d_dso_registry (&dso);  */
-  tree call_expr = build_call_expr (get_dso_registry_fn (), 1,
-				    build_address (dso));
-  expr_list = compound_expr (expr_list, call_expr);
-
-  add_stmt (build_vcondition (if_cond, expr_list, void_node));
-  finish_function (old_context);
-
-  return decl;
-}
-
-/* Build a variable used in the dso_registry code identified by NAME,
-   and data type TYPE.  The variable always has VISIBILITY_HIDDEN and
-   TREE_PUBLIC flags set.  */
-
-static tree
-build_dso_registry_var (const char * name, tree type)
-{
-  tree var = declare_extern_var (get_identifier (name), type);
-  DECL_VISIBILITY (var) = VISIBILITY_HIDDEN;
-  DECL_VISIBILITY_SPECIFIED (var) = 1;
-  return var;
-}
-
-/* Place a reference to the ModuleInfo symbol MINFO for DECL into the
-   `minfo' section.  Then create the global ctors/dtors to call the
-   _d_dso_registry function if necessary.  */
+/* Place a reference to the ModuleInfo symbol MINFO for DECL into the designated
+   `minfo' section for the target.  */
 
 static void
 register_moduleinfo (Module *decl, tree minfo)
@@ -427,41 +266,6 @@  register_moduleinfo (Module *decl, tree minfo)
   symtab_node::get (mref)->implicit_section = true;
   d_pushdecl (mref);
   rest_of_decl_compilation (mref, 1, 0);
-
-  /* Only for the first D module being emitted do we need to generate a static
-     constructor and destructor for.  These are only required once per shared
-     library, so it's safe to emit them only once per object file.  */
-  static bool first_module = true;
-  if (!first_module)
-    return;
-
-  start_minfo_node = build_dso_registry_var (targetdm.d_minfo_start_name,
-					     ptr_type_node);
-  rest_of_decl_compilation (start_minfo_node, 1, 0);
-
-  stop_minfo_node = build_dso_registry_var (targetdm.d_minfo_end_name,
-					    ptr_type_node);
-  rest_of_decl_compilation (stop_minfo_node, 1, 0);
-
-  /* Declare dso_slot and dso_initialized.  */
-  dso_slot_node = build_dso_registry_var (GDC_PREFIX ("dso_slot"),
-					  ptr_type_node);
-  d_finish_decl (dso_slot_node);
-
-  dso_initialized_node = build_dso_registry_var (GDC_PREFIX ("dso_initialized"),
-						 boolean_type_node);
-  d_finish_decl (dso_initialized_node);
-
-  /* Declare dso_ctor() and dso_dtor().  */
-  tree dso_ctor = build_dso_cdtor_fn (true);
-  DECL_STATIC_CONSTRUCTOR (dso_ctor) = 1;
-  decl_init_priority_insert (dso_ctor, DEFAULT_INIT_PRIORITY);
-
-  tree dso_dtor = build_dso_cdtor_fn (false);
-  DECL_STATIC_DESTRUCTOR (dso_dtor) = 1;
-  decl_fini_priority_insert (dso_dtor, DEFAULT_INIT_PRIORITY);
-
-  first_module = false;
 }
 
 /* Convenience function for layout_moduleinfo_fields.  Adds a field of TYPE to
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index b0ea39884aa..4c095d5d1e9 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -11039,18 +11039,6 @@  collect all modules for each loaded shared library and executable.  The
 default value of @code{NULL} disables the use of sections altogether.
 @end deftypevr
 
-@deftypevr {D Target Hook} {const char *} TARGET_D_MINFO_START_NAME
-If @code{TARGET_D_MINFO_SECTION} is defined, then this must also be defined
-as the name of the symbol indicating the start address of the module info
-section
-@end deftypevr
-
-@deftypevr {D Target Hook} {const char *} TARGET_D_MINFO_END_NAME
-If @code{TARGET_D_MINFO_SECTION} is defined, then this must also be defined
-as the name of the symbol indicating the end address of the module info
-section
-@end deftypevr
-
 @deftypefn {D Target Hook} bool TARGET_D_HAS_STDCALL_CONVENTION (unsigned int *@var{link_system}, unsigned int *@var{link_windows})
 Returns @code{true} if the target supports the stdcall calling convention.
 The hook should also set @var{link_system} to @code{1} if the @code{stdcall}
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index f869ddd5e5b..ac880b3d681 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -7319,10 +7319,6 @@  floating-point support; they are not included in this mechanism.
 
 @hook TARGET_D_MINFO_SECTION
 
-@hook TARGET_D_MINFO_START_NAME
-
-@hook TARGET_D_MINFO_END_NAME
-
 @hook TARGET_D_HAS_STDCALL_CONVENTION
 
 @hook TARGET_D_TEMPLATES_ALWAYS_COMDAT
diff --git a/gcc/testsuite/lib/gdc-utils.exp b/gcc/testsuite/lib/gdc-utils.exp
index ffbaa277e8e..e32efe35d0d 100644
--- a/gcc/testsuite/lib/gdc-utils.exp
+++ b/gcc/testsuite/lib/gdc-utils.exp
@@ -75,6 +75,9 @@  proc gdc-convert-args { args } {
 	} elseif [string match "-c" $arg] {
 	    lappend out "-c"
 
+	} elseif [string match "-defaultlib=" $arg] {
+	    lappend out "-nophoboslib"
+
 	} elseif [regexp -- {^-check=(\w+)=off} $arg pattern value] {
 	    lappend out "-fno-check=$value"
 
diff --git a/libphobos/Makefile.in b/libphobos/Makefile.in
index 2e9360a5238..73705ae1928 100644
--- a/libphobos/Makefile.in
+++ b/libphobos/Makefile.in
@@ -222,7 +222,7 @@  DCFG_HAVE_64BIT_ATOMICS = @DCFG_HAVE_64BIT_ATOMICS@
 DCFG_HAVE_ATOMIC_BUILTINS = @DCFG_HAVE_ATOMIC_BUILTINS@
 DCFG_HAVE_LIBATOMIC = @DCFG_HAVE_LIBATOMIC@
 DCFG_HAVE_QSORT_R = @DCFG_HAVE_QSORT_R@
-DCFG_MINFO_BRACKETING = @DCFG_MINFO_BRACKETING@
+DCFG_NAMED_SECTIONS = @DCFG_NAMED_SECTIONS@
 DCFG_THREAD_MODEL = @DCFG_THREAD_MODEL@
 DEFS = @DEFS@
 DSYMUTIL = @DSYMUTIL@
diff --git a/libphobos/configure b/libphobos/configure
index 9da06f087d0..10dbcb22987 100755
--- a/libphobos/configure
+++ b/libphobos/configure
@@ -657,9 +657,7 @@  DCFG_HAVE_ATOMIC_BUILTINS
 DCFG_HAVE_QSORT_R
 OS_LINK_SPEC
 DCFG_DLPI_TLS_MODID
-DRUNTIME_OS_MINFO_BRACKETING_FALSE
-DRUNTIME_OS_MINFO_BRACKETING_TRUE
-DCFG_MINFO_BRACKETING
+DCFG_NAMED_SECTIONS
 DRUNTIME_OS_ARM_EABI_UNWINDER_FALSE
 DRUNTIME_OS_ARM_EABI_UNWINDER_TRUE
 DCFG_ARM_EABI_UNWINDER
@@ -825,7 +823,7 @@  PACKAGE_TARNAME
 PACKAGE_NAME
 PATH_SEPARATOR
 SHELL'
-ac_subst_files='DRTSTUFF_SPEC'
+ac_subst_files=''
 ac_user_opts='
 enable_option_checking
 enable_multilib
@@ -11750,7 +11748,7 @@  else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 11753 "configure"
+#line 11751 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -11856,7 +11854,7 @@  else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 11859 "configure"
+#line 11857 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -14430,53 +14428,31 @@  ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
 ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
 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
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for named sections support" >&5
+$as_echo_n "checking for named sections support... " >&6; }
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
-    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 __attribute__((section ("minfo"))) modref;
 
-    int main()
-    {
-        // Never run, just to prevent compiler from optimizing access
-        return (int)(&stop_minfo - &start_minfo);
-    }
+int
+main ()
+{
 
+  ;
+  return 0;
+}
 _ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"; then :
   { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
-     DCFG_MINFO_BRACKETING=true
+     DCFG_NAMED_SECTIONS=true
 else
   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
-     DCFG_MINFO_BRACKETING=false
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext conftest.$ac_ext
-
-   if test "$DCFG_MINFO_BRACKETING" = "true"; then
-  DRUNTIME_OS_MINFO_BRACKETING_TRUE=
-  DRUNTIME_OS_MINFO_BRACKETING_FALSE='#'
-else
-  DRUNTIME_OS_MINFO_BRACKETING_TRUE='#'
-  DRUNTIME_OS_MINFO_BRACKETING_FALSE=
+     DCFG_NAMED_SECTIONS=false
 fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 
   ac_ext=c
 ac_cpp='$CPP $CPPFLAGS'
@@ -15541,14 +15517,6 @@  IFS="$ac_save_IFS"
 CHECKING_DFLAGS="$RELEASE_FLAG $ASSERT_FLAG"
 
 
-# Add drtbegin.o/drtend.o to startfile/endfile specs in libgphobos.spec
-if test "$DCFG_MINFO_BRACKETING" = "false"; then
-    DRTSTUFF_SPEC=$srcdir/src/drtstuff.spec
-else
-    DRTSTUFF_SPEC=/dev/null
-fi
-
-
 # Add dependencies for libgphobos.spec file
 SPEC_PHOBOS_DEPS="$LIBS"
 
@@ -15802,10 +15770,6 @@  if test -z "${DRUNTIME_OS_ARM_EABI_UNWINDER_TRUE}" && test -z "${DRUNTIME_OS_ARM
   as_fn_error $? "conditional \"DRUNTIME_OS_ARM_EABI_UNWINDER\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
 fi
-if test -z "${DRUNTIME_OS_MINFO_BRACKETING_TRUE}" && test -z "${DRUNTIME_OS_MINFO_BRACKETING_FALSE}"; then
-  as_fn_error $? "conditional \"DRUNTIME_OS_MINFO_BRACKETING\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
 if test -z "${ENABLE_LIBPHOBOS_TRUE}" && test -z "${ENABLE_LIBPHOBOS_FALSE}"; then
   as_fn_error $? "conditional \"ENABLE_LIBPHOBOS\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
@@ -16814,24 +16778,7 @@  ac_tmp=$tmp
 # This happens for instance with `./config.status config.h'.
 if test -n "$CONFIG_FILES"; then
 
-if $AWK 'BEGIN { getline <"/dev/null" }' </dev/null 2>/dev/null; then
-  ac_cs_awk_getline=:
-  ac_cs_awk_pipe_init=
-  ac_cs_awk_read_file='
-      while ((getline aline < (F[key])) > 0)
-	print(aline)
-      close(F[key])'
-  ac_cs_awk_pipe_fini=
-else
-  ac_cs_awk_getline=false
-  ac_cs_awk_pipe_init="print \"cat <<'|#_!!_#|' &&\""
-  ac_cs_awk_read_file='
-      print "|#_!!_#|"
-      print "cat " F[key] " &&"
-      '$ac_cs_awk_pipe_init
-  # The final `:' finishes the AND list.
-  ac_cs_awk_pipe_fini='END { print "|#_!!_#|"; print ":" }'
-fi
+
 ac_cr=`echo X | tr X '\015'`
 # On cygwin, bash can eat \r inside `` if the user requested igncr.
 # But we know of no other shell where ac_cr would be empty at this
@@ -16849,17 +16796,6 @@  fi
 echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
 _ACEOF
 
-# Create commands to substitute file output variables.
-{
-  echo "cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1" &&
-  echo 'cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&' &&
-  echo "$ac_subst_files" | sed 's/.*/F["&"]="$&"/' &&
-  echo "_ACAWK" &&
-  echo "_ACEOF"
-} >conf$$files.sh &&
-. ./conf$$files.sh ||
-  as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
-rm -f conf$$files.sh
 
 {
   echo "cat >conf$$subs.awk <<_ACEOF" &&
@@ -16936,7 +16872,7 @@  _ACAWK
 cat >>"\$ac_tmp/subs1.awk" <<_ACAWK &&
   for (key in S) S_is_set[key] = 1
   FS = ""
-  \$ac_cs_awk_pipe_init
+
 }
 {
   line = $ 0
@@ -16954,16 +16890,10 @@  cat >>"\$ac_tmp/subs1.awk" <<_ACAWK &&
     } else
       len += 1 + keylen
   }
-  if (nfields == 3 && !substed) {
-    key = field[2]
-    if (F[key] != "" && line ~ /^[	 ]*@.*@[	 ]*$/) {
-      \$ac_cs_awk_read_file
-      next
-    }
-  }
+
   print line
 }
-\$ac_cs_awk_pipe_fini
+
 _ACAWK
 _ACEOF
 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
@@ -17310,12 +17240,7 @@  s&@INSTALL@&$ac_INSTALL&;t t
 s&@MKDIR_P@&$ac_MKDIR_P&;t t
 $ac_datarootdir_hack
 "
-eval sed \"\$ac_sed_extra\" "$ac_file_inputs" |
-if $ac_cs_awk_getline; then
-  $AWK -f "$ac_tmp/subs.awk"
-else
-  $AWK -f "$ac_tmp/subs.awk" | $SHELL
-fi \
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
   >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5
 
 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
diff --git a/libphobos/configure.ac b/libphobos/configure.ac
index 31209ba2920..d1c0e911285 100644
--- a/libphobos/configure.ac
+++ b/libphobos/configure.ac
@@ -142,7 +142,7 @@  DRUNTIME_CPU_SOURCES
 DRUNTIME_OS_SOURCES
 DRUNTIME_OS_THREAD_MODEL
 DRUNTIME_OS_ARM_EABI_UNWINDER
-DRUNTIME_OS_MINFO_BRACKETING
+DRUNTIME_OS_NAMED_SECTIONS
 DRUNTIME_OS_DLPI_TLS_MODID
 DRUNTIME_OS_LINK_SPEC
 DRUNTIME_LIBRARIES_CLIB
@@ -240,14 +240,6 @@  IFS="$ac_save_IFS"
 CHECKING_DFLAGS="$RELEASE_FLAG $ASSERT_FLAG"
 AC_SUBST(CHECKING_DFLAGS)
 
-# Add drtbegin.o/drtend.o to startfile/endfile specs in libgphobos.spec
-if test "$DCFG_MINFO_BRACKETING" = "false"; then
-    DRTSTUFF_SPEC=$srcdir/src/drtstuff.spec
-else
-    DRTSTUFF_SPEC=/dev/null
-fi
-AC_SUBST_FILE(DRTSTUFF_SPEC)
-
 # Add dependencies for libgphobos.spec file
 SPEC_PHOBOS_DEPS="$LIBS"
 AC_SUBST(SPEC_PHOBOS_DEPS)
diff --git a/libphobos/libdruntime/Makefile.am b/libphobos/libdruntime/Makefile.am
index 56b332d4efa..36889f7ccd1 100644
--- a/libphobos/libdruntime/Makefile.am
+++ b/libphobos/libdruntime/Makefile.am
@@ -104,17 +104,17 @@  if DRUNTIME_CPU_S390
 endif
 
 # Provide __start_minfo, __stop_minfo if linker doesn't.
-if !DRUNTIME_OS_MINFO_BRACKETING
-    DRTSTUFF = gcc/drtbegin.o gcc/drtend.o
+DRTSTUFF = gcc/drtbegin.o gcc/drtend.o
 
-    toolexeclib_DATA = $(DRTSTUFF)
+toolexeclib_DATA = $(DRTSTUFF)
 
-gcc/drtbegin.o: gcc/drtstuff.c
-	$(COMPILE) -DDRT_BEGIN -c -o $@ $<
+gcc/drtbegin.o: gcc/drtstuff.d
+	$(GDC) -fno-druntime -fversion=DRT_BEGIN $(GDCFLAGS) $(MULTIFLAGS) \
+		$(D_EXTRA_DFLAGS) -c -o $@ $<
 
-gcc/drtend.o: gcc/drtstuff.c
-	$(COMPILE) -DDRT_END -c -o $@ $<
-endif
+gcc/drtend.o: gcc/drtstuff.d
+	$(GDC) -fno-druntime -fversion=DRT_END $(GDCFLAGS) $(MULTIFLAGS) \
+		$(D_EXTRA_DFLAGS) -c -o $@ $<
 
 # Generated by configure
 DRUNTIME_DSOURCES_GENERATED = gcc/config.d gcc/libbacktrace.d
diff --git a/libphobos/libdruntime/Makefile.in b/libphobos/libdruntime/Makefile.in
index 24865fb258a..7c911e5cfd4 100644
--- a/libphobos/libdruntime/Makefile.in
+++ b/libphobos/libdruntime/Makefile.in
@@ -620,7 +620,7 @@  DCFG_HAVE_64BIT_ATOMICS = @DCFG_HAVE_64BIT_ATOMICS@
 DCFG_HAVE_ATOMIC_BUILTINS = @DCFG_HAVE_ATOMIC_BUILTINS@
 DCFG_HAVE_LIBATOMIC = @DCFG_HAVE_LIBATOMIC@
 DCFG_HAVE_QSORT_R = @DCFG_HAVE_QSORT_R@
-DCFG_MINFO_BRACKETING = @DCFG_MINFO_BRACKETING@
+DCFG_NAMED_SECTIONS = @DCFG_NAMED_SECTIONS@
 DCFG_THREAD_MODEL = @DCFG_THREAD_MODEL@
 DEFS = @DEFS@
 DSYMUTIL = @DSYMUTIL@
@@ -792,8 +792,8 @@  DRUNTIME_SOURCES_CONFIGURED = $(am__append_1) $(am__append_2) \
 	$(am__append_18)
 
 # Provide __start_minfo, __stop_minfo if linker doesn't.
-@DRUNTIME_OS_MINFO_BRACKETING_FALSE@DRTSTUFF = gcc/drtbegin.o gcc/drtend.o
-@DRUNTIME_OS_MINFO_BRACKETING_FALSE@toolexeclib_DATA = $(DRTSTUFF)
+DRTSTUFF = gcc/drtbegin.o gcc/drtend.o
+toolexeclib_DATA = $(DRTSTUFF)
 
 # Generated by configure
 DRUNTIME_DSOURCES_GENERATED = gcc/config.d gcc/libbacktrace.d
@@ -2489,11 +2489,13 @@  uninstall-am: uninstall-toolexeclibDATA \
 .d.lo:
 	$(LTDCOMPILE) $(GDCFLAGS) $(MULTIFLAGS) $(D_EXTRA_DFLAGS) -c -o $@ $<
 
-@DRUNTIME_OS_MINFO_BRACKETING_FALSE@gcc/drtbegin.o: gcc/drtstuff.c
-@DRUNTIME_OS_MINFO_BRACKETING_FALSE@	$(COMPILE) -DDRT_BEGIN -c -o $@ $<
+gcc/drtbegin.o: gcc/drtstuff.d
+	$(GDC) -fno-druntime -fversion=DRT_BEGIN $(GDCFLAGS) $(MULTIFLAGS) \
+		$(D_EXTRA_DFLAGS) -c -o $@ $<
 
-@DRUNTIME_OS_MINFO_BRACKETING_FALSE@gcc/drtend.o: gcc/drtstuff.c
-@DRUNTIME_OS_MINFO_BRACKETING_FALSE@	$(COMPILE) -DDRT_END -c -o $@ $<
+gcc/drtend.o: gcc/drtstuff.d
+	$(GDC) -fno-druntime -fversion=DRT_END $(GDCFLAGS) $(MULTIFLAGS) \
+		$(D_EXTRA_DFLAGS) -c -o $@ $<
 
 # Handles generated files as well
 install-data-local:
diff --git a/libphobos/libdruntime/gcc/config.d.in b/libphobos/libdruntime/gcc/config.d.in
index eaf47beaf9a..b299e64c209 100644
--- a/libphobos/libdruntime/gcc/config.d.in
+++ b/libphobos/libdruntime/gcc/config.d.in
@@ -52,3 +52,6 @@  enum Have_Qsort_R = @DCFG_HAVE_QSORT_R@;
 
 // Whether libphobos been configured with --enable-cet.
 enum GNU_Enable_CET = @DCFG_ENABLE_CET@;
+
+// Whether the target supports named sections for ModuleInfo support.
+enum OS_Have_Named_Sections = @DCFG_NAMED_SECTIONS@;
diff --git a/libphobos/libdruntime/gcc/drtstuff.c b/libphobos/libdruntime/gcc/drtstuff.c
deleted file mode 100644
index cc05e7c2a6a..00000000000
--- a/libphobos/libdruntime/gcc/drtstuff.c
+++ /dev/null
@@ -1,39 +0,0 @@ 
-/* Provide minfo section bracketing for D executables and shared libraries
-   when the linker doesn't provide it.
-   Copyright (C) 2019-2022 Free Software Foundation, Inc.
-
-This file is part of GCC.
-
-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/>.  */
-
-/* Avoid interference with targets without support for named sections.  */
-#ifdef __ELF__
-
-#ifdef DRT_BEGIN
-void *__start_minfo[]
-__attribute__((used, section("minfo"), aligned(sizeof(void *)))) = { };
-#endif
-
-#ifdef DRT_END
-void *__stop_minfo[]
-__attribute__((used, section("minfo"), aligned(sizeof(void *)))) = { };
-#endif
-
-#endif /* __ELF__ */
diff --git a/libphobos/libdruntime/gcc/drtstuff.d b/libphobos/libdruntime/gcc/drtstuff.d
new file mode 100644
index 00000000000..7d3e2ad0eaf
--- /dev/null
+++ b/libphobos/libdruntime/gcc/drtstuff.d
@@ -0,0 +1,105 @@ 
+/* Provide minfo section bracketing for D executables and shared libraries,
+   and register modules with D runtime.
+   Copyright (C) 2019-2022 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+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/>.  */
+
+import gcc.config;
+import gcc.attributes;
+import gcc.sections.common;
+
+private:
+
+// Avoid interference with targets without support for named sections.
+static if (OS_Have_Named_Sections):
+
+// Section names - keep this in sync with TARGET_D_MINFO_SECTION.
+version (Windows)
+{
+    enum minfo_section = "minfo";
+    enum minfo_start_name = "__start_minfo";
+    enum minfo_end_name = "__stop_minfo";
+}
+else version (OSX)
+{
+    enum minfo_section = "__DATA,__minfodata";
+    enum minfo_start_name = "*section$start$__DATA$__minfodata";
+    enum minfo_end_name = "*section$end$__DATA$__minfodata";
+}
+else version (Posix)
+{
+    enum minfo_section = "minfo";
+    enum minfo_start_name = "__start_minfo";
+    enum minfo_end_name = "__stop_minfo";
+}
+
+extern(C)
+{
+    extern void _d_dso_registry(CompilerDSOData*);
+}
+
+// All variables and functions should be unique in every shared object.
+@hidden @used:
+
+version (DRT_BEGIN)
+{
+    // Per-DSO data that is passed to the DSO registry function.
+    __gshared CompilerDSOData dsoData;
+
+    // This is the handle the DSO registry uses to determine whether the
+    // shared object has been registered against D runtime.
+    __gshared void* dsoSlot;
+
+    // Registers this DSO with D runtime.
+    pragma(crt_constructor)
+    void register_dso()
+    {
+        dsoData._version = 1;
+        dsoData._slot = &dsoSlot;
+        dsoData._minfo_beg = __start_minfo.ptr;
+        dsoData._minfo_end = __stop_minfo.ptr;
+        _d_dso_registry(&dsoData);
+    }
+
+    // Unregisters this DSO from D runtime.
+    pragma(crt_destructor)
+    void unregister_dso()
+    {
+        _d_dso_registry(&dsoData);
+    }
+
+    // Special symbols for bracketing the minfo section.
+    extern(C) __gshared
+    {
+        pragma(mangle, minfo_start_name)
+        @section(minfo_section) immutable(ModuleInfo*)[0] __start_minfo;
+
+        pragma(mangle, minfo_end_name)
+        extern @section(minfo_section) immutable(ModuleInfo*)[0] __stop_minfo;
+    }
+}
+
+version (DRT_END)
+{
+    pragma(mangle, minfo_end_name)
+    @section(minfo_section) __gshared immutable(ModuleInfo*)[0] __stop_minfo;
+}
diff --git a/libphobos/libdruntime/gcc/sections/common.d b/libphobos/libdruntime/gcc/sections/common.d
index 5fda4ca7460..6a27dd55813 100644
--- a/libphobos/libdruntime/gcc/sections/common.d
+++ b/libphobos/libdruntime/gcc/sections/common.d
@@ -37,3 +37,14 @@  package(gcc) void safeAssert(
     import core.internal.abort;
     condition || abort(msg, file, line);
 }
+
+/**
+ * The data structure passed to _d_dso_registry() from drtstuff.
+ */
+struct CompilerDSOData
+{
+    size_t _version;                            // currently 1
+    void** _slot;                               // can be used to store runtime data
+    immutable(object.ModuleInfo*)* _minfo_beg;  // array of modules in this object file
+    immutable(object.ModuleInfo*)* _minfo_end;
+}
diff --git a/libphobos/libdruntime/gcc/sections/elf.d b/libphobos/libdruntime/gcc/sections/elf.d
index 5819811f3fe..21f3d6c838c 100644
--- a/libphobos/libdruntime/gcc/sections/elf.d
+++ b/libphobos/libdruntime/gcc/sections/elf.d
@@ -412,17 +412,6 @@  else
 // 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
diff --git a/libphobos/libdruntime/gcc/sections/macho.d b/libphobos/libdruntime/gcc/sections/macho.d
index 84083668e2c..1faaa0ffa86 100644
--- a/libphobos/libdruntime/gcc/sections/macho.d
+++ b/libphobos/libdruntime/gcc/sections/macho.d
@@ -309,17 +309,6 @@  struct MachHeader
     intptr_t slide;             // virtural memory address slide amount
 }
 
-/****
- * 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
diff --git a/libphobos/libdruntime/gcc/sections/pecoff.d b/libphobos/libdruntime/gcc/sections/pecoff.d
index fd2779800e0..30a56aa48a5 100644
--- a/libphobos/libdruntime/gcc/sections/pecoff.d
+++ b/libphobos/libdruntime/gcc/sections/pecoff.d
@@ -304,17 +304,6 @@  else
 // 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
diff --git a/libphobos/m4/druntime/os.m4 b/libphobos/m4/druntime/os.m4
index 15cde3b04b8..3d8e9d888e5 100644
--- a/libphobos/m4/druntime/os.m4
+++ b/libphobos/m4/druntime/os.m4
@@ -144,45 +144,23 @@  AC_DEFUN([DRUNTIME_OS_ARM_EABI_UNWINDER],
 ])
 
 
-# DRUNTIME_OS_MINFO_BRACKETING
+# DRUNTIME_OS_NAMED_SECTIONS
 # ----------------------------
-# Check if the linker provides __start_minfo and __stop_minfo symbols and
-# substitute DCFG_MINFO_BRACKETING.
-AC_DEFUN([DRUNTIME_OS_MINFO_BRACKETING],
+# Check if named sections are supported, and substitute DCFG_NAMED_SECTIONS.
+AC_DEFUN([DRUNTIME_OS_NAMED_SECTIONS],
 [
   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 ("$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 (int)(&stop_minfo - &start_minfo);
-    }
+  AC_MSG_CHECKING([for named sections support])
+  AC_COMPILE_IFELSE([AC_LANG_PROGRAM([
+    int __attribute__((section ("minfo"))) modref;
   ])],
     [AC_MSG_RESULT([yes])
-     DCFG_MINFO_BRACKETING=true],
+     DCFG_NAMED_SECTIONS=true],
     [AC_MSG_RESULT([no])
-     DCFG_MINFO_BRACKETING=false])
-  AC_SUBST(DCFG_MINFO_BRACKETING)
-  AM_CONDITIONAL([DRUNTIME_OS_MINFO_BRACKETING], [test "$DCFG_MINFO_BRACKETING" = "true"])
+     DCFG_NAMED_SECTIONS=false])
+  AC_SUBST(DCFG_NAMED_SECTIONS)
   AC_LANG_POP([C])
 ])
 
diff --git a/libphobos/src/Makefile.in b/libphobos/src/Makefile.in
index 6f58fee01ac..51e9fae96d7 100644
--- a/libphobos/src/Makefile.in
+++ b/libphobos/src/Makefile.in
@@ -365,7 +365,7 @@  DCFG_HAVE_64BIT_ATOMICS = @DCFG_HAVE_64BIT_ATOMICS@
 DCFG_HAVE_ATOMIC_BUILTINS = @DCFG_HAVE_ATOMIC_BUILTINS@
 DCFG_HAVE_LIBATOMIC = @DCFG_HAVE_LIBATOMIC@
 DCFG_HAVE_QSORT_R = @DCFG_HAVE_QSORT_R@
-DCFG_MINFO_BRACKETING = @DCFG_MINFO_BRACKETING@
+DCFG_NAMED_SECTIONS = @DCFG_NAMED_SECTIONS@
 DCFG_THREAD_MODEL = @DCFG_THREAD_MODEL@
 DEFS = @DEFS@
 DSYMUTIL = @DSYMUTIL@
diff --git a/libphobos/src/libgphobos.spec.in b/libphobos/src/libgphobos.spec.in
index 97a9ceaf48c..a6d86183cc2 100644
--- a/libphobos/src/libgphobos.spec.in
+++ b/libphobos/src/libgphobos.spec.in
@@ -4,7 +4,11 @@ 
 # order.
 #
 
-@DRTSTUFF_SPEC@
+%rename startfile startfile_orig
+*startfile: %(startfile_orig) drtbegin.o%s
+
+%rename endfile endfile_orig
+*endfile: %(endfile_orig) drtend.o%s
 
 %rename link linkorig_gdc_renamed
 *link: %(linkorig_gdc_renamed) @OS_LINK_SPEC@
diff --git a/libphobos/testsuite/Makefile.in b/libphobos/testsuite/Makefile.in
index 885548018ba..79dc21c5014 100644
--- a/libphobos/testsuite/Makefile.in
+++ b/libphobos/testsuite/Makefile.in
@@ -166,7 +166,7 @@  DCFG_HAVE_64BIT_ATOMICS = @DCFG_HAVE_64BIT_ATOMICS@
 DCFG_HAVE_ATOMIC_BUILTINS = @DCFG_HAVE_ATOMIC_BUILTINS@
 DCFG_HAVE_LIBATOMIC = @DCFG_HAVE_LIBATOMIC@
 DCFG_HAVE_QSORT_R = @DCFG_HAVE_QSORT_R@
-DCFG_MINFO_BRACKETING = @DCFG_MINFO_BRACKETING@
+DCFG_NAMED_SECTIONS = @DCFG_NAMED_SECTIONS@
 DCFG_THREAD_MODEL = @DCFG_THREAD_MODEL@
 DEFS = @DEFS@
 DSYMUTIL = @DSYMUTIL@