Bug 938437 - Replace nsStaticXULComponents.cpp with smart use of sections. r=bsmedberg,irc-r=decoder,r=nfroyd,r=gps
authorMike Hommey <mh+mozilla@glandium.org>
Tue, 19 Nov 2013 13:45:31 +0900
changeset 190915 f4f90287d00a84337ad32878c2e7b6a2fa449b34
parent 190914 87c1ed6a0ed1b598188cefc93c84721c5c3e10ed
child 190916 15e8c8100ed72fcfd6b8af2fe9d45adcd1537e5a
push id27019
push usercbook@mozilla.com
push dateThu, 26 Jun 2014 13:33:43 +0000
treeherdermozilla-central@4c9d8c885791 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbsmedberg, nfroyd, gps
bugs938437
milestone33.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 938437 - Replace nsStaticXULComponents.cpp with smart use of sections. r=bsmedberg,irc-r=decoder,r=nfroyd,r=gps
build/autoconf/compiler-opts.m4
config/config.mk
toolkit/library/StaticXULComponents.ld
toolkit/library/StaticXULComponentsEnd/StaticXULComponentsEnd.cpp
toolkit/library/StaticXULComponentsEnd/moz.build
toolkit/library/StaticXULComponentsStart.cpp
toolkit/library/libxul.mk
toolkit/library/moz.build
toolkit/library/nsStaticXULComponents.cpp
xpcom/components/Module.h
xpcom/components/nsComponentManager.cpp
--- a/build/autoconf/compiler-opts.m4
+++ b/build/autoconf/compiler-opts.m4
@@ -235,16 +235,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/config.mk
+++ b/config/config.mk
@@ -817,16 +817,17 @@ endif
 
 ifeq (,$(filter $(OS_TARGET),WINNT Darwin))
 CHECK_TEXTREL = @$(TOOLCHAIN_PREFIX)readelf -d $(1) | grep TEXTREL > /dev/null && echo 'TEST-UNEXPECTED-FAIL | check_textrel | We do not want text relocations in libraries and programs' || true
 endif
 
 define CHECK_BINARY
 $(call CHECK_STDCXX,$(1))
 $(call CHECK_TEXTREL,$(1))
+$(call LOCAL_CHECKS,$(1))
 endef
 
 # autoconf.mk sets OBJ_SUFFIX to an error to avoid use before including
 # this file
 OBJ_SUFFIX := $(_OBJ_SUFFIX)
 
 # PGO builds with GCC build objects with instrumentation in a first pass,
 # then objects optimized, without instrumentation, in a second pass. If
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'
+
+DEFINES['MOZILLA_INTERNAL_API'] = 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/libxul.mk
+++ b/toolkit/library/libxul.mk
@@ -241,8 +241,33 @@ LIBXUL_AUTOLOAD = $(topsrcdir)/toolkit/l
 LIBXUL_AUTOLOAD_FLAGS := -Dtopsrcdir=$(abspath $(topsrcdir))
 endif
 
 OS_LIBS += $(LIBICONV)
 
 ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
 OS_LIBS += $(call EXPAND_LIBNAME,usp10 oleaut32)
 endif
+
+EXTRA_DSO_LDOPTS += $(call EXPAND_LIBNAME_PATH,StaticXULComponentsEnd,$(DEPTH)/toolkit/library/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 += $(topsrcdir)/toolkit/library/StaticXULComponents.ld
+endif
+
+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
--- a/toolkit/library/moz.build
+++ b/toolkit/library/moz.build
@@ -2,59 +2,34 @@
 # vim: set filetype=python:
 # 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/.
 
 LIBRARY_NAME = 'xul'
 
 SOURCES += [
-    'nsStaticXULComponents.cpp',
+    'StaticXULComponentsStart.cpp',
 ]
 
+# This, combined with the fact the file is first, makes the start pointer
+# it contains first in Windows PGO builds.
+SOURCES['StaticXULComponentsStart.cpp'].no_pgo = True
+
 if CONFIG['OS_ARCH'] == 'WINNT':
     SOURCES += [
         'nsDllMain.cpp',
     ]
 
-# component libraries
-additional_defines = (
-    'MOZ_AUTH_EXTENSION',
-    'MOZ_GIO_COMPONENT',
-    'MOZ_JSDEBUGGER',
-    'MOZ_PERMISSIONS',
-    'MOZ_PREF_EXTENSIONS',
-    'MOZ_SPELLCHECK',
-    'MOZ_UNIVERSALCHARDET',
-    'MOZ_ZIPWRITER',
-)
-
-for var in additional_defines:
-    if CONFIG[var]:
-        DEFINES[var] = True
-
-if CONFIG['MOZ_DEBUG'] and CONFIG['ENABLE_TESTS']:
-    DEFINES['ENABLE_LAYOUTDEBUG'] = True
-
-if CONFIG['MOZ_WIDGET_TOOLKIT'] not in ('android', 'gonk', 'qt',
-                                        'cocoa', 'windows') and \
-   CONFIG['MOZ_XUL']:
-    DEFINES['MOZ_FILEVIEW'] = True
-
-# Platform-specific icon channel stuff - supported mostly-everywhere
-if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'mac', 'cocoa',
-                                    'gtk2', 'gtk3', 'qt', 'android'):
-    DEFINES['ICON_DECODER'] = True
-
 LOCAL_INCLUDES += [
     '/config',
     # need widget/windows for resource.h (included from widget.rc)
     '/widget/windows',
 ]
 
 if CONFIG['OS_ARCH'] == 'WINNT' and not CONFIG['GNU_CC']:
     LOCAL_INCLUDES += [
         '/xpcom/base',
     ]
 
 FAIL_ON_WARNINGS = True
 
-DIRS += ['build', 'gtest']
+DIRS += ['StaticXULComponentsEnd', 'build', 'gtest']
deleted file mode 100644
--- a/toolkit/library/nsStaticXULComponents.cpp
+++ /dev/null
@@ -1,276 +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(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
-
-#ifndef MOZ_B2G
-#define CONTENT_PROCESS_WIDGET_MODULES MODULE(nsContentProcessWidgetModule)
-#else
-#define CONTENT_PROCESS_WIDGET_MODULES
-#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                           \
-    CONTENT_PROCESS_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(WifiCertServiceModule)
-MODULE(WifiProxyServiceModule)
-MODULE(NetworkWorkerModule)
-#endif
-
-#undef MODULE
-
-#define MODULE(_name) \
-    &NSMODULE_NAME(_name),
-
-extern const mozilla::Module *const *const kPStaticModules[] = {
-  XUL_MODULES
-#ifdef MOZ_WIDGET_GONK
-MODULE(WifiCertServiceModule)
-MODULE(WifiProxyServiceModule)
-MODULE(NetworkWorkerModule)
-#endif
-  nullptr
-};
-
-#undef MODULE
--- a/xpcom/components/Module.h
+++ b/xpcom/components/Module.h
@@ -113,16 +113,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
@@ -76,20 +76,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.
@@ -273,26 +269,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()
 {