Bug 938437 - Replace nsStaticXULComponents.cpp with smart use of sections. r=bsmedberg,irc-r=decoder,r=nfroyd
☠☠ backed out by ed4f3c12c532 ☠ ☠
authorMike Hommey <mh+mozilla@glandium.org>
Tue, 19 Nov 2013 13:45:31 +0900
changeset 157360 1eb6ceed2cdab03108bd5de27dfab737e5093822
parent 157359 2656e9b931148c0a487742944a2fdbb32a3e5ad0
child 157361 c30371a66429ff76a0af42baaa1afa172105db84
push id270
push userpvanderbeken@mozilla.com
push dateThu, 06 Mar 2014 09:24:21 +0000
reviewersbsmedberg, nfroyd
bugs938437
milestone28.0a1
Bug 938437 - Replace nsStaticXULComponents.cpp with smart use of sections. r=bsmedberg,irc-r=decoder,r=nfroyd
build/autoconf/compiler-opts.m4
config/rules.mk
js/src/build/autoconf/compiler-opts.m4
js/src/config/rules.mk
toolkit/library/Makefile.in
toolkit/library/StaticXULComponents.ld
toolkit/library/StaticXULComponentsEnd/StaticXULComponentsEnd.cpp
toolkit/library/StaticXULComponentsEnd/moz.build
toolkit/library/StaticXULComponentsStart.cpp
toolkit/library/moz.build
toolkit/library/nsStaticXULComponents.cpp
toolkit/toolkit.mozbuild
xpcom/components/Module.h
xpcom/components/nsComponentManager.cpp
--- a/build/autoconf/compiler-opts.m4
+++ b/build/autoconf/compiler-opts.m4
@@ -242,16 +242,23 @@ if test "$GNU_CC" -a -n "$MOZ_FORCE_GOLD
             if $CC -B $_objdir/build/unix/gold -Wl,--version 2>&1 | grep -q "GNU gold"; then
                 LDFLAGS="$LDFLAGS -B $_objdir/build/unix/gold"
             else
                 rm -rf $_objdir/build/unix/gold
             fi
         fi
     fi
 fi
+if test "$GNU_CC"; then
+    if $CC $LDFLAGS -Wl,--version 2>&1 | grep -q "GNU ld"; then
+        LD_IS_BFD=1
+    fi
+fi
+
+AC_SUBST([LD_IS_BFD])
 
 if test "$GNU_CC"; then
     if test -z "$DEVELOPER_OPTIONS"; then
         CFLAGS="$CFLAGS -ffunction-sections -fdata-sections"
         CXXFLAGS="$CXXFLAGS -ffunction-sections -fdata-sections"
     fi
     CFLAGS="$CFLAGS -fno-math-errno"
     CXXFLAGS="$CXXFLAGS -fno-exceptions -fno-math-errno"
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -772,16 +772,17 @@ endif	# MSVC with manifest tool
 ifdef MOZ_PROFILE_GENERATE
 # touch it a few seconds into the future to work around FAT's
 # 2-second granularity
 	touch -t `date +%Y%m%d%H%M.%S -d "now+5seconds"` pgo.relink
 endif
 else # !WINNT || GNU_CC
 	$(EXPAND_CCC) -o $@ $(CXXFLAGS) $(PROGOBJS) $(RESFILE) $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(WRAP_LDFLAGS) $(LIBS_DIR) $(LIBS) $(MOZ_GLUE_PROGRAM_LDFLAGS) $(OS_LIBS) $(EXTRA_LIBS) $(BIN_FLAGS) $(EXE_DEF_FILE) $(STLPORT_LIBS)
 	@$(call CHECK_STDCXX,$@)
+	@$(call LOCAL_CHECKS,$@)
 endif # WINNT && !GNU_CC
 
 ifdef ENABLE_STRIP
 	$(STRIP) $(STRIP_FLAGS) $@
 endif
 ifdef MOZ_POST_PROGRAM_COMMAND
 	$(MOZ_POST_PROGRAM_COMMAND) $@
 endif
@@ -828,16 +829,17 @@ ifdef MSMANIFEST_TOOL
 	@if test -f $@.manifest; then \
 		mt.exe -NOLOGO -MANIFEST $@.manifest -OUTPUTRESOURCE:$@\;1; \
 		rm -f $@.manifest; \
 	fi
 endif	# MSVC with manifest tool
 else
 	$(EXPAND_CCC) $(CXXFLAGS) -o $@ $< $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(WRAP_LDFLAGS) $(LIBS_DIR) $(LIBS) $(MOZ_GLUE_PROGRAM_LDFLAGS) $(OS_LIBS) $(EXTRA_LIBS) $(BIN_FLAGS) $(STLPORT_LIBS)
 	@$(call CHECK_STDCXX,$@)
+	@$(call LOCAL_CHECKS,$@)
 endif # WINNT && !GNU_CC
 
 ifdef ENABLE_STRIP
 	$(STRIP) $(STRIP_FLAGS) $@
 endif
 ifdef MOZ_POST_PROGRAM_COMMAND
 	$(MOZ_POST_PROGRAM_COMMAND) $@
 endif
@@ -930,16 +932,17 @@ ifndef XP_MACOSX
 	dtrace -G -C -s $(MOZILLA_DTRACE_SRC) -o  $(DTRACE_PROBE_OBJ) $(shell $(EXPAND_LIBS) $(MOZILLA_PROBE_LIBS))
 endif
 	$(EXPAND_MKSHLIB) $(SHLIB_LDSTARTFILE) $(OBJS) $(SUB_SHLOBJS) $(DTRACE_PROBE_OBJ) $(MOZILLA_PROBE_LIBS) $(RESFILE) $(LDFLAGS) $(WRAP_LDFLAGS) $(SHARED_LIBRARY_LIBS) $(EXTRA_DSO_LDOPTS) $(MOZ_GLUE_LDFLAGS) $(OS_LIBS) $(EXTRA_LIBS) $(DEF_FILE) $(SHLIB_LDENDFILE) $(if $(LIB_IS_C_ONLY),,$(STLPORT_LIBS))
 	@$(RM) $(DTRACE_PROBE_OBJ)
 else # ! DTRACE_LIB_DEPENDENT
 	$(EXPAND_MKSHLIB) $(SHLIB_LDSTARTFILE) $(OBJS) $(SUB_SHLOBJS) $(RESFILE) $(LDFLAGS) $(WRAP_LDFLAGS) $(SHARED_LIBRARY_LIBS) $(EXTRA_DSO_LDOPTS) $(MOZ_GLUE_LDFLAGS) $(OS_LIBS) $(EXTRA_LIBS) $(DEF_FILE) $(SHLIB_LDENDFILE) $(if $(LIB_IS_C_ONLY),,$(STLPORT_LIBS))
 endif # DTRACE_LIB_DEPENDENT
 	@$(call CHECK_STDCXX,$@)
+	@$(call LOCAL_CHECKS,$@)
 
 ifeq (_WINNT,$(GNU_CC)_$(OS_ARCH))
 ifdef MSMANIFEST_TOOL
 ifdef EMBED_MANIFEST_AT
 	@if test -f $@.manifest; then \
 		mt.exe -NOLOGO -MANIFEST $@.manifest -OUTPUTRESOURCE:$@\;$(EMBED_MANIFEST_AT); \
 		rm -f $@.manifest; \
 	fi
--- a/js/src/build/autoconf/compiler-opts.m4
+++ b/js/src/build/autoconf/compiler-opts.m4
@@ -242,16 +242,23 @@ if test "$GNU_CC" -a -n "$MOZ_FORCE_GOLD
             if $CC -B $_objdir/build/unix/gold -Wl,--version 2>&1 | grep -q "GNU gold"; then
                 LDFLAGS="$LDFLAGS -B $_objdir/build/unix/gold"
             else
                 rm -rf $_objdir/build/unix/gold
             fi
         fi
     fi
 fi
+if test "$GNU_CC"; then
+    if $CC $LDFLAGS -Wl,--version 2>&1 | grep -q "GNU ld"; then
+        LD_IS_BFD=1
+    fi
+fi
+
+AC_SUBST([LD_IS_BFD])
 
 if test "$GNU_CC"; then
     if test -z "$DEVELOPER_OPTIONS"; then
         CFLAGS="$CFLAGS -ffunction-sections -fdata-sections"
         CXXFLAGS="$CXXFLAGS -ffunction-sections -fdata-sections"
     fi
     CFLAGS="$CFLAGS -fno-math-errno"
     CXXFLAGS="$CXXFLAGS -fno-exceptions -fno-math-errno"
--- a/js/src/config/rules.mk
+++ b/js/src/config/rules.mk
@@ -772,16 +772,17 @@ endif	# MSVC with manifest tool
 ifdef MOZ_PROFILE_GENERATE
 # touch it a few seconds into the future to work around FAT's
 # 2-second granularity
 	touch -t `date +%Y%m%d%H%M.%S -d "now+5seconds"` pgo.relink
 endif
 else # !WINNT || GNU_CC
 	$(EXPAND_CCC) -o $@ $(CXXFLAGS) $(PROGOBJS) $(RESFILE) $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(WRAP_LDFLAGS) $(LIBS_DIR) $(LIBS) $(MOZ_GLUE_PROGRAM_LDFLAGS) $(OS_LIBS) $(EXTRA_LIBS) $(BIN_FLAGS) $(EXE_DEF_FILE) $(STLPORT_LIBS)
 	@$(call CHECK_STDCXX,$@)
+	@$(call LOCAL_CHECKS,$@)
 endif # WINNT && !GNU_CC
 
 ifdef ENABLE_STRIP
 	$(STRIP) $(STRIP_FLAGS) $@
 endif
 ifdef MOZ_POST_PROGRAM_COMMAND
 	$(MOZ_POST_PROGRAM_COMMAND) $@
 endif
@@ -828,16 +829,17 @@ ifdef MSMANIFEST_TOOL
 	@if test -f $@.manifest; then \
 		mt.exe -NOLOGO -MANIFEST $@.manifest -OUTPUTRESOURCE:$@\;1; \
 		rm -f $@.manifest; \
 	fi
 endif	# MSVC with manifest tool
 else
 	$(EXPAND_CCC) $(CXXFLAGS) -o $@ $< $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(WRAP_LDFLAGS) $(LIBS_DIR) $(LIBS) $(MOZ_GLUE_PROGRAM_LDFLAGS) $(OS_LIBS) $(EXTRA_LIBS) $(BIN_FLAGS) $(STLPORT_LIBS)
 	@$(call CHECK_STDCXX,$@)
+	@$(call LOCAL_CHECKS,$@)
 endif # WINNT && !GNU_CC
 
 ifdef ENABLE_STRIP
 	$(STRIP) $(STRIP_FLAGS) $@
 endif
 ifdef MOZ_POST_PROGRAM_COMMAND
 	$(MOZ_POST_PROGRAM_COMMAND) $@
 endif
@@ -930,16 +932,17 @@ ifndef XP_MACOSX
 	dtrace -G -C -s $(MOZILLA_DTRACE_SRC) -o  $(DTRACE_PROBE_OBJ) $(shell $(EXPAND_LIBS) $(MOZILLA_PROBE_LIBS))
 endif
 	$(EXPAND_MKSHLIB) $(SHLIB_LDSTARTFILE) $(OBJS) $(SUB_SHLOBJS) $(DTRACE_PROBE_OBJ) $(MOZILLA_PROBE_LIBS) $(RESFILE) $(LDFLAGS) $(WRAP_LDFLAGS) $(SHARED_LIBRARY_LIBS) $(EXTRA_DSO_LDOPTS) $(MOZ_GLUE_LDFLAGS) $(OS_LIBS) $(EXTRA_LIBS) $(DEF_FILE) $(SHLIB_LDENDFILE) $(if $(LIB_IS_C_ONLY),,$(STLPORT_LIBS))
 	@$(RM) $(DTRACE_PROBE_OBJ)
 else # ! DTRACE_LIB_DEPENDENT
 	$(EXPAND_MKSHLIB) $(SHLIB_LDSTARTFILE) $(OBJS) $(SUB_SHLOBJS) $(RESFILE) $(LDFLAGS) $(WRAP_LDFLAGS) $(SHARED_LIBRARY_LIBS) $(EXTRA_DSO_LDOPTS) $(MOZ_GLUE_LDFLAGS) $(OS_LIBS) $(EXTRA_LIBS) $(DEF_FILE) $(SHLIB_LDENDFILE) $(if $(LIB_IS_C_ONLY),,$(STLPORT_LIBS))
 endif # DTRACE_LIB_DEPENDENT
 	@$(call CHECK_STDCXX,$@)
+	@$(call LOCAL_CHECKS,$@)
 
 ifeq (_WINNT,$(GNU_CC)_$(OS_ARCH))
 ifdef MSMANIFEST_TOOL
 ifdef EMBED_MANIFEST_AT
 	@if test -f $@.manifest; then \
 		mt.exe -NOLOGO -MANIFEST $@.manifest -OUTPUTRESOURCE:$@\;$(EMBED_MANIFEST_AT); \
 		rm -f $@.manifest; \
 	fi
--- a/toolkit/library/Makefile.in
+++ b/toolkit/library/Makefile.in
@@ -64,59 +64,16 @@ symverscript: symverscript.in
 	$(call py_action,preprocessor, \
 		-DVERSION="$(LIBRARY_NAME)$(MOZILLA_SYMBOLVERSION)" $< -o $@)
 
 EXTRA_DEPS += symverscript
 endif
 endif
 
 # component libraries
-ifdef MOZ_JSDEBUGGER
-DEFINES += -DMOZ_JSDEBUGGER
-endif
-
-ifdef MOZ_PREF_EXTENSIONS
-DEFINES += -DMOZ_PREF_EXTENSIONS
-endif
-
-ifdef MOZ_AUTH_EXTENSION
-DEFINES += -DMOZ_AUTH_EXTENSION
-endif
-
-ifdef MOZ_PERMISSIONS
-DEFINES += -DMOZ_PERMISSIONS
-endif
-
-ifdef MOZ_UNIVERSALCHARDET
-DEFINES += -DMOZ_UNIVERSALCHARDET
-endif
-
-ifeq (,$(filter android gonk qt os2 cocoa windows,$(MOZ_WIDGET_TOOLKIT)))
-ifdef MOZ_XUL
-DEFINES += -DMOZ_FILEVIEW
-endif
-endif
-
-# Platform-specific icon channel stuff - supported mostly-everywhere
-ifneq (,$(filter windows os2 mac cocoa gtk2 gtk3 qt android,$(MOZ_WIDGET_TOOLKIT)))
-DEFINES += -DICON_DECODER
-endif
-
-ifdef MOZ_SPELLCHECK
-DEFINES += -DMOZ_SPELLCHECK
-endif
-
-ifdef MOZ_ZIPWRITER
-DEFINES += -DMOZ_ZIPWRITER
-endif
-
-ifdef MOZ_GIO_COMPONENT
-DEFINES += -DMOZ_GIO_COMPONENT
-endif
-
 ifdef MOZ_APP_COMPONENT_LIBS
 COMPONENT_LIBS += $(MOZ_APP_COMPONENT_LIBS)
 endif
 
 ifeq ($(MOZ_WIDGET_TOOLKIT),cocoa)
 OS_LIBS += -framework OpenGL -lcups
 endif
 
@@ -395,22 +352,16 @@ OS_LIBS += $(LIBICONV)
 DEFINES += \
   -DIMPL_LIBXUL \
   $(NULL)
 
 ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
 OS_LIBS += $(call EXPAND_LIBNAME,usp10 oleaut32)
 endif
 
-ifdef MOZ_DEBUG
-ifdef ENABLE_TESTS
-DEFINES += -DENABLE_LAYOUTDEBUG
-endif
-endif
-
 ifeq (WINNT_1,$(OS_TARGET)_$(MOZ_PROFILE_USE))
 # Wrap linker to measure peak virtual memory usage.
 LD := $(PYTHON) $(topsrcdir)/build/link.py $(CURDIR)/linker-vsize $(LD)
 endif
 
 ifndef LINK_GTEST
 ifdef COMPILE_ENVIRONMENT
 libs:: $(FINAL_TARGET)/dependentlibs.list
@@ -439,8 +390,37 @@ COMPONENT_LIBS += \
   gtest \
   gfxtest \
   ssltest \
   $(NULL)
 endif
 
 $(FINAL_TARGET)/dependentlibs.list: dependentlibs.py $(SHARED_LIBRARY) $(wildcard $(if $(wildcard $(FINAL_TARGET)/dependentlibs.list),$(addprefix $(FINAL_TARGET)/,$(shell cat $(FINAL_TARGET)/dependentlibs.list))))
 	$(PYTHON) $< $(SHARED_LIBRARY) -L $(FINAL_TARGET) $(if $(TOOLCHAIN_PREFIX),$(addprefix -p ,$(TOOLCHAIN_PREFIX))) > $@
+
+EXTRA_DSO_LDOPTS += $(call EXPAND_LIBNAME_PATH,StaticXULComponentsEnd,$(CURDIR)/StaticXULComponentsEnd)
+
+# BFD ld doesn't create multiple PT_LOADs as usual when an unknown section
+# exists. Using an implicit linker script to make it fold that section in
+# .data.rel.ro makes it create multiple PT_LOADs. That implicit linker
+# script however makes gold misbehave, first because it doesn't like that
+# the linker script is given after crtbegin.o, and even past that, replaces
+# the default section rules with those from the script instead of
+# supplementing them. Which leads to a lib with a huge load of sections.
+ifdef LD_IS_BFD
+EXTRA_DSO_LDOPTS += $(srcdir)/StaticXULComponents.ld
+endif
+
+# This, combined with the fact the file is first, makes the start pointer
+# first in Windows PGO builds.
+NO_PROFILE_GUIDED_OPTIMIZE = StaticXULComponentsStart.cpp
+
+ifeq (WINNT,$(OS_TARGET))
+get_first_and_last = dumpbin -exports $1 | grep _NSModule@@ | sort -k 3 | sed -n 's/^.*?\([^@]*\)@@.*$$/\1/;1p;$$p'
+else
+get_first_and_last = $(TOOLCHAIN_PREFIX)nm -g $1 | grep _NSModule$$ | sort | sed -n 's/^.* _*\([^ ]*\)$$/\1/;1p;$$p'
+endif
+
+LOCAL_CHECKS = test "$$($(get_first_and_last) | xargs echo)" != "start_kPStaticModules_NSModule end_kPStaticModules_NSModule" && echo "NSModules are not ordered appropriately" && exit 1 || exit 0
+
+ifeq (Linux,$(OS_ARCH))
+LOCAL_CHECKS += ; test "$$($(TOOLCHAIN_PREFIX)readelf -l $1 | awk '$1 == "LOAD" { t += 1 } END { print t }')" -le 1 && echo "Only one PT_LOAD segment" && exit 1 || exit 0
+endif
new file mode 100644
--- /dev/null
+++ b/toolkit/library/StaticXULComponents.ld
@@ -0,0 +1,5 @@
+SECTIONS {
+  .data.rel.ro : {
+    *(.kPStaticModules)
+  }
+}
new file mode 100644
--- /dev/null
+++ b/toolkit/library/StaticXULComponentsEnd/StaticXULComponentsEnd.cpp
@@ -0,0 +1,14 @@
+#include "mozilla/Module.h"
+#include "mozilla/NullPtr.h"
+
+/* Ensure end_kPStaticModules is at the end of the .kPStaticModules section
+ * on Windows. Somehow, placing the object last is not enough with PGO/LTCG. */
+#ifdef _MSC_VER
+/* Sections on Windows are in two parts, separated with $. When linking,
+ * sections with the same first part are all grouped, and ordered
+ * alphabetically with the second part as sort key. */
+#  pragma section(".kPStaticModules$Z", read)
+#  undef NSMODULE_SECTION
+#  define NSMODULE_SECTION __declspec(allocate(".kPStaticModules$Z"), dllexport)
+#endif
+NSMODULE_DEFN(end_kPStaticModules) = nullptr;
new file mode 100644
--- /dev/null
+++ b/toolkit/library/StaticXULComponentsEnd/moz.build
@@ -0,0 +1,11 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+SOURCES += [
+    'StaticXULComponentsEnd.cpp',
+]
+
+LIBRARY_NAME = 'StaticXULComponentsEnd'
+
+LIBXUL_LIBRARY = True
new file mode 100644
--- /dev/null
+++ b/toolkit/library/StaticXULComponentsStart.cpp
@@ -0,0 +1,4 @@
+#include "mozilla/Module.h"
+#include "mozilla/NullPtr.h"
+
+NSMODULE_DEFN(start_kPStaticModules) = nullptr;
--- a/toolkit/library/moz.build
+++ b/toolkit/library/moz.build
@@ -5,17 +5,17 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 if CONFIG['MOZ_METRO'] and CONFIG['OS_ARCH'] == 'WINNT':
     DIRS += ['winvccorlib']
 
 LIBRARY_NAME = 'xul'
 
 SOURCES += [
-    'nsStaticXULComponents.cpp',
+    'StaticXULComponentsStart.cpp',
 ]
 
 if CONFIG['OS_ARCH'] == 'WINNT':
     SOURCES += [
         'nsDllMain.cpp',
     ]
 
 MSVC_ENABLE_PGO = True
deleted file mode 100644
--- a/toolkit/library/nsStaticXULComponents.cpp
+++ /dev/null
@@ -1,267 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "mozilla/Module.h"
-#include "nsXPCOM.h"
-#include "nsMemory.h"
-
-#ifdef MOZ_AUTH_EXTENSION
-#define AUTH_MODULE    MODULE(nsAuthModule)
-#else
-#define AUTH_MODULE
-#endif
-
-#ifdef MOZ_PERMISSIONS
-#define PERMISSIONS_MODULES                  \
-    MODULE(nsCookieModule)                   \
-    MODULE(nsPermissionsModule)
-#else
-#define PERMISSIONS_MODULES
-#endif
-
-#ifdef MOZ_UNIVERSALCHARDET
-#define UNIVERSALCHARDET_MODULE MODULE(nsUniversalCharDetModule)
-#else
-#define UNIVERSALCHARDET_MODULE
-#endif
-
-#ifdef XP_WIN
-#  define WIDGET_MODULES MODULE(nsWidgetModule)
-#elif defined(XP_MACOSX)
-#  define WIDGET_MODULES MODULE(nsWidgetMacModule)
-#elif defined(XP_OS2)
-#  define WIDGET_MODULES MODULE(nsWidgetOS2Module)
-#elif defined(MOZ_WIDGET_GTK)
-#  define WIDGET_MODULES MODULE(nsWidgetGtk2Module)
-#elif defined(MOZ_WIDGET_QT)
-#  define WIDGET_MODULES MODULE(nsWidgetQtModule)
-#elif defined(MOZ_WIDGET_ANDROID)
-#  define WIDGET_MODULES MODULE(nsWidgetAndroidModule)
-#elif defined(MOZ_WIDGET_GONK)
-#  define WIDGET_MODULES MODULE(nsWidgetGonkModule)
-#else
-#  error Unknown widget module.
-#endif
-
-#ifdef ICON_DECODER
-#define ICON_MODULE MODULE(nsIconDecoderModule)
-#else
-#define ICON_MODULE
-#endif
-
-#ifdef MOZ_ENABLE_XREMOTE
-#define XREMOTE_MODULES MODULE(RemoteServiceModule)
-#else
-#define XREMOTE_MODULES
-#endif
-
-#ifdef MOZ_PREF_EXTENSIONS
-#define SYSTEMPREF_MODULES MODULE(nsAutoConfigModule)
-#else
-#define SYSTEMPREF_MODULES
-#endif
-
-#ifdef ENABLE_LAYOUTDEBUG
-#define LAYOUT_DEBUG_MODULE MODULE(nsLayoutDebugModule)
-#else
-#define LAYOUT_DEBUG_MODULE
-#endif
-
-#ifdef MOZ_JSDEBUGGER
-#define JSDEBUGGER_MODULES \
-    MODULE(JavaScript_Debugger)
-#else
-#define JSDEBUGGER_MODULES
-#endif
-
-#if defined(MOZ_FILEVIEW) && defined(MOZ_XUL)
-#define FILEVIEW_MODULE MODULE(nsFileViewModule)
-#else
-#define FILEVIEW_MODULE
-#endif
-
-#ifdef MOZ_ZIPWRITER
-#define ZIPWRITER_MODULE MODULE(ZipWriterModule)
-#else
-#define ZIPWRITER_MODULE
-#endif
-
-#ifdef MOZ_PLACES
-#define PLACES_MODULES \
-    MODULE(nsPlacesModule)
-#else
-#define PLACES_MODULES
-#endif
-
-#ifdef MOZ_XUL
-#define XULENABLED_MODULES                   \
-    MODULE(tkAutoCompleteModule)             \
-    MODULE(satchel)                          \
-    MODULE(PKI)
-#else
-#define XULENABLED_MODULES
-#endif
-
-#ifdef MOZ_SPELLCHECK
-#define SPELLCHECK_MODULE MODULE(mozSpellCheckerModule)
-#else
-#define SPELLCHECK_MODULE
-#endif
-
-#ifdef MOZ_XUL
-#ifdef MOZ_WIDGET_GTK
-#define UNIXPROXY_MODULE MODULE(nsUnixProxyModule)
-#endif
-#if defined(MOZ_WIDGET_QT)
-#define UNIXPROXY_MODULE MODULE(nsUnixProxyModule)
-#endif
-#endif
-#ifndef UNIXPROXY_MODULE
-#define UNIXPROXY_MODULE
-#endif
-
-#if defined(XP_MACOSX)
-#define OSXPROXY_MODULE MODULE(nsOSXProxyModule)
-#else
-#define OSXPROXY_MODULE
-#endif
-
-#if defined(XP_WIN)
-#define WINDOWSPROXY_MODULE MODULE(nsWindowsProxyModule)
-#else
-#define WINDOWSPROXY_MODULE
-#endif
-
-#if defined(MOZ_WIDGET_ANDROID)
-#define ANDROIDPROXY_MODULE MODULE(nsAndroidProxyModule)
-#else
-#define ANDROIDPROXY_MODULE
-#endif
-
-#if defined(BUILD_CTYPES)
-#define JSCTYPES_MODULE MODULE(jsctypes)
-#else
-#define JSCTYPES_MODULE
-#endif
-
-#ifndef MOZ_APP_COMPONENT_MODULES
-#if defined(MOZ_APP_COMPONENT_INCLUDE)
-#include MOZ_APP_COMPONENT_INCLUDE
-#define MOZ_APP_COMPONENT_MODULES APP_COMPONENT_MODULES
-#else
-#define MOZ_APP_COMPONENT_MODULES
-#endif
-#endif
-
-#if defined(MOZ_ENABLE_PROFILER_SPS)
-#define PROFILER_MODULE MODULE(nsProfilerModule)
-#else
-#define PROFILER_MODULE
-#endif
-
-#if defined(MOZ_WEBRTC)
-#define PEERCONNECTION_MODULE MODULE(peerconnection)
-#else
-#define PEERCONNECTION_MODULE
-#endif
-
-#if defined(MOZ_GIO_COMPONENT)
-#define GIO_MODULE MODULE(nsGIOModule)
-#else
-#define GIO_MODULE
-#endif
-
-#if defined(MOZ_SYNTH_PICO)
-#define SYNTH_PICO_MODULE MODULE(synthpico)
-#else
-#define SYNTH_PICO_MODULE
-#endif
-
-#define XUL_MODULES                          \
-    MODULE(nsUConvModule)                    \
-    MODULE(nsI18nModule)                     \
-    MODULE(nsChardetModule)                  \
-    UNIVERSALCHARDET_MODULE                  \
-    MODULE(necko)                            \
-    PERMISSIONS_MODULES                      \
-    AUTH_MODULE                              \
-    MODULE(nsJarModule)                      \
-    ZIPWRITER_MODULE                         \
-    MODULE(StartupCacheModule)               \
-    MODULE(nsPrefModule)                     \
-    MODULE(nsRDFModule)                      \
-    MODULE(nsWindowDataSourceModule)         \
-    MODULE(nsParserModule)                   \
-    MODULE(nsImageLib2Module)                \
-    MODULE(nsMediaSnifferModule)             \
-    MODULE(nsGfxModule)                      \
-    PROFILER_MODULE                          \
-    WIDGET_MODULES                           \
-    ICON_MODULE                              \
-    MODULE(nsPluginModule)                   \
-    MODULE(nsLayoutModule)                   \
-    MODULE(docshell_provider)                \
-    MODULE(embedcomponents)                  \
-    MODULE(Browser_Embedding_Module)         \
-    MODULE(appshell)                         \
-    MODULE(nsTransactionManagerModule)       \
-    MODULE(nsComposerModule)                 \
-    MODULE(application)                      \
-    MODULE(Apprunner)                        \
-    MODULE(CommandLineModule)                \
-    FILEVIEW_MODULE                          \
-    MODULE(mozStorageModule)                 \
-    PLACES_MODULES                           \
-    XULENABLED_MODULES                       \
-    MODULE(nsToolkitCompsModule)             \
-    XREMOTE_MODULES                          \
-    JSDEBUGGER_MODULES                       \
-    MODULE(BOOT)                             \
-    MODULE(NSS)                              \
-    SYSTEMPREF_MODULES                       \
-    SPELLCHECK_MODULE                        \
-    LAYOUT_DEBUG_MODULE                      \
-    UNIXPROXY_MODULE                         \
-    OSXPROXY_MODULE                          \
-    WINDOWSPROXY_MODULE                      \
-    ANDROIDPROXY_MODULE                      \
-    JSCTYPES_MODULE                          \
-    MODULE(jsreflect)                        \
-    MODULE(jsperf)                           \
-    MODULE(identity)                         \
-    MODULE(nsServicesCryptoModule)           \
-    MOZ_APP_COMPONENT_MODULES                \
-    MODULE(nsTelemetryModule)                \
-    MODULE(jsinspector)                      \
-    MODULE(jsdebugger)                       \
-    PEERCONNECTION_MODULE                    \
-    GIO_MODULE                               \
-    SYNTH_PICO_MODULE                        \
-    MODULE(DiskSpaceWatcherModule)           \
-    /* end of list */
-
-#define MODULE(_name) \
-  NSMODULE_DECL(_name);
-
-XUL_MODULES
-
-#ifdef MOZ_WIDGET_GONK
-MODULE(WifiProxyServiceModule)
-#endif
-
-#undef MODULE
-
-#define MODULE(_name) \
-    &NSMODULE_NAME(_name),
-
-extern const mozilla::Module *const *const kPStaticModules[] = {
-  XUL_MODULES
-#ifdef MOZ_WIDGET_GONK
-MODULE(WifiProxyServiceModule)
-#endif
-  nullptr
-};
-
-#undef MODULE
--- a/toolkit/toolkit.mozbuild
+++ b/toolkit/toolkit.mozbuild
@@ -156,16 +156,17 @@ add_tier_dir('platform', 'other-licenses
 if CONFIG['MOZ_GIO_COMPONENT']:
     add_tier_dir('platform', 'extensions/gio')
 
 # Applications can cheat and ask for code to be
 # built before libxul so it can be linked into libxul.
 add_tier_dir('platform', app_libxul_dirs)
 add_tier_dir('platform', app_libxul_static_dirs, static=True)
 
+add_tier_dir('platform', 'toolkit/library/StaticXULComponentsEnd')
 add_tier_dir('platform', 'toolkit/library')
 
 if CONFIG['MOZ_REPLACE_MALLOC']:
     add_tier_dir('platform', 'memory/replace')
 
 if CONFIG['NS_TRACE_MALLOC']:
     add_tier_dir('platform', 'tools/trace-malloc')
 
--- a/xpcom/components/Module.h
+++ b/xpcom/components/Module.h
@@ -100,16 +100,29 @@ struct Module
   LoadFuncPtr loadProc;
   UnloadFuncPtr unloadProc;
 };
 
 } // namespace
 
 #if defined(MOZILLA_INTERNAL_API)
 #  define NSMODULE_NAME(_name) _name##_NSModule
-#  define NSMODULE_DECL(_name) extern mozilla::Module const *const NSMODULE_NAME(_name)
-#  define NSMODULE_DEFN(_name) NSMODULE_DECL(_name)
+#  if defined(_MSC_VER)
+#    pragma section(".kPStaticModules$M", read)
+#    pragma comment(linker, "/merge:.kPStaticModules=.rdata")
+#    define NSMODULE_SECTION __declspec(allocate(".kPStaticModules$M"), dllexport)
+#  elif defined(__GNUC__)
+#    if defined(__ELF__)
+#      define NSMODULE_SECTION __attribute__((section(".kPStaticModules"), visibility("protected")))
+#    elif defined(__MACH__)
+#      define NSMODULE_SECTION __attribute__((section("__DATA, .kPStaticModules"), visibility("default")))
+#    endif
+#  endif
+#  if !defined(NSMODULE_SECTION)
+#    error Do not know how to define sections.
+#  endif
+#  define NSMODULE_DEFN(_name) extern NSMODULE_SECTION mozilla::Module const *const NSMODULE_NAME(_name)
 #else
 #  define NSMODULE_NAME(_name) NSModule
 #  define NSMODULE_DEFN(_name) extern "C" NS_EXPORT mozilla::Module const *const NSModule
 #endif
 
 #endif // mozilla_Module_h
--- a/xpcom/components/nsComponentManager.cpp
+++ b/xpcom/components/nsComponentManager.cpp
@@ -77,20 +77,16 @@
 #include "mozilla/Omnijar.h"
 
 #include "prlog.h"
 
 using namespace mozilla;
 
 PRLogModuleInfo* nsComponentManagerLog = nullptr;
 
-// defined in nsStaticXULComponents.cpp to contain all the components in
-// libxul.
-extern mozilla::Module const *const *const kPStaticModules[];
-
 #if 0 || defined (DEBUG_timeless)
  #define SHOW_DENIED_ON_SHUTDOWN
  #define SHOW_CI_ON_EXISTING_SERVICE
 #endif
 
 // Bloated registry buffer size to improve startup performance -- needs to
 // be big enough to fit the entire file into memory or it'll thrash.
 // 512K is big enough to allow for some future growth in the registry.
@@ -320,26 +316,36 @@ nsComponentManagerImpl::nsComponentManag
     , mContractIDs(CONTRACTID_HASHTABLE_INITIAL_SIZE)
     , mLock("nsComponentManagerImpl.mLock")
     , mStatus(NOT_INITIALIZED)
 {
 }
 
 nsTArray<const mozilla::Module*>* nsComponentManagerImpl::sStaticModules;
 
+NSMODULE_DEFN(start_kPStaticModules);
+NSMODULE_DEFN(end_kPStaticModules);
+
+/* The content between start_kPStaticModules and end_kPStaticModules is gathered
+ * by the linker from various objects containing symbols in a specific section.
+ * ASAN considers (rightfully) the use of this content as a global buffer
+ * overflow. But this is a deliberate and well-considered choice, with no proper
+ * way to make ASAN happy. */
+MOZ_ASAN_BLACKLIST
 /* static */ void
 nsComponentManagerImpl::InitializeStaticModules()
 {
     if (sStaticModules)
         return;
 
     sStaticModules = new nsTArray<const mozilla::Module*>;
-    for (const mozilla::Module *const *const *staticModules = kPStaticModules;
-         *staticModules; ++staticModules)
-        sStaticModules->AppendElement(**staticModules);
+    for (const mozilla::Module *const *staticModules = &NSMODULE_NAME(start_kPStaticModules) + 1;
+         staticModules < &NSMODULE_NAME(end_kPStaticModules); ++staticModules)
+        if (*staticModules) // ASAN adds padding
+            sStaticModules->AppendElement(*staticModules);
 }
 
 nsTArray<nsComponentManagerImpl::ComponentLocation>*
 nsComponentManagerImpl::sModuleLocations;
 
 /* static */ void
 nsComponentManagerImpl::InitializeModuleLocations()
 {