Browse Source

cleanups and reshuffle

Frank-Rainer Grahl 9 months ago
parent
commit
ab2a0a1bc6

+ 6 - 5
mozilla-release/patches/1506798-65a1.patch

@@ -2,13 +2,14 @@
 # User Jon Coppeard <jcoppeard@mozilla.com>
 # Date 1542462498 0
 # Node ID 764c5b94a3950791427e782e59e3e826921cffac
-# Parent  6266a98f3d3d0d409800f37125a70410ae7fe937
+# Parent  9bafb506ded214249b8ea46f64892b091869867f
 Bug 1506798 - Fix possible data race updating scope object during compacting GC r=pbone
 
 diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp
 --- a/js/src/jsgc.cpp
 +++ b/js/src/jsgc.cpp
-@@ -2812,21 +2812,21 @@ static const AllocKinds UpdatePhaseMisc 
+@@ -2811,21 +2811,21 @@ GCRuntime::updateCellPointers(MovingTrac
+ static const AllocKinds UpdatePhaseMisc {
      AllocKind::SCRIPT,
      AllocKind::LAZY_SCRIPT,
      AllocKind::BASE_SHAPE,
@@ -16,9 +17,9 @@ diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp
      AllocKind::ACCESSOR_SHAPE,
      AllocKind::OBJECT_GROUP,
      AllocKind::STRING,
-     AllocKind::JITCODE,
--    AllocKind::SCOPE,
-     AllocKind::REGEXP_SHARED
+-    AllocKind::JITCODE,
+-    AllocKind::SCOPE
++    AllocKind::JITCODE
  };
  
  static const AllocKinds UpdatePhaseObjects {

+ 5 - 5
mozilla-release/patches/1639815-1-78a1.patch

@@ -3,7 +3,7 @@
 # Date 1590100726 0
 #      Thu May 21 22:38:46 2020 +0000
 # Node ID a98fde98a836ac69aa7b1fedf3616ab969c3b8a0
-# Parent  76108d91c8822de4498b7b070c4c88f098956c33
+# Parent  5758d4b24dfbb26e830f1e9a469385d14e4fefd7
 Bug 1639815 - Move --with-qemu-exe and --with-cross-lib to python configure. r=froydnj
 
 Differential Revision: https://phabricator.services.mozilla.com/D76285
@@ -46,13 +46,13 @@ diff --git a/build/moz.configure/old.configure b/build/moz.configure/old.configu
 diff --git a/js/moz.configure b/js/moz.configure
 --- a/js/moz.configure
 +++ b/js/moz.configure
-@@ -430,16 +430,26 @@ js_option('--enable-pipeline-operator', 
- def enable_pipeline_operator(value):
+@@ -444,16 +444,26 @@ js_option('--enable-new-regexp', default
+ def enable_new_regexp(value):
      if value:
          return True
  
- set_config('ENABLE_PIPELINE_OPERATOR', enable_pipeline_operator)
- set_define('ENABLE_PIPELINE_OPERATOR', enable_pipeline_operator)
+ set_config('ENABLE_NEW_REGEXP', enable_new_regexp)
+ set_define('ENABLE_NEW_REGEXP', enable_new_regexp)
  
  
 +# Options for generating the shell as a script

+ 6705 - 0
mozilla-release/patches/NOBUG-nukemozlinker-25319.patch

@@ -0,0 +1,6705 @@
+# HG changeset patch
+# User Frank-Rainer Grahl <frgrahl@gmx.net>
+# Date 1705411363 -3600
+# Parent  0014187ad33748871d5a6945e8e005826fd4bd9c
+No Bug - Nuke custom linker. r=me a=me
+
+It was only needed for Android.
+
+diff --git a/browser/app/moz.build b/browser/app/moz.build
+--- a/browser/app/moz.build
++++ b/browser/app/moz.build
+@@ -97,19 +97,16 @@ if CONFIG['MOZ_SANDBOX'] and CONFIG['OS_
+ # The heap will grow if need be.
+ #
+ # Set it to 256k.  See bug 127069.
+ if CONFIG['OS_ARCH'] == 'WINNT' and CONFIG['CC_TYPE'] not in ('clang', 'gcc'):
+     LDFLAGS += ['/HEAP:0x40000']
+ 
+ DisableStlWrapping()
+ 
+-if CONFIG['MOZ_LINKER']:
+-    OS_LIBS += CONFIG['MOZ_ZLIB_LIBS']
+-
+ if CONFIG['HAVE_CLOCK_MONOTONIC']:
+     OS_LIBS += CONFIG['REALTIME_LIBS']
+ 
+ if CONFIG['MOZ_LINUX_32_SSE2_STARTUP_ERROR']:
+     DEFINES['MOZ_LINUX_32_SSE2_STARTUP_ERROR'] = True
+     COMPILE_FLAGS['OS_CXXFLAGS'] = [
+         f for f in COMPILE_FLAGS.get('OS_CXXFLAGS', [])
+         if not f.startswith('-march=') and f not in ('-msse', '-msse2', '-mfpmath=sse')
+diff --git a/js/src/js-config.mozbuild b/js/src/js-config.mozbuild
+--- a/js/src/js-config.mozbuild
++++ b/js/src/js-config.mozbuild
+@@ -36,12 +36,8 @@ if CONFIG['MOZ_DEBUG'] or CONFIG['NIGHTL
+ # NOTE: This Realm creation options decide if this is exposed to script.
+ DEFINES['ENABLE_SHARED_ARRAY_BUFFER'] = True
+ 
+ # CTypes
+ if CONFIG['JS_HAS_CTYPES']:
+     DEFINES['JS_HAS_CTYPES'] = True
+     if not CONFIG['MOZ_SYSTEM_FFI']:
+         DEFINES['FFI_BUILDING'] = True
+-
+-# Forward MOZ_LINKER config
+-if CONFIG['MOZ_LINKER']:
+-    DEFINES['MOZ_LINKER'] = True
+diff --git a/js/src/old-configure.in b/js/src/old-configure.in
+--- a/js/src/old-configure.in
++++ b/js/src/old-configure.in
+@@ -1510,17 +1510,16 @@ AC_SUBST(TARGET_XPCOM_ABI)
+ 
+ dnl === -AC_SUBST(GCC_USE_GNU_LD) Bug 1478499 part 5 ===
+ 
+ AC_SUBST_LIST(DSO_CFLAGS)
+ AC_SUBST_LIST(DSO_PIC_CFLAGS)
+ AC_SUBST(DSO_LDOPTS)
+ AC_SUBST(BIN_SUFFIX)
+ AC_SUBST(USE_N32)
+-AC_SUBST(MOZ_LINKER)
+ AC_SUBST(WIN32_CONSOLE_EXE_LDFLAGS)
+ AC_SUBST(WIN32_GUI_EXE_LDFLAGS)
+ 
+ AC_CHECK_FUNCS(posix_fadvise posix_fallocate)
+ 
+ dnl Set various defines and substitutions
+ dnl ========================================================
+ 
+diff --git a/js/src/wasm/WasmSignalHandlers.cpp b/js/src/wasm/WasmSignalHandlers.cpp
+--- a/js/src/wasm/WasmSignalHandlers.cpp
++++ b/js/src/wasm/WasmSignalHandlers.cpp
+@@ -36,19 +36,16 @@ using namespace js::jit;
+ using namespace js::wasm;
+ 
+ using JS::GenericNaN;
+ using mozilla::DebugOnly;
+ using mozilla::PodArrayZero;
+ 
+ #if defined(ANDROID)
+ # include <sys/system_properties.h>
+-# if defined(MOZ_LINKER)
+-extern "C" MFBT_API bool IsSignalHandlingBroken();
+-# endif
+ #endif
+ 
+ // Crashing inside the signal handler can cause the handler to be recursively
+ // invoked, eventually blowing the stack without actually showing a crash
+ // report dialog via Breakpad. To guard against this we watch for such
+ // recursion and fall through to the next handler immediately rather than
+ // trying to handle it.
+ 
+@@ -1607,21 +1604,16 @@ ProcessHasSignalHandlers()
+     // EINTRquisition.
+     char version_string[PROP_VALUE_MAX];
+     PodArrayZero(version_string);
+     if (__system_property_get("ro.build.version.sdk", version_string) > 0) {
+         if (atol(version_string) < 19)
+             return false;
+     }
+ # endif
+-# if defined(MOZ_LINKER)
+-    // Signal handling is broken on some android systems.
+-    if (IsSignalHandlingBroken())
+-        return false;
+-# endif
+ #endif
+ 
+     // The interrupt handler allows the active thread to be paused from another
+     // thread (see InterruptRunningJitCode).
+ #if defined(XP_WIN)
+     // Windows uses SuspendThread to stop the active thread from another thread.
+ #else
+     struct sigaction interruptHandler;
+diff --git a/js/sub.configure b/js/sub.configure
+--- a/js/sub.configure
++++ b/js/sub.configure
+@@ -82,17 +82,17 @@ def js_subconfigure(host, target, build_
+     # Variables that were explicitly exported from old-configure, and those
+     # explicitly set in the environment when invoking old-configure, were
+     # automatically inherited from subconfigure. We assume the relevant ones
+     # have a corresponding AC_SUBST in old-configure, making them available
+     # in `substs`.
+     for var in (
+         'MOZ_SYSTEM_ZLIB', 'MOZ_ZLIB_CFLAGS', 'MOZ_ZLIB_LIBS',
+         'MOZ_APP_NAME', 'MOZ_APP_REMOTINGNAME', 'MOZ_DEV_EDITION',
+-        'STLPORT_LIBS', 'DIST', 'MOZ_LINKER', 'ZLIB_IN_MOZGLUE', 'RANLIB',
++        'STLPORT_LIBS', 'DIST', 'ZLIB_IN_MOZGLUE', 'RANLIB',
+         'AR', 'CPP', 'CC', 'CXX', 'CPPFLAGS', 'CFLAGS', 'CXXFLAGS',
+         'LDFLAGS', 'HOST_CC', 'HOST_CXX', 'HOST_CPPFLAGS',
+         'HOST_CXXFLAGS', 'HOST_LDFLAGS'
+     ):
+         if var not in from_assignment and var in substs:
+             value = substs[var]
+         elif var in assignments:
+             value = assignments[var]
+diff --git a/mozglue/build/moz.build b/mozglue/build/moz.build
+--- a/mozglue/build/moz.build
++++ b/mozglue/build/moz.build
+@@ -99,21 +99,16 @@ if CONFIG['MOZ_WIDGET_TOOLKIT']:
+             'arm.cpp',
+         ]
+ 
+     if CONFIG['CPU_ARCH'].startswith('mips'):
+         SOURCES += [
+             'mips.cpp',
+         ]
+ 
+-    if CONFIG['MOZ_LINKER']:
+-        USE_LIBS += [
+-            'zlib',
+-        ]
+-
+ USE_LIBS += [
+     'mfbt',
+ ]
+ 
+ DEFINES['IMPL_MFBT'] = True
+ LIBRARY_DEFINES['MOZ_HAS_MOZGLUE'] = True
+ 
+ if CONFIG['OS_TARGET'] == 'Darwin':
+@@ -121,16 +116,9 @@ if CONFIG['OS_TARGET'] == 'Darwin':
+     # symbol resolution for symbols that jemalloc itself uses. While it
+     # might be possible to find a way to avoid all such symbol resolutions,
+     # it's currently not possible because at the very least there's a call
+     # to pthread_self from tsd_init_check_recursion, which is necessary
+     # because somehow clang doesn't want to accept the __thread keyword
+     # for TLS.
+     LDFLAGS += ['-Wl,-bind_at_load']
+ 
+-if CONFIG['MOZ_LINKER'] and CONFIG['TARGET_CPU'] == 'arm':
+-    LDFLAGS += ['-Wl,-version-script,%s/arm-eabi-filter' % SRCDIR]
+-
+-# Bug 1477081
+-# -if CONFIG['MOZ_LINKER'] and CONFIG['TARGET_CPU'] == 'arm':
+-# +if CONFIG['MOZ_LINKER'] and CONFIG['CPU_ARCH'] == 'arm':
+-
+ DIST_INSTALL = True
+diff --git a/mozglue/linker/BaseElf.cpp b/mozglue/linker/BaseElf.cpp
+deleted file mode 100644
+--- a/mozglue/linker/BaseElf.cpp
++++ /dev/null
+@@ -1,216 +0,0 @@
+-/* 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 "BaseElf.h"
+-#include "Elfxx.h"
+-#include "Logging.h"
+-#include "mozilla/IntegerPrintfMacros.h"
+-#include "mozilla/RefPtr.h"
+-
+-using namespace Elf;
+-using namespace mozilla;
+-
+-unsigned long
+-BaseElf::Hash(const char *symbol)
+-{
+-  const unsigned char *sym = reinterpret_cast<const unsigned char *>(symbol);
+-  unsigned long h = 0, g;
+-  while (*sym) {
+-    h = (h << 4) + *sym++;
+-    g = h & 0xf0000000;
+-    h ^= g;
+-    h ^= g >> 24;
+-  }
+-  return h;
+-}
+-
+-void *
+-BaseElf::GetSymbolPtr(const char *symbol) const
+-{
+-  return GetSymbolPtr(symbol, Hash(symbol));
+-}
+-
+-void *
+-BaseElf::GetSymbolPtr(const char *symbol, unsigned long hash) const
+-{
+-  const Sym *sym = GetSymbol(symbol, hash);
+-  void *ptr = nullptr;
+-  if (sym && sym->st_shndx != SHN_UNDEF)
+-    ptr = GetPtr(sym->st_value);
+-  DEBUG_LOG("BaseElf::GetSymbolPtr(%p [\"%s\"], \"%s\") = %p",
+-            reinterpret_cast<const void *>(this), GetPath(), symbol, ptr);
+-  return ptr;
+-}
+-
+-const Sym *
+-BaseElf::GetSymbol(const char *symbol, unsigned long hash) const
+-{
+-  /* Search symbol with the buckets and chains tables.
+-   * The hash computed from the symbol name gives an index in the buckets
+-   * table. The corresponding value in the bucket table is an index in the
+-   * symbols table and in the chains table.
+-   * If the corresponding symbol in the symbols table matches, we're done.
+-   * Otherwise, the corresponding value in the chains table is a new index
+-   * in both tables, which corresponding symbol is tested and so on and so
+-   * forth */
+-  size_t bucket = hash % buckets.numElements();
+-  for (size_t y = buckets[bucket]; y != STN_UNDEF; y = chains[y]) {
+-    if (strcmp(symbol, strtab.GetStringAt(symtab[y].st_name)))
+-      continue;
+-    return &symtab[y];
+-  }
+-  return nullptr;
+-}
+-
+-bool
+-BaseElf::Contains(void *addr) const
+-{
+-  return base.Contains(addr);
+-}
+-
+-#ifdef __ARM_EABI__
+-const void *
+-BaseElf::FindExidx(int *pcount) const
+-{
+-  if (arm_exidx) {
+-    *pcount = arm_exidx.numElements();
+-    return arm_exidx;
+-  }
+-  *pcount = 0;
+-  return nullptr;
+-}
+-#endif
+-
+-already_AddRefed<LibHandle>
+-LoadedElf::Create(const char *path, void *base_addr)
+-{
+-  DEBUG_LOG("LoadedElf::Create(\"%s\", %p) = ...", path, base_addr);
+-
+-  uint8_t mapped;
+-  /* If the page is not mapped, mincore returns an error. If base_addr is
+-   * nullptr, as would happen if the corresponding binary is prelinked with
+-   * the prelink look (but not with the android apriori tool), no page being
+-   * mapped there (right?), mincore returns an error, too, which makes
+-   * prelinked libraries on glibc unsupported. This is not an interesting
+-   * use case for now, so don't try supporting that case.
+-   */
+-  if (mincore(const_cast<void*>(base_addr), PageSize(), &mapped))
+-    return nullptr;
+-
+-  RefPtr<LoadedElf> elf = new LoadedElf(path);
+-
+-  const Ehdr *ehdr = Ehdr::validate(base_addr);
+-  if (!ehdr)
+-    return nullptr;
+-
+-  Addr min_vaddr = (Addr) -1; // We want to find the lowest and biggest
+-  Addr max_vaddr = 0;         // virtual address used by this Elf.
+-  const Phdr *dyn = nullptr;
+-#ifdef __ARM_EABI__
+-  const Phdr *arm_exidx_phdr = nullptr;
+-#endif
+-
+-  Array<Phdr> phdrs(reinterpret_cast<const char *>(ehdr) + ehdr->e_phoff,
+-                    ehdr->e_phnum);
+-  for (auto phdr = phdrs.begin(); phdr < phdrs.end(); ++phdr) {
+-    switch (phdr->p_type) {
+-      case PT_LOAD:
+-        if (phdr->p_vaddr < min_vaddr)
+-          min_vaddr = phdr->p_vaddr;
+-        if (max_vaddr < phdr->p_vaddr + phdr->p_memsz)
+-          max_vaddr = phdr->p_vaddr + phdr->p_memsz;
+-        break;
+-      case PT_DYNAMIC:
+-        dyn = &*phdr;
+-        break;
+-#ifdef __ARM_EABI__
+-      case PT_ARM_EXIDX:
+-        /* We cannot initialize arm_exidx here
+-           because we don't have a base yet */
+-        arm_exidx_phdr = &*phdr;
+-        break;
+-#endif
+-    }
+-  }
+-
+-  /* If the lowest PT_LOAD virtual address in headers is not 0, then the ELF
+-   * is either prelinked or a non-PIE executable. The former case is not
+-   * possible, because base_addr would be nullptr and the mincore test above
+-   * would already have made us return.
+-   * For a non-PIE executable, PT_LOADs contain absolute addresses, so in
+-   * practice, this means min_vaddr should be equal to base_addr. max_vaddr
+-   * can thus be adjusted accordingly.
+-   */
+-  if (min_vaddr != 0) {
+-    void *min_vaddr_ptr = reinterpret_cast<void *>(
+-      static_cast<uintptr_t>(min_vaddr));
+-    if (min_vaddr_ptr != base_addr) {
+-      LOG("%s: %p != %p", elf->GetPath(), min_vaddr_ptr, base_addr);
+-      return nullptr;
+-    }
+-    max_vaddr -= min_vaddr;
+-  }
+-  if (!dyn) {
+-    LOG("%s: No PT_DYNAMIC segment found", elf->GetPath());
+-    return nullptr;
+-  }
+-
+-  elf->base.Assign(base_addr, max_vaddr);
+-
+-  if (!elf->InitDyn(dyn))
+-    return nullptr;
+-
+-#ifdef __ARM_EABI__
+-  if (arm_exidx_phdr)
+-    elf->arm_exidx.InitSize(elf->GetPtr(arm_exidx_phdr->p_vaddr),
+-                            arm_exidx_phdr->p_memsz);
+-#endif
+-
+-  DEBUG_LOG("LoadedElf::Create(\"%s\", %p) = %p", path, base_addr,
+-    static_cast<void *>(elf));
+-
+-  ElfLoader::Singleton.Register(elf);
+-  return elf.forget();
+-}
+-
+-bool
+-LoadedElf::InitDyn(const Phdr *pt_dyn)
+-{
+-  Array<Dyn> dyns;
+-  dyns.InitSize(GetPtr<Dyn>(pt_dyn->p_vaddr), pt_dyn->p_filesz);
+-
+-  size_t symnum = 0;
+-  for (auto dyn = dyns.begin(); dyn < dyns.end() && dyn->d_tag; ++dyn) {
+-    switch (dyn->d_tag) {
+-      case DT_HASH:
+-        {
+-          DEBUG_LOG("%s 0x%08" PRIxPTR, "DT_HASH", uintptr_t(dyn->d_un.d_val));
+-          const Elf::Word *hash_table_header = \
+-            GetPtr<Elf::Word>(dyn->d_un.d_ptr);
+-          symnum = hash_table_header[1];
+-          buckets.Init(&hash_table_header[2], hash_table_header[0]);
+-          chains.Init(&*buckets.end());
+-        }
+-        break;
+-      case DT_STRTAB:
+-        DEBUG_LOG("%s 0x%08" PRIxPTR, "DT_STRTAB", uintptr_t(dyn->d_un.d_val));
+-        strtab.Init(GetPtr(dyn->d_un.d_ptr));
+-        break;
+-      case DT_SYMTAB:
+-        DEBUG_LOG("%s 0x%08" PRIxPTR, "DT_SYMTAB", uintptr_t(dyn->d_un.d_val));
+-        symtab.Init(GetPtr(dyn->d_un.d_ptr));
+-        break;
+-    }
+-  }
+-  if (!buckets || !symnum) {
+-    ERROR("%s: Missing or broken DT_HASH", GetPath());
+-  } else if (!strtab) {
+-    ERROR("%s: Missing DT_STRTAB", GetPath());
+-  } else if (!symtab) {
+-    ERROR("%s: Missing DT_SYMTAB", GetPath());
+-  } else {
+-    return true;
+-  }
+-  return false;
+-}
+diff --git a/mozglue/linker/BaseElf.h b/mozglue/linker/BaseElf.h
+deleted file mode 100644
+--- a/mozglue/linker/BaseElf.h
++++ /dev/null
+@@ -1,141 +0,0 @@
+-/* 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/. */
+-
+-#ifndef BaseElf_h
+-#define BaseElf_h
+-
+-#include "ElfLoader.h"
+-#include "Elfxx.h"
+-
+-
+-/**
+- * Base class for ELF libraries. This class includes things that will be
+- * common between SystemElfs and CustomElfs.
+- */
+-class BaseElf: public LibHandle
+-{
+-public:
+-  /**
+-   * Hash function for symbol lookup, as defined in ELF standard for System V.
+-   */
+-  static unsigned long Hash(const char *symbol);
+-
+-  /**
+-   * Returns the address corresponding to the given symbol name (with a
+-   * pre-computed hash).
+-   */
+-  void *GetSymbolPtr(const char *symbol, unsigned long hash) const;
+-
+-  /**
+-   * Returns a pointer to the Elf Symbol in the Dynamic Symbol table
+-   * corresponding to the given symbol name (with a pre-computed hash).
+-   */
+-  const Elf::Sym *GetSymbol(const char *symbol, unsigned long hash) const;
+-
+-  BaseElf(const char *path, Mappable *mappable = nullptr)
+-  : LibHandle(path)
+-  , mappable(mappable)
+-  {
+-  }
+-
+-protected:
+-   /**
+-    * Inherited from LibHandle. Those are temporary and are not supposed to
+-    * be used.
+-    */
+-   virtual void *GetSymbolPtr(const char *symbol) const;
+-   virtual bool Contains(void *addr) const;
+-   virtual void *GetBase() const { return GetPtr(0); }
+-
+-#ifdef __ARM_EABI__
+-  virtual const void *FindExidx(int *pcount) const;
+-#endif
+-
+-  virtual Mappable *GetMappable() const { return NULL; };
+-
+-public:
+-/* private: */
+-  /**
+-   * Returns a pointer relative to the base address where the library is
+-   * loaded.
+-   */
+-  void *GetPtr(const Elf::Addr offset) const
+-  {
+-    if (reinterpret_cast<void *>(offset) > base)
+-      return reinterpret_cast<void *>(offset);
+-    return base + offset;
+-  }
+-
+-  /**
+-   * Like the above, but returns a typed (const) pointer
+-   */
+-  template <typename T>
+-  const T *GetPtr(const Elf::Addr offset) const
+-  {
+-    if (reinterpret_cast<void *>(offset) > base)
+-      return reinterpret_cast<const T *>(offset);
+-    return reinterpret_cast<const T *>(base + offset);
+-  }
+-
+-  /* Appropriated Mappable */
+-  /* /!\ we rely on this being nullptr for BaseElf instances, but not
+-   * CustomElf instances. */
+-  RefPtr<Mappable> mappable;
+-
+-  /* Base address where the library is loaded */
+-  MappedPtr base;
+-
+-  /* Buckets and chains for the System V symbol hash table */
+-  Array<Elf::Word> buckets;
+-  UnsizedArray<Elf::Word> chains;
+-
+-/* protected: */
+-  /* String table */
+-  Elf::Strtab strtab;
+-
+-  /* Symbol table */
+-  UnsizedArray<Elf::Sym> symtab;
+-
+-#ifdef __ARM_EABI__
+-  /* ARM.exidx information used by FindExidx */
+-  Array<uint32_t[2]> arm_exidx;
+-#endif
+-};
+-
+-
+-/**
+- * Class for ELF libraries that already loaded in memory.
+- */
+-class LoadedElf: public BaseElf
+-{
+-public:
+-  /**
+-   * Returns a LoadedElf corresponding to the already loaded ELF
+-   * at the given base address.
+-   */
+-  static already_AddRefed<LibHandle> Create(const char *path,
+-                                                 void *base_addr);
+-
+-private:
+-  LoadedElf(const char *path)
+-  : BaseElf(path) { }
+-
+-  ~LoadedElf()
+-  {
+-    /* Avoid base's destructor unmapping something that doesn't actually
+-     * belong to it. */
+-    base.release();
+-    ElfLoader::Singleton.Forget(this);
+-  }
+-
+-  /**
+-   * Initializes the library according to information found in the given
+-   * PT_DYNAMIC header.
+-   * Returns whether this succeeded or failed.
+-   */
+-  bool InitDyn(const Elf::Phdr *pt_dyn);
+-};
+-
+-
+-#endif /* BaseElf_h */
+diff --git a/mozglue/linker/CustomElf.cpp b/mozglue/linker/CustomElf.cpp
+deleted file mode 100644
+--- a/mozglue/linker/CustomElf.cpp
++++ /dev/null
+@@ -1,749 +0,0 @@
+-/* 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 <cstring>
+-#include <sys/mman.h>
+-#include <vector>
+-#include <dlfcn.h>
+-#include <signal.h>
+-#include <string.h>
+-#include "CustomElf.h"
+-#include "BaseElf.h"
+-#include "Mappable.h"
+-#include "Logging.h"
+-#include "mozilla/IntegerPrintfMacros.h"
+-
+-using namespace Elf;
+-using namespace mozilla;
+-
+-/* TODO: Fill ElfLoader::Singleton.lastError on errors. */
+-
+-/* Function used to report library mappings from the custom linker to Gecko
+- * crash reporter */
+-#ifdef ANDROID
+-extern "C" {
+-  void report_mapping(char *name, void *base, uint32_t len, uint32_t offset);
+-  void delete_mapping(const char *name);
+-}
+-#else
+-#define report_mapping(...)
+-#define delete_mapping(...)
+-#endif
+-
+-const Ehdr *Ehdr::validate(const void *buf)
+-{
+-  if (!buf || buf == MAP_FAILED)
+-    return nullptr;
+-
+-  const Ehdr *ehdr = reinterpret_cast<const Ehdr *>(buf);
+-
+-  /* Only support ELF executables or libraries for the host system */
+-  if (memcmp(ELFMAG, &ehdr->e_ident, SELFMAG) ||
+-      ehdr->e_ident[EI_CLASS] != ELFCLASS ||
+-      ehdr->e_ident[EI_DATA] != ELFDATA ||
+-      ehdr->e_ident[EI_VERSION] != 1 ||
+-      (ehdr->e_ident[EI_OSABI] != ELFOSABI && ehdr->e_ident[EI_OSABI] != ELFOSABI_NONE) ||
+-#ifdef EI_ABIVERSION
+-      ehdr->e_ident[EI_ABIVERSION] != ELFABIVERSION ||
+-#endif
+-      (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN) ||
+-      ehdr->e_machine != ELFMACHINE ||
+-      ehdr->e_version != 1 ||
+-      ehdr->e_phentsize != sizeof(Phdr))
+-    return nullptr;
+-
+-  return ehdr;
+-}
+-
+-namespace {
+-
+-void debug_phdr(const char *type, const Phdr *phdr)
+-{
+-  DEBUG_LOG("%s @0x%08" PRIxPTR " ("
+-            "filesz: 0x%08" PRIxPTR ", "
+-            "memsz: 0x%08" PRIxPTR ", "
+-            "offset: 0x%08" PRIxPTR ", "
+-            "flags: %c%c%c)",
+-            type, uintptr_t(phdr->p_vaddr), uintptr_t(phdr->p_filesz),
+-            uintptr_t(phdr->p_memsz), uintptr_t(phdr->p_offset),
+-            phdr->p_flags & PF_R ? 'r' : '-',
+-            phdr->p_flags & PF_W ? 'w' : '-', phdr->p_flags & PF_X ? 'x' : '-');
+-}
+-
+-static int p_flags_to_mprot(Word flags)
+-{
+-  return ((flags & PF_X) ? PROT_EXEC : 0) |
+-         ((flags & PF_W) ? PROT_WRITE : 0) |
+-         ((flags & PF_R) ? PROT_READ : 0);
+-}
+-
+-} /* anonymous namespace */
+-
+-/**
+- * RAII wrapper for a mapping of the first page off a Mappable object.
+- * This calls Mappable::munmap instead of system munmap.
+- */
+-class Mappable1stPagePtr: public GenericMappedPtr<Mappable1stPagePtr> {
+-public:
+-  Mappable1stPagePtr(Mappable *mappable)
+-  : GenericMappedPtr<Mappable1stPagePtr>(
+-      mappable->mmap(nullptr, PageSize(), PROT_READ, MAP_PRIVATE, 0))
+-  , mappable(mappable)
+-  {
+-  }
+-
+-private:
+-  friend class GenericMappedPtr<Mappable1stPagePtr>;
+-  void munmap(void *buf, size_t length) {
+-    mappable->munmap(buf, length);
+-  }
+-
+-  RefPtr<Mappable> mappable;
+-};
+-
+-
+-already_AddRefed<LibHandle>
+-CustomElf::Load(Mappable *mappable, const char *path, int flags)
+-{
+-  DEBUG_LOG("CustomElf::Load(\"%s\", 0x%x) = ...", path, flags);
+-  if (!mappable)
+-    return nullptr;
+-  /* Keeping a RefPtr of the CustomElf is going to free the appropriate
+-   * resources when returning nullptr */
+-  RefPtr<CustomElf> elf = new CustomElf(mappable, path);
+-  /* Map the first page of the Elf object to access Elf and program headers */
+-  Mappable1stPagePtr ehdr_raw(mappable);
+-  if (ehdr_raw == MAP_FAILED)
+-    return nullptr;
+-
+-  const Ehdr *ehdr = Ehdr::validate(ehdr_raw);
+-  if (!ehdr)
+-    return nullptr;
+-
+-  /* Scan Elf Program Headers and gather some information about them */
+-  std::vector<const Phdr *> pt_loads;
+-  Addr min_vaddr = (Addr) -1; // We want to find the lowest and biggest
+-  Addr max_vaddr = 0;         // virtual address used by this Elf.
+-  const Phdr *dyn = nullptr;
+-
+-  const Phdr *first_phdr = reinterpret_cast<const Phdr *>(
+-                           reinterpret_cast<const char *>(ehdr) + ehdr->e_phoff);
+-  const Phdr *end_phdr = &first_phdr[ehdr->e_phnum];
+-#ifdef __ARM_EABI__
+-  const Phdr *arm_exidx_phdr = nullptr;
+-#endif
+-
+-  for (const Phdr *phdr = first_phdr; phdr < end_phdr; phdr++) {
+-    switch (phdr->p_type) {
+-      case PT_LOAD:
+-        debug_phdr("PT_LOAD", phdr);
+-        pt_loads.push_back(phdr);
+-        if (phdr->p_vaddr < min_vaddr)
+-          min_vaddr = phdr->p_vaddr;
+-        if (max_vaddr < phdr->p_vaddr + phdr->p_memsz)
+-          max_vaddr = phdr->p_vaddr + phdr->p_memsz;
+-        break;
+-      case PT_DYNAMIC:
+-        debug_phdr("PT_DYNAMIC", phdr);
+-        if (!dyn) {
+-          dyn = phdr;
+-        } else {
+-          ERROR("%s: Multiple PT_DYNAMIC segments detected", elf->GetPath());
+-          return nullptr;
+-        }
+-        break;
+-      case PT_TLS:
+-        debug_phdr("PT_TLS", phdr);
+-        if (phdr->p_memsz) {
+-          ERROR("%s: TLS is not supported", elf->GetPath());
+-          return nullptr;
+-        }
+-        break;
+-      case PT_GNU_STACK:
+-        debug_phdr("PT_GNU_STACK", phdr);
+-// Skip on Android until bug 706116 is fixed
+-#ifndef ANDROID
+-        if (phdr->p_flags & PF_X) {
+-          ERROR("%s: Executable stack is not supported", elf->GetPath());
+-          return nullptr;
+-        }
+-#endif
+-        break;
+-#ifdef __ARM_EABI__
+-      case PT_ARM_EXIDX:
+-        /* We cannot initialize arm_exidx here
+-           because we don't have a base yet */
+-        arm_exidx_phdr = phdr;
+-        break;
+-#endif
+-      default:
+-        DEBUG_LOG("%s: Program header type #%d not handled",
+-                  elf->GetPath(), phdr->p_type);
+-    }
+-  }
+-
+-  if (min_vaddr != 0) {
+-    ERROR("%s: Unsupported minimal virtual address: 0x%08" PRIxPTR,
+-        elf->GetPath(), uintptr_t(min_vaddr));
+-    return nullptr;
+-  }
+-  if (!dyn) {
+-    ERROR("%s: No PT_DYNAMIC segment found", elf->GetPath());
+-    return nullptr;
+-  }
+-
+-  /* Reserve enough memory to map the complete virtual address space for this
+-   * library.
+-   * As we are using the base address from here to mmap something else with
+-   * MAP_FIXED | MAP_SHARED, we need to make sure these mmaps will work. For
+-   * instance, on armv6, MAP_SHARED mappings require a 16k alignment, but mmap
+-   * MAP_PRIVATE only returns a 4k aligned address. So we first get a base
+-   * address with MAP_SHARED, which guarantees the kernel returns an address
+-   * that we'll be able to use with MAP_FIXED, and then remap MAP_PRIVATE at
+-   * the same address, because of some bad side effects of keeping it as
+-   * MAP_SHARED. */
+-  elf->base.Assign(MemoryRange::mmap(nullptr, max_vaddr, PROT_NONE,
+-                                     MAP_SHARED | MAP_ANONYMOUS, -1, 0));
+-  if ((elf->base == MAP_FAILED) ||
+-      (mmap(elf->base, max_vaddr, PROT_NONE,
+-            MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0) != elf->base)) {
+-    ERROR("%s: Failed to mmap", elf->GetPath());
+-    return nullptr;
+-  }
+-
+-  /* Load and initialize library */
+-  for (std::vector<const Phdr *>::iterator it = pt_loads.begin();
+-       it < pt_loads.end(); ++it)
+-    if (!elf->LoadSegment(*it))
+-      return nullptr;
+-
+-  /* We're not going to mmap anymore */
+-  mappable->finalize();
+-
+-  report_mapping(const_cast<char *>(elf->GetName()), elf->base,
+-                 (max_vaddr + PAGE_SIZE - 1) & PAGE_MASK, 0);
+-
+-  elf->l_addr = elf->base;
+-  elf->l_name = elf->GetPath();
+-  elf->l_ld = elf->GetPtr<Dyn>(dyn->p_vaddr);
+-  ElfLoader::Singleton.Register(elf);
+-
+-  if (!elf->InitDyn(dyn))
+-    return nullptr;
+-
+-  if (elf->has_text_relocs) {
+-    for (std::vector<const Phdr *>::iterator it = pt_loads.begin();
+-         it < pt_loads.end(); ++it)
+-      mprotect(PageAlignedPtr(elf->GetPtr((*it)->p_vaddr)),
+-               PageAlignedEndPtr((*it)->p_memsz),
+-               p_flags_to_mprot((*it)->p_flags) | PROT_WRITE);
+-  }
+-
+-  if (!elf->Relocate() || !elf->RelocateJumps())
+-    return nullptr;
+-
+-  if (elf->has_text_relocs) {
+-    for (std::vector<const Phdr *>::iterator it = pt_loads.begin();
+-         it < pt_loads.end(); ++it)
+-      mprotect(PageAlignedPtr(elf->GetPtr((*it)->p_vaddr)),
+-               PageAlignedEndPtr((*it)->p_memsz),
+-               p_flags_to_mprot((*it)->p_flags));
+-  }
+-
+-  if (!elf->CallInit())
+-    return nullptr;
+-
+-#ifdef __ARM_EABI__
+-  if (arm_exidx_phdr)
+-    elf->arm_exidx.InitSize(elf->GetPtr(arm_exidx_phdr->p_vaddr),
+-                            arm_exidx_phdr->p_memsz);
+-#endif
+-
+-  DEBUG_LOG("CustomElf::Load(\"%s\", 0x%x) = %p", path, flags,
+-            static_cast<void *>(elf));
+-  return elf.forget();
+-}
+-
+-CustomElf::~CustomElf()
+-{
+-  DEBUG_LOG("CustomElf::~CustomElf(%p [\"%s\"])",
+-            reinterpret_cast<void *>(this), GetPath());
+-  CallFini();
+-  /* Normally, __cxa_finalize is called by the .fini function. However,
+-   * Android NDK before r6b doesn't do that. Our wrapped cxa_finalize only
+-   * calls destructors once, so call it in all cases. */
+-  ElfLoader::__wrap_cxa_finalize(this);
+-  ElfLoader::Singleton.Forget(this);
+-  delete_mapping(GetName());
+-}
+-
+-void *
+-CustomElf::GetSymbolPtrInDeps(const char *symbol) const
+-{
+-  /* Resolve dlopen and related functions to point to ours */
+-  if (symbol[0] == 'd' && symbol[1] == 'l') {
+-    if (strcmp(symbol + 2, "open") == 0)
+-      return FunctionPtr(__wrap_dlopen);
+-    if (strcmp(symbol + 2, "error") == 0)
+-      return FunctionPtr(__wrap_dlerror);
+-    if (strcmp(symbol + 2, "close") == 0)
+-      return FunctionPtr(__wrap_dlclose);
+-    if (strcmp(symbol + 2, "sym") == 0)
+-      return FunctionPtr(__wrap_dlsym);
+-    if (strcmp(symbol + 2, "addr") == 0)
+-      return FunctionPtr(__wrap_dladdr);
+-    if (strcmp(symbol + 2, "_iterate_phdr") == 0)
+-      return FunctionPtr(__wrap_dl_iterate_phdr);
+-  } else if (symbol[0] == '_' && symbol[1] == '_') {
+-  /* Resolve a few C++ ABI specific functions to point to ours */
+-#ifdef __ARM_EABI__
+-    if (strcmp(symbol + 2, "aeabi_atexit") == 0)
+-      return FunctionPtr(&ElfLoader::__wrap_aeabi_atexit);
+-#else
+-    if (strcmp(symbol + 2, "cxa_atexit") == 0)
+-      return FunctionPtr(&ElfLoader::__wrap_cxa_atexit);
+-#endif
+-    if (strcmp(symbol + 2, "cxa_finalize") == 0)
+-      return FunctionPtr(&ElfLoader::__wrap_cxa_finalize);
+-    if (strcmp(symbol + 2, "dso_handle") == 0)
+-      return const_cast<CustomElf *>(this);
+-#ifdef __ARM_EABI__
+-    if (strcmp(symbol + 2, "gnu_Unwind_Find_exidx") == 0)
+-      return FunctionPtr(__wrap___gnu_Unwind_Find_exidx);
+-#endif
+-  } else if (symbol[0] == 's' && symbol[1] == 'i') {
+-    if (strcmp(symbol + 2, "gnal") == 0)
+-      return FunctionPtr(signal);
+-    if (strcmp(symbol + 2, "gaction") == 0)
+-      return FunctionPtr(sigaction);
+-  }
+-
+-  void *sym;
+-
+-  unsigned long hash = Hash(symbol);
+-
+-  /* self_elf should never be NULL, but better safe than sorry. */
+-  if (ElfLoader::Singleton.self_elf) {
+-    /* We consider the library containing this code a permanent LD_PRELOAD,
+-     * so, check if the symbol exists here first. */
+-    sym = static_cast<BaseElf *>(
+-      ElfLoader::Singleton.self_elf.get())->GetSymbolPtr(symbol, hash);
+-    if (sym)
+-      return sym;
+-  }
+-
+-  /* Then search the symbol in our dependencies. Since we already searched in
+-   * libraries the system linker loaded, skip those (on glibc systems). We
+-   * also assume the symbol is to be found in one of the dependent libraries
+-   * directly, not in their own dependent libraries. Building libraries with
+-   * --no-allow-shlib-undefined ensures such indirect symbol dependency don't
+-   * happen. */
+-  for (std::vector<RefPtr<LibHandle> >::const_iterator it = dependencies.begin();
+-       it < dependencies.end(); ++it) {
+-    /* Skip if it's the library containing this code, since we've already
+-     * looked at it above. */
+-    if (*it == ElfLoader::Singleton.self_elf)
+-      continue;
+-    if (BaseElf *be = (*it)->AsBaseElf()) {
+-      sym = be->GetSymbolPtr(symbol, hash);
+-    } else {
+-      sym = (*it)->GetSymbolPtr(symbol);
+-    }
+-    if (sym)
+-      return sym;
+-  }
+-  return nullptr;
+-}
+-
+-bool
+-CustomElf::LoadSegment(const Phdr *pt_load) const
+-{
+-  if (pt_load->p_type != PT_LOAD) {
+-    DEBUG_LOG("%s: Elf::LoadSegment only takes PT_LOAD program headers", GetPath());
+-    return false;;
+-  }
+-
+-  int prot = p_flags_to_mprot(pt_load->p_flags);
+-
+-  /* Mmap at page boundary */
+-  Addr align = PageSize();
+-  Addr align_offset;
+-  void *mapped, *where;
+-  do {
+-    align_offset = pt_load->p_vaddr - AlignedPtr(pt_load->p_vaddr, align);
+-    where = GetPtr(pt_load->p_vaddr - align_offset);
+-    DEBUG_LOG("%s: Loading segment @%p %c%c%c", GetPath(), where,
+-                                                prot & PROT_READ ? 'r' : '-',
+-                                                prot & PROT_WRITE ? 'w' : '-',
+-                                                prot & PROT_EXEC ? 'x' : '-');
+-    mapped = mappable->mmap(where, pt_load->p_filesz + align_offset,
+-                            prot, MAP_PRIVATE | MAP_FIXED,
+-                            pt_load->p_offset - align_offset);
+-    if ((mapped != MAP_FAILED) || (pt_load->p_vaddr == 0) ||
+-        (pt_load->p_align == align))
+-      break;
+-    /* The virtual address space for the library is properly aligned at
+-     * 16k on ARMv6 (see CustomElf::Load), and so is the first segment
+-     * (p_vaddr == 0). But subsequent segments may not be 16k aligned
+-     * and fail to mmap. In such case, try to mmap again at the p_align
+-     * boundary instead of page boundary. */
+-    DEBUG_LOG("%s: Failed to mmap, retrying", GetPath());
+-    align = pt_load->p_align;
+-  } while (1);
+-
+-  if (mapped != where) {
+-    if (mapped == MAP_FAILED) {
+-      ERROR("%s: Failed to mmap", GetPath());
+-    } else {
+-      ERROR("%s: Didn't map at the expected location (wanted: %p, got: %p)",
+-          GetPath(), where, mapped);
+-    }
+-    return false;
+-  }
+-
+-  /* When p_memsz is greater than p_filesz, we need to have nulled out memory
+-   * after p_filesz and before p_memsz.
+-   * Above the end of the last page, and up to p_memsz, we already have nulled
+-   * out memory because we mapped anonymous memory on the whole library virtual
+-   * address space. We just need to adjust this anonymous memory protection
+-   * flags. */
+-  if (pt_load->p_memsz > pt_load->p_filesz) {
+-    Addr file_end = pt_load->p_vaddr + pt_load->p_filesz;
+-    Addr mem_end = pt_load->p_vaddr + pt_load->p_memsz;
+-    Addr next_page = PageAlignedEndPtr(file_end);
+-    if (next_page > file_end) {
+-      void *ptr = GetPtr(file_end);
+-      memset(ptr, 0, next_page - file_end);
+-    }
+-    if (mem_end > next_page) {
+-      if (mprotect(GetPtr(next_page), mem_end - next_page, prot) < 0) {
+-        ERROR("%s: Failed to mprotect", GetPath());
+-        return false;
+-      }
+-    }
+-  }
+-  return true;
+-}
+-
+-namespace {
+-
+-void debug_dyn(const char *type, const Dyn *dyn)
+-{
+-  DEBUG_LOG("%s 0x%08" PRIxPTR, type, uintptr_t(dyn->d_un.d_val));
+-}
+-
+-} /* anonymous namespace */
+-
+-bool
+-CustomElf::InitDyn(const Phdr *pt_dyn)
+-{
+-  /* Scan PT_DYNAMIC segment and gather some information */
+-  const Dyn *first_dyn = GetPtr<Dyn>(pt_dyn->p_vaddr);
+-  const Dyn *end_dyn = GetPtr<Dyn>(pt_dyn->p_vaddr + pt_dyn->p_filesz);
+-  std::vector<Word> dt_needed;
+-  size_t symnum = 0;
+-  for (const Dyn *dyn = first_dyn; dyn < end_dyn && dyn->d_tag; dyn++) {
+-    switch (dyn->d_tag) {
+-      case DT_NEEDED:
+-        debug_dyn("DT_NEEDED", dyn);
+-        dt_needed.push_back(dyn->d_un.d_val);
+-        break;
+-      case DT_HASH:
+-        {
+-          debug_dyn("DT_HASH", dyn);
+-          const Word *hash_table_header = GetPtr<Word>(dyn->d_un.d_ptr);
+-          symnum = hash_table_header[1];
+-          buckets.Init(&hash_table_header[2], hash_table_header[0]);
+-          chains.Init(&*buckets.end());
+-        }
+-        break;
+-      case DT_STRTAB:
+-        debug_dyn("DT_STRTAB", dyn);
+-        strtab.Init(GetPtr(dyn->d_un.d_ptr));
+-        break;
+-      case DT_SYMTAB:
+-        debug_dyn("DT_SYMTAB", dyn);
+-        symtab.Init(GetPtr(dyn->d_un.d_ptr));
+-        break;
+-      case DT_SYMENT:
+-        debug_dyn("DT_SYMENT", dyn);
+-        if (dyn->d_un.d_val != sizeof(Sym)) {
+-          ERROR("%s: Unsupported DT_SYMENT", GetPath());
+-          return false;
+-        }
+-        break;
+-      case DT_TEXTREL:
+-        if (strcmp("libflashplayer.so", GetName()) == 0) {
+-          has_text_relocs = true;
+-        } else {
+-          ERROR("%s: Text relocations are not supported", GetPath());
+-          return false;
+-        }
+-        break;
+-      case DT_STRSZ: /* Ignored */
+-        debug_dyn("DT_STRSZ", dyn);
+-        break;
+-      case UNSUPPORTED_RELOC():
+-      case UNSUPPORTED_RELOC(SZ):
+-      case UNSUPPORTED_RELOC(ENT):
+-        ERROR("%s: Unsupported relocations", GetPath());
+-        return false;
+-      case RELOC():
+-        debug_dyn(STR_RELOC(), dyn);
+-        relocations.Init(GetPtr(dyn->d_un.d_ptr));
+-        break;
+-      case RELOC(SZ):
+-        debug_dyn(STR_RELOC(SZ), dyn);
+-        relocations.InitSize(dyn->d_un.d_val);
+-        break;
+-      case RELOC(ENT):
+-        debug_dyn(STR_RELOC(ENT), dyn);
+-        if (dyn->d_un.d_val != sizeof(Reloc)) {
+-          ERROR("%s: Unsupported DT_RELENT", GetPath());
+-          return false;
+-        }
+-        break;
+-      case DT_JMPREL:
+-        debug_dyn("DT_JMPREL", dyn);
+-        jumprels.Init(GetPtr(dyn->d_un.d_ptr));
+-        break;
+-      case DT_PLTRELSZ:
+-        debug_dyn("DT_PLTRELSZ", dyn);
+-        jumprels.InitSize(dyn->d_un.d_val);
+-        break;
+-      case DT_PLTGOT:
+-        debug_dyn("DT_PLTGOT", dyn);
+-        break;
+-      case DT_INIT:
+-        debug_dyn("DT_INIT", dyn);
+-        init = dyn->d_un.d_ptr;
+-        break;
+-      case DT_INIT_ARRAY:
+-        debug_dyn("DT_INIT_ARRAY", dyn);
+-        init_array.Init(GetPtr(dyn->d_un.d_ptr));
+-        break;
+-      case DT_INIT_ARRAYSZ:
+-        debug_dyn("DT_INIT_ARRAYSZ", dyn);
+-        init_array.InitSize(dyn->d_un.d_val);
+-        break;
+-      case DT_FINI:
+-        debug_dyn("DT_FINI", dyn);
+-        fini = dyn->d_un.d_ptr;
+-        break;
+-      case DT_FINI_ARRAY:
+-        debug_dyn("DT_FINI_ARRAY", dyn);
+-        fini_array.Init(GetPtr(dyn->d_un.d_ptr));
+-        break;
+-      case DT_FINI_ARRAYSZ:
+-        debug_dyn("DT_FINI_ARRAYSZ", dyn);
+-        fini_array.InitSize(dyn->d_un.d_val);
+-        break;
+-      case DT_PLTREL:
+-        if (dyn->d_un.d_val != RELOC()) {
+-          ERROR("%s: Error: DT_PLTREL is not " STR_RELOC(), GetPath());
+-          return false;
+-        }
+-        break;
+-      case DT_FLAGS:
+-        {
+-           Addr flags = dyn->d_un.d_val;
+-           /* Treat as a DT_TEXTREL tag */
+-           if (flags & DF_TEXTREL) {
+-             if (strcmp("libflashplayer.so", GetName()) == 0) {
+-               has_text_relocs = true;
+-             } else {
+-               ERROR("%s: Text relocations are not supported", GetPath());
+-               return false;
+-             }
+-           }
+-           /* we can treat this like having a DT_SYMBOLIC tag */
+-           flags &= ~DF_SYMBOLIC;
+-           if (flags)
+-             WARN("%s: unhandled flags #%" PRIxPTR" not handled",
+-                 GetPath(), uintptr_t(flags));
+-        }
+-        break;
+-      case DT_SONAME: /* Should match GetName(), but doesn't matter */
+-      case DT_SYMBOLIC: /* Indicates internal symbols should be looked up in
+-                         * the library itself first instead of the executable,
+-                         * which is actually what this linker does by default */
+-      case RELOC(COUNT): /* Indicates how many relocations are relative, which
+-                          * is usually used to skip relocations on prelinked
+-                          * libraries. They are not supported anyways. */
+-      case UNSUPPORTED_RELOC(COUNT): /* This should error out, but it doesn't
+-                                      * really matter. */
+-      case DT_FLAGS_1: /* Additional linker-internal flags that we don't care about. See
+-                        * DF_1_* values in src/include/elf/common.h in binutils. */
+-      case DT_VERSYM: /* DT_VER* entries are used for symbol versioning, which */
+-      case DT_VERDEF: /* this linker doesn't support yet. */
+-      case DT_VERDEFNUM:
+-      case DT_VERNEED:
+-      case DT_VERNEEDNUM:
+-        /* Ignored */
+-        break;
+-      default:
+-        WARN("%s: dynamic header type #%" PRIxPTR" not handled",
+-            GetPath(), uintptr_t(dyn->d_tag));
+-    }
+-  }
+-
+-  if (!buckets || !symnum) {
+-    ERROR("%s: Missing or broken DT_HASH", GetPath());
+-    return false;
+-  }
+-  if (!strtab) {
+-    ERROR("%s: Missing DT_STRTAB", GetPath());
+-    return false;
+-  }
+-  if (!symtab) {
+-    ERROR("%s: Missing DT_SYMTAB", GetPath());
+-    return false;
+-  }
+-
+-  /* Load dependent libraries */
+-  for (size_t i = 0; i < dt_needed.size(); i++) {
+-    const char *name = strtab.GetStringAt(dt_needed[i]);
+-    RefPtr<LibHandle> handle =
+-      ElfLoader::Singleton.Load(name, RTLD_GLOBAL | RTLD_LAZY, this);
+-    if (!handle)
+-      return false;
+-    dependencies.push_back(handle);
+-  }
+-
+-  return true;
+-}
+-
+-bool
+-CustomElf::Relocate()
+-{
+-  DEBUG_LOG("Relocate %s @%p", GetPath(), static_cast<void *>(base));
+-  uint32_t symtab_index = (uint32_t) -1;
+-  void *symptr = nullptr;
+-  for (Array<Reloc>::iterator rel = relocations.begin();
+-       rel < relocations.end(); ++rel) {
+-    /* Location of the relocation */
+-    void *ptr = GetPtr(rel->r_offset);
+-
+-    /* R_*_RELATIVE relocations apply directly at the given location */
+-    if (ELF_R_TYPE(rel->r_info) == R_RELATIVE) {
+-      *(void **) ptr = GetPtr(rel->GetAddend(base));
+-      continue;
+-    }
+-    /* Other relocation types need a symbol resolution */
+-    /* Avoid symbol resolution when it's the same symbol as last iteration */
+-    if (symtab_index != ELF_R_SYM(rel->r_info)) {
+-      symtab_index = ELF_R_SYM(rel->r_info);
+-      const Sym sym = symtab[symtab_index];
+-      if (sym.st_shndx != SHN_UNDEF) {
+-        symptr = GetPtr(sym.st_value);
+-      } else {
+-        /* TODO: handle symbol resolving to nullptr vs. being undefined. */
+-        symptr = GetSymbolPtrInDeps(strtab.GetStringAt(sym.st_name));
+-      }
+-    }
+-
+-    if (symptr == nullptr)
+-      WARN("%s: Relocation to NULL @0x%08" PRIxPTR,
+-          GetPath(), uintptr_t(rel->r_offset));
+-
+-    /* Apply relocation */
+-    switch (ELF_R_TYPE(rel->r_info)) {
+-    case R_GLOB_DAT:
+-      /* R_*_GLOB_DAT relocations simply use the symbol value */
+-      *(void **) ptr = symptr;
+-      break;
+-    case R_ABS:
+-      /* R_*_ABS* relocations add the relocation added to the symbol value */
+-      *(const char **) ptr = (const char *)symptr + rel->GetAddend(base);
+-      break;
+-    default:
+-      ERROR("%s: Unsupported relocation type: 0x%" PRIxPTR,
+-          GetPath(), uintptr_t(ELF_R_TYPE(rel->r_info)));
+-      return false;
+-    }
+-  }
+-  return true;
+-}
+-
+-bool
+-CustomElf::RelocateJumps()
+-{
+-  /* TODO: Dynamic symbol resolution */
+-  for (Array<Reloc>::iterator rel = jumprels.begin();
+-       rel < jumprels.end(); ++rel) {
+-    /* Location of the relocation */
+-    void *ptr = GetPtr(rel->r_offset);
+-
+-    /* Only R_*_JMP_SLOT relocations are expected */
+-    if (ELF_R_TYPE(rel->r_info) != R_JMP_SLOT) {
+-      ERROR("%s: Jump relocation type mismatch", GetPath());
+-      return false;
+-    }
+-
+-    /* TODO: Avoid code duplication with the relocations above */
+-    const Sym sym = symtab[ELF_R_SYM(rel->r_info)];
+-    void *symptr;
+-    if (sym.st_shndx != SHN_UNDEF)
+-      symptr = GetPtr(sym.st_value);
+-    else
+-      symptr = GetSymbolPtrInDeps(strtab.GetStringAt(sym.st_name));
+-
+-    if (symptr == nullptr) {
+-      if (ELF_ST_BIND(sym.st_info) == STB_WEAK) {
+-        WARN("%s: Relocation to NULL @0x%08" PRIxPTR " for symbol \"%s\"",
+-            GetPath(),
+-            uintptr_t(rel->r_offset), strtab.GetStringAt(sym.st_name));
+-      } else {
+-        ERROR("%s: Relocation to NULL @0x%08" PRIxPTR " for symbol \"%s\"",
+-            GetPath(),
+-            uintptr_t(rel->r_offset), strtab.GetStringAt(sym.st_name));
+-        return false;
+-      }
+-    }
+-    /* Apply relocation */
+-    *(void **) ptr = symptr;
+-  }
+-  return true;
+-}
+-
+-bool
+-CustomElf::CallInit()
+-{
+-  if (init)
+-    CallFunction(init);
+-
+-  for (Array<void *>::iterator it = init_array.begin();
+-       it < init_array.end(); ++it) {
+-    /* Android x86 NDK wrongly puts 0xffffffff in INIT_ARRAY */
+-    if (*it && *it != reinterpret_cast<void *>(-1))
+-      CallFunction(*it);
+-  }
+-  initialized = true;
+-  return true;
+-}
+-
+-void
+-CustomElf::CallFini()
+-{
+-  if (!initialized)
+-    return;
+-  for (Array<void *>::reverse_iterator it = fini_array.rbegin();
+-       it < fini_array.rend(); ++it) {
+-    /* Android x86 NDK wrongly puts 0xffffffff in FINI_ARRAY */
+-    if (*it && *it != reinterpret_cast<void *>(-1))
+-      CallFunction(*it);
+-  }
+-  if (fini)
+-    CallFunction(fini);
+-}
+-
+-Mappable *
+-CustomElf::GetMappable() const
+-{
+-  if (!mappable)
+-    return nullptr;
+-  if (mappable->GetKind() == Mappable::MAPPABLE_EXTRACT_FILE)
+-    return mappable;
+-  return ElfLoader::GetMappableFromPath(GetPath());
+-}
+diff --git a/mozglue/linker/CustomElf.h b/mozglue/linker/CustomElf.h
+deleted file mode 100644
+--- a/mozglue/linker/CustomElf.h
++++ /dev/null
+@@ -1,152 +0,0 @@
+-/* 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/. */
+-
+-#ifndef CustomElf_h
+-#define CustomElf_h
+-
+-#include "ElfLoader.h"
+-#include "BaseElf.h"
+-#include "Logging.h"
+-#include "Elfxx.h"
+-
+-/**
+- * Library Handle class for ELF libraries we don't let the system linker
+- * handle.
+- */
+-class CustomElf: public BaseElf, private ElfLoader::link_map
+-{
+-  friend class ElfLoader;
+-  friend class SEGVHandler;
+-public:
+-  /**
+-   * Returns a new CustomElf using the given file descriptor to map ELF
+-   * content. The file descriptor ownership is stolen, and it will be closed
+-   * in CustomElf's destructor if an instance is created, or by the Load
+-   * method otherwise. The path corresponds to the file descriptor, and flags
+-   * are the same kind of flags that would be given to dlopen(), though
+-   * currently, none are supported and the behaviour is more or less that of
+-   * RTLD_GLOBAL | RTLD_BIND_NOW.
+-   */
+-  static already_AddRefed<LibHandle> Load(Mappable *mappable,
+-                                               const char *path, int flags);
+-
+-  /**
+-   * Inherited from LibHandle/BaseElf
+-   */
+-  virtual ~CustomElf();
+-
+-protected:
+-  virtual Mappable *GetMappable() const;
+-
+-public:
+-  /**
+-   * Returns the instance, casted as BaseElf. (short of a better way to do
+-   * this without RTTI)
+-   */
+-  virtual BaseElf *AsBaseElf() { return this; }
+-
+-private:
+-  /**
+-   * Scan dependent libraries to find the address corresponding to the
+-   * given symbol name. This is used to find symbols that are undefined
+-   * in the Elf object.
+-   */
+-  void *GetSymbolPtrInDeps(const char *symbol) const;
+-
+-  /**
+-   * Private constructor
+-   */
+-  CustomElf(Mappable *mappable, const char *path)
+-  : BaseElf(path, mappable)
+-  , link_map()
+-  , init(0)
+-  , fini(0)
+-  , initialized(false)
+-  , has_text_relocs(false)
+-  { }
+-
+-  /**
+-   * Loads an Elf segment defined by the given PT_LOAD header.
+-   * Returns whether this succeeded or failed.
+-   */
+-  bool LoadSegment(const Elf::Phdr *pt_load) const;
+-
+-  /**
+-   * Initializes the library according to information found in the given
+-   * PT_DYNAMIC header.
+-   * Returns whether this succeeded or failed.
+-   */
+-  bool InitDyn(const Elf::Phdr *pt_dyn);
+-
+-  /**
+-   * Apply .rel.dyn/.rela.dyn relocations.
+-   * Returns whether this succeeded or failed.
+-   */
+-  bool Relocate();
+-
+-  /**
+-   * Apply .rel.plt/.rela.plt relocations.
+-   * Returns whether this succeeded or failed.
+-   */
+-  bool RelocateJumps();
+-
+-  /**
+-   * Call initialization functions (.init/.init_array)
+-   * Returns true;
+-   */
+-  bool CallInit();
+-
+-  /**
+-   * Call destructor functions (.fini_array/.fini)
+-   * Returns whether this succeeded or failed.
+-   */
+-  void CallFini();
+-
+-  /**
+-   * Call a function given a pointer to its location.
+-   */
+-  void CallFunction(void *ptr) const
+-  {
+-    /* C++ doesn't allow direct conversion between pointer-to-object
+-     * and pointer-to-function. */
+-    union {
+-      void *ptr;
+-      void (*func)(void);
+-    } f;
+-    f.ptr = ptr;
+-    DEBUG_LOG("%s: Calling function @%p", GetPath(), ptr);
+-    f.func();
+-  }
+-
+-  /**
+-   * Call a function given a an address relative to the library base
+-   */
+-  void CallFunction(Elf::Addr addr) const
+-  {
+-    return CallFunction(GetPtr(addr));
+-  }
+-
+-  /* List of dependent libraries */
+-  std::vector<RefPtr<LibHandle> > dependencies;
+-
+-  /* List of .rel.dyn/.rela.dyn relocations */
+-  Array<Elf::Reloc> relocations;
+-
+-  /* List of .rel.plt/.rela.plt relocation */
+-  Array<Elf::Reloc> jumprels;
+-
+-  /* Relative address of the initialization and destruction functions
+-   * (.init/.fini) */
+-  Elf::Addr init, fini;
+-
+-  /* List of initialization and destruction functions
+-   * (.init_array/.fini_array) */
+-  Array<void *> init_array, fini_array;
+-
+-  bool initialized;
+-
+-  bool has_text_relocs;
+-};
+-
+-#endif /* CustomElf_h */
+diff --git a/mozglue/linker/ElfLoader.cpp b/mozglue/linker/ElfLoader.cpp
+deleted file mode 100644
+--- a/mozglue/linker/ElfLoader.cpp
++++ /dev/null
+@@ -1,1301 +0,0 @@
+-/* 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 <string>
+-#include <cstring>
+-#include <cstdlib>
+-#include <cstdio>
+-#include <dlfcn.h>
+-#include <unistd.h>
+-#include <errno.h>
+-#include <algorithm>
+-#include <fcntl.h>
+-#include "ElfLoader.h"
+-#include "BaseElf.h"
+-#include "CustomElf.h"
+-#include "Mappable.h"
+-#include "Logging.h"
+-#include <inttypes.h>
+-
+-#if defined(ANDROID)
+-#include <sys/syscall.h>
+-#include <math.h>
+-
+-#include <android/api-level.h>
+-#if __ANDROID_API__ < 8
+-/* Android API < 8 doesn't provide sigaltstack */
+-
+-extern "C" {
+-
+-inline int sigaltstack(const stack_t *ss, stack_t *oss) {
+-  return syscall(__NR_sigaltstack, ss, oss);
+-}
+-
+-} /* extern "C" */
+-#endif /* __ANDROID_API__ */
+-#endif /* ANDROID */
+-
+-#ifdef __ARM_EABI__
+-extern "C" MOZ_EXPORT const void *
+-__gnu_Unwind_Find_exidx(void *pc, int *pcount) __attribute__((weak));
+-#endif
+-
+-/* Pointer to the PT_DYNAMIC section of the executable or library
+- * containing this code. */
+-extern "C" Elf::Dyn _DYNAMIC[];
+-
+-using namespace mozilla;
+-
+-/**
+- * dlfcn.h replacements functions
+- */
+-
+-void *
+-__wrap_dlopen(const char *path, int flags)
+-{
+-  RefPtr<LibHandle> handle = ElfLoader::Singleton.Load(path, flags);
+-  if (handle)
+-    handle->AddDirectRef();
+-  return handle;
+-}
+-
+-const char *
+-__wrap_dlerror(void)
+-{
+-  const char *error = ElfLoader::Singleton.lastError;
+-  ElfLoader::Singleton.lastError = nullptr;
+-  return error;
+-}
+-
+-void *
+-__wrap_dlsym(void *handle, const char *symbol)
+-{
+-  if (!handle) {
+-    ElfLoader::Singleton.lastError = "dlsym(NULL, sym) unsupported";
+-    return nullptr;
+-  }
+-  if (handle != RTLD_DEFAULT && handle != RTLD_NEXT) {
+-    LibHandle *h = reinterpret_cast<LibHandle *>(handle);
+-    return h->GetSymbolPtr(symbol);
+-  }
+-  return dlsym(handle, symbol);
+-}
+-
+-int
+-__wrap_dlclose(void *handle)
+-{
+-  if (!handle) {
+-    ElfLoader::Singleton.lastError = "No handle given to dlclose()";
+-    return -1;
+-  }
+-  reinterpret_cast<LibHandle *>(handle)->ReleaseDirectRef();
+-  return 0;
+-}
+-
+-int
+-__wrap_dladdr(void *addr, Dl_info *info)
+-{
+-  RefPtr<LibHandle> handle = ElfLoader::Singleton.GetHandleByPtr(addr);
+-  if (!handle) {
+-    return dladdr(addr, info);
+-  }
+-  info->dli_fname = handle->GetPath();
+-  info->dli_fbase = handle->GetBase();
+-  return 1;
+-}
+-
+-int
+-__wrap_dl_iterate_phdr(dl_phdr_cb callback, void *data)
+-{
+-  if (!ElfLoader::Singleton.dbg)
+-    return -1;
+-
+-  int pipefd[2];
+-  bool valid_pipe = (pipe(pipefd) == 0);
+-  AutoCloseFD read_fd(pipefd[0]);
+-  AutoCloseFD write_fd(pipefd[1]);
+-
+-  for (ElfLoader::DebuggerHelper::iterator it = ElfLoader::Singleton.dbg.begin();
+-       it < ElfLoader::Singleton.dbg.end(); ++it) {
+-    dl_phdr_info info;
+-    info.dlpi_addr = reinterpret_cast<Elf::Addr>(it->l_addr);
+-    info.dlpi_name = it->l_name;
+-    info.dlpi_phdr = nullptr;
+-    info.dlpi_phnum = 0;
+-
+-    // Assuming l_addr points to Elf headers (in most cases, this is true),
+-    // get the Phdr location from there.
+-    // Unfortunately, when l_addr doesn't point to Elf headers, it may point
+-    // to unmapped memory, or worse, unreadable memory. The only way to detect
+-    // the latter without causing a SIGSEGV is to use the pointer in a system
+-    // call that will try to read from there, and return an EFAULT error if
+-    // it can't. One such system call is write(). It used to be possible to
+-    // use a file descriptor on /dev/null for these kind of things, but recent
+-    // Linux kernels never return an EFAULT error when using /dev/null.
+-    // So instead, we use a self pipe. We do however need to read() from the
+-    // read end of the pipe as well so as to not fill up the pipe buffer and
+-    // block on subsequent writes.
+-    // In the unlikely event reads from or write to the pipe fail for some
+-    // other reason than EFAULT, we don't try any further and just skip setting
+-    // the Phdr location for all subsequent libraries, rather than trying to
+-    // start over with a new pipe.
+-    int can_read = true;
+-    if (valid_pipe) {
+-      int ret;
+-      char raw_ehdr[sizeof(Elf::Ehdr)];
+-      static_assert(sizeof(raw_ehdr) < PIPE_BUF, "PIPE_BUF is too small");
+-      do {
+-        // writes are atomic when smaller than PIPE_BUF, per POSIX.1-2008.
+-        ret = write(write_fd, it->l_addr, sizeof(raw_ehdr));
+-      } while (ret == -1 && errno == EINTR);
+-      if (ret != sizeof(raw_ehdr)) {
+-        if (ret == -1 && errno == EFAULT) {
+-          can_read = false;
+-        } else {
+-          valid_pipe = false;
+-        }
+-      } else {
+-        size_t nbytes = 0;
+-        do {
+-          // Per POSIX.1-2008, interrupted reads can return a length smaller
+-          // than the given one instead of failing with errno EINTR.
+-          ret = read(read_fd, raw_ehdr + nbytes, sizeof(raw_ehdr) - nbytes);
+-          if (ret > 0)
+-              nbytes += ret;
+-        } while ((nbytes != sizeof(raw_ehdr) && ret > 0) ||
+-                 (ret == -1 && errno == EINTR));
+-        if (nbytes != sizeof(raw_ehdr)) {
+-          valid_pipe = false;
+-        }
+-      }
+-    }
+-
+-    if (valid_pipe && can_read) {
+-      const Elf::Ehdr *ehdr = Elf::Ehdr::validate(it->l_addr);
+-      if (ehdr) {
+-        info.dlpi_phdr = reinterpret_cast<const Elf::Phdr *>(
+-                         reinterpret_cast<const char *>(ehdr) + ehdr->e_phoff);
+-        info.dlpi_phnum = ehdr->e_phnum;
+-      }
+-    }
+-
+-    int ret = callback(&info, sizeof(dl_phdr_info), data);
+-    if (ret)
+-      return ret;
+-  }
+-  return 0;
+-}
+-
+-#ifdef __ARM_EABI__
+-const void *
+-__wrap___gnu_Unwind_Find_exidx(void *pc, int *pcount)
+-{
+-  RefPtr<LibHandle> handle = ElfLoader::Singleton.GetHandleByPtr(pc);
+-  if (handle)
+-    return handle->FindExidx(pcount);
+-  if (__gnu_Unwind_Find_exidx)
+-    return __gnu_Unwind_Find_exidx(pc, pcount);
+-  *pcount = 0;
+-  return nullptr;
+-}
+-#endif
+-
+-/**
+- * faulty.lib public API
+- */
+-
+-MFBT_API size_t
+-__dl_get_mappable_length(void *handle) {
+-  if (!handle)
+-    return 0;
+-  return reinterpret_cast<LibHandle *>(handle)->GetMappableLength();
+-}
+-
+-MFBT_API void *
+-__dl_mmap(void *handle, void *addr, size_t length, off_t offset)
+-{
+-  if (!handle)
+-    return nullptr;
+-  return reinterpret_cast<LibHandle *>(handle)->MappableMMap(addr, length,
+-                                                             offset);
+-}
+-
+-MFBT_API void
+-__dl_munmap(void *handle, void *addr, size_t length)
+-{
+-  if (!handle)
+-    return;
+-  return reinterpret_cast<LibHandle *>(handle)->MappableMUnmap(addr, length);
+-}
+-
+-MFBT_API bool
+-IsSignalHandlingBroken()
+-{
+-  return ElfLoader::Singleton.isSignalHandlingBroken();
+-}
+-
+-namespace {
+-
+-/**
+- * Returns the part after the last '/' for the given path
+- */
+-const char *
+-LeafName(const char *path)
+-{
+-  const char *lastSlash = strrchr(path, '/');
+-  if (lastSlash)
+-    return lastSlash + 1;
+-  return path;
+-}
+-
+-} /* Anonymous namespace */
+-
+-/**
+- * LibHandle
+- */
+-LibHandle::~LibHandle()
+-{
+-  free(path);
+-}
+-
+-const char *
+-LibHandle::GetName() const
+-{
+-  return path ? LeafName(path) : nullptr;
+-}
+-
+-size_t
+-LibHandle::GetMappableLength() const
+-{
+-  if (!mappable)
+-    mappable = GetMappable();
+-  if (!mappable)
+-    return 0;
+-  return mappable->GetLength();
+-}
+-
+-void *
+-LibHandle::MappableMMap(void *addr, size_t length, off_t offset) const
+-{
+-  if (!mappable)
+-    mappable = GetMappable();
+-  if (!mappable)
+-    return MAP_FAILED;
+-  void* mapped = mappable->mmap(addr, length, PROT_READ, MAP_PRIVATE, offset);
+-  return mapped;
+-}
+-
+-void
+-LibHandle::MappableMUnmap(void *addr, size_t length) const
+-{
+-  if (mappable)
+-    mappable->munmap(addr, length);
+-}
+-
+-/**
+- * SystemElf
+- */
+-already_AddRefed<LibHandle>
+-SystemElf::Load(const char *path, int flags)
+-{
+-  /* The Android linker returns a handle when the file name matches an
+-   * already loaded library, even when the full path doesn't exist */
+-  if (path && path[0] == '/' && (access(path, F_OK) == -1)){
+-    DEBUG_LOG("dlopen(\"%s\", 0x%x) = %p", path, flags, (void *)nullptr);
+-    return nullptr;
+-  }
+-
+-  void *handle = dlopen(path, flags);
+-  DEBUG_LOG("dlopen(\"%s\", 0x%x) = %p", path, flags, handle);
+-  ElfLoader::Singleton.lastError = dlerror();
+-  if (handle) {
+-    SystemElf *elf = new SystemElf(path, handle);
+-    ElfLoader::Singleton.Register(elf);
+-    RefPtr<LibHandle> lib(elf);
+-    return lib.forget();
+-  }
+-  return nullptr;
+-}
+-
+-SystemElf::~SystemElf()
+-{
+-  if (!dlhandle)
+-    return;
+-  DEBUG_LOG("dlclose(%p [\"%s\"])", dlhandle, GetPath());
+-  dlclose(dlhandle);
+-  ElfLoader::Singleton.lastError = dlerror();
+-  ElfLoader::Singleton.Forget(this);
+-}
+-
+-void *
+-SystemElf::GetSymbolPtr(const char *symbol) const
+-{
+-  void *sym = dlsym(dlhandle, symbol);
+-  DEBUG_LOG("dlsym(%p [\"%s\"], \"%s\") = %p", dlhandle, GetPath(), symbol, sym);
+-  ElfLoader::Singleton.lastError = dlerror();
+-  return sym;
+-}
+-
+-Mappable *
+-SystemElf::GetMappable() const
+-{
+-  const char *path = GetPath();
+-  if (!path)
+-    return nullptr;
+-#ifdef ANDROID
+-  /* On Android, if we don't have the full path, try in /system/lib */
+-  const char *name = LeafName(path);
+-  std::string systemPath;
+-  if (name == path) {
+-    systemPath = "/system/lib/";
+-    systemPath += path;
+-    path = systemPath.c_str();
+-  }
+-#endif
+-
+-  return MappableFile::Create(path);
+-}
+-
+-#ifdef __ARM_EABI__
+-const void *
+-SystemElf::FindExidx(int *pcount) const
+-{
+-  /* TODO: properly implement when ElfLoader::GetHandleByPtr
+-     does return SystemElf handles */
+-  *pcount = 0;
+-  return nullptr;
+-}
+-#endif
+-
+-/**
+- * ElfLoader
+- */
+-
+-/* Unique ElfLoader instance */
+-ElfLoader ElfLoader::Singleton;
+-
+-already_AddRefed<LibHandle>
+-ElfLoader::Load(const char *path, int flags, LibHandle *parent)
+-{
+-  /* Ensure logging is initialized or refresh if environment changed. */
+-  Logging::Init();
+-
+-  /* Ensure self_elf initialization. */
+-  if (!self_elf)
+-    Init();
+-
+-  RefPtr<LibHandle> handle;
+-
+-  /* Handle dlopen(nullptr) directly. */
+-  if (!path) {
+-    handle = SystemElf::Load(nullptr, flags);
+-    return handle.forget();
+-  }
+-
+-  /* TODO: Handle relative paths correctly */
+-  const char *name = LeafName(path);
+-
+-  /* Search the list of handles we already have for a match. When the given
+-   * path is not absolute, compare file names, otherwise compare full paths. */
+-  if (name == path) {
+-    AutoLock lock(&handlesMutex);
+-    for (LibHandleList::iterator it = handles.begin(); it < handles.end(); ++it)
+-      if ((*it)->GetName() && (strcmp((*it)->GetName(), name) == 0)) {
+-        handle = *it;
+-        return handle.forget();
+-      }
+-  } else {
+-    AutoLock lock(&handlesMutex);
+-    for (LibHandleList::iterator it = handles.begin(); it < handles.end(); ++it)
+-      if ((*it)->GetPath() && (strcmp((*it)->GetPath(), path) == 0)) {
+-        handle = *it;
+-        return handle.forget();
+-      }
+-  }
+-
+-  char *abs_path = nullptr;
+-  const char *requested_path = path;
+-
+-  /* When the path is not absolute and the library is being loaded for
+-   * another, first try to load the library from the directory containing
+-   * that parent library. */
+-  if ((name == path) && parent) {
+-    const char *parentPath = parent->GetPath();
+-    abs_path = new char[strlen(parentPath) + strlen(path)];
+-    strcpy(abs_path, parentPath);
+-    char *slash = strrchr(abs_path, '/');
+-    strcpy(slash + 1, path);
+-    path = abs_path;
+-  }
+-
+-  Mappable *mappable = GetMappableFromPath(path);
+-
+-  /* Try loading with the custom linker if we have a Mappable */
+-  if (mappable)
+-    handle = CustomElf::Load(mappable, path, flags);
+-
+-  /* Try loading with the system linker if everything above failed */
+-  if (!handle)
+-    handle = SystemElf::Load(path, flags);
+-
+-  /* If we didn't have an absolute path and haven't been able to load
+-   * a library yet, try in the system search path */
+-  if (!handle && abs_path)
+-    handle = SystemElf::Load(name, flags);
+-
+-  delete [] abs_path;
+-  DEBUG_LOG("ElfLoader::Load(\"%s\", 0x%x, %p [\"%s\"]) = %p", requested_path, flags,
+-            reinterpret_cast<void *>(parent), parent ? parent->GetPath() : "",
+-            static_cast<void *>(handle));
+-
+-  return handle.forget();
+-}
+-
+-already_AddRefed<LibHandle>
+-ElfLoader::GetHandleByPtr(void *addr)
+-{
+-  AutoLock lock(&handlesMutex);
+-  /* Scan the list of handles we already have for a match */
+-  for (LibHandleList::iterator it = handles.begin(); it < handles.end(); ++it) {
+-    if ((*it)->Contains(addr)) {
+-      RefPtr<LibHandle> lib = *it;
+-      return lib.forget();
+-    }
+-  }
+-  return nullptr;
+-}
+-
+-Mappable *
+-ElfLoader::GetMappableFromPath(const char *path)
+-{
+-  const char *name = LeafName(path);
+-  Mappable *mappable = nullptr;
+-  RefPtr<Zip> zip;
+-  const char *subpath;
+-  if ((subpath = strchr(path, '!'))) {
+-    char *zip_path = strndup(path, subpath - path);
+-    while (*(++subpath) == '/') { }
+-    zip = ZipCollection::GetZip(zip_path);
+-    free(zip_path);
+-    Zip::Stream s;
+-    if (zip && zip->GetStream(subpath, &s)) {
+-      /* When the MOZ_LINKER_EXTRACT environment variable is set to "1",
+-       * compressed libraries are going to be (temporarily) extracted as
+-       * files, in the directory pointed by the MOZ_LINKER_CACHE
+-       * environment variable. */
+-      const char *extract = getenv("MOZ_LINKER_EXTRACT");
+-      if (extract && !strncmp(extract, "1", 2 /* Including '\0' */))
+-        mappable = MappableExtractFile::Create(name, zip, &s);
+-      if (!mappable) {
+-        if (s.GetType() == Zip::Stream::DEFLATE) {
+-          mappable = MappableDeflate::Create(name, zip, &s);
+-        }
+-      }
+-    }
+-  }
+-  /* If we couldn't load above, try with a MappableFile */
+-  if (!mappable && !zip)
+-    mappable = MappableFile::Create(path);
+-
+-  return mappable;
+-}
+-
+-void
+-ElfLoader::Register(LibHandle *handle)
+-{
+-  AutoLock lock(&handlesMutex);
+-  handles.push_back(handle);
+-}
+-
+-void
+-ElfLoader::Register(CustomElf *handle)
+-{
+-  Register(static_cast<LibHandle *>(handle));
+-  if (dbg) {
+-    dbg.Add(handle);
+-  }
+-}
+-
+-void
+-ElfLoader::Forget(LibHandle *handle)
+-{
+-  /* Ensure logging is initialized or refresh if environment changed. */
+-  Logging::Init();
+-
+-  AutoLock lock(&handlesMutex);
+-  LibHandleList::iterator it = std::find(handles.begin(), handles.end(), handle);
+-  if (it != handles.end()) {
+-    DEBUG_LOG("ElfLoader::Forget(%p [\"%s\"])", reinterpret_cast<void *>(handle),
+-                                                handle->GetPath());
+-    handles.erase(it);
+-  } else {
+-    DEBUG_LOG("ElfLoader::Forget(%p [\"%s\"]): Handle not found",
+-              reinterpret_cast<void *>(handle), handle->GetPath());
+-  }
+-}
+-
+-void
+-ElfLoader::Forget(CustomElf *handle)
+-{
+-  Forget(static_cast<LibHandle *>(handle));
+-  if (dbg) {
+-    dbg.Remove(handle);
+-  }
+-}
+-
+-void
+-ElfLoader::Init()
+-{
+-  Dl_info info;
+-  /* On Android < 4.1 can't reenter dl* functions. So when the library
+-   * containing this code is dlopen()ed, it can't call dladdr from a
+-   * static initializer. */
+-  if (dladdr(_DYNAMIC, &info) != 0) {
+-    self_elf = LoadedElf::Create(info.dli_fname, info.dli_fbase);
+-  }
+-#if defined(ANDROID)
+-  if (dladdr(FunctionPtr(syscall), &info) != 0) {
+-    libc = LoadedElf::Create(info.dli_fname, info.dli_fbase);
+-  }
+-  if (dladdr(FunctionPtr<int (*)(double)>(isnan), &info) != 0) {
+-    libm = LoadedElf::Create(info.dli_fname, info.dli_fbase);
+-  }
+-#endif
+-}
+-
+-ElfLoader::~ElfLoader()
+-{
+-  LibHandleList list;
+-
+-  if (!Singleton.IsShutdownExpected()) {
+-    MOZ_CRASH("Unexpected shutdown");
+-  }
+-
+-  /* Release self_elf and libc */
+-  self_elf = nullptr;
+-#if defined(ANDROID)
+-  libc = nullptr;
+-  libm = nullptr;
+-#endif
+-
+-  AutoLock lock(&handlesMutex);
+-  /* Build up a list of all library handles with direct (external) references.
+-   * We actually skip system library handles because we want to keep at least
+-   * some of these open. Most notably, Mozilla codebase keeps a few libgnome
+-   * libraries deliberately open because of the mess that libORBit destruction
+-   * is. dlclose()ing these libraries actually leads to problems. */
+-  for (LibHandleList::reverse_iterator it = handles.rbegin();
+-       it < handles.rend(); ++it) {
+-    if ((*it)->DirectRefCount()) {
+-      if (SystemElf *se = (*it)->AsSystemElf()) {
+-        se->Forget();
+-      } else {
+-        list.push_back(*it);
+-      }
+-    }
+-  }
+-  /* Force release all external references to the handles collected above */
+-  for (LibHandleList::iterator it = list.begin(); it < list.end(); ++it) {
+-    while ((*it)->ReleaseDirectRef()) { }
+-  }
+-  /* Remove the remaining system handles. */
+-  if (handles.size()) {
+-    list = handles;
+-    for (LibHandleList::reverse_iterator it = list.rbegin();
+-         it < list.rend(); ++it) {
+-      if ((*it)->AsSystemElf()) {
+-        DEBUG_LOG("ElfLoader::~ElfLoader(): Remaining handle for \"%s\" "
+-                  "[%" PRIdPTR " direct refs, %" PRIdPTR " refs total]",
+-                  (*it)->GetPath(), (*it)->DirectRefCount(), (*it)->refCount());
+-      } else {
+-        DEBUG_LOG("ElfLoader::~ElfLoader(): Unexpected remaining handle for \"%s\" "
+-                  "[%" PRIdPTR " direct refs, %" PRIdPTR " refs total]",
+-                  (*it)->GetPath(), (*it)->DirectRefCount(), (*it)->refCount());
+-        /* Not removing, since it could have references to other libraries,
+-         * destroying them as a side effect, and possibly leaving dangling
+-         * pointers in the handle list we're scanning */
+-      }
+-    }
+-  }
+-  pthread_mutex_destroy(&handlesMutex);
+-}
+-
+-#ifdef __ARM_EABI__
+-int
+-ElfLoader::__wrap_aeabi_atexit(void *that, ElfLoader::Destructor destructor,
+-                               void *dso_handle)
+-{
+-  Singleton.destructors.push_back(
+-    DestructorCaller(destructor, that, dso_handle));
+-  return 0;
+-}
+-#else
+-int
+-ElfLoader::__wrap_cxa_atexit(ElfLoader::Destructor destructor, void *that,
+-                             void *dso_handle)
+-{
+-  Singleton.destructors.push_back(
+-    DestructorCaller(destructor, that, dso_handle));
+-  return 0;
+-}
+-#endif
+-
+-void
+-ElfLoader::__wrap_cxa_finalize(void *dso_handle)
+-{
+-  /* Call all destructors for the given DSO handle in reverse order they were
+-   * registered. */
+-  std::vector<DestructorCaller>::reverse_iterator it;
+-  for (it = Singleton.destructors.rbegin();
+-       it < Singleton.destructors.rend(); ++it) {
+-    if (it->IsForHandle(dso_handle)) {
+-      it->Call();
+-    }
+-  }
+-}
+-
+-void
+-ElfLoader::DestructorCaller::Call()
+-{
+-  if (destructor) {
+-    DEBUG_LOG("ElfLoader::DestructorCaller::Call(%p, %p, %p)",
+-              FunctionPtr(destructor), object, dso_handle);
+-    destructor(object);
+-    destructor = nullptr;
+-  }
+-}
+-
+-ElfLoader::DebuggerHelper::DebuggerHelper(): dbg(nullptr), firstAdded(nullptr)
+-{
+-  /* Find ELF auxiliary vectors.
+-   *
+-   * The kernel stores the following data on the stack when starting a
+-   * program:
+-   *   argc
+-   *   argv[0] (pointer into argv strings defined below)
+-   *   argv[1] (likewise)
+-   *   ...
+-   *   argv[argc - 1] (likewise)
+-   *   nullptr
+-   *   envp[0] (pointer into environment strings defined below)
+-   *   envp[1] (likewise)
+-   *   ...
+-   *   envp[n] (likewise)
+-   *   nullptr
+-   *   ... (more NULLs on some platforms such as Android 4.3)
+-   *   auxv[0] (first ELF auxiliary vector)
+-   *   auxv[1] (second ELF auxiliary vector)
+-   *   ...
+-   *   auxv[p] (last ELF auxiliary vector)
+-   *   (AT_NULL, nullptr)
+-   *   padding
+-   *   argv strings, separated with '\0'
+-   *   environment strings, separated with '\0'
+-   *   nullptr
+-   *
+-   * What we are after are the auxv values defined by the following struct.
+-   */
+-  struct AuxVector {
+-    Elf::Addr type;
+-    Elf::Addr value;
+-  };
+-
+-  /* Pointer to the environment variables list */
+-  extern char **environ;
+-
+-  /* The environment may have changed since the program started, in which
+-   * case the environ variables list isn't the list the kernel put on stack
+-   * anymore. But in this new list, variables that didn't change still point
+-   * to the strings the kernel put on stack. It is quite unlikely that two
+-   * modified environment variables point to two consecutive strings in memory,
+-   * so we assume that if two consecutive environment variables point to two
+-   * consecutive strings, we found strings the kernel put on stack. */
+-  char **env;
+-  for (env = environ; *env; env++)
+-    if (*env + strlen(*env) + 1 == env[1])
+-      break;
+-  if (!*env)
+-    return;
+-
+-  /* Next, we scan the stack backwards to find a pointer to one of those
+-   * strings we found above, which will give us the location of the original
+-   * envp list. As we are looking for pointers, we need to look at 32-bits or
+-   * 64-bits aligned values, depening on the architecture. */
+-  char **scan = reinterpret_cast<char **>(
+-                reinterpret_cast<uintptr_t>(*env) & ~(sizeof(void *) - 1));
+-  while (*env != *scan)
+-    scan--;
+-
+-  /* Finally, scan forward to find the last environment variable pointer and
+-   * thus the first auxiliary vector. */
+-  while (*scan++);
+-
+-  /* Some platforms have more NULLs here, so skip them if we encounter them */
+-  while (!*scan)
+-    scan++;
+-
+-  AuxVector *auxv = reinterpret_cast<AuxVector *>(scan);
+-
+-  /* The two values of interest in the auxiliary vectors are AT_PHDR and
+-   * AT_PHNUM, which gives us the the location and size of the ELF program
+-   * headers. */
+-  Array<Elf::Phdr> phdrs;
+-  char *base = nullptr;
+-  while (auxv->type) {
+-    if (auxv->type == AT_PHDR) {
+-      phdrs.Init(reinterpret_cast<Elf::Phdr*>(auxv->value));
+-      /* Assume the base address is the first byte of the same page */
+-      base = reinterpret_cast<char *>(PageAlignedPtr(auxv->value));
+-    }
+-    if (auxv->type == AT_PHNUM)
+-      phdrs.Init(auxv->value);
+-    auxv++;
+-  }
+-
+-  if (!phdrs) {
+-    DEBUG_LOG("Couldn't find program headers");
+-    return;
+-  }
+-
+-  /* In some cases, the address for the program headers we get from the
+-   * auxiliary vectors is not mapped, because of the PT_LOAD segments
+-   * definitions in the program executable. Trying to map anonymous memory
+-   * with a hint giving the base address will return a different address
+-   * if something is mapped there, and the base address otherwise. */
+-  MappedPtr mem(MemoryRange::mmap(base, PageSize(), PROT_NONE,
+-                                  MAP_PRIVATE | MAP_ANONYMOUS, -1, 0));
+-  if (mem == base) {
+-    /* If program headers aren't mapped, try to map them */
+-    int fd = open("/proc/self/exe", O_RDONLY);
+-    if (fd == -1) {
+-      DEBUG_LOG("Failed to open /proc/self/exe");
+-      return;
+-    }
+-    mem.Assign(MemoryRange::mmap(base, PageSize(), PROT_READ, MAP_PRIVATE,
+-                                 fd, 0));
+-    /* If we don't manage to map at the right address, just give up. */
+-    if (mem != base) {
+-      DEBUG_LOG("Couldn't read program headers");
+-      return;
+-    }
+-  }
+-  /* Sanity check: the first bytes at the base address should be an ELF
+-   * header. */
+-  if (!Elf::Ehdr::validate(base)) {
+-     DEBUG_LOG("Couldn't find program base");
+-     return;
+-  }
+-
+-  /* Search for the program PT_DYNAMIC segment */
+-  Array<Elf::Dyn> dyns;
+-  for (Array<Elf::Phdr>::iterator phdr = phdrs.begin(); phdr < phdrs.end();
+-       ++phdr) {
+-    /* While the program headers are expected within the first mapped page of
+-     * the program executable, the executable PT_LOADs may actually make them
+-     * loaded at an address that is not the wanted base address of the
+-     * library. We thus need to adjust the base address, compensating for the
+-     * virtual address of the PT_LOAD segment corresponding to offset 0. */
+-    if (phdr->p_type == PT_LOAD && phdr->p_offset == 0)
+-      base -= phdr->p_vaddr;
+-    if (phdr->p_type == PT_DYNAMIC)
+-      dyns.Init(base + phdr->p_vaddr, phdr->p_filesz);
+-  }
+-  if (!dyns) {
+-    DEBUG_LOG("Failed to find PT_DYNAMIC section in program");
+-    return;
+-  }
+-
+-  /* Search for the DT_DEBUG information */
+-  for (Array<Elf::Dyn>::iterator dyn = dyns.begin(); dyn < dyns.end(); ++dyn) {
+-    if (dyn->d_tag == DT_DEBUG) {
+-      dbg = reinterpret_cast<r_debug *>(dyn->d_un.d_ptr);
+-      break;
+-    }
+-  }
+-  DEBUG_LOG("DT_DEBUG points at %p", static_cast<void *>(dbg));
+-}
+-
+-/**
+- * Helper class to ensure the given pointer is writable within the scope of
+- * an instance. Permissions to the memory page where the pointer lies are
+- * restored to their original value when the instance is destroyed.
+- */
+-class EnsureWritable
+-{
+-public:
+-  template <typename T>
+-  EnsureWritable(T *ptr, size_t length_ = sizeof(T))
+-  {
+-    MOZ_ASSERT(length_ < PageSize());
+-    prot = -1;
+-    page = MAP_FAILED;
+-
+-    char *firstPage = PageAlignedPtr(reinterpret_cast<char *>(ptr));
+-    char *lastPageEnd = PageAlignedEndPtr(reinterpret_cast<char *>(ptr) + length_);
+-    length = lastPageEnd - firstPage;
+-    uintptr_t start = reinterpret_cast<uintptr_t>(firstPage);
+-    uintptr_t end;
+-
+-    prot = getProt(start, &end);
+-    if (prot == -1 || (start + length) > end)
+-      MOZ_CRASH();
+-
+-    if (prot & PROT_WRITE)
+-      return;
+-
+-    page = firstPage;
+-    mprotect(page, length, prot | PROT_WRITE);
+-  }
+-
+-  ~EnsureWritable()
+-  {
+-    if (page != MAP_FAILED) {
+-      mprotect(page, length, prot);
+-}
+-  }
+-
+-private:
+-  int getProt(uintptr_t addr, uintptr_t *end)
+-  {
+-    /* The interesting part of the /proc/self/maps format looks like:
+-     * startAddr-endAddr rwxp */
+-    int result = 0;
+-    AutoCloseFILE f(fopen("/proc/self/maps", "r"));
+-    while (f) {
+-      unsigned long long startAddr, endAddr;
+-      char perms[5];
+-      if (fscanf(f, "%llx-%llx %4s %*1024[^\n] ", &startAddr, &endAddr, perms) != 3)
+-        return -1;
+-      if (addr < startAddr || addr >= endAddr)
+-        continue;
+-      if (perms[0] == 'r')
+-        result |= PROT_READ;
+-      else if (perms[0] != '-')
+-        return -1;
+-      if (perms[1] == 'w')
+-        result |= PROT_WRITE;
+-      else if (perms[1] != '-')
+-        return -1;
+-      if (perms[2] == 'x')
+-        result |= PROT_EXEC;
+-      else if (perms[2] != '-')
+-        return -1;
+-      *end = endAddr;
+-      return result;
+-    }
+-    return -1;
+-  }
+-
+-  int prot;
+-  void *page;
+-  size_t length;
+-};
+-
+-/**
+- * The system linker maintains a doubly linked list of library it loads
+- * for use by the debugger. Unfortunately, it also uses the list pointers
+- * in a lot of operations and adding our data in the list is likely to
+- * trigger crashes when the linker tries to use data we don't provide or
+- * that fall off the amount data we allocated. Fortunately, the linker only
+- * traverses the list forward and accesses the head of the list from a
+- * private pointer instead of using the value in the r_debug structure.
+- * This means we can safely add members at the beginning of the list.
+- * Unfortunately, gdb checks the coherency of l_prev values, so we have
+- * to adjust the l_prev value for the first element the system linker
+- * knows about. Fortunately, it doesn't use l_prev, and the first element
+- * is not ever going to be released before our elements, since it is the
+- * program executable, so the system linker should not be changing
+- * r_debug::r_map.
+- */
+-void
+-ElfLoader::DebuggerHelper::Add(ElfLoader::link_map *map)
+-{
+-  if (!dbg->r_brk)
+-    return;
+-  dbg->r_state = r_debug::RT_ADD;
+-  dbg->r_brk();
+-  map->l_prev = nullptr;
+-  map->l_next = dbg->r_map;
+-  if (!firstAdded) {
+-    firstAdded = map;
+-    /* When adding a library for the first time, r_map points to data
+-     * handled by the system linker, and that data may be read-only */
+-    EnsureWritable w(&dbg->r_map->l_prev);
+-    dbg->r_map->l_prev = map;
+-  } else
+-    dbg->r_map->l_prev = map;
+-  dbg->r_map = map;
+-  dbg->r_state = r_debug::RT_CONSISTENT;
+-  dbg->r_brk();
+-}
+-
+-void
+-ElfLoader::DebuggerHelper::Remove(ElfLoader::link_map *map)
+-{
+-  if (!dbg->r_brk)
+-    return;
+-  dbg->r_state = r_debug::RT_DELETE;
+-  dbg->r_brk();
+-  if (dbg->r_map == map)
+-    dbg->r_map = map->l_next;
+-  else if (map->l_prev) {
+-    map->l_prev->l_next = map->l_next;
+-  }
+-  if (map == firstAdded) {
+-    firstAdded = map->l_prev;
+-    /* When removing the first added library, its l_next is going to be
+-     * data handled by the system linker, and that data may be read-only */
+-    EnsureWritable w(&map->l_next->l_prev);
+-    map->l_next->l_prev = map->l_prev;
+-  } else if (map->l_next) {
+-    map->l_next->l_prev = map->l_prev;
+-  }
+-  dbg->r_state = r_debug::RT_CONSISTENT;
+-  dbg->r_brk();
+-}
+-
+-#if defined(ANDROID) && defined(__NR_sigaction)
+-/* As some system libraries may be calling signal() or sigaction() to
+- * set a SIGSEGV handler, effectively breaking MappableSeekableZStream,
+- * or worse, restore our SIGSEGV handler with wrong flags (which using
+- * signal() will do), we want to hook into the system's sigaction() to
+- * replace it with our own wrapper instead, so that our handler is never
+- * replaced. We used to only do that with libraries this linker loads,
+- * but it turns out at least one system library does call signal() and
+- * breaks us (libsc-a3xx.so on the Samsung Galaxy S4).
+- * As libc's signal (bsd_signal/sysv_signal, really) calls sigaction
+- * under the hood, instead of calling the signal system call directly,
+- * we only need to hook sigaction. This is true for both bionic and
+- * glibc.
+- */
+-
+-/* libc's sigaction */
+-extern "C" int
+-sigaction(int signum, const struct sigaction *act,
+-          struct sigaction *oldact);
+-
+-/* Simple reimplementation of sigaction. This is roughly equivalent
+- * to the assembly that comes in bionic, but not quite equivalent to
+- * glibc's implementation, so we only use this on Android. */
+-int
+-sys_sigaction(int signum, const struct sigaction *act,
+-              struct sigaction *oldact)
+-{
+-  return syscall(__NR_sigaction, signum, act, oldact);
+-}
+-
+-/* Replace the first instructions of the given function with a jump
+- * to the given new function. */
+-template <typename T>
+-static bool
+-Divert(T func, T new_func)
+-{
+-  void *ptr = FunctionPtr(func);
+-  uintptr_t addr = reinterpret_cast<uintptr_t>(ptr);
+-
+-#if defined(__i386__)
+-  // A 32-bit jump is a 5 bytes instruction.
+-  EnsureWritable w(ptr, 5);
+-  *reinterpret_cast<unsigned char *>(addr) = 0xe9; // jmp
+-  *reinterpret_cast<intptr_t *>(addr + 1) =
+-    reinterpret_cast<uintptr_t>(new_func) - addr - 5; // target displacement
+-  return true;
+-#elif defined(__arm__) || defined(__aarch64__)
+-  const unsigned char trampoline[] = {
+-# ifdef __arm__
+-                            // .thumb
+-    0x46, 0x04,             // nop
+-    0x78, 0x47,             // bx pc
+-    0x46, 0x04,             // nop
+-                            // .arm
+-    0x04, 0xf0, 0x1f, 0xe5, // ldr pc, [pc, #-4]
+-                            // .word <new_func>
+-# else // __aarch64__
+-    0x50, 0x00, 0x00, 0x58, // ldr x16, [pc, #8]   ; x16 (aka ip0) is the first
+-    0x00, 0x02, 0x1f, 0xd6, // br x16              ; intra-procedure-call
+-                            // .word <new_func.lo> ; scratch register.
+-                            // .word <new_func.hi>
+-# endif
+-  };
+-  const unsigned char *start;
+-# ifdef __arm__
+-  if (addr & 0x01) {
+-    /* Function is thumb, the actual address of the code is without the
+-     * least significant bit. */
+-    addr--;
+-    /* The arm part of the trampoline needs to be 32-bit aligned */
+-    if (addr & 0x02)
+-      start = trampoline;
+-    else
+-      start = trampoline + 2;
+-  } else {
+-    /* Function is arm, we only need the arm part of the trampoline */
+-    start = trampoline + 6;
+-  }
+-# else // __aarch64__
+-  start = trampoline;
+-#endif
+-
+-  size_t len = sizeof(trampoline) - (start - trampoline);
+-  EnsureWritable w(reinterpret_cast<void *>(addr), len + sizeof(void *));
+-  memcpy(reinterpret_cast<void *>(addr), start, len);
+-  *reinterpret_cast<void **>(addr + len) = FunctionPtr(new_func);
+-  __builtin___clear_cache(reinterpret_cast<char*>(addr),
+-                          reinterpret_cast<char*>(addr + len + sizeof(void *)));
+-  return true;
+-#else
+-  return false;
+-#endif
+-}
+-#else
+-#define sys_sigaction sigaction
+-template <typename T>
+-static bool
+-Divert(T func, T new_func)
+-{
+-  return false;
+-}
+-#endif
+-
+-namespace {
+-
+-/* Clock that only accounts for time spent in the current process. */
+-static uint64_t ProcessTimeStamp_Now()
+-{
+-  struct timespec ts;
+-  int rv = clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts);
+-
+-  if (rv != 0) {
+-    return 0;
+-  }
+-
+-  uint64_t baseNs = (uint64_t)ts.tv_sec * 1000000000;
+-  return baseNs + (uint64_t)ts.tv_nsec;
+-}
+-
+-}
+-
+-/* Data structure used to pass data to the temporary signal handler,
+- * as well as triggering a test crash. */
+-struct TmpData {
+-  volatile int crash_int;
+-  volatile uint64_t crash_timestamp;
+-};
+-
+-SEGVHandler::SEGVHandler()
+-: initialized(false), registeredHandler(false), signalHandlingBroken(true)
+-, signalHandlingSlow(true)
+-{
+-  /* Ensure logging is initialized before the DEBUG_LOG in the test_handler.
+-   * As this constructor runs before the ElfLoader constructor (by effect
+-   * of ElfLoader inheriting from this class), this also initializes on behalf
+-   * of ElfLoader and DebuggerHelper. */
+-  Logging::Init();
+-
+-  /* Initialize oldStack.ss_flags to an invalid value when used to set
+-   * an alternative stack, meaning we haven't got information about the
+-   * original alternative stack and thus don't mean to restore it in
+-   * the destructor. */
+-  oldStack.ss_flags = SS_ONSTACK;
+-
+-  /* Get the current segfault signal handler. */
+-  struct sigaction old_action;
+-  sys_sigaction(SIGSEGV, nullptr, &old_action);
+-
+-  /* Some devices don't provide useful information to their SIGSEGV handlers,
+-   * making it impossible for on-demand decompression to work. To check if
+-   * we're on such a device, setup a temporary handler and deliberately
+-   * trigger a segfault. The handler will set signalHandlingBroken if the
+-   * provided information is bogus.
+-   * Some other devices have a kernel option enabled that makes SIGSEGV handler
+-   * have an overhead so high that it affects how on-demand decompression
+-   * performs. The handler will also set signalHandlingSlow if the triggered
+-   * SIGSEGV took too much time. */
+-  struct sigaction action;
+-  action.sa_sigaction = &SEGVHandler::test_handler;
+-  sigemptyset(&action.sa_mask);
+-  action.sa_flags = SA_SIGINFO | SA_NODEFER;
+-  action.sa_restorer = nullptr;
+-  stackPtr.Assign(MemoryRange::mmap(nullptr, PageSize(),
+-                                    PROT_READ | PROT_WRITE,
+-                                    MAP_PRIVATE | MAP_ANONYMOUS, -1, 0));
+-  if (stackPtr.get() == MAP_FAILED)
+-    return;
+-  if (sys_sigaction(SIGSEGV, &action, nullptr))
+-    return;
+-
+-  TmpData *data = reinterpret_cast<TmpData*>(stackPtr.get());
+-  data->crash_timestamp = ProcessTimeStamp_Now();
+-  mprotect(stackPtr, stackPtr.GetLength(), PROT_NONE);
+-  data->crash_int = 123;
+-  /* Restore the original segfault signal handler. */
+-  sys_sigaction(SIGSEGV, &old_action, nullptr);
+-  stackPtr.Assign(MAP_FAILED, 0);
+-}
+-
+-void
+-SEGVHandler::FinishInitialization()
+-{
+-  /* Ideally, we'd need some locking here, but in practice, we're not
+-   * going to race with another thread. */
+-  initialized = true;
+-
+-  if (signalHandlingBroken || signalHandlingSlow)
+-    return;
+-
+-  typedef int (*sigaction_func)(int, const struct sigaction *,
+-                                struct sigaction *);
+-
+-  sigaction_func libc_sigaction;
+-
+-#if defined(ANDROID)
+-  /* Android > 4.4 comes with a sigaction wrapper in a LD_PRELOADed library
+-   * (libsigchain) for ART. That wrapper kind of does the same trick as we
+-   * do, so we need extra care in handling it.
+-   * - Divert the libc's sigaction, assuming the LD_PRELOADed library uses
+-   *   it under the hood (which is more or less true according to the source
+-   *   of that library, since it's doing a lookup in RTLD_NEXT)
+-   * - With the LD_PRELOADed library in place, all calls to sigaction from
+-   *   from system libraries will go to the LD_PRELOADed library.
+-   * - The LD_PRELOADed library calls to sigaction go to our __wrap_sigaction.
+-   * - The calls to sigaction from libraries faulty.lib loads are sent to
+-   *   the LD_PRELOADed library.
+-   * In practice, for signal handling, this means:
+-   * - The signal handler registered to the kernel is ours.
+-   * - Our handler redispatches to the LD_PRELOADed library's if there's a
+-   *   segfault we don't handle.
+-   * - The LD_PRELOADed library redispatches according to whatever system
+-   *   library or faulty.lib-loaded library set with sigaction.
+-   *
+-   * When there is no sigaction wrapper in place:
+-   * - Divert the libc's sigaction.
+-   * - Calls to sigaction from system library and faulty.lib-loaded libraries
+-   *   all go to the libc's sigaction, which end up in our __wrap_sigaction.
+-   * - The signal handler registered to the kernel is ours.
+-   * - Our handler redispatches according to whatever system library or
+-   *   faulty.lib-loaded library set with sigaction.
+-   */
+-  void *libc = dlopen("libc.so", RTLD_GLOBAL | RTLD_LAZY);
+-  if (libc) {
+-    /*
+-     * Lollipop bionic only has a small trampoline in sigaction, with the real
+-     * work happening in __sigaction. Divert there instead of sigaction if it exists.
+-     * Bug 1154803
+-     */
+-    libc_sigaction = reinterpret_cast<sigaction_func>(dlsym(libc, "__sigaction"));
+-
+-    if (!libc_sigaction) {
+-      libc_sigaction =
+-        reinterpret_cast<sigaction_func>(dlsym(libc, "sigaction"));
+-    }
+-  } else
+-#endif
+-  {
+-    libc_sigaction = sigaction;
+-  }
+-
+-  if (!Divert(libc_sigaction, __wrap_sigaction))
+-    return;
+-
+-  /* Setup an alternative stack if the already existing one is not big
+-   * enough, or if there is none. */
+-  if (sigaltstack(nullptr, &oldStack) == 0) {
+-    if (oldStack.ss_flags == SS_ONSTACK)
+-      oldStack.ss_flags = 0;
+-    if (!oldStack.ss_sp || oldStack.ss_size < stackSize) {
+-      stackPtr.Assign(MemoryRange::mmap(nullptr, stackSize,
+-                                        PROT_READ | PROT_WRITE,
+-                                        MAP_PRIVATE | MAP_ANONYMOUS, -1, 0));
+-      if (stackPtr.get() == MAP_FAILED)
+-        return;
+-      stack_t stack;
+-      stack.ss_sp = stackPtr;
+-      stack.ss_size = stackSize;
+-      stack.ss_flags = 0;
+-      if (sigaltstack(&stack, nullptr) != 0)
+-        return;
+-    }
+-  }
+-  /* Register our own handler, and store the already registered one in
+-   * SEGVHandler's struct sigaction member */
+-  action.sa_sigaction = &SEGVHandler::handler;
+-  action.sa_flags = SA_SIGINFO | SA_NODEFER | SA_ONSTACK;
+-  registeredHandler = !sys_sigaction(SIGSEGV, &action, &this->action);
+-}
+-
+-SEGVHandler::~SEGVHandler()
+-{
+-  /* Restore alternative stack for signals */
+-  if (oldStack.ss_flags != SS_ONSTACK)
+-    sigaltstack(&oldStack, nullptr);
+-  /* Restore original signal handler */
+-  if (registeredHandler)
+-    sys_sigaction(SIGSEGV, &this->action, nullptr);
+-}
+-
+-/* Test handler for a deliberately triggered SIGSEGV that determines whether
+- * useful information is provided to signal handlers, particularly whether
+- * si_addr is filled in properly, and whether the segfault handler is called
+- * quickly enough. */
+-void SEGVHandler::test_handler(int signum, siginfo_t *info, void *context)
+-{
+-  SEGVHandler &that = ElfLoader::Singleton;
+-  if (signum == SIGSEGV && info &&
+-      info->si_addr == that.stackPtr.get())
+-    that.signalHandlingBroken = false;
+-  mprotect(that.stackPtr, that.stackPtr.GetLength(), PROT_READ | PROT_WRITE);
+-  TmpData *data = reinterpret_cast<TmpData*>(that.stackPtr.get());
+-  uint64_t latency = ProcessTimeStamp_Now() - data->crash_timestamp;
+-  DEBUG_LOG("SEGVHandler latency: %" PRIu64, latency);
+-  /* See bug 886736 for timings on different devices, 150 µs is reasonably above
+-   * the latency on "working" devices and seems to be short enough to not incur
+-   * a huge overhead to on-demand decompression. */
+-  if (latency <= 150000)
+-    that.signalHandlingSlow = false;
+-}
+-
+-/* TODO: "properly" handle signal masks and flags */
+-void SEGVHandler::handler(int signum, siginfo_t *info, void *context)
+-{
+-  //ASSERT(signum == SIGSEGV);
+-  DEBUG_LOG("Caught segmentation fault @%p", info->si_addr);
+-
+-  /* Redispatch to the registered handler */
+-  SEGVHandler &that = ElfLoader::Singleton;
+-  if (that.action.sa_flags & SA_SIGINFO) {
+-    DEBUG_LOG("Redispatching to registered handler @%p",
+-              FunctionPtr(that.action.sa_sigaction));
+-    that.action.sa_sigaction(signum, info, context);
+-  } else if (that.action.sa_handler == SIG_DFL) {
+-    DEBUG_LOG("Redispatching to default handler");
+-    /* Reset the handler to the default one, and trigger it. */
+-    sys_sigaction(signum, &that.action, nullptr);
+-    raise(signum);
+-  } else if (that.action.sa_handler != SIG_IGN) {
+-    DEBUG_LOG("Redispatching to registered handler @%p",
+-              FunctionPtr(that.action.sa_handler));
+-    that.action.sa_handler(signum);
+-  } else {
+-    DEBUG_LOG("Ignoring");
+-  }
+-}
+-
+-int
+-SEGVHandler::__wrap_sigaction(int signum, const struct sigaction *act,
+-                              struct sigaction *oldact)
+-{
+-  SEGVHandler &that = ElfLoader::Singleton;
+-
+-  /* Use system sigaction() function for all but SIGSEGV signals. */
+-  if (!that.registeredHandler || (signum != SIGSEGV))
+-    return sys_sigaction(signum, act, oldact);
+-
+-  if (oldact)
+-    *oldact = that.action;
+-  if (act)
+-    that.action = *act;
+-  return 0;
+-}
+-
+-Logging Logging::Singleton;
+diff --git a/mozglue/linker/ElfLoader.h b/mozglue/linker/ElfLoader.h
+deleted file mode 100644
+--- a/mozglue/linker/ElfLoader.h
++++ /dev/null
+@@ -1,669 +0,0 @@
+-/* 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/. */
+-
+-#ifndef ElfLoader_h
+-#define ElfLoader_h
+-
+-#include <vector>
+-#include <dlfcn.h>
+-#include <signal.h>
+-#include "mozilla/RefCounted.h"
+-#include "mozilla/RefPtr.h"
+-#include "mozilla/UniquePtr.h"
+-#include "Zip.h"
+-#include "Elfxx.h"
+-#include "Mappable.h"
+-
+-/**
+- * dlfcn.h replacement functions
+- */
+-extern "C" {
+-  void *__wrap_dlopen(const char *path, int flags);
+-  const char *__wrap_dlerror(void);
+-  void *__wrap_dlsym(void *handle, const char *symbol);
+-  int __wrap_dlclose(void *handle);
+-
+-#ifndef HAVE_DLADDR
+-  typedef struct {
+-    const char *dli_fname;
+-    void *dli_fbase;
+-    const char *dli_sname;
+-    void *dli_saddr;
+-  } Dl_info;
+-#endif
+-  int __wrap_dladdr(void *addr, Dl_info *info);
+-
+-  struct dl_phdr_info {
+-    Elf::Addr dlpi_addr;
+-    const char *dlpi_name;
+-    const Elf::Phdr *dlpi_phdr;
+-    Elf::Half dlpi_phnum;
+-  };
+-
+-  typedef int (*dl_phdr_cb)(struct dl_phdr_info *, size_t, void *);
+-  int __wrap_dl_iterate_phdr(dl_phdr_cb callback, void *data);
+-
+-#ifdef __ARM_EABI__
+-  const void *__wrap___gnu_Unwind_Find_exidx(void *pc, int *pcount);
+-#endif
+-
+-/**
+- * faulty.lib public API
+- */
+-MFBT_API size_t
+-__dl_get_mappable_length(void *handle);
+-
+-MFBT_API void *
+-__dl_mmap(void *handle, void *addr, size_t length, off_t offset);
+-
+-MFBT_API void
+-__dl_munmap(void *handle, void *addr, size_t length);
+-
+-MFBT_API bool
+-IsSignalHandlingBroken();
+-
+-}
+-
+-/* Forward declarations for use in LibHandle */
+-class BaseElf;
+-class CustomElf;
+-class SystemElf;
+-
+-/**
+- * Specialize RefCounted template for LibHandle. We may get references to
+- * LibHandles during the execution of their destructor, so we need
+- * RefCounted<LibHandle>::Release to support some reentrancy. See further
+- * below.
+- */
+-class LibHandle;
+-
+-namespace mozilla {
+-namespace detail {
+-
+-template <> inline void RefCounted<LibHandle, AtomicRefCount>::Release() const;
+-
+-template <> inline RefCounted<LibHandle, AtomicRefCount>::~RefCounted()
+-{
+-  MOZ_ASSERT(mRefCnt == 0x7fffdead);
+-}
+-
+-} /* namespace detail */
+-} /* namespace mozilla */
+-
+-/**
+- * Abstract class for loaded libraries. Libraries may be loaded through the
+- * system linker or this linker, both cases will be derived from this class.
+- */
+-class LibHandle: public mozilla::external::AtomicRefCounted<LibHandle>
+-{
+-public:
+-  MOZ_DECLARE_REFCOUNTED_TYPENAME(LibHandle)
+-  /**
+-   * Constructor. Takes the path of the loaded library and will store a copy
+-   * of the leaf name.
+-   */
+-  LibHandle(const char *path)
+-  : directRefCnt(0), path(path ? strdup(path) : nullptr), mappable(nullptr)
+-  {
+-  }
+-
+-  /**
+-   * Destructor.
+-   */
+-  virtual ~LibHandle();
+-
+-  /**
+-   * Returns the pointer to the address to which the given symbol resolves
+-   * inside the library. It is not supposed to resolve the symbol in other
+-   * libraries, although in practice, it will for system libraries.
+-   */
+-  virtual void *GetSymbolPtr(const char *symbol) const = 0;
+-
+-  /**
+-   * Returns whether the given address is part of the virtual address space
+-   * covered by the loaded library.
+-   */
+-  virtual bool Contains(void *addr) const = 0;
+-
+-  /**
+-   * Returns the base address of the loaded library.
+-   */
+-  virtual void *GetBase() const = 0;
+-
+-  /**
+-   * Returns the file name of the library without the containing directory.
+-   */
+-  const char *GetName() const;
+-
+-  /**
+-   * Returns the full path of the library, when available. Otherwise, returns
+-   * the file name.
+-   */
+-  const char *GetPath() const
+-  {
+-    return path;
+-  }
+-
+-  /**
+-   * Library handles can be referenced from other library handles or
+-   * externally (when dlopen()ing using this linker). We need to be
+-   * able to distinguish between the two kind of referencing for better
+-   * bookkeeping.
+-   */
+-  void AddDirectRef()
+-  {
+-    mozilla::external::AtomicRefCounted<LibHandle>::AddRef();
+-    ++directRefCnt;
+-  }
+-
+-  /**
+-   * Releases a direct reference, and returns whether there are any direct
+-   * references left.
+-   */
+-  bool ReleaseDirectRef()
+-  {
+-    const MozRefCountType count = --directRefCnt;
+-    MOZ_ASSERT(count + 1 > 0);
+-    MOZ_ASSERT(count + 1 <=
+-               mozilla::external::AtomicRefCounted<LibHandle>::refCount());
+-    mozilla::external::AtomicRefCounted<LibHandle>::Release();
+-    return !!count;
+-  }
+-
+-  /**
+-   * Returns the number of direct references
+-   */
+-  MozRefCountType DirectRefCount()
+-  {
+-    return directRefCnt;
+-  }
+-
+-  /**
+-   * Returns the complete size of the file or stream behind the library
+-   * handle.
+-   */
+-  size_t GetMappableLength() const;
+-
+-  /**
+-   * Returns a memory mapping of the file or stream behind the library
+-   * handle.
+-   */
+-  void *MappableMMap(void *addr, size_t length, off_t offset) const;
+-
+-  /**
+-   * Unmaps a memory mapping of the file or stream behind the library
+-   * handle.
+-   */
+-  void MappableMUnmap(void *addr, size_t length) const;
+-
+-#ifdef __ARM_EABI__
+-  /**
+-   * Find the address and entry count of the ARM.exidx section
+-   * associated with the library
+-   */
+-  virtual const void *FindExidx(int *pcount) const = 0;
+-#endif
+-
+-protected:
+-  /**
+-   * Returns a mappable object for use by MappableMMap and related functions.
+-   */
+-  virtual Mappable *GetMappable() const = 0;
+-
+-  /**
+-   * Returns the instance, casted as the wanted type. Returns nullptr if
+-   * that's not the actual type. (short of a better way to do this without
+-   * RTTI)
+-   */
+-  friend class ElfLoader;
+-  friend class CustomElf;
+-  friend class SEGVHandler;
+-  virtual BaseElf *AsBaseElf() { return nullptr; }
+-  virtual SystemElf *AsSystemElf() { return nullptr; }
+-
+-private:
+-  mozilla::Atomic<MozRefCountType> directRefCnt;
+-  char *path;
+-
+-  /* Mappable object keeping the result of GetMappable() */
+-  mutable RefPtr<Mappable> mappable;
+-};
+-
+-/**
+- * Specialized RefCounted<LibHandle>::Release. Under normal operation, when
+- * mRefCnt reaches 0, the LibHandle is deleted. Its mRefCnt is however
+- * increased to 1 on normal builds, and 0x7fffdead on debug builds so that the
+- * LibHandle can still be referenced while the destructor is executing. The
+- * mRefCnt is allowed to grow > 0x7fffdead, but not to decrease under that
+- * value, which would mean too many Releases from within the destructor.
+- */
+-namespace mozilla {
+-namespace detail {
+-
+-template <> inline void RefCounted<LibHandle, AtomicRefCount>::Release() const {
+-#ifdef DEBUG
+-  if (mRefCnt > 0x7fff0000)
+-    MOZ_ASSERT(mRefCnt > 0x7fffdead);
+-#endif
+-  MOZ_ASSERT(mRefCnt > 0);
+-  if (mRefCnt > 0) {
+-    if (0 == --mRefCnt) {
+-#ifdef DEBUG
+-      mRefCnt = 0x7fffdead;
+-#else
+-      mRefCnt = 1;
+-#endif
+-      delete static_cast<const LibHandle*>(this);
+-    }
+-  }
+-}
+-
+-} /* namespace detail */
+-} /* namespace mozilla */
+-
+-/**
+- * Class handling libraries loaded by the system linker
+- */
+-class SystemElf: public LibHandle
+-{
+-public:
+-  /**
+-   * Returns a new SystemElf for the given path. The given flags are passed
+-   * to dlopen().
+-   */
+-  static already_AddRefed<LibHandle> Load(const char *path, int flags);
+-
+-  /**
+-   * Inherited from LibHandle
+-   */
+-  virtual ~SystemElf();
+-  virtual void *GetSymbolPtr(const char *symbol) const;
+-  virtual bool Contains(void *addr) const { return false; /* UNIMPLEMENTED */ }
+-  virtual void *GetBase() const { return nullptr; /* UNIMPLEMENTED */ }
+-
+-#ifdef __ARM_EABI__
+-  virtual const void *FindExidx(int *pcount) const;
+-#endif
+-
+-protected:
+-  virtual Mappable *GetMappable() const;
+-
+-  /**
+-   * Returns the instance, casted as SystemElf. (short of a better way to do
+-   * this without RTTI)
+-   */
+-  friend class ElfLoader;
+-  virtual SystemElf *AsSystemElf() { return this; }
+-
+-  /**
+-   * Remove the reference to the system linker handle. This avoids dlclose()
+-   * being called when the instance is destroyed.
+-   */
+-  void Forget()
+-  {
+-    dlhandle = nullptr;
+-  }
+-
+-private:
+-  /**
+-   * Private constructor
+-   */
+-  SystemElf(const char *path, void *handle)
+-  : LibHandle(path), dlhandle(handle) { }
+-
+-  /* Handle as returned by system dlopen() */
+-  void *dlhandle;
+-};
+-
+-/**
+- * The ElfLoader registers its own SIGSEGV handler to handle segmentation
+- * faults within the address space of the loaded libraries. It however
+- * allows a handler to be set for faults in other places, and redispatches
+- * to the handler set through signal() or sigaction().
+- */
+-class SEGVHandler
+-{
+-public:
+-  bool hasRegisteredHandler() {
+-    if (! initialized)
+-      FinishInitialization();
+-    return registeredHandler;
+-  }
+-
+-  bool isSignalHandlingBroken() {
+-    return signalHandlingBroken;
+-  }
+-
+-  static int __wrap_sigaction(int signum, const struct sigaction *act,
+-                              struct sigaction *oldact);
+-
+-protected:
+-  SEGVHandler();
+-  ~SEGVHandler();
+-
+-private:
+-
+-  /**
+-   * The constructor doesn't do all initialization, and the tail is done
+-   * at a later time.
+-   */
+-  void FinishInitialization();
+-
+-  /**
+-   * SIGSEGV handler registered with __wrap_signal or __wrap_sigaction.
+-   */
+-  struct sigaction action;
+-
+-  /**
+-   * ElfLoader SIGSEGV handler.
+-   */
+-  static void handler(int signum, siginfo_t *info, void *context);
+-
+-  /**
+-   * Temporary test handler.
+-   */
+-  static void test_handler(int signum, siginfo_t *info, void *context);
+-
+-  /**
+-   * Size of the alternative stack. The printf family requires more than 8KB
+-   * of stack, and our signal handler may print a few things.
+-   */
+-  static const size_t stackSize = 12 * 1024;
+-
+-  /**
+-   * Alternative stack information used before initialization.
+-   */
+-  stack_t oldStack;
+-
+-  /**
+-   * Pointer to an alternative stack for signals. Only set if oldStack is
+-   * not set or not big enough.
+-   */
+-  MappedPtr stackPtr;
+-
+-  bool initialized;
+-  bool registeredHandler;
+-  bool signalHandlingBroken;
+-  bool signalHandlingSlow;
+-};
+-
+-/**
+- * Elf Loader class in charge of loading and bookkeeping libraries.
+- */
+-class ElfLoader: public SEGVHandler
+-{
+-public:
+-  /**
+-   * The Elf Loader instance
+-   */
+-  static ElfLoader Singleton;
+-
+-  /**
+-   * Loads the given library with the given flags. Equivalent to dlopen()
+-   * The extra "parent" argument optionally gives the handle of the library
+-   * requesting the given library to be loaded. The loader may look in the
+-   * directory containing that parent library for the library to load.
+-   */
+-  already_AddRefed<LibHandle> Load(const char *path, int flags,
+-                                        LibHandle *parent = nullptr);
+-
+-  /**
+-   * Returns the handle of the library containing the given address in
+-   * its virtual address space, i.e. the library handle for which
+-   * LibHandle::Contains returns true. Its purpose is to allow to
+-   * implement dladdr().
+-   */
+-  already_AddRefed<LibHandle> GetHandleByPtr(void *addr);
+-
+-  /**
+-   * Returns a Mappable object for the path. Paths in the form
+-   *   /foo/bar/baz/archive!/directory/lib.so
+-   * try to load the directory/lib.so in /foo/bar/baz/archive, provided
+-   * that file is a Zip archive.
+-   */
+-  static Mappable *GetMappableFromPath(const char *path);
+-
+-  void ExpectShutdown(bool val) { expect_shutdown = val; }
+-  bool IsShutdownExpected() { return expect_shutdown; }
+-
+-private:
+-  bool expect_shutdown;
+-
+-protected:
+-  /**
+-   * Registers the given handle. This method is meant to be called by
+-   * LibHandle subclass creators.
+-   */
+-  void Register(LibHandle *handle);
+-  void Register(CustomElf *handle);
+-
+-  /**
+-   * Forget about the given handle. This method is meant to be called by
+-   * LibHandle subclass destructors.
+-   */
+-  void Forget(LibHandle *handle);
+-  void Forget(CustomElf *handle);
+-
+-  /* Last error. Used for dlerror() */
+-  friend class SystemElf;
+-  friend const char *__wrap_dlerror(void);
+-  friend void *__wrap_dlsym(void *handle, const char *symbol);
+-  friend int __wrap_dlclose(void *handle);
+-  const char *lastError;
+-
+-private:
+-  ElfLoader() : expect_shutdown(true)
+-  {
+-    pthread_mutex_init(&handlesMutex, nullptr);
+-  }
+-
+-  ~ElfLoader();
+-
+-  /* Initialization code that can't run during static initialization. */
+-  void Init();
+-
+-  /* System loader handle for the library/program containing our code. This
+-   * is used to resolve wrapped functions. */
+-  RefPtr<LibHandle> self_elf;
+-
+-#if defined(ANDROID)
+-  /* System loader handle for the libc. This is used to resolve weak symbols
+-   * that some libcs contain that the Android linker won't dlsym(). Normally,
+-   * we wouldn't treat non-Android differently, but glibc uses versioned
+-   * symbols which this linker doesn't support. */
+-  RefPtr<LibHandle> libc;
+-
+-  /* And for libm. */
+-  RefPtr<LibHandle> libm;
+-#endif
+-
+-  /* Bookkeeping */
+-  typedef std::vector<LibHandle *> LibHandleList;
+-  LibHandleList handles;
+-
+-  pthread_mutex_t handlesMutex;
+-
+-protected:
+-  friend class CustomElf;
+-  friend class LoadedElf;
+-
+-  /* Definition of static destructors as to be used for C++ ABI compatibility */
+-  typedef void (*Destructor)(void *object);
+-
+-  /**
+-   * C++ ABI makes static initializers register destructors through a specific
+-   * atexit interface. On glibc/linux systems, the dso_handle is a pointer
+-   * within a given library. On bionic/android systems, it is an undefined
+-   * symbol. Making sense of the value is not really important, and all that
+-   * is really important is that it is different for each loaded library, so
+-   * that they can be discriminated when shutting down. For convenience, on
+-   * systems where the dso handle is a symbol, that symbol is resolved to
+-   * point at corresponding CustomElf.
+-   *
+-   * Destructors are registered with __*_atexit with an associated object to
+-   * be passed as argument when it is called.
+-   *
+-   * When __cxa_finalize is called, destructors registered for the given
+-   * DSO handle are called in the reverse order they were registered.
+-   */
+-#ifdef __ARM_EABI__
+-  static int __wrap_aeabi_atexit(void *that, Destructor destructor,
+-                                 void *dso_handle);
+-#else
+-  static int __wrap_cxa_atexit(Destructor destructor, void *that,
+-                               void *dso_handle);
+-#endif
+-
+-  static void __wrap_cxa_finalize(void *dso_handle);
+-
+-  /**
+-   * Registered destructor. Keeps track of the destructor function pointer,
+-   * associated object to call it with, and DSO handle.
+-   */
+-  class DestructorCaller {
+-  public:
+-    DestructorCaller(Destructor destructor, void *object, void *dso_handle)
+-    : destructor(destructor), object(object), dso_handle(dso_handle) { }
+-
+-    /**
+-     * Call the destructor function with the associated object.
+-     * Call only once, see CustomElf::~CustomElf.
+-     */
+-    void Call();
+-
+-    /**
+-     * Returns whether the destructor is associated to the given DSO handle
+-     */
+-    bool IsForHandle(void *handle) const
+-    {
+-      return handle == dso_handle;
+-    }
+-
+-  private:
+-    Destructor destructor;
+-    void *object;
+-    void *dso_handle;
+-  };
+-
+-private:
+-  /* Keep track of all registered destructors */
+-  std::vector<DestructorCaller> destructors;
+-
+-  /* Forward declaration, see further below */
+-  class DebuggerHelper;
+-public:
+-  /* Loaded object descriptor for the debugger interface below*/
+-  struct link_map {
+-    /* Base address of the loaded object. */
+-    const void *l_addr;
+-    /* File name */
+-    const char *l_name;
+-    /* Address of the PT_DYNAMIC segment. */
+-    const void *l_ld;
+-
+-  private:
+-    friend class ElfLoader::DebuggerHelper;
+-    /* Double linked list of loaded objects. */
+-    link_map *l_next, *l_prev;
+-  };
+-
+-private:
+-  /* Data structure used by the linker to give details about shared objects it
+-   * loaded to debuggers. This is normally defined in link.h, but Android
+-   * headers lack this file. */
+-  struct r_debug {
+-    /* Version number of the protocol. */
+-    int r_version;
+-
+-    /* Head of the linked list of loaded objects. */
+-    link_map *r_map;
+-
+-    /* Function to be called when updates to the linked list of loaded objects
+-     * are going to occur. The function is to be called before and after
+-     * changes. */
+-    void (*r_brk)(void);
+-
+-    /* Indicates to the debugger what state the linked list of loaded objects
+-     * is in when the function above is called. */
+-    enum {
+-      RT_CONSISTENT, /* Changes are complete */
+-      RT_ADD,        /* Beginning to add a new object */
+-      RT_DELETE      /* Beginning to remove an object */
+-    } r_state;
+-  };
+-
+-  /* Memory representation of ELF Auxiliary Vectors */
+-  struct AuxVector {
+-    Elf::Addr type;
+-    Elf::Addr value;
+-  };
+-
+-  /* Helper class used to integrate libraries loaded by this linker in
+-   * r_debug */
+-  class DebuggerHelper
+-  {
+-  public:
+-    DebuggerHelper();
+-
+-    void Init(AuxVector *auvx);
+-
+-    operator bool()
+-    {
+-      return dbg;
+-    }
+-
+-    /* Make the debugger aware of a new loaded object */
+-    void Add(link_map *map);
+-
+-    /* Make the debugger aware of the unloading of an object */
+-    void Remove(link_map *map);
+-
+-    /* Iterates over all link_maps */
+-    class iterator
+-    {
+-    public:
+-      const link_map *operator ->() const
+-      {
+-        return item;
+-      }
+-
+-      const link_map &operator ++()
+-      {
+-        item = item->l_next;
+-        return *item;
+-      }
+-
+-      bool operator<(const iterator &other) const
+-      {
+-        if (other.item == nullptr)
+-          return item ? true : false;
+-        MOZ_CRASH("DebuggerHelper::iterator::operator< called with something else than DebuggerHelper::end()");
+-      }
+-    protected:
+-      friend class DebuggerHelper;
+-      iterator(const link_map *item): item(item) { }
+-
+-    private:
+-      const link_map *item;
+-    };
+-
+-    iterator begin() const
+-    {
+-      return iterator(dbg ? dbg->r_map : nullptr);
+-    }
+-
+-    iterator end() const
+-    {
+-      return iterator(nullptr);
+-    }
+-
+-  private:
+-    r_debug *dbg;
+-    link_map *firstAdded;
+-  };
+-  friend int __wrap_dl_iterate_phdr(dl_phdr_cb callback, void *data);
+-  DebuggerHelper dbg;
+-};
+-
+-#endif /* ElfLoader_h */
+diff --git a/mozglue/linker/Elfxx.h b/mozglue/linker/Elfxx.h
+deleted file mode 100644
+--- a/mozglue/linker/Elfxx.h
++++ /dev/null
+@@ -1,253 +0,0 @@
+-/* 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/. */
+-
+-#ifndef Elfxx_h
+-#define Elfxx_h
+-
+-/**
+- * Android system headers have two different elf.h file. The one under linux/
+- * is the most complete on older Android API versions without unified headers.
+- */
+-#if defined(ANDROID) && __ANDROID_API__ < 21 && !defined(__ANDROID_API_L__)
+-#include <linux/elf.h>
+-#else
+-#include <elf.h>
+-#endif
+-#include <endian.h>
+-
+-#if defined(__ARM_EABI__) && !defined(PT_ARM_EXIDX)
+-#define PT_ARM_EXIDX 0x70000001
+-#endif
+-
+-/**
+- * Generic ELF macros for the target system
+- */
+-#ifdef __LP64__
+-#define Elf_(type) Elf64_ ## type
+-#define ELFCLASS ELFCLASS64
+-#define ELF_R_TYPE ELF64_R_TYPE
+-#define ELF_R_SYM ELF64_R_SYM
+-#ifndef ELF_ST_BIND
+-#define ELF_ST_BIND ELF64_ST_BIND
+-#endif
+-#else
+-#define Elf_(type) Elf32_ ## type
+-#define ELFCLASS ELFCLASS32
+-#define ELF_R_TYPE ELF32_R_TYPE
+-#define ELF_R_SYM ELF32_R_SYM
+-#ifndef ELF_ST_BIND
+-#define ELF_ST_BIND ELF32_ST_BIND
+-#endif
+-#endif
+-
+-#ifndef __BYTE_ORDER
+-#error Cannot find endianness
+-#endif
+-
+-#if __BYTE_ORDER == __LITTLE_ENDIAN
+-#define ELFDATA ELFDATA2LSB
+-#elif __BYTE_ORDER == __BIG_ENDIAN
+-#define ELFDATA ELFDATA2MSB
+-#endif
+-
+-#ifdef __linux__
+-#define ELFOSABI ELFOSABI_LINUX
+-#ifdef EI_ABIVERSION
+-#define ELFABIVERSION 0
+-#endif
+-#else
+-#error Unknown ELF OSABI
+-#endif
+-
+-#if defined(__i386__)
+-#define ELFMACHINE EM_386
+-
+-// Doing this way probably doesn't scale to other architectures
+-#define R_ABS R_386_32
+-#define R_GLOB_DAT R_386_GLOB_DAT
+-#define R_JMP_SLOT R_386_JMP_SLOT
+-#define R_RELATIVE R_386_RELATIVE
+-#define RELOC(n) DT_REL ## n
+-#define UNSUPPORTED_RELOC(n) DT_RELA ## n
+-#define STR_RELOC(n) "DT_REL" # n
+-#define Reloc Rel
+-
+-#elif defined(__x86_64__)
+-#define ELFMACHINE EM_X86_64
+-
+-#define R_ABS R_X86_64_64
+-#define R_GLOB_DAT R_X86_64_GLOB_DAT
+-#define R_JMP_SLOT R_X86_64_JUMP_SLOT
+-#define R_RELATIVE R_X86_64_RELATIVE
+-#define RELOC(n) DT_RELA ## n
+-#define UNSUPPORTED_RELOC(n) DT_REL ## n
+-#define STR_RELOC(n) "DT_RELA" # n
+-#define Reloc Rela
+-
+-#elif defined(__arm__)
+-#define ELFMACHINE EM_ARM
+-
+-#ifndef R_ARM_ABS32
+-#define R_ARM_ABS32 2
+-#endif
+-#ifndef R_ARM_GLOB_DAT
+-#define R_ARM_GLOB_DAT 21
+-#endif
+-#ifndef R_ARM_JUMP_SLOT
+-#define R_ARM_JUMP_SLOT 22
+-#endif
+-#ifndef R_ARM_RELATIVE
+-#define R_ARM_RELATIVE 23
+-#endif
+-
+-#define R_ABS R_ARM_ABS32
+-#define R_GLOB_DAT R_ARM_GLOB_DAT
+-#define R_JMP_SLOT R_ARM_JUMP_SLOT
+-#define R_RELATIVE R_ARM_RELATIVE
+-#define RELOC(n) DT_REL ## n
+-#define UNSUPPORTED_RELOC(n) DT_RELA ## n
+-#define STR_RELOC(n) "DT_REL" # n
+-#define Reloc Rel
+-
+-#elif defined(__aarch64__)
+-#define ELFMACHINE EM_AARCH64
+-
+-#define R_ABS R_AARCH64_ABS64
+-#define R_GLOB_DAT R_AARCH64_GLOB_DAT
+-#define R_JMP_SLOT R_AARCH64_JUMP_SLOT
+-#define R_RELATIVE R_AARCH64_RELATIVE
+-#define RELOC(n) DT_RELA ## n
+-#define UNSUPPORTED_RELOC(n) DT_REL ## n
+-#define STR_RELOC(n) "DT_RELA" # n
+-#define Reloc Rela
+-
+-#else
+-#error Unknown ELF machine type
+-#endif
+-
+-/**
+- * Android system headers don't have all definitions
+- */
+-#ifndef STN_UNDEF
+-#define STN_UNDEF 0
+-#endif
+-#ifndef DT_INIT_ARRAY
+-#define DT_INIT_ARRAY 25
+-#endif
+-#ifndef DT_FINI_ARRAY
+-#define DT_FINI_ARRAY 26
+-#endif
+-#ifndef DT_INIT_ARRAYSZ
+-#define DT_INIT_ARRAYSZ 27
+-#endif
+-#ifndef DT_FINI_ARRAYSZ
+-#define DT_FINI_ARRAYSZ 28
+-#endif
+-#ifndef DT_RELACOUNT
+-#define DT_RELACOUNT 0x6ffffff9
+-#endif
+-#ifndef DT_RELCOUNT
+-#define DT_RELCOUNT 0x6ffffffa
+-#endif
+-#ifndef DT_VERSYM
+-#define DT_VERSYM 0x6ffffff0
+-#endif
+-#ifndef DT_VERDEF
+-#define DT_VERDEF 0x6ffffffc
+-#endif
+-#ifndef DT_VERDEFNUM
+-#define DT_VERDEFNUM 0x6ffffffd
+-#endif
+-#ifndef DT_VERNEED
+-#define DT_VERNEED 0x6ffffffe
+-#endif
+-#ifndef DT_VERNEEDNUM
+-#define DT_VERNEEDNUM 0x6fffffff
+-#endif
+-#ifndef DT_FLAGS_1
+-#define DT_FLAGS_1 0x6ffffffb
+-#endif
+-#ifndef DT_FLAGS
+-#define DT_FLAGS 30
+-#endif
+-#ifndef DF_SYMBOLIC
+-#define DF_SYMBOLIC 0x00000002
+-#endif
+-#ifndef DF_TEXTREL
+-#define DF_TEXTREL 0x00000004
+-#endif
+-
+-namespace Elf {
+-
+-/**
+- * Define a few basic Elf Types
+- */
+-typedef Elf_(Phdr) Phdr;
+-typedef Elf_(Dyn) Dyn;
+-typedef Elf_(Sym) Sym;
+-typedef Elf_(Addr) Addr;
+-typedef Elf_(Word) Word;
+-typedef Elf_(Half) Half;
+-
+-/**
+- * Helper class around the standard Elf header struct
+- */
+-struct Ehdr: public Elf_(Ehdr)
+-{
+-  /**
+-   * Equivalent to reinterpret_cast<const Ehdr *>(buf), but additionally
+-   * checking that this is indeed an Elf header and that the Elf type
+-   * corresponds to that of the system
+-   */
+-  static const Ehdr *validate(const void *buf);
+-};
+-
+-/**
+- * Elf String table
+- */
+-class Strtab: public UnsizedArray<const char>
+-{
+-public:
+-  /**
+-   * Returns the string at the given index in the table
+-   */
+-  const char *GetStringAt(off_t index) const
+-  {
+-    return &UnsizedArray<const char>::operator[](index);
+-  }
+-};
+-
+-/**
+- * Helper class around Elf relocation.
+- */
+-struct Rel: public Elf_(Rel)
+-{
+-  /**
+-   * Returns the addend for the relocation, which is the value stored
+-   * at r_offset.
+-   */
+-  Addr GetAddend(void *base) const
+-  {
+-    return *(reinterpret_cast<const Addr *>(
+-                   reinterpret_cast<const char *>(base) + r_offset));
+-  }
+-};
+-
+-/**
+- * Helper class around Elf relocation with addend.
+- */
+-struct Rela: public Elf_(Rela)
+-{
+-  /**
+-   * Returns the addend for the relocation.
+-   */
+-  Addr GetAddend(void *base) const
+-  {
+-    return r_addend;
+-  }
+-};
+-
+-} /* namespace Elf */
+-
+-#endif /* Elfxx_h */
+diff --git a/mozglue/linker/Logging.h b/mozglue/linker/Logging.h
+deleted file mode 100644
+--- a/mozglue/linker/Logging.h
++++ /dev/null
+@@ -1,75 +0,0 @@
+-/* 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/. */
+-
+-#ifndef Logging_h
+-#define Logging_h
+-
+-#include "mozilla/Likely.h"
+-
+-#ifdef ANDROID
+-#include <android/log.h>
+-#define LOG(...) __android_log_print(ANDROID_LOG_INFO, "GeckoLinker", __VA_ARGS__)
+-#define WARN(...) __android_log_print(ANDROID_LOG_WARN, "GeckoLinker", __VA_ARGS__)
+-#define ERROR(...) __android_log_print(ANDROID_LOG_ERROR, "GeckoLinker", __VA_ARGS__)
+-#else
+-#include <cstdio>
+-
+-/* Expand to 1 or m depending on whether there is one argument or more
+- * given. */
+-#define MOZ_ONE_OR_MORE_ARGS_IMPL2(_1, _2, _3, _4, _5, _6, _7, _8, _9, N, ...) \
+-  N
+-#define MOZ_ONE_OR_MORE_ARGS_IMPL(args) MOZ_ONE_OR_MORE_ARGS_IMPL2 args
+-#define MOZ_ONE_OR_MORE_ARGS(...) \
+-  MOZ_ONE_OR_MORE_ARGS_IMPL((__VA_ARGS__, m, m, m, m, m, m, m, m, 1, 0))
+-
+-#define MOZ_MACRO_GLUE(a, b) a b
+-#define MOZ_CONCAT2(a, b) a ## b
+-#define MOZ_CONCAT1(a, b) MOZ_CONCAT2(a, b)
+-#define MOZ_CONCAT(a, b) MOZ_CONCAT1(a, b)
+-
+-/* Some magic to choose between LOG1 and LOGm depending on the number of
+- * arguments */
+-#define MOZ_CHOOSE_LOG(...) \
+-  MOZ_MACRO_GLUE(MOZ_CONCAT(LOG, MOZ_ONE_OR_MORE_ARGS(__VA_ARGS__)), \
+-                 (__VA_ARGS__))
+-
+-#define LOG1(format) fprintf(stderr, format "\n")
+-#define LOGm(format, ...) fprintf(stderr, format "\n", __VA_ARGS__)
+-#define LOG(...) MOZ_CHOOSE_LOG(__VA_ARGS__)
+-#define WARN(...) MOZ_CHOOSE_LOG("Warning: " __VA_ARGS__)
+-#define ERROR(...) MOZ_CHOOSE_LOG("Error: " __VA_ARGS__)
+-
+-#endif
+-
+-class Logging
+-{
+-public:
+-  static bool isVerbose()
+-  {
+-    return Singleton.verbose;
+-  }
+-
+-private:
+-  bool verbose;
+-
+-public:
+-  static void Init()
+-  {
+-    const char *env = getenv("MOZ_DEBUG_LINKER");
+-    if (env && *env == '1')
+-      Singleton.verbose = true;
+-  }
+-
+-private:
+-  static Logging Singleton;
+-};
+-
+-#define DEBUG_LOG(...)   \
+-  do {                   \
+-    if (MOZ_UNLIKELY(Logging::isVerbose())) {  \
+-      LOG(__VA_ARGS__);  \
+-    }                    \
+-  } while(0)
+-
+-#endif /* Logging_h */
+diff --git a/mozglue/linker/Mappable.cpp b/mozglue/linker/Mappable.cpp
+deleted file mode 100644
+--- a/mozglue/linker/Mappable.cpp
++++ /dev/null
+@@ -1,454 +0,0 @@
+-/* 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 <fcntl.h>
+-#include <unistd.h>
+-#include <sys/mman.h>
+-#include <sys/stat.h>
+-#include <cstring>
+-#include <cstdlib>
+-#include <cstdio>
+-#include <string>
+-
+-#include "Mappable.h"
+-
+-#include "mozilla/IntegerPrintfMacros.h"
+-#include "mozilla/UniquePtr.h"
+-
+-#ifdef ANDROID
+-#include <linux/ashmem.h>
+-#endif
+-#include <sys/stat.h>
+-#include <errno.h>
+-#include "ElfLoader.h"
+-#include "XZStream.h"
+-#include "Logging.h"
+-
+-using mozilla::MakeUnique;
+-using mozilla::UniquePtr;
+-
+-class CacheValidator
+-{
+-public:
+-  CacheValidator(const char* aCachedLibPath, Zip* aZip, Zip::Stream* aStream)
+-    : mCachedLibPath(aCachedLibPath)
+-  {
+-    static const char kChecksumSuffix[] = ".crc";
+-
+-    mCachedChecksumPath =
+-      MakeUnique<char[]>(strlen(aCachedLibPath) + sizeof(kChecksumSuffix));
+-    sprintf(mCachedChecksumPath.get(), "%s%s", aCachedLibPath, kChecksumSuffix);
+-    DEBUG_LOG("mCachedChecksumPath: %s", mCachedChecksumPath.get());
+-
+-    mChecksum = aStream->GetCRC32();
+-    DEBUG_LOG("mChecksum: %x", mChecksum);
+-  }
+-
+-  // Returns whether the cache is valid and up-to-date.
+-  bool IsValid() const
+-  {
+-    // Validate based on checksum.
+-    RefPtr<Mappable> checksumMap = MappableFile::Create(mCachedChecksumPath.get());
+-    if (!checksumMap) {
+-      // Force caching if checksum is missing in cache.
+-      return false;
+-    }
+-
+-    DEBUG_LOG("Comparing %x with %s", mChecksum, mCachedChecksumPath.get());
+-    MappedPtr checksumBuf = checksumMap->mmap(nullptr, checksumMap->GetLength(),
+-                                              PROT_READ, MAP_PRIVATE, 0);
+-    if (checksumBuf == MAP_FAILED) {
+-      WARN("Couldn't map %s to validate checksum", mCachedChecksumPath.get());
+-      return false;
+-    }
+-    if (memcmp(checksumBuf, &mChecksum, sizeof(mChecksum))) {
+-      return false;
+-    }
+-    return !access(mCachedLibPath.c_str(), R_OK);
+-  }
+-
+-  // Caches the APK-provided checksum used in future cache validations.
+-  void CacheChecksum() const
+-  {
+-    AutoCloseFD fd(open(mCachedChecksumPath.get(),
+-                        O_TRUNC | O_RDWR | O_CREAT | O_NOATIME,
+-                        S_IRUSR | S_IWUSR));
+-    if (fd == -1) {
+-      WARN("Couldn't open %s to update checksum", mCachedChecksumPath.get());
+-      return;
+-    }
+-
+-    DEBUG_LOG("Updating checksum %s", mCachedChecksumPath.get());
+-
+-    const size_t size = sizeof(mChecksum);
+-    size_t written = 0;
+-    while (written < size) {
+-      ssize_t ret = write(fd,
+-                          reinterpret_cast<const uint8_t*>(&mChecksum) + written,
+-                          size - written);
+-      if (ret >= 0) {
+-        written += ret;
+-      } else if (errno != EINTR) {
+-        WARN("Writing checksum %s failed with errno %d",
+-             mCachedChecksumPath.get(), errno);
+-        break;
+-      }
+-    }
+-  }
+-
+-private:
+-  const std::string mCachedLibPath;
+-  UniquePtr<char[]> mCachedChecksumPath;
+-  uint32_t mChecksum;
+-};
+-
+-Mappable *
+-MappableFile::Create(const char *path)
+-{
+-  int fd = open(path, O_RDONLY);
+-  if (fd != -1)
+-    return new MappableFile(fd);
+-  return nullptr;
+-}
+-
+-MemoryRange
+-MappableFile::mmap(const void *addr, size_t length, int prot, int flags,
+-                   off_t offset)
+-{
+-  MOZ_ASSERT(fd != -1);
+-  MOZ_ASSERT(!(flags & MAP_SHARED));
+-  flags |= MAP_PRIVATE;
+-
+-  return MemoryRange::mmap(const_cast<void *>(addr), length, prot, flags,
+-                           fd, offset);
+-}
+-
+-void
+-MappableFile::finalize()
+-{
+-  /* Close file ; equivalent to close(fd.forget()) */
+-  fd = -1;
+-}
+-
+-size_t
+-MappableFile::GetLength() const
+-{
+-  struct stat st;
+-  return fstat(fd, &st) ? 0 : st.st_size;
+-}
+-
+-Mappable *
+-MappableExtractFile::Create(const char *name, Zip *zip, Zip::Stream *stream)
+-{
+-  MOZ_ASSERT(zip && stream);
+-
+-  const char *cachePath = getenv("MOZ_LINKER_CACHE");
+-  if (!cachePath || !*cachePath) {
+-    WARN("MOZ_LINKER_EXTRACT is set, but not MOZ_LINKER_CACHE; "
+-        "not extracting");
+-    return nullptr;
+-  }
+-
+-  // Ensure that the cache dir is private.
+-  chmod(cachePath, 0770);
+-
+-  UniquePtr<char[]> path =
+-    MakeUnique<char[]>(strlen(cachePath) + strlen(name) + 2);
+-  sprintf(path.get(), "%s/%s", cachePath, name);
+-
+-  CacheValidator validator(path.get(), zip, stream);
+-  if (validator.IsValid()) {
+-    DEBUG_LOG("Reusing %s", static_cast<char *>(path.get()));
+-    return MappableFile::Create(path.get());
+-  }
+-  DEBUG_LOG("Extracting to %s", static_cast<char *>(path.get()));
+-  AutoCloseFD fd;
+-  fd = open(path.get(), O_TRUNC | O_RDWR | O_CREAT | O_NOATIME,
+-                        S_IRUSR | S_IWUSR);
+-  if (fd == -1) {
+-    ERROR("Couldn't open %s to decompress library", path.get());
+-    return nullptr;
+-  }
+-  AutoUnlinkFile file(path.release());
+-  if (stream->GetType() == Zip::Stream::DEFLATE) {
+-    if (ftruncate(fd, stream->GetUncompressedSize()) == -1) {
+-      ERROR("Couldn't ftruncate %s to decompress library", file.get());
+-      return nullptr;
+-    }
+-    /* Map the temporary file for use as inflate buffer */
+-    MappedPtr buffer(MemoryRange::mmap(nullptr, stream->GetUncompressedSize(),
+-                                       PROT_WRITE, MAP_SHARED, fd, 0));
+-    if (buffer == MAP_FAILED) {
+-      ERROR("Couldn't map %s to decompress library", file.get());
+-      return nullptr;
+-    }
+-
+-    zxx_stream zStream = stream->GetZStream(buffer);
+-
+-    /* Decompress */
+-    if (inflateInit2(&zStream, -MAX_WBITS) != Z_OK) {
+-      ERROR("inflateInit failed: %s", zStream.msg);
+-      return nullptr;
+-    }
+-    if (inflate(&zStream, Z_FINISH) != Z_STREAM_END) {
+-      ERROR("inflate failed: %s", zStream.msg);
+-      return nullptr;
+-    }
+-    if (inflateEnd(&zStream) != Z_OK) {
+-      ERROR("inflateEnd failed: %s", zStream.msg);
+-      return nullptr;
+-    }
+-    if (zStream.total_out != stream->GetUncompressedSize()) {
+-      ERROR("File not fully uncompressed! %ld / %d", zStream.total_out,
+-          static_cast<unsigned int>(stream->GetUncompressedSize()));
+-      return nullptr;
+-    }
+-  } else if (XZStream::IsXZ(stream->GetBuffer(), stream->GetSize())) {
+-    XZStream xzStream(stream->GetBuffer(), stream->GetSize());
+-
+-    if (!xzStream.Init()) {
+-      ERROR("Couldn't initialize XZ decoder");
+-      return nullptr;
+-    }
+-    DEBUG_LOG("XZStream created, compressed=%" PRIuPTR
+-              ", uncompressed=%" PRIuPTR,
+-              xzStream.Size(), xzStream.UncompressedSize());
+-
+-    if (ftruncate(fd, xzStream.UncompressedSize()) == -1) {
+-      ERROR("Couldn't ftruncate %s to decompress library", file.get());
+-      return nullptr;
+-    }
+-    MappedPtr buffer(MemoryRange::mmap(nullptr, xzStream.UncompressedSize(),
+-                                       PROT_WRITE, MAP_SHARED, fd, 0));
+-    if (buffer == MAP_FAILED) {
+-      ERROR("Couldn't map %s to decompress library", file.get());
+-      return nullptr;
+-    }
+-    const size_t written = xzStream.Decode(buffer, buffer.GetLength());
+-    DEBUG_LOG("XZStream decoded %" PRIuPTR, written);
+-    if (written != buffer.GetLength()) {
+-      ERROR("Error decoding XZ file %s", file.get());
+-      return nullptr;
+-    }
+-  } else {
+-    return nullptr;
+-  }
+-
+-  validator.CacheChecksum();
+-  return new MappableExtractFile(fd.forget(), file.release());
+-}
+-
+-/**
+- * _MappableBuffer is a buffer which content can be mapped at different
+- * locations in the virtual address space.
+- * On Linux, uses a (deleted) temporary file on a tmpfs for sharable content.
+- * On Android, uses ashmem.
+- */
+-class _MappableBuffer: public MappedPtr
+-{
+-public:
+-  /**
+-   * Returns a _MappableBuffer instance with the given name and the given
+-   * length.
+-   */
+-  static _MappableBuffer *Create(const char *name, size_t length)
+-  {
+-    AutoCloseFD fd;
+-#ifdef ANDROID
+-    /* On Android, initialize an ashmem region with the given length */
+-    fd = open("/" ASHMEM_NAME_DEF, O_RDWR, 0600);
+-    if (fd == -1)
+-      return nullptr;
+-    char str[ASHMEM_NAME_LEN];
+-    strlcpy(str, name, sizeof(str));
+-    ioctl(fd, ASHMEM_SET_NAME, str);
+-    if (ioctl(fd, ASHMEM_SET_SIZE, length))
+-      return nullptr;
+-
+-    /* The Gecko crash reporter is confused by adjacent memory mappings of
+-     * the same file and chances are we're going to map from the same file
+-     * descriptor right away. To avoid problems with the crash reporter,
+-     * create an empty anonymous page before or after the ashmem mapping,
+-     * depending on how mappings grow in the address space.
+-     */
+-#if defined(__arm__)
+-    // Address increases on ARM.
+-    void *buf = ::mmap(nullptr, length + PAGE_SIZE, PROT_READ | PROT_WRITE,
+-                       MAP_SHARED, fd, 0);
+-    if (buf != MAP_FAILED) {
+-      ::mmap(AlignedEndPtr(reinterpret_cast<char *>(buf) + length, PAGE_SIZE),
+-             PAGE_SIZE, PROT_NONE, MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+-      DEBUG_LOG("Decompression buffer of size 0x%" PRIxPTR
+-                " in ashmem \"%s\", mapped @%p",
+-                length, str, buf);
+-      return new _MappableBuffer(fd.forget(), buf, length);
+-    }
+-#elif defined(__i386__) || defined(__aarch64__)
+-    // Address decreases on x86 and AArch64.
+-    size_t anon_mapping_length = length + PAGE_SIZE;
+-    void *buf = ::mmap(nullptr, anon_mapping_length, PROT_NONE,
+-                       MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+-    if (buf != MAP_FAILED) {
+-      char *first_page = reinterpret_cast<char *>(buf);
+-      char *map_page = first_page + PAGE_SIZE;
+-
+-      void *actual_buf = ::mmap(map_page, length, PROT_READ | PROT_WRITE,
+-                                MAP_FIXED | MAP_SHARED, fd, 0);
+-      if (actual_buf == MAP_FAILED) {
+-        ::munmap(buf, anon_mapping_length);
+-        DEBUG_LOG("Fixed allocation of decompression buffer at %p failed", map_page);
+-        return nullptr;
+-      }
+-
+-      DEBUG_LOG("Decompression buffer of size 0x%" PRIxPTR
+-                " in ashmem \"%s\", mapped @%p", length, str, actual_buf);
+-      return new _MappableBuffer(fd.forget(), actual_buf, length);
+-    }
+-#else
+-#error need to add a case for your CPU
+-#endif
+-#else
+-    /* On Linux, use /dev/shm as base directory for temporary files, assuming
+-     * it's on tmpfs */
+-    /* TODO: check that /dev/shm is tmpfs */
+-    char path[256];
+-    sprintf(path, "/dev/shm/%s.XXXXXX", name);
+-    fd = mkstemp(path);
+-    if (fd == -1)
+-      return nullptr;
+-    unlink(path);
+-    ftruncate(fd, length);
+-
+-    void *buf = ::mmap(nullptr, length, PROT_READ | PROT_WRITE,
+-                       MAP_SHARED, fd, 0);
+-    if (buf != MAP_FAILED) {
+-      DEBUG_LOG("Decompression buffer of size %ld in \"%s\", mapped @%p",
+-                length, path, buf);
+-      return new _MappableBuffer(fd.forget(), buf, length);
+-    }
+-#endif
+-    return nullptr;
+-  }
+-
+-  void *mmap(const void *addr, size_t length, int prot, int flags, off_t offset)
+-  {
+-    MOZ_ASSERT(fd != -1);
+-#ifdef ANDROID
+-    /* Mapping ashmem MAP_PRIVATE is like mapping anonymous memory, even when
+-     * there is content in the ashmem */
+-    if (flags & MAP_PRIVATE) {
+-      flags &= ~MAP_PRIVATE;
+-      flags |= MAP_SHARED;
+-    }
+-#endif
+-    return ::mmap(const_cast<void *>(addr), length, prot, flags, fd, offset);
+-  }
+-
+-#ifdef ANDROID
+-  ~_MappableBuffer() {
+-    /* Free the additional page we allocated. See _MappableBuffer::Create */
+-#if defined(__arm__)
+-    ::munmap(AlignedEndPtr(*this + GetLength(), PAGE_SIZE), PAGE_SIZE);
+-#elif defined(__i386__) || defined(__aarch64__)
+-    ::munmap(*this - PAGE_SIZE, GetLength() + PAGE_SIZE);
+-#else
+-#error need to add a case for your CPU
+-#endif
+-  }
+-#endif
+-
+-private:
+-  _MappableBuffer(int fd, void *buf, size_t length)
+-  : MappedPtr(buf, length), fd(fd) { }
+-
+-  /* File descriptor for the temporary file or ashmem */
+-  AutoCloseFD fd;
+-};
+-
+-
+-Mappable *
+-MappableDeflate::Create(const char *name, Zip *zip, Zip::Stream *stream)
+-{
+-  MOZ_ASSERT(stream->GetType() == Zip::Stream::DEFLATE);
+-  _MappableBuffer *buf = _MappableBuffer::Create(name, stream->GetUncompressedSize());
+-  if (buf)
+-    return new MappableDeflate(buf, zip, stream);
+-  return nullptr;
+-}
+-
+-MappableDeflate::MappableDeflate(_MappableBuffer *buf, Zip *zip,
+-                                 Zip::Stream *stream)
+-: zip(zip), buffer(buf), zStream(stream->GetZStream(*buf)) { }
+-
+-MappableDeflate::~MappableDeflate() { }
+-
+-MemoryRange
+-MappableDeflate::mmap(const void *addr, size_t length, int prot, int flags, off_t offset)
+-{
+-  MOZ_ASSERT(buffer);
+-  MOZ_ASSERT(!(flags & MAP_SHARED));
+-  flags |= MAP_PRIVATE;
+-
+-  /* The deflate stream is uncompressed up to the required offset + length, if
+-   * it hasn't previously been uncompressed */
+-  ssize_t missing = offset + length + zStream.avail_out - buffer->GetLength();
+-  if (missing > 0) {
+-    uInt avail_out = zStream.avail_out;
+-    zStream.avail_out = missing;
+-    if ((*buffer == zStream.next_out) &&
+-        (inflateInit2(&zStream, -MAX_WBITS) != Z_OK)) {
+-      ERROR("inflateInit failed: %s", zStream.msg);
+-      return MemoryRange(MAP_FAILED, 0);
+-    }
+-    int ret = inflate(&zStream, Z_SYNC_FLUSH);
+-    if (ret < 0) {
+-      ERROR("inflate failed: %s", zStream.msg);
+-      return MemoryRange(MAP_FAILED, 0);
+-    }
+-    if (ret == Z_NEED_DICT) {
+-      ERROR("zstream requires a dictionary. %s", zStream.msg);
+-      return MemoryRange(MAP_FAILED, 0);
+-    }
+-    zStream.avail_out = avail_out - missing + zStream.avail_out;
+-    if (ret == Z_STREAM_END) {
+-      if (inflateEnd(&zStream) != Z_OK) {
+-        ERROR("inflateEnd failed: %s", zStream.msg);
+-        return MemoryRange(MAP_FAILED, 0);
+-      }
+-      if (zStream.total_out != buffer->GetLength()) {
+-        ERROR("File not fully uncompressed! %ld / %d", zStream.total_out,
+-            static_cast<unsigned int>(buffer->GetLength()));
+-        return MemoryRange(MAP_FAILED, 0);
+-      }
+-    }
+-  }
+-#if defined(ANDROID) && defined(__arm__)
+-  if (prot & PROT_EXEC) {
+-    /* We just extracted data that may be executed in the future.
+-     * We thus need to ensure Instruction and Data cache coherency. */
+-    DEBUG_LOG("cacheflush(%p, %p)", *buffer + offset, *buffer + (offset + length));
+-    cacheflush(reinterpret_cast<uintptr_t>(*buffer + offset),
+-               reinterpret_cast<uintptr_t>(*buffer + (offset + length)), 0);
+-  }
+-#endif
+-
+-  return MemoryRange(buffer->mmap(addr, length, prot, flags, offset), length);
+-}
+-
+-void
+-MappableDeflate::finalize()
+-{
+-  /* Free zlib internal buffers */
+-  inflateEnd(&zStream);
+-  /* Free decompression buffer */
+-  buffer = nullptr;
+-  /* Remove reference to Zip archive */
+-  zip = nullptr;
+-}
+-
+-size_t
+-MappableDeflate::GetLength() const
+-{
+-  return buffer->GetLength();
+-}
+diff --git a/mozglue/linker/Mappable.h b/mozglue/linker/Mappable.h
+deleted file mode 100644
+--- a/mozglue/linker/Mappable.h
++++ /dev/null
+@@ -1,163 +0,0 @@
+-/* 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/. */
+-
+-#ifndef Mappable_h
+-#define Mappable_h
+-
+-#include "Zip.h"
+-#include "mozilla/RefPtr.h"
+-#include "mozilla/UniquePtr.h"
+-#include "zlib.h"
+-
+-/**
+- * Abstract class to handle mmap()ing from various kind of entities, such as
+- * plain files or Zip entries. The virtual members are meant to act as the
+- * equivalent system functions, except mapped memory is always MAP_PRIVATE,
+- * even though a given implementation may use something different internally.
+- */
+-class Mappable: public mozilla::RefCounted<Mappable>
+-{
+-public:
+-  MOZ_DECLARE_REFCOUNTED_TYPENAME(Mappable)
+-  virtual ~Mappable() { }
+-
+-  virtual MemoryRange mmap(const void *addr, size_t length, int prot, int flags,
+-                           off_t offset) = 0;
+-
+-  enum Kind {
+-    MAPPABLE_FILE,
+-    MAPPABLE_EXTRACT_FILE,
+-    MAPPABLE_DEFLATE,
+-    MAPPABLE_SEEKABLE_ZSTREAM
+-  };
+-
+-  virtual Kind GetKind() const = 0;
+-
+-private:
+-  virtual void munmap(void *addr, size_t length) {
+-    ::munmap(addr, length);
+-  }
+-  /* Limit use of Mappable::munmap to classes that keep track of the address
+-   * and size of the mapping. This allows to ignore ::munmap return value. */
+-  friend class Mappable1stPagePtr;
+-  friend class LibHandle;
+-
+-public:
+-  /**
+-   * Indicate to a Mappable instance that no further mmap is going to happen.
+-   */
+-  virtual void finalize() = 0;
+-
+-  /**
+-   * Returns the maximum length that can be mapped from this Mappable for
+-   * offset = 0.
+-   */
+-  virtual size_t GetLength() const = 0;
+-};
+-
+-/**
+- * Mappable implementation for plain files
+- */
+-class MappableFile: public Mappable
+-{
+-public:
+-  ~MappableFile() { }
+-
+-  /**
+-   * Create a MappableFile instance for the given file path.
+-   */
+-  static Mappable *Create(const char *path);
+-
+-  /* Inherited from Mappable */
+-  virtual MemoryRange mmap(const void *addr, size_t length, int prot, int flags, off_t offset);
+-  virtual void finalize();
+-  virtual size_t GetLength() const;
+-
+-  virtual Kind GetKind() const { return MAPPABLE_FILE; };
+-protected:
+-  MappableFile(int fd): fd(fd) { }
+-
+-private:
+-  /* File descriptor */
+-  AutoCloseFD fd;
+-};
+-
+-/**
+- * Mappable implementation for deflated stream in a Zip archive
+- * Inflates the complete stream into a cache file.
+- */
+-class MappableExtractFile: public MappableFile
+-{
+-public:
+-  ~MappableExtractFile() = default;
+-
+-  /**
+-   * Create a MappableExtractFile instance for the given Zip stream. The name
+-   * argument is used to create the cache file in the cache directory.
+-   */
+-  static Mappable *Create(const char *name, Zip *zip, Zip::Stream *stream);
+-
+-  /* Override finalize from MappableFile */
+-  virtual void finalize() {}
+-
+-  virtual Kind GetKind() const { return MAPPABLE_EXTRACT_FILE; };
+-private:
+-  /**
+-   * AutoUnlinkFile keeps track of a file name and removes (unlinks) the file
+-   * when the instance is destroyed.
+-   */
+-  struct UnlinkFile
+-  {
+-    void operator()(char *value) {
+-      unlink(value);
+-      delete [] value;
+-    }
+-  };
+-  typedef mozilla::UniquePtr<char[], UnlinkFile> AutoUnlinkFile;
+-
+-  MappableExtractFile(int fd, const char* path)
+-  : MappableFile(fd), path(path) { }
+-
+-  /* Extracted file path */
+-  mozilla::UniquePtr<const char[]> path;
+-};
+-
+-class _MappableBuffer;
+-
+-/**
+- * Mappable implementation for deflated stream in a Zip archive.
+- * Inflates the mapped bits in a temporary buffer.
+- */
+-class MappableDeflate: public Mappable
+-{
+-public:
+-  ~MappableDeflate();
+-
+-  /**
+-   * Create a MappableDeflate instance for the given Zip stream. The name
+-   * argument is used for an appropriately named temporary file, and the Zip
+-   * instance is given for the MappableDeflate to keep a reference of it.
+-   */
+-  static Mappable *Create(const char *name, Zip *zip, Zip::Stream *stream);
+-
+-  /* Inherited from Mappable */
+-  virtual MemoryRange mmap(const void *addr, size_t length, int prot, int flags, off_t offset);
+-  virtual void finalize();
+-  virtual size_t GetLength() const;
+-
+-  virtual Kind GetKind() const { return MAPPABLE_DEFLATE; };
+-private:
+-  MappableDeflate(_MappableBuffer *buf, Zip *zip, Zip::Stream *stream);
+-
+-  /* Zip reference */
+-  RefPtr<Zip> zip;
+-
+-  /* Decompression buffer */
+-  mozilla::UniquePtr<_MappableBuffer> buffer;
+-
+-  /* Zlib data */
+-  zxx_stream zStream;
+-};
+-
+-#endif /* Mappable_h */
+diff --git a/mozglue/linker/Utils.h b/mozglue/linker/Utils.h
+deleted file mode 100644
+--- a/mozglue/linker/Utils.h
++++ /dev/null
+@@ -1,618 +0,0 @@
+-/* 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/. */
+-
+-#ifndef Utils_h
+-#define Utils_h
+-
+-#include <pthread.h>
+-#include <stdint.h>
+-#include <stddef.h>
+-#include <sys/mman.h>
+-#include <unistd.h>
+-#include "mozilla/Assertions.h"
+-#include "mozilla/Scoped.h"
+-
+-/**
+- * On architectures that are little endian and that support unaligned reads,
+- * we can use direct type, but on others, we want to have a special class
+- * to handle conversion and alignment issues.
+- */
+-#if !defined(DEBUG) && (defined(__i386__) || defined(__x86_64__))
+-typedef uint16_t le_uint16;
+-typedef uint32_t le_uint32;
+-#else
+-
+-/**
+- * Template that allows to find an unsigned int type from a (computed) bit size
+- */
+-template <int s> struct UInt { };
+-template <> struct UInt<16> { typedef uint16_t Type; };
+-template <> struct UInt<32> { typedef uint32_t Type; };
+-
+-/**
+- * Template to access 2 n-bit sized words as a 2*n-bit sized word, doing
+- * conversion from little endian and avoiding alignment issues.
+- */
+-template <typename T>
+-class le_to_cpu
+-{
+-public:
+-  typedef typename UInt<16 * sizeof(T)>::Type Type;
+-
+-  operator Type() const
+-  {
+-    return (b << (sizeof(T) * 8)) | a;
+-  }
+-
+-  const le_to_cpu& operator =(const Type &v)
+-  {
+-    a = v & ((1 << (sizeof(T) * 8)) - 1);
+-    b = v >> (sizeof(T) * 8);
+-    return *this;
+-  }
+-
+-  le_to_cpu() { }
+-  le_to_cpu(const Type &v)
+-  {
+-    operator =(v);
+-  }
+-
+-  const le_to_cpu& operator +=(const Type &v)
+-  {
+-    return operator =(operator Type() + v);
+-  }
+-
+-  const le_to_cpu& operator ++(int)
+-  {
+-    return operator =(operator Type() + 1);
+-  }
+-
+-private:
+-  T a, b;
+-};
+-
+-/**
+- * Type definitions
+- */
+-typedef le_to_cpu<unsigned char> le_uint16;
+-typedef le_to_cpu<le_uint16> le_uint32;
+-#endif
+-
+-
+-/**
+- * AutoCloseFD is a RAII wrapper for POSIX file descriptors
+- */
+-struct AutoCloseFDTraits
+-{
+-  typedef int type;
+-  static int empty() { return -1; }
+-  static void release(int fd) { if (fd != -1) close(fd); }
+-};
+-typedef mozilla::Scoped<AutoCloseFDTraits> AutoCloseFD;
+-
+-/**
+- * AutoCloseFILE is a RAII wrapper for POSIX streams
+- */
+-struct AutoCloseFILETraits
+-{
+-  typedef FILE *type;
+-  static FILE *empty() { return nullptr; }
+-  static void release(FILE *f) { if (f) fclose(f); }
+-};
+-typedef mozilla::Scoped<AutoCloseFILETraits> AutoCloseFILE;
+-
+-/**
+- * Page alignment helpers
+- */
+-static inline size_t PageSize()
+-{
+-  return 4096;
+-}
+-
+-static inline uintptr_t AlignedPtr(uintptr_t ptr, size_t alignment)
+-{
+-  return ptr & ~(alignment - 1);
+-}
+-
+-template <typename T>
+-static inline T *AlignedPtr(T *ptr, size_t alignment)
+-{
+-  return reinterpret_cast<T *>(
+-         AlignedPtr(reinterpret_cast<uintptr_t>(ptr), alignment));
+-}
+-
+-template <typename T>
+-static inline T PageAlignedPtr(T ptr)
+-{
+-  return AlignedPtr(ptr, PageSize());
+-}
+-
+-static inline uintptr_t AlignedEndPtr(uintptr_t ptr, size_t alignment)
+-{
+-  return AlignedPtr(ptr + alignment - 1, alignment);
+-}
+-
+-template <typename T>
+-static inline T *AlignedEndPtr(T *ptr, size_t alignment)
+-{
+-  return reinterpret_cast<T *>(
+-         AlignedEndPtr(reinterpret_cast<uintptr_t>(ptr), alignment));
+-}
+-
+-template <typename T>
+-static inline T PageAlignedEndPtr(T ptr)
+-{
+-  return AlignedEndPtr(ptr,  PageSize());
+-}
+-
+-static inline size_t AlignedSize(size_t size, size_t alignment)
+-{
+-  return (size + alignment - 1) & ~(alignment - 1);
+-}
+-
+-static inline size_t PageAlignedSize(size_t size)
+-{
+-  return AlignedSize(size, PageSize());
+-}
+-
+-static inline bool IsAlignedPtr(uintptr_t ptr, size_t alignment)
+-{
+-  return ptr % alignment == 0;
+-}
+-
+-template <typename T>
+-static inline bool IsAlignedPtr(T *ptr, size_t alignment)
+-{
+-  return IsAlignedPtr(reinterpret_cast<uintptr_t>(ptr), alignment);
+-}
+-
+-template <typename T>
+-static inline bool IsPageAlignedPtr(T ptr)
+-{
+-  return IsAlignedPtr(ptr, PageSize());
+-}
+-
+-static inline bool IsAlignedSize(size_t size, size_t alignment)
+-{
+-  return size % alignment == 0;
+-}
+-
+-static inline bool IsPageAlignedSize(size_t size)
+-{
+-  return IsAlignedSize(size, PageSize());
+-}
+-
+-static inline size_t PageNumber(size_t size)
+-{
+-  return (size + PageSize() - 1) / PageSize();
+-}
+-
+-/**
+- * MemoryRange stores a pointer, size pair.
+- */
+-class MemoryRange
+-{
+-public:
+-  MemoryRange(void *buf, size_t length): buf(buf), length(length) { }
+-
+-  void Assign(void *b, size_t len) {
+-    buf = b;
+-    length = len;
+-  }
+-
+-  void Assign(const MemoryRange& other) {
+-    buf = other.buf;
+-    length = other.length;
+-  }
+-
+-  void *get() const
+-  {
+-    return buf;
+-  }
+-
+-  operator void *() const
+-  {
+-    return buf;
+-  }
+-
+-  operator unsigned char *() const
+-  {
+-    return reinterpret_cast<unsigned char *>(buf);
+-  }
+-
+-  bool operator ==(void *ptr) const {
+-    return buf == ptr;
+-  }
+-
+-  bool operator ==(unsigned char *ptr) const {
+-    return buf == ptr;
+-  }
+-
+-  void *operator +(off_t offset) const
+-  {
+-    return reinterpret_cast<char *>(buf) + offset;
+-  }
+-
+-  /**
+-   * Returns whether the given address is within the mapped range
+-   */
+-  bool Contains(void *ptr) const
+-  {
+-    return (ptr >= buf) && (ptr < reinterpret_cast<char *>(buf) + length);
+-  }
+-
+-  /**
+-   * Returns the length of the mapped range
+-   */
+-  size_t GetLength() const
+-  {
+-    return length;
+-  }
+-
+-  static MemoryRange mmap(void *addr, size_t length, int prot, int flags,
+-                          int fd, off_t offset) {
+-    return MemoryRange(::mmap(addr, length, prot, flags, fd, offset), length);
+-  }
+-
+-private:
+-  void *buf;
+-  size_t length;
+-};
+-
+-/**
+- * MappedPtr is a RAII wrapper for mmap()ed memory. It can be used as
+- * a simple void * or unsigned char *.
+- *
+- * It is defined as a derivative of a template that allows to use a
+- * different unmapping strategy.
+- */
+-template <typename T>
+-class GenericMappedPtr: public MemoryRange
+-{
+-public:
+-  GenericMappedPtr(void *buf, size_t length): MemoryRange(buf, length) { }
+-  GenericMappedPtr(const MemoryRange& other): MemoryRange(other) { }
+-  GenericMappedPtr(): MemoryRange(MAP_FAILED, 0) { }
+-
+-  void Assign(void *b, size_t len) {
+-    if (get() != MAP_FAILED)
+-      static_cast<T *>(this)->munmap(get(), GetLength());
+-    MemoryRange::Assign(b, len);
+-  }
+-
+-  void Assign(const MemoryRange& other) {
+-    Assign(other.get(), other.GetLength());
+-  }
+-
+-  ~GenericMappedPtr()
+-  {
+-    if (get() != MAP_FAILED)
+-      static_cast<T *>(this)->munmap(get(), GetLength());
+-  }
+-
+-  void release()
+-  {
+-    MemoryRange::Assign(MAP_FAILED, 0);
+-  }
+-};
+-
+-struct MappedPtr: public GenericMappedPtr<MappedPtr>
+-{
+-  MappedPtr(void *buf, size_t length)
+-  : GenericMappedPtr<MappedPtr>(buf, length) { }
+-  MappedPtr(const MemoryRange& other)
+-  : GenericMappedPtr<MappedPtr>(other) { }
+-  MappedPtr(): GenericMappedPtr<MappedPtr>() { }
+-
+-private:
+-  friend class GenericMappedPtr<MappedPtr>;
+-  void munmap(void *buf, size_t length)
+-  {
+-    ::munmap(buf, length);
+-  }
+-};
+-
+-/**
+- * UnsizedArray is a way to access raw arrays of data in memory.
+- *
+- *   struct S { ... };
+- *   UnsizedArray<S> a(buf);
+- *   UnsizedArray<S> b; b.Init(buf);
+- *
+- * This is roughly equivalent to
+- *   const S *a = reinterpret_cast<const S *>(buf);
+- *   const S *b = nullptr; b = reinterpret_cast<const S *>(buf);
+- *
+- * An UnsizedArray has no known length, and it's up to the caller to make
+- * sure the accessed memory is mapped and makes sense.
+- */
+-template <typename T>
+-class UnsizedArray
+-{
+-public:
+-  typedef size_t idx_t;
+-
+-  /**
+-   * Constructors and Initializers
+-   */
+-  UnsizedArray(): contents(nullptr) { }
+-  UnsizedArray(const void *buf): contents(reinterpret_cast<const T *>(buf)) { }
+-
+-  void Init(const void *buf)
+-  {
+-    MOZ_ASSERT(contents == nullptr);
+-    contents = reinterpret_cast<const T *>(buf);
+-  }
+-
+-  /**
+-   * Returns the nth element of the array
+-   */
+-  const T &operator[](const idx_t index) const
+-  {
+-    MOZ_ASSERT(contents);
+-    return contents[index];
+-  }
+-
+-  operator const T *() const
+-  {
+-    return contents;
+-  }
+-  /**
+-   * Returns whether the array points somewhere
+-   */
+-  operator bool() const
+-  {
+-    return contents != nullptr;
+-  }
+-private:
+-  const T *contents;
+-};
+-
+-/**
+- * Array, like UnsizedArray, is a way to access raw arrays of data in memory.
+- * Unlike UnsizedArray, it has a known length, and is enumerable with an
+- * iterator.
+- *
+- *   struct S { ... };
+- *   Array<S> a(buf, len);
+- *   UnsizedArray<S> b; b.Init(buf, len);
+- *
+- * In the above examples, len is the number of elements in the array. It is
+- * also possible to initialize an Array with the buffer size:
+- *
+- *   Array<S> c; c.InitSize(buf, size);
+- *
+- * It is also possible to initialize an Array in two steps, only providing
+- * one data at a time:
+- *
+- *   Array<S> d;
+- *   d.Init(buf);
+- *   d.Init(len); // or d.InitSize(size);
+- *
+- */
+-template <typename T>
+-class Array: public UnsizedArray<T>
+-{
+-public:
+-  typedef typename UnsizedArray<T>::idx_t idx_t;
+-
+-  /**
+-   * Constructors and Initializers
+-   */
+-  Array(): UnsizedArray<T>(), length(0) { }
+-  Array(const void *buf, const idx_t length)
+-  : UnsizedArray<T>(buf), length(length) { }
+-
+-  void Init(const void *buf)
+-  {
+-    UnsizedArray<T>::Init(buf);
+-  }
+-
+-  void Init(const idx_t len)
+-  {
+-    MOZ_ASSERT(length == 0);
+-    length = len;
+-  }
+-
+-  void InitSize(const idx_t size)
+-  {
+-    Init(size / sizeof(T));
+-  }
+-
+-  void Init(const void *buf, const idx_t len)
+-  {
+-    UnsizedArray<T>::Init(buf);
+-    Init(len);
+-  }
+-
+-  void InitSize(const void *buf, const idx_t size)
+-  {
+-    UnsizedArray<T>::Init(buf);
+-    InitSize(size);
+-  }
+-
+-  /**
+-   * Returns the nth element of the array
+-   */
+-  const T &operator[](const idx_t index) const
+-  {
+-    MOZ_ASSERT(index < length);
+-    MOZ_ASSERT(operator bool());
+-    return UnsizedArray<T>::operator[](index);
+-  }
+-
+-  /**
+-   * Returns the number of elements in the array
+-   */
+-  idx_t numElements() const
+-  {
+-    return length;
+-  }
+-
+-  /**
+-   * Returns whether the array points somewhere and has at least one element.
+-   */
+-  operator bool() const
+-  {
+-    return (length > 0) && UnsizedArray<T>::operator bool();
+-  }
+-
+-  /**
+-   * Iterator for an Array. Use is similar to that of STL const_iterators:
+-   *
+-   *   struct S { ... };
+-   *   Array<S> a(buf, len);
+-   *   for (Array<S>::iterator it = a.begin(); it < a.end(); ++it) {
+-   *     // Do something with *it.
+-   *   }
+-   */
+-  class iterator
+-  {
+-  public:
+-    iterator(): item(nullptr) { }
+-
+-    const T &operator *() const
+-    {
+-      return *item;
+-    }
+-
+-    const T *operator ->() const
+-    {
+-      return item;
+-    }
+-
+-    iterator &operator ++()
+-    {
+-      ++item;
+-      return *this;
+-    }
+-
+-    bool operator<(const iterator &other) const
+-    {
+-      return item < other.item;
+-    }
+-  protected:
+-    friend class Array<T>;
+-    iterator(const T &item): item(&item) { }
+-
+-  private:
+-    const T *item;
+-  };
+-
+-  /**
+-   * Returns an iterator pointing at the beginning of the Array
+-   */
+-  iterator begin() const {
+-    if (length)
+-      return iterator(UnsizedArray<T>::operator[](0));
+-    return iterator();
+-  }
+-
+-  /**
+-   * Returns an iterator pointing past the end of the Array
+-   */
+-  iterator end() const {
+-    if (length)
+-      return iterator(UnsizedArray<T>::operator[](length));
+-    return iterator();
+-  }
+-
+-  /**
+-   * Reverse iterator for an Array. Use is similar to that of STL
+-   * const_reverse_iterators:
+-   *
+-   *   struct S { ... };
+-   *   Array<S> a(buf, len);
+-   *   for (Array<S>::reverse_iterator it = a.rbegin(); it < a.rend(); ++it) {
+-   *     // Do something with *it.
+-   *   }
+-   */
+-  class reverse_iterator
+-  {
+-  public:
+-    reverse_iterator(): item(nullptr) { }
+-
+-    const T &operator *() const
+-    {
+-      const T *tmp = item;
+-      return *--tmp;
+-    }
+-
+-    const T *operator ->() const
+-    {
+-      return &operator*();
+-    }
+-
+-    reverse_iterator &operator ++()
+-    {
+-      --item;
+-      return *this;
+-    }
+-
+-    bool operator<(const reverse_iterator &other) const
+-    {
+-      return item > other.item;
+-    }
+-  protected:
+-    friend class Array<T>;
+-    reverse_iterator(const T &item): item(&item) { }
+-
+-  private:
+-    const T *item;
+-  };
+-
+-  /**
+-   * Returns a reverse iterator pointing at the end of the Array
+-   */
+-  reverse_iterator rbegin() const {
+-    if (length)
+-      return reverse_iterator(UnsizedArray<T>::operator[](length));
+-    return reverse_iterator();
+-  }
+-
+-  /**
+-   * Returns a reverse iterator pointing past the beginning of the Array
+-   */
+-  reverse_iterator rend() const {
+-    if (length)
+-      return reverse_iterator(UnsizedArray<T>::operator[](0));
+-    return reverse_iterator();
+-  }
+-private:
+-  idx_t length;
+-};
+-
+-/**
+- * Transforms a pointer-to-function to a pointer-to-object pointing at the
+- * same address.
+- */
+-template <typename T>
+-void *FunctionPtr(T func)
+-{
+-  union {
+-    void *ptr;
+-    T func;
+-  } f;
+-  f.func = func;
+-  return f.ptr;
+-}
+-
+-class AutoLock {
+-public:
+-  AutoLock(pthread_mutex_t *mutex): mutex(mutex)
+-  {
+-    if (pthread_mutex_lock(mutex))
+-      MOZ_CRASH("pthread_mutex_lock failed");
+-  }
+-  ~AutoLock()
+-  {
+-    if (pthread_mutex_unlock(mutex))
+-      MOZ_CRASH("pthread_mutex_unlock failed");
+-  }
+-private:
+-  pthread_mutex_t *mutex;
+-};
+-
+-#endif /* Utils_h */
+-
+diff --git a/mozglue/linker/XZStream.cpp b/mozglue/linker/XZStream.cpp
+deleted file mode 100644
+--- a/mozglue/linker/XZStream.cpp
++++ /dev/null
+@@ -1,237 +0,0 @@
+-#include "XZStream.h"
+-
+-#include <algorithm>
+-#include "mozilla/Assertions.h"
+-#include "mozilla/CheckedInt.h"
+-#include "Logging.h"
+-
+-// LZMA dictionary size, should have a minimum size for the given compression
+-// rate, see XZ Utils docs for details.
+-static const uint32_t kDictSize = 1 << 24;
+-
+-static const size_t kFooterSize = 12;
+-
+-// Parses a variable-length integer (VLI),
+-// see http://tukaani.org/xz/xz-file-format.txt for details.
+-static size_t
+-ParseVarLenInt(const uint8_t* aBuf, size_t aBufSize, uint64_t* aValue)
+-{
+-  if (!aBufSize) {
+-    return 0;
+-  }
+-  aBufSize = std::min(size_t(9), aBufSize);
+-
+-  *aValue = aBuf[0] & 0x7F;
+-  size_t i = 0;
+-
+-  while (aBuf[i++] & 0x80) {
+-    if (i >= aBufSize || aBuf[i] == 0x0) {
+-      return 0;
+-    }
+-    *aValue |= static_cast<uint64_t>(aBuf[i] & 0x7F) << (i * 7);
+-  }
+-  return i;
+-}
+-
+-/* static */ bool
+-XZStream::IsXZ(const void* aBuf, size_t aBufSize)
+-{
+-  static const uint8_t kXzMagic[] = {0xfd, '7', 'z', 'X', 'Z', 0x0};
+-  MOZ_ASSERT(aBuf);
+-  return aBufSize > sizeof(kXzMagic) &&
+-         !memcmp(reinterpret_cast<const void*>(kXzMagic), aBuf, sizeof(kXzMagic));
+-}
+-
+-XZStream::XZStream(const void* aInBuf, size_t aInSize)
+-  : mInBuf(static_cast<const uint8_t*>(aInBuf))
+-  , mUncompSize(0)
+-  , mDec(nullptr)
+-{
+-  mBuffers.in = mInBuf;
+-  mBuffers.in_pos = 0;
+-  mBuffers.in_size = aInSize;
+-}
+-
+-XZStream::~XZStream()
+-{
+-  xz_dec_end(mDec);
+-}
+-
+-bool
+-XZStream::Init()
+-{
+-#ifdef XZ_USE_CRC64
+-  xz_crc64_init();
+-#endif
+-  xz_crc32_init();
+-
+-  mDec = xz_dec_init(XZ_DYNALLOC, kDictSize);
+-
+-  if (!mDec) {
+-    return false;
+-  }
+-
+-  mUncompSize = ParseUncompressedSize();
+-  if (!mUncompSize) {
+-    return false;
+-  }
+-
+-  return true;
+-}
+-
+-size_t
+-XZStream::Decode(void* aOutBuf, size_t aOutSize)
+-{
+-  if (!mDec) {
+-    return 0;
+-  }
+-
+-  mBuffers.out = static_cast<uint8_t*>(aOutBuf);
+-  mBuffers.out_pos = 0;
+-  mBuffers.out_size = aOutSize;
+-
+-  while (mBuffers.in_pos < mBuffers.in_size &&
+-         mBuffers.out_pos < mBuffers.out_size) {
+-    const xz_ret ret = xz_dec_run(mDec, &mBuffers);
+-
+-    switch (ret) {
+-      case XZ_STREAM_END:
+-        // Stream ended, the next loop iteration should terminate.
+-        MOZ_ASSERT(mBuffers.in_pos == mBuffers.in_size);
+-        MOZ_FALLTHROUGH;
+-#ifdef XZ_DEC_ANY_CHECK
+-      case XZ_UNSUPPORTED_CHECK:
+-        // Ignore unsupported check.
+-        MOZ_FALLTHROUGH;
+-#endif
+-      case XZ_OK:
+-        // Chunk decoded, proceed.
+-        break;
+-
+-      case XZ_MEM_ERROR:
+-        ERROR("XZ decoding: memory allocation failed");
+-        return 0;
+-
+-      case XZ_MEMLIMIT_ERROR:
+-        ERROR("XZ decoding: memory usage limit reached");
+-        return 0;
+-
+-      case XZ_FORMAT_ERROR:
+-        ERROR("XZ decoding: invalid stream format");
+-        return 0;
+-
+-      case XZ_OPTIONS_ERROR:
+-        ERROR("XZ decoding: unsupported header options");
+-        return 0;
+-
+-      case XZ_DATA_ERROR:
+-        MOZ_FALLTHROUGH;
+-      case XZ_BUF_ERROR:
+-        ERROR("XZ decoding: corrupt input stream");
+-        return 0;
+-
+-      default:
+-        MOZ_ASSERT_UNREACHABLE("XZ decoding: unknown error condition");
+-        return 0;
+-    }
+-  }
+-  return mBuffers.out_pos;
+-}
+-
+-size_t
+-XZStream::RemainingInput() const
+-{
+-  return mBuffers.in_size - mBuffers.in_pos;
+-}
+-
+-size_t
+-XZStream::Size() const
+-{
+-  return mBuffers.in_size;
+-}
+-
+-size_t
+-XZStream::UncompressedSize() const
+-{
+-  return mUncompSize;
+-}
+-
+-size_t
+-XZStream::ParseIndexSize() const
+-{
+-  static const uint8_t kFooterMagic[] = {'Y', 'Z'};
+-
+-  const uint8_t* footer = mInBuf + mBuffers.in_size - kFooterSize;
+-  // The magic bytes are at the end of the footer.
+-  if (memcmp(reinterpret_cast<const void*>(kFooterMagic),
+-             footer + kFooterSize - sizeof(kFooterMagic),
+-             sizeof(kFooterMagic))) {
+-    // Not a valid footer at stream end.
+-    ERROR("XZ parsing: Invalid footer at end of stream");
+-    return 0;
+-  }
+-  // Backward size is a 32 bit LE integer field positioned after the 32 bit CRC32
+-  // code. It encodes the index size as a multiple of 4 bytes with a minimum
+-  // size of 4 bytes.
+-  const uint32_t backwardSizeRaw = *(footer + 4);
+-  // Check for overflow.
+-  mozilla::CheckedInt<size_t> backwardSizeBytes(backwardSizeRaw);
+-  backwardSizeBytes = (backwardSizeBytes + 1) * 4;
+-  if (!backwardSizeBytes.isValid()) {
+-    ERROR("XZ parsing: Cannot parse index size");
+-    return 0;
+-  }
+-  return backwardSizeBytes.value();
+-}
+-
+-size_t
+-XZStream::ParseUncompressedSize() const
+-{
+-  static const uint8_t kIndexIndicator[] = {0x0};
+-
+-  const size_t indexSize = ParseIndexSize();
+-  if (!indexSize) {
+-    return 0;
+-  }
+-  // The footer follows directly the index, so we can use it as a reference.
+-  const uint8_t* end = mInBuf + mBuffers.in_size;
+-  const uint8_t* index = end - kFooterSize - indexSize;
+-
+-  // The xz stream index consists of three concatenated elements:
+-  //  (1) 1 byte indicator (always OxOO)
+-  //  (2) a Variable Length Integer (VLI) field for the number of records
+-  //  (3) a list of records
+-  // See https://tukaani.org/xz/xz-file-format-1.0.4.txt
+-  // Each record contains a VLI field for unpadded size followed by a var field for
+-  // uncompressed size. We only support xz streams with a single record.
+-
+-  if (memcmp(reinterpret_cast<const void*>(kIndexIndicator),
+-             index, sizeof(kIndexIndicator))) {
+-    ERROR("XZ parsing: Invalid stream index");
+-    return 0;
+-  }
+-
+-  index += sizeof(kIndexIndicator);
+-  uint64_t numRecords = 0;
+-  index += ParseVarLenInt(index, end - index, &numRecords);
+-  // Only streams with a single record are supported.
+-  if (numRecords != 1) {
+-    ERROR("XZ parsing: Multiple records not supported");
+-    return 0;
+-  }
+-  uint64_t unpaddedSize = 0;
+-  index += ParseVarLenInt(index, end - index, &unpaddedSize);
+-  if (!unpaddedSize) {
+-    ERROR("XZ parsing: Unpadded size is 0");
+-    return 0;
+-  }
+-  uint64_t uncompressedSize = 0;
+-  index += ParseVarLenInt(index, end - index, &uncompressedSize);
+-  mozilla::CheckedInt<size_t> checkedSize(uncompressedSize);
+-  if (!checkedSize.isValid()) {
+-    ERROR("XZ parsing: Uncompressed stream size is too large");
+-    return 0;
+-  }
+-
+-  return checkedSize.value();
+-}
+diff --git a/mozglue/linker/XZStream.h b/mozglue/linker/XZStream.h
+deleted file mode 100644
+--- a/mozglue/linker/XZStream.h
++++ /dev/null
+@@ -1,49 +0,0 @@
+-/* 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/. */
+-
+-#ifndef XZSTREAM_h
+-#define XZSTREAM_h
+-
+-#include <cstdlib>
+-#include <stdint.h>
+-
+-#define XZ_DEC_DYNALLOC
+-#include "xz.h"
+-
+-// Used to decode XZ stream buffers.
+-class XZStream
+-{
+-public:
+-  // Returns whether the provided buffer is likely a XZ stream.
+-  static bool IsXZ(const void* aBuf, size_t aBufSize);
+-
+-  // Creates a XZ stream object for the given input buffer.
+-  XZStream(const void* aInBuf, size_t aInSize);
+-  ~XZStream();
+-
+-  // Initializes the decoder and returns whether decoding may commence.
+-  bool Init();
+-  // Decodes the next chunk of input into the given output buffer.
+-  size_t Decode(void* aOutBuf, size_t aOutSize);
+-  // Returns the number of yet undecoded bytes in the input buffer.
+-  size_t RemainingInput() const;
+-  // Returns the total number of bytes in the input buffer (compressed size).
+-  size_t Size() const;
+-  // Returns the expected final number of bytes in the output buffer.
+-  // Note: will return 0 before successful Init().
+-  size_t UncompressedSize() const;
+-
+-private:
+-  // Parses the stream footer and returns the size of the index in bytes.
+-  size_t ParseIndexSize() const;
+-  // Parses the stream index and returns the expected uncompressed size in bytes.
+-  size_t ParseUncompressedSize() const;
+-
+-  const uint8_t* mInBuf;
+-  size_t mUncompSize;
+-  xz_buf mBuffers;
+-  xz_dec* mDec;
+-};
+-
+-#endif // XZSTREAM_h
+diff --git a/mozglue/linker/Zip.cpp b/mozglue/linker/Zip.cpp
+deleted file mode 100644
+--- a/mozglue/linker/Zip.cpp
++++ /dev/null
+@@ -1,230 +0,0 @@
+-/* 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 <sys/mman.h>
+-#include <sys/stat.h>
+-#include <fcntl.h>
+-#include <errno.h>
+-#include <unistd.h>
+-#include <cstdlib>
+-#include <algorithm>
+-#include "Logging.h"
+-#include "Zip.h"
+-
+-already_AddRefed<Zip>
+-Zip::Create(const char *filename)
+-{
+-  /* Open and map the file in memory */
+-  AutoCloseFD fd(open(filename, O_RDONLY));
+-  if (fd == -1) {
+-    ERROR("Error opening %s: %s", filename, strerror(errno));
+-    return nullptr;
+-  }
+-  struct stat st;
+-  if (fstat(fd, &st) == -1) {
+-    ERROR("Error stating %s: %s", filename, strerror(errno));
+-    return nullptr;
+-  }
+-  size_t size = st.st_size;
+-  if (size <= sizeof(CentralDirectoryEnd)) {
+-    ERROR("Error reading %s: too short", filename);
+-    return nullptr;
+-  }
+-  void *mapped = mmap(nullptr, size, PROT_READ, MAP_SHARED, fd, 0);
+-  if (mapped == MAP_FAILED) {
+-    ERROR("Error mmapping %s: %s", filename, strerror(errno));
+-    return nullptr;
+-  }
+-  DEBUG_LOG("Mapped %s @%p", filename, mapped);
+-
+-  return Create(filename, mapped, size);
+-}
+-
+-already_AddRefed<Zip>
+-Zip::Create(const char *filename, void *mapped, size_t size)
+-{
+-  RefPtr<Zip> zip = new Zip(filename, mapped, size);
+-
+-  // If neither the first Local File entry nor central directory entries
+-  // have been found, the zip was invalid.
+-  if (!zip->nextFile && !zip->entries) {
+-    ERROR("%s - Invalid zip", filename);
+-    return nullptr;
+-  }
+-
+-  ZipCollection::Singleton.Register(zip);
+-  return zip.forget();
+-}
+-
+-Zip::Zip(const char *filename, void *mapped, size_t size)
+-: name(filename ? strdup(filename) : nullptr)
+-, mapped(mapped)
+-, size(size)
+-, nextFile(LocalFile::validate(mapped)) // first Local File entry
+-, nextDir(nullptr)
+-, entries(nullptr)
+-{
+-  pthread_mutex_init(&mutex, nullptr);
+-  // If the first local file entry couldn't be found (which can happen
+-  // with optimized jars), check the first central directory entry.
+-  if (!nextFile)
+-    GetFirstEntry();
+-}
+-
+-Zip::~Zip()
+-{
+-  if (name) {
+-    munmap(mapped, size);
+-    DEBUG_LOG("Unmapped %s @%p", name, mapped);
+-    free(name);
+-  }
+-  pthread_mutex_destroy(&mutex);
+-}
+-
+-bool
+-Zip::GetStream(const char *path, Zip::Stream *out) const
+-{
+-  AutoLock lock(&mutex);
+-
+-  DEBUG_LOG("%s - GetFile %s", name, path);
+-  /* Fast path: if the Local File header on store matches, we can return the
+-   * corresponding stream right away.
+-   * However, the Local File header may not contain enough information, in
+-   * which case the 3rd bit on the generalFlag is set. Unfortunately, this
+-   * bit is also set in some archives even when we do have the data (most
+-   * notably the android packages as built by the Mozilla build system).
+-   * So instead of testing the generalFlag bit, only use the fast path when
+-   * we haven't read the central directory entries yet, and when the
+-   * compressed size as defined in the header is not filled (which is a
+-   * normal condition for the bit to be set). */
+-  if (nextFile && nextFile->GetName().Equals(path) &&
+-      !entries && (nextFile->compressedSize != 0)) {
+-    DEBUG_LOG("%s - %s was next file: fast path", name, path);
+-    /* Fill Stream info from Local File header content */
+-    const char *data = reinterpret_cast<const char *>(nextFile->GetData());
+-    out->compressedBuf = data;
+-    out->compressedSize = nextFile->compressedSize;
+-    out->uncompressedSize = nextFile->uncompressedSize;
+-    out->CRC32 = nextFile->CRC32;
+-    out->type = static_cast<Stream::Type>(uint16_t(nextFile->compression));
+-
+-    /* Find the next Local File header. It is usually simply following the
+-     * compressed stream, but in cases where the 3rd bit of the generalFlag
+-     * is set, there is a Data Descriptor header before. */
+-    data += nextFile->compressedSize;
+-    if ((nextFile->generalFlag & 0x8) && DataDescriptor::validate(data)) {
+-      data += sizeof(DataDescriptor);
+-    }
+-    nextFile = LocalFile::validate(data);
+-    return true;
+-  }
+-
+-  /* If the directory entry we have in store doesn't match, scan the Central
+-   * Directory for the entry corresponding to the given path */
+-  if (!nextDir || !nextDir->GetName().Equals(path)) {
+-    const DirectoryEntry *entry = GetFirstEntry();
+-    DEBUG_LOG("%s - Scan directory entries in search for %s", name, path);
+-    while (entry && !entry->GetName().Equals(path)) {
+-      entry = entry->GetNext();
+-    }
+-    nextDir = entry;
+-  }
+-  if (!nextDir) {
+-    DEBUG_LOG("%s - Couldn't find %s", name, path);
+-    return false;
+-  }
+-
+-  /* Find the Local File header corresponding to the Directory entry that
+-   * was found. */
+-  nextFile = LocalFile::validate(static_cast<const char *>(mapped)
+-                             + nextDir->offset);
+-  if (!nextFile) {
+-    ERROR("%s - Couldn't find the Local File header for %s", name, path);
+-    return false;
+-  }
+-
+-  /* Fill Stream info from Directory entry content */
+-  const char *data = reinterpret_cast<const char *>(nextFile->GetData());
+-  out->compressedBuf = data;
+-  out->compressedSize = nextDir->compressedSize;
+-  out->uncompressedSize = nextDir->uncompressedSize;
+-  out->CRC32 = nextDir->CRC32;
+-  out->type = static_cast<Stream::Type>(uint16_t(nextDir->compression));
+-
+-  /* Store the next directory entry */
+-  nextDir = nextDir->GetNext();
+-  nextFile = nullptr;
+-  return true;
+-}
+-
+-const Zip::DirectoryEntry *
+-Zip::GetFirstEntry() const
+-{
+-  if (entries)
+-    return entries;
+-
+-  const CentralDirectoryEnd *end = nullptr;
+-  const char *_end = static_cast<const char *>(mapped) + size
+-                     - sizeof(CentralDirectoryEnd);
+-
+-  /* Scan for the Central Directory End */
+-  for (; _end > mapped && !end; _end--)
+-    end = CentralDirectoryEnd::validate(_end);
+-  if (!end) {
+-    ERROR("%s - Couldn't find end of central directory record", name);
+-    return nullptr;
+-  }
+-
+-  entries = DirectoryEntry::validate(static_cast<const char *>(mapped)
+-                                 + end->offset);
+-  if (!entries) {
+-    ERROR("%s - Couldn't find central directory record", name);
+-  }
+-  return entries;
+-}
+-
+-ZipCollection ZipCollection::Singleton;
+-
+-static pthread_mutex_t sZipCollectionMutex = PTHREAD_MUTEX_INITIALIZER;
+-
+-already_AddRefed<Zip>
+-ZipCollection::GetZip(const char *path)
+-{
+-  {
+-    AutoLock lock(&sZipCollectionMutex);
+-    /* Search the list of Zips we already have for a match */
+-    for (const auto& zip: Singleton.zips) {
+-      if (zip->GetName() && (strcmp(zip->GetName(), path) == 0)) {
+-        return RefPtr<Zip>(zip).forget();
+-      }
+-    }
+-  }
+-  return Zip::Create(path);
+-}
+-
+-void
+-ZipCollection::Register(Zip *zip)
+-{
+-  AutoLock lock(&sZipCollectionMutex);
+-  DEBUG_LOG("ZipCollection::Register(\"%s\")", zip->GetName());
+-  Singleton.zips.push_back(zip);
+-}
+-
+-void
+-ZipCollection::Forget(const Zip *zip)
+-{
+-  AutoLock lock(&sZipCollectionMutex);
+-  if (zip->refCount() > 1) {
+-    // Someone has acquired a reference before we had acquired the lock,
+-    // ignore this request.
+-    return;
+-  }
+-  DEBUG_LOG("ZipCollection::Forget(\"%s\")", zip->GetName());
+-  const auto it = std::find(Singleton.zips.begin(), Singleton.zips.end(), zip);
+-  if (*it == zip) {
+-    Singleton.zips.erase(it);
+-  } else {
+-    DEBUG_LOG("ZipCollection::Forget: didn't find \"%s\" in bookkeeping", zip->GetName());
+-  }
+-}
+diff --git a/mozglue/linker/Zip.h b/mozglue/linker/Zip.h
+deleted file mode 100644
+--- a/mozglue/linker/Zip.h
++++ /dev/null
+@@ -1,536 +0,0 @@
+-/* 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/. */
+-
+-#ifndef Zip_h
+-#define Zip_h
+-
+-#include <cstring>
+-#include <stdint.h>
+-#include <vector>
+-#include <zlib.h>
+-#include <pthread.h>
+-#include "Utils.h"
+-#include "mozilla/Assertions.h"
+-#include "mozilla/RefCounted.h"
+-#include "mozilla/RefPtr.h"
+-
+-/**
+- * Helper class wrapping z_stream to avoid malloc() calls during
+- * inflate. Do not use for deflate.
+- * inflateInit allocates two buffers:
+- * - one for its internal state, which is "approximately 10K bytes" according
+- *   to inflate.h from zlib.
+- * - one for the compression window, which depends on the window size passed
+- *   to inflateInit2, but is never greater than 32K (1 << MAX_WBITS).
+- * Those buffers are created at instantiation time instead of when calling
+- * inflateInit2. When inflateInit2 is called, it will call zxx_stream::Alloc
+- * to get both these buffers. zxx_stream::Alloc will choose one of the
+- * pre-allocated buffers depending on the requested size.
+- */
+-class zxx_stream: public z_stream
+-{
+-public:
+-  /* Forward declaration */
+-  class StaticAllocator;
+-
+-  explicit zxx_stream(StaticAllocator *allocator_=nullptr)
+-  : allocator(allocator_)
+-  {
+-    memset(this, 0, sizeof(z_stream));
+-    zalloc = Alloc;
+-    zfree = Free;
+-    opaque = this;
+-  }
+-
+-private:
+-  static void *Alloc(void *data, uInt items, uInt size)
+-  {
+-    zxx_stream *zStream = reinterpret_cast<zxx_stream *>(data);
+-    if (zStream->allocator) {
+-      return zStream->allocator->Alloc(items, size);
+-    }
+-    size_t buf_size = items * size;
+-    return ::operator new(buf_size);
+-  }
+-
+-  static void Free(void *data, void *ptr)
+-  {
+-    zxx_stream *zStream = reinterpret_cast<zxx_stream *>(data);
+-    if (zStream->allocator) {
+-      zStream->allocator->Free(ptr);
+-    } else {
+-      ::operator delete(ptr);
+-    }
+-  }
+-
+-  /**
+-   * Helper class for each buffer in StaticAllocator.
+-   */
+-  template <size_t Size>
+-  class ZStreamBuf
+-  {
+-  public:
+-    ZStreamBuf() : inUse(false) { }
+-
+-    bool get(char*& out)
+-    {
+-      if (!inUse) {
+-        inUse = true;
+-        out = buf;
+-        return true;
+-      } else {
+-        return false;
+-      }
+-    }
+-
+-    void Release()
+-    {
+-      memset(buf, 0, Size);
+-      inUse = false;
+-    }
+-
+-    bool Equals(const void *other) { return other == buf; }
+-
+-    static const size_t size = Size;
+-
+-  private:
+-    char buf[Size];
+-    bool inUse;
+-  };
+-
+-public:
+-  /**
+-   * Special allocator that uses static buffers to allocate from.
+-   */
+-  class StaticAllocator
+-  {
+-  public:
+-    void *Alloc(uInt items, uInt size)
+-    {
+-      if (items == 1 && size <= stateBuf1.size) {
+-        char* res = nullptr;
+-        if (stateBuf1.get(res) || stateBuf2.get(res)) {
+-          return res;
+-        }
+-        MOZ_CRASH("ZStreamBuf already in use");
+-      } else if (items * size == windowBuf1.size) {
+-        char* res = nullptr;
+-        if (windowBuf1.get(res) || windowBuf2.get(res)) {
+-          return res;
+-        }
+-        MOZ_CRASH("ZStreamBuf already in use");
+-      } else {
+-        MOZ_CRASH("No ZStreamBuf for allocation");
+-      }
+-    }
+-
+-    void Free(void *ptr)
+-    {
+-      if (stateBuf1.Equals(ptr)) {
+-        stateBuf1.Release();
+-      } else if (stateBuf2.Equals(ptr)) {
+-        stateBuf2.Release();
+-      }else if (windowBuf1.Equals(ptr)) {
+-        windowBuf1.Release();
+-      } else if (windowBuf2.Equals(ptr)) {
+-        windowBuf2.Release();
+-      } else {
+-        MOZ_CRASH("Pointer doesn't match a ZStreamBuf");
+-      }
+-    }
+-
+-    // 0x3000 is an arbitrary size above 10K.
+-    ZStreamBuf<0x3000> stateBuf1, stateBuf2;
+-    ZStreamBuf<1 << MAX_WBITS> windowBuf1, windowBuf2;
+-  };
+-
+-private:
+-  StaticAllocator *allocator;
+-};
+-
+-/**
+- * Forward declaration
+- */
+-class ZipCollection;
+-
+-/**
+- * Class to handle access to Zip archive streams. The Zip archive is mapped
+- * in memory, and streams are direct references to that mapped memory.
+- * Zip files are assumed to be correctly formed. No boundary checks are
+- * performed, which means hand-crafted malicious Zip archives can make the
+- * code fail in bad ways. However, since the only intended use is to load
+- * libraries from Zip archives, there is no interest in making this code
+- * safe, since the libraries could contain malicious code anyways.
+- */
+-class Zip: public mozilla::external::AtomicRefCounted<Zip>
+-{
+-public:
+-  MOZ_DECLARE_REFCOUNTED_TYPENAME(Zip)
+-  /**
+-   * Create a Zip instance for the given file name. Returns nullptr in case
+-   * of failure.
+-   */
+-  static already_AddRefed<Zip> Create(const char *filename);
+-
+-  /**
+-   * Create a Zip instance using the given buffer.
+-   */
+-  static already_AddRefed<Zip> Create(void *buffer, size_t size) {
+-    return Create(nullptr, buffer, size);
+-  }
+-
+-private:
+-  static already_AddRefed<Zip> Create(const char *filename,
+-                                           void *buffer, size_t size);
+-
+-  /**
+-   * Private constructor
+-   */
+-  Zip(const char *filename, void *buffer, size_t size);
+-
+-public:
+-  /**
+-   * Destructor
+-   */
+-  ~Zip();
+-
+-  /**
+-   * Class used to access Zip archive item streams
+-   */
+-  class Stream
+-  {
+-  public:
+-    /**
+-     * Stream types
+-     */
+-    enum Type {
+-      STORE = 0,
+-      DEFLATE = 8
+-    };
+-
+-    /**
+-     * Constructor
+-     */
+-    Stream(): compressedBuf(nullptr), compressedSize(0), uncompressedSize(0)
+-            , CRC32(0)
+-            , type(STORE) { }
+-
+-    /**
+-     * Getters
+-     */
+-    const void *GetBuffer() { return compressedBuf; }
+-    size_t GetSize() { return compressedSize; }
+-    size_t GetUncompressedSize() { return uncompressedSize; }
+-    size_t GetCRC32() { return CRC32; }
+-    Type GetType() { return type; }
+-
+-    /**
+-     * Returns a zxx_stream for use with inflate functions using the given
+-     * buffer as inflate output. The caller is expected to allocate enough
+-     * memory for the Stream uncompressed size.
+-     */
+-    zxx_stream GetZStream(void *buf)
+-    {
+-      zxx_stream zStream;
+-      zStream.avail_in = compressedSize;
+-      zStream.next_in = reinterpret_cast<Bytef *>(
+-                        const_cast<void *>(compressedBuf));
+-      zStream.avail_out = uncompressedSize;
+-      zStream.next_out = static_cast<Bytef *>(buf);
+-      return zStream;
+-    }
+-
+-  protected:
+-    friend class Zip;
+-    const void *compressedBuf;
+-    size_t compressedSize;
+-    size_t uncompressedSize;
+-    size_t CRC32;
+-    Type type;
+-  };
+-
+-  /**
+-   * Returns a stream from the Zip archive.
+-   */
+-  bool GetStream(const char *path, Stream *out) const;
+-
+-  /**
+-   * Returns the file name of the archive
+-   */
+-  const char *GetName() const
+-  {
+-    return name;
+-  }
+-
+-private:
+-  /* File name of the archive */
+-  char *name;
+-  /* Address where the Zip archive is mapped */
+-  void *mapped;
+-  /* Size of the archive */
+-  size_t size;
+-
+-  /**
+-   * Strings (file names, comments, etc.) in the Zip headers are NOT zero
+-   * terminated. This class is a helper around them.
+-   */
+-  class StringBuf
+-  {
+-  public:
+-    /**
+-     * Constructor
+-     */
+-    StringBuf(const char *buf, size_t length): buf(buf), length(length) { }
+-
+-    /**
+-     * Returns whether the string has the same content as the given zero
+-     * terminated string.
+-     */
+-    bool Equals(const char *str) const
+-    {
+-      return (strncmp(str, buf, length) == 0 && str[length] == '\0');
+-    }
+-
+-  private:
+-    const char *buf;
+-    size_t length;
+-  };
+-
+-/* All the following types need to be packed */
+-#pragma pack(1)
+-public:
+-  /**
+-   * A Zip archive is an aggregate of entities which all start with a
+-   * signature giving their type. This template is to be used as a base
+-   * class for these entities.
+-   */
+-  template <typename T>
+-  class SignedEntity
+-  {
+-  public:
+-    /**
+-     * Equivalent to reinterpret_cast<const T *>(buf), with an additional
+-     * check of the signature.
+-     */
+-    static const T *validate(const void *buf)
+-    {
+-      const T *ret = static_cast<const T *>(buf);
+-      if (ret->signature == T::magic)
+-        return ret;
+-      return nullptr;
+-    }
+-
+-    SignedEntity(uint32_t magic): signature(magic) { }
+-  private:
+-    le_uint32 signature;
+-  };
+-
+-private:
+-  /**
+-   * Header used to describe a Local File entry. The header is followed by
+-   * the file name and an extra field, then by the data stream.
+-   */
+-  struct LocalFile: public SignedEntity<LocalFile>
+-  {
+-    /* Signature for a Local File header */
+-    static const uint32_t magic = 0x04034b50;
+-
+-    /**
+-     * Returns the file name
+-     */
+-    StringBuf GetName() const
+-    {
+-      return StringBuf(reinterpret_cast<const char *>(this) + sizeof(*this),
+-                       filenameSize);
+-    }
+-
+-    /**
+-     * Returns a pointer to the data associated with this header
+-     */
+-    const void *GetData() const
+-    {
+-      return reinterpret_cast<const char *>(this) + sizeof(*this)
+-             + filenameSize + extraFieldSize;
+-    }
+-
+-    le_uint16 minVersion;
+-    le_uint16 generalFlag;
+-    le_uint16 compression;
+-    le_uint16 lastModifiedTime;
+-    le_uint16 lastModifiedDate;
+-    le_uint32 CRC32;
+-    le_uint32 compressedSize;
+-    le_uint32 uncompressedSize;
+-    le_uint16 filenameSize;
+-    le_uint16 extraFieldSize;
+-  };
+-
+-  /**
+-   * In some cases, when a zip archive is created, compressed size and CRC
+-   * are not known when writing the Local File header. In these cases, the
+-   * 3rd bit of the general flag in the Local File header is set, and there
+-   * is an additional header following the compressed data.
+-   */
+-  struct DataDescriptor: public SignedEntity<DataDescriptor>
+-  {
+-    /* Signature for a Data Descriptor header */
+-    static const uint32_t magic = 0x08074b50;
+-
+-    le_uint32 CRC32;
+-    le_uint32 compressedSize;
+-    le_uint32 uncompressedSize;
+-  };
+-
+-  /**
+-   * Header used to describe a Central Directory Entry. The header is
+-   * followed by the file name, an extra field, and a comment.
+-   */
+-  struct DirectoryEntry: public SignedEntity<DirectoryEntry>
+-  {
+-    /* Signature for a Central Directory Entry header */
+-    static const uint32_t magic = 0x02014b50;
+-
+-    /**
+-     * Returns the file name
+-     */
+-    StringBuf GetName() const
+-    {
+-      return StringBuf(reinterpret_cast<const char *>(this) + sizeof(*this),
+-                       filenameSize);
+-    }
+-
+-    /**
+-     * Returns  the Central Directory Entry following this one.
+-     */
+-    const DirectoryEntry *GetNext() const
+-    {
+-      return validate(reinterpret_cast<const char *>(this) + sizeof(*this)
+-                      + filenameSize + extraFieldSize + fileCommentSize);
+-    }
+-
+-    le_uint16 creatorVersion;
+-    le_uint16 minVersion;
+-    le_uint16 generalFlag;
+-    le_uint16 compression;
+-    le_uint16 lastModifiedTime;
+-    le_uint16 lastModifiedDate;
+-    le_uint32 CRC32;
+-    le_uint32 compressedSize;
+-    le_uint32 uncompressedSize;
+-    le_uint16 filenameSize;
+-    le_uint16 extraFieldSize;
+-    le_uint16 fileCommentSize;
+-    le_uint16 diskNum;
+-    le_uint16 internalAttributes;
+-    le_uint32 externalAttributes;
+-    le_uint32 offset;
+-  };
+-
+-  /**
+-   * Header used to describe the End of Central Directory Record.
+-   */
+-  struct CentralDirectoryEnd: public SignedEntity<CentralDirectoryEnd>
+-  {
+-    /* Signature for the End of Central Directory Record */
+-    static const uint32_t magic = 0x06054b50;
+-
+-    le_uint16 diskNum;
+-    le_uint16 startDisk;
+-    le_uint16 recordsOnDisk;
+-    le_uint16 records;
+-    le_uint32 size;
+-    le_uint32 offset;
+-    le_uint16 commentSize;
+-  };
+-#pragma pack()
+-
+-  /**
+-   * Returns the first Directory entry
+-   */
+-  const DirectoryEntry *GetFirstEntry() const;
+-
+-  /* Pointer to the Local File Entry following the last one GetStream() used.
+-   * This is used by GetStream to avoid scanning the Directory Entries when the
+-   * requested entry is that one. */
+-  mutable const LocalFile *nextFile;
+-
+-  /* Likewise for the next Directory entry */
+-  mutable const DirectoryEntry *nextDir;
+-
+-  /* Pointer to the Directory entries */
+-  mutable const DirectoryEntry *entries;
+-
+-  mutable pthread_mutex_t mutex;
+-};
+-
+-/**
+- * Class for bookkeeping Zip instances
+- */
+-class ZipCollection
+-{
+-public:
+-  static ZipCollection Singleton;
+-
+-  /**
+-   * Get a Zip instance for the given path. If there is an existing one
+-   * already, return that one, otherwise create a new one.
+-   */
+-  static already_AddRefed<Zip> GetZip(const char *path);
+-
+-protected:
+-  friend class Zip;
+-  friend class mozilla::detail::RefCounted<Zip, mozilla::detail::AtomicRefCount>;
+-
+-  /**
+-   * Register the given Zip instance. This method is meant to be called
+-   * by Zip::Create.
+-   */
+-  static void Register(Zip *zip);
+-
+-  /**
+-   * Forget about the given Zip instance. This method is meant to be called
+-   * by the Zip destructor.
+-   */
+-  static void Forget(const Zip *zip);
+-
+-private:
+-  /* Zip instances bookkept in this collection */
+-  std::vector<RefPtr<Zip>> zips;
+-};
+-
+-namespace mozilla {
+-namespace detail {
+-
+-template<>
+-inline void
+-RefCounted<Zip, AtomicRefCount>::Release() const
+-{
+-  MOZ_ASSERT(static_cast<int32_t>(mRefCnt) > 0);
+-  const auto count = --mRefCnt;
+-  if (count == 1) {
+-    // No external references are left, attempt to remove it from the collection.
+-    // If it's successfully removed from the collection, Release() will be called
+-    // with mRefCnt = 1, which will finally delete this zip.
+-    ZipCollection::Forget(static_cast<const Zip*>(this));
+-  } else if (count == 0) {
+-#ifdef DEBUG
+-    mRefCnt = detail::DEAD;
+-#endif
+-    delete static_cast<const Zip*>(this);
+-  }
+-}
+-
+-template<>
+-inline
+-RefCounted<Zip, AtomicRefCount>::~RefCounted()
+-{
+-  MOZ_ASSERT(mRefCnt == detail::DEAD);
+-}
+-
+-} // namespace detail
+-} // namespace mozilla
+-
+-
+-
+-#endif /* Zip_h */
+diff --git a/mozglue/linker/dladdr.h b/mozglue/linker/dladdr.h
+deleted file mode 100644
+--- a/mozglue/linker/dladdr.h
++++ /dev/null
+@@ -1,16 +0,0 @@
+-/* 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 <dlfcn.h>
+-
+-#ifndef HAVE_DLADDR
+-typedef struct {
+-  const char *dli_fname;
+-  void *dli_fbase;
+-  const char *dli_sname;
+-  void *dli_saddr;
+-} Dl_info;
+-extern int dladdr(void *addr, Dl_info *info) __attribute__((weak));
+-#define HAVE_DLADDR 1
+-#endif
+diff --git a/mozglue/linker/moz.build b/mozglue/linker/moz.build
+deleted file mode 100644
+--- a/mozglue/linker/moz.build
++++ /dev/null
+@@ -1,33 +0,0 @@
+-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+-# 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/.
+-
+-SOURCES += [
+-    'BaseElf.cpp',
+-    'CustomElf.cpp',
+-    'ElfLoader.cpp',
+-    'Mappable.cpp',
+-    'XZStream.cpp',
+-    'Zip.cpp',
+-]
+-
+-Library('linker')
+-
+-FINAL_LIBRARY = 'mozglue'
+-
+-DEFINES['IMPL_MFBT'] = True
+-
+-DisableStlWrapping()
+-
+-TEST_DIRS += ['tests']
+-
+-if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
+-    CXXFLAGS += ['-Wno-error=shadow']
+-
+-DEFINES['XZ_USE_CRC64'] = 1
+-
+-USE_LIBS += [
+-    'xz-embedded',
+-]
+diff --git a/mozglue/linker/tests/TestZip.cpp b/mozglue/linker/tests/TestZip.cpp
+deleted file mode 100644
+--- a/mozglue/linker/tests/TestZip.cpp
++++ /dev/null
+@@ -1,69 +0,0 @@
+-/* 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 <cstdio>
+-#include <unistd.h>
+-#include "Zip.h"
+-#include "mozilla/RefPtr.h"
+-
+-extern "C" void report_mapping() { }
+-extern "C" void delete_mapping() { }
+-
+-/**
+- * test.zip is a basic test zip file with a central directory. It contains
+- * four entries, in the following order:
+- * "foo", "bar", "baz", "qux".
+- * The entries are going to be read out of order.
+- */
+-const char *test_entries[] = {
+-  "baz", "foo", "bar", "qux"
+-};
+-
+-/**
+- * no_central_dir.zip is a hand crafted test zip with no central directory
+- * entries. The Zip reader is expected to be able to traverse these entries
+- * if requested in order, without reading a central directory
+- * - First entry is a file "a", STOREd.
+- * - Second entry is a file "b", STOREd, using a data descriptor. CRC is
+- *   unknown, but compressed and uncompressed sizes are known in the local
+- *   file header.
+- * - Third entry is a file "c", DEFLATEd, using a data descriptor. CRC,
+- *   compressed and uncompressed sizes are known in the local file header.
+- *   This is the kind of entry that can be found in a zip that went through
+- *   zipalign if it had a data descriptor originally.
+- * - Fourth entry is a file "d", STOREd.
+- */
+-const char *no_central_dir_entries[] = {
+-  "a", "b", "c", "d"
+-};
+-
+-int main(int argc, char *argv[])
+-{
+-  if (argc != 2) {
+-    fprintf(stderr, "TEST-FAIL | TestZip | Expecting the directory containing test Zips\n");
+-    return 1;
+-  }
+-  chdir(argv[1]);
+-  Zip::Stream s;
+-  RefPtr<Zip> z = ZipCollection::GetZip("test.zip");
+-  for (size_t i = 0; i < sizeof(test_entries) / sizeof(*test_entries); i++) {
+-    if (!z->GetStream(test_entries[i], &s)) {
+-      fprintf(stderr, "TEST-UNEXPECTED-FAIL | TestZip | test.zip: Couldn't get entry \"%s\"\n", test_entries[i]);
+-      return 1;
+-    }
+-  }
+-  fprintf(stderr, "TEST-PASS | TestZip | test.zip could be accessed fully\n");
+-
+-  z = ZipCollection::GetZip("no_central_dir.zip");
+-  for (size_t i = 0; i < sizeof(no_central_dir_entries)
+-                         / sizeof(*no_central_dir_entries); i++) {
+-    if (!z->GetStream(no_central_dir_entries[i], &s)) {
+-      fprintf(stderr, "TEST-UNEXPECTED-FAIL | TestZip | no_central_dir.zip: Couldn't get entry \"%s\"\n", no_central_dir_entries[i]);
+-      return 1;
+-    }
+-  }
+-  fprintf(stderr, "TEST-PASS | TestZip | no_central_dir.zip could be accessed in order\n");
+-
+-  return 0;
+-}
+diff --git a/mozglue/linker/tests/moz.build b/mozglue/linker/tests/moz.build
+deleted file mode 100644
+--- a/mozglue/linker/tests/moz.build
++++ /dev/null
+@@ -1,26 +0,0 @@
+-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+-# 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/.
+-
+-DIST_INSTALL = False
+-
+-SimplePrograms([
+-    'TestZip',
+-])
+-LOCAL_INCLUDES += ['..']
+-USE_LIBS += [
+-    'linker',
+-    'mfbt',
+-]
+-if CONFIG['ZLIB_IN_MOZGLUE']:
+-    USE_LIBS += [ 'modules_zlib_src' ]
+-else:
+-    OS_LIBS += CONFIG['MOZ_ZLIB_LIBS']
+-DisableStlWrapping()
+-
+-PYTHON_UNITTEST_MANIFESTS += ['python.ini']
+-
+-if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
+-    CXXFLAGS += ['-Wno-error=shadow']
+diff --git a/mozglue/linker/tests/no_central_dir.zip b/mozglue/linker/tests/no_central_dir.zip
+deleted file mode 100644
+index df882220d19f3da6c90426f5c6d998cf4d4ffc20..0000000000000000000000000000000000000000
+GIT binary patch
+literal 0
+Hc$@<O00001
+
+diff --git a/mozglue/linker/tests/python.ini b/mozglue/linker/tests/python.ini
+deleted file mode 100644
+--- a/mozglue/linker/tests/python.ini
++++ /dev/null
+@@ -1,4 +0,0 @@
+-[DEFAULT]
+-skip-if = python == 3
+-
+-[run_test_zip.py]
+diff --git a/mozglue/linker/tests/run_test_zip.py b/mozglue/linker/tests/run_test_zip.py
+deleted file mode 100644
+--- a/mozglue/linker/tests/run_test_zip.py
++++ /dev/null
+@@ -1,21 +0,0 @@
+-#!/usr/bin/env python
+-#
+-# Any copyright is dedicated to the Public Domain.
+-# http://creativecommons.org/publicdomain/zero/1.0/
+-
+-import buildconfig
+-import mozpack.path as mozpath
+-import mozunit
+-import subprocess
+-import unittest
+-
+-class TestZip(unittest.TestCase):
+-    def test_zip(self):
+-        srcdir = mozpath.dirname(__file__)
+-        relsrcdir = mozpath.relpath(srcdir, buildconfig.topsrcdir)
+-        test_bin = mozpath.join(buildconfig.topobjdir, relsrcdir,
+-                                'TestZip' + buildconfig.substs['BIN_SUFFIX'])
+-        self.assertEqual(0, subprocess.call([test_bin, srcdir]))
+-
+-if __name__ == '__main__':
+-    mozunit.main()
+diff --git a/mozglue/linker/tests/test.zip b/mozglue/linker/tests/test.zip
+deleted file mode 100644
+index 657835b0cac2fd84b1631590a4cf6b7181b78c60..0000000000000000000000000000000000000000
+GIT binary patch
+literal 0
+Hc$@<O00001
+
+diff --git a/mozglue/moz.build b/mozglue/moz.build
+--- a/mozglue/moz.build
++++ b/mozglue/moz.build
+@@ -2,18 +2,15 @@
+ # 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/.
+ 
+ with Files("**"):
+     BUG_COMPONENT = ("Core", "mozglue")
+ 
+-if CONFIG['MOZ_LINKER']:
+-    DIRS += ['linker']
+-
+ DIRS += [
+   'build',
+   'misc',
+ ]
+ 
+ if CONFIG['MOZ_WIDGET_TOOLKIT']:
+     TEST_DIRS += ['tests']
+diff --git a/old-configure.in b/old-configure.in
+--- a/old-configure.in
++++ b/old-configure.in
+@@ -601,20 +601,16 @@ case "$target" in
+     fi
+ 
+     MOZ_FIX_LINK_PATHS=
+     ;;
+ 
+ *-android*|*-linuxandroid*)
+     AC_DEFINE(NO_PW_GECOS)
+ 
+-    if test "$COMPILE_ENVIRONMENT"; then
+-        MOZ_LINKER=1
+-    fi
+-
+     MOZ_GFX_OPTIMIZE_MOBILE=1
+     if test -z "$CLANG_CC"; then
+         MOZ_OPTIMIZE_FLAGS="-freorder-blocks -fno-reorder-functions -Os"
+     else
+         # From https://github.com/android-ndk/ndk/issues/133#issuecomment-308549264
+         # -Oz is smaller than -Os on clang.
+         MOZ_OPTIMIZE_FLAGS="-Oz"
+     fi
+@@ -932,23 +928,16 @@ if test -z "$MOZ_OPTIMIZE_FLAGS"; then
+     MOZ_OPTIMIZE_FLAGS="-O"
+ fi
+ 
+ AC_SUBST_LIST(MMX_FLAGS)
+ AC_SUBST_LIST(SSE_FLAGS)
+ AC_SUBST_LIST(SSE2_FLAGS)
+ AC_SUBST_LIST(SSSE3_FLAGS)
+ 
+-AC_SUBST(MOZ_LINKER)
+-if test -n "$MOZ_LINKER"; then
+-  AC_DEFINE(MOZ_LINKER)
+-  MOZ_LINKER_EXTRACT=1
+-  AC_CHECK_PROGS(XZ, xz)
+-fi
+-
+ if test -z "$COMPILE_ENVIRONMENT"; then
+     SKIP_COMPILER_CHECKS=1
+     SKIP_LIBRARY_CHECKS=1
+     MOZ_DEBUGGING_OPTS
+ else
+     MOZ_COMPILER_OPTS
+ fi # COMPILE_ENVIRONMENT
+ 
+@@ -1390,17 +1379,17 @@ AC_CACHE_CHECK(for __thread keyword for 
+                ac_cv_thread_keyword,
+                [AC_TRY_LINK([__thread bool tlsIsMainThread = false;],
+                             [return tlsIsMainThread;],
+                             ac_cv_thread_keyword=yes,
+                             ac_cv_thread_keyword=no)])
+ LDFLAGS=$_SAVE_LDFLAGS
+ # The custom dynamic linker doesn't support TLS variables
+ MOZ_TLS=
+-if test "$ac_cv_thread_keyword" = yes -a "$MOZ_LINKER" != 1; then
++if test "$ac_cv_thread_keyword" = yes; then
+   # mips builds fail with TLS variables because of a binutils bug.
+   # See bug 528687
+   # OpenBSD doesn't have TLS support, and the test succeeds with clang++
+   case "${target}" in
+     mips*-*)
+       :
+       ;;
+     *-android*|*-linuxandroid*)
+@@ -1411,33 +1400,16 @@ if test "$ac_cv_thread_keyword" = yes -a
+       ;;
+     *)
+       AC_DEFINE(HAVE_THREAD_TLS_KEYWORD)
+       MOZ_TLS=1
+       ;;
+   esac
+ fi
+ 
+-dnl Using the custom linker on ARMv6 requires 16k alignment of ELF segments.
+-if test -n "$MOZ_LINKER"; then
+-  if test "$CPU_ARCH" = arm; then
+-    dnl When building for < ARMv7, we need to ensure 16k alignment of ELF segments
+-    if test -n "$ARM_ARCH" && test "$ARM_ARCH" -lt 7; then
+-      LDFLAGS="$LDFLAGS -Wl,-z,max-page-size=0x4000 -Wl,-z,common-page-size=0x4000"
+-      _SUBDIR_LDFLAGS="$_SUBDIR_LDFLAGS -Wl,-z,max-page-size=0x4000 -Wl,-z,common-page-size=0x4000"
+-    fi
+-  fi
+-
+-dnl gold emits wrong sysv-style elf hash tables when building both sysv and
+-dnl style tables. https://sourceware.org/bugzilla/show_bug.cgi?id=13597
+-dnl Since the linker only understands the sysv ones, no need to build the
+-dnl gnu style tables anyways.
+-  LDFLAGS="$LDFLAGS -Wl,--hash-style=sysv"
+-fi
+-
+ dnl End of C++ language/feature checks
+ AC_LANG_C
+ 
+ dnl ========================================================
+ dnl =  Internationalization checks
+ dnl ========================================================
+ dnl
+ dnl Internationalization and Locale support is different
+@@ -2482,17 +2454,17 @@ fi # COMPILE_ENVIRONMENT
+ dnl ========================================================
+ dnl =
+ dnl = Static Build Options
+ dnl =
+ dnl ========================================================
+ MOZ_ARG_HEADER(Static build options)
+ 
+ if test -z "$MOZ_SYSTEM_ZLIB"; then
+-if test -n "$JS_SHARED_LIBRARY" -o -n "$MOZ_LINKER"; then
++if test -n "$JS_SHARED_LIBRARY"; then
+   ZLIB_IN_MOZGLUE=1
+   AC_DEFINE(ZLIB_IN_MOZGLUE)
+ fi
+ fi
+ 
+ AC_SUBST(ZLIB_IN_MOZGLUE)
+ 
+ dnl ========================================================
+@@ -2741,17 +2713,16 @@ AC_SUBST(MOZ_ANDROID_APPLICATION_CLASS)
+ AC_SUBST(MOZ_ANDROID_BROWSER_INTENT_CLASS)
+ AC_SUBST(MOZ_EXCLUDE_HYPHENATION_DICTIONARIES)
+ AC_SUBST(STRIP_FLAGS)
+ AC_SUBST(INCREMENTAL_LINKER)
+ 
+ AC_SUBST_LIST(MOZ_FIX_LINK_PATHS)
+ 
+ AC_SUBST(MOZ_POST_PROGRAM_COMMAND)
+-AC_SUBST(MOZ_LINKER_EXTRACT)
+ 
+ if test -n "$MOZ_BINARY_EXTENSIONS"; then
+   AC_DEFINE(MOZ_BINARY_EXTENSIONS)
+ fi
+ 
+ AC_SUBST(MOZ_ADDON_SIGNING)
+ if test "$MOZ_ADDON_SIGNING" = 1; then
+   AC_DEFINE(MOZ_ADDON_SIGNING)
+diff --git a/testing/xpcshell/remotexpcshelltests.py b/testing/xpcshell/remotexpcshelltests.py
+--- a/testing/xpcshell/remotexpcshelltests.py
++++ b/testing/xpcshell/remotexpcshelltests.py
+@@ -341,17 +341,16 @@ class XPCShellRemote(xpcshell.XPCShellTe
+         self.device.pushFile(localWrapper, self.remoteClearDirScript)
+         os.remove(localWrapper)
+ 
+         self.device.chmodDir(self.remoteBinDir)
+ 
+     def buildEnvironment(self):
+         self.buildCoreEnvironment()
+         self.setLD_LIBRARY_PATH()
+-        self.env["MOZ_LINKER_CACHE"] = self.remoteBinDir
+         if self.options['localAPK'] and self.appRoot:
+             self.env["GRE_HOME"] = self.appRoot
+         self.env["XPCSHELL_TEST_PROFILE_DIR"] = self.profileDir
+         self.env["TMPDIR"] = self.remoteTmpDir
+         self.env["HOME"] = self.profileDir
+         self.env["XPCSHELL_TEST_TEMP_DIR"] = self.remoteTmpDir
+         self.env["XPCSHELL_MINIDUMP_DIR"] = self.remoteMinidumpDir
+         if self.options['setup']:
+diff --git a/toolkit/xre/nsAppRunner.cpp b/toolkit/xre/nsAppRunner.cpp
+--- a/toolkit/xre/nsAppRunner.cpp
++++ b/toolkit/xre/nsAppRunner.cpp
+@@ -275,20 +275,16 @@ nsString gAbsoluteArgv0Path;
+ #endif
+ #ifdef MOZ_X11
+ #include <gdk/gdkx.h>
+ #endif /* MOZ_X11 */
+ #include <fontconfig/fontconfig.h>
+ #endif
+ #include "BinaryPath.h"
+ 
+-#ifdef MOZ_LINKER
+-extern "C" MFBT_API bool IsSignalHandlingBroken();
+-#endif
+-
+ #ifdef FUZZING
+ #include "FuzzerRunner.h"
+ 
+ namespace mozilla {
+ FuzzerRunner* fuzzerRunner = 0;
+ } // namespace mozilla
+ 
+ #ifdef LIBFUZZER
+@@ -3343,21 +3339,16 @@ XREMain::XRE_mainInit(bool* aExitFlag)
+                                          nsDependentCString(mAppData->buildID));
+ 
+     nsDependentCString packageVersion(NS_STRINGIFY(MOZ_PKG_VERSION));
+     CrashReporter::AnnotateCrashReport(
+       CrashReporter::Annotation::PackageVersion, packageVersion);
+     nsDependentCString releaseChannel(NS_STRINGIFY(MOZ_UPDATE_CHANNEL));
+     CrashReporter::AnnotateCrashReport(
+       CrashReporter::Annotation::ReleaseChannel, releaseChannel);
+-#ifdef MOZ_LINKER
+-    CrashReporter::AnnotateCrashReport(
+-      CrashReporter::Annotation::CrashAddressLikelyWrong,
+-      IsSignalHandlingBroken());
+-#endif
+ 
+ #ifdef XP_WIN
+     nsAutoString appInitDLLs;
+     if (widget::WinUtils::GetAppInitDLLs(appInitDLLs)) {
+       CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::AppInitDLLs,
+                                          NS_ConvertUTF16toUTF8(appInitDLLs));
+     }
+ #endif
+diff --git a/tools/profiler/moz.build b/tools/profiler/moz.build
+--- a/tools/profiler/moz.build
++++ b/tools/profiler/moz.build
+@@ -80,17 +80,16 @@ if CONFIG['MOZ_GECKO_PROFILER']:
+         SOURCES += [
+             'core/shared-libraries-win32.cc',
+         ]
+ 
+     LOCAL_INCLUDES += [
+         '/caps',
+         '/docshell/base',
+         '/ipc/chromium/src',
+-        '/mozglue/linker',
+         '/toolkit/crashreporter/google-breakpad/src',
+         '/tools/profiler/core/',
+         '/tools/profiler/gecko/',
+         '/xpcom/base',
+     ]
+ 
+     if CONFIG['OS_TARGET'] == 'Android':
+         DEFINES['ANDROID_NDK_MAJOR_VERSION'] = CONFIG['ANDROID_NDK_MAJOR_VERSION']
+diff --git a/xpcom/glue/standalone/nsXPCOMGlue.cpp b/xpcom/glue/standalone/nsXPCOMGlue.cpp
+--- a/xpcom/glue/standalone/nsXPCOMGlue.cpp
++++ b/xpcom/glue/standalone/nsXPCOMGlue.cpp
+@@ -75,28 +75,16 @@ static void
+ CloseLibHandle(LibHandleType aLibHandle)
+ {
+   FreeLibrary(aLibHandle);
+ }
+ 
+ #else
+ #include <dlfcn.h>
+ 
+-#if defined(MOZ_LINKER)
+-extern "C" {
+-NS_HIDDEN __typeof(dlopen) __wrap_dlopen;
+-NS_HIDDEN __typeof(dlsym) __wrap_dlsym;
+-NS_HIDDEN __typeof(dlclose) __wrap_dlclose;
+-}
+-
+-#define dlopen __wrap_dlopen
+-#define dlsym __wrap_dlsym
+-#define dlclose __wrap_dlclose
+-#endif
+-
+ typedef void* LibHandleType;
+ 
+ static LibHandleType
+ GetLibHandle(pathstr_t aDependentLib)
+ {
+   LibHandleType libHandle = dlopen(aDependentLib,
+                                    RTLD_GLOBAL | RTLD_LAZY
+ #ifdef XP_MACOSX
+@@ -111,24 +99,22 @@ GetLibHandle(pathstr_t aDependentLib)
+ }
+ 
+ static NSFuncPtr
+ GetSymbol(LibHandleType aLibHandle, const char* aSymbol)
+ {
+   return (NSFuncPtr)dlsym(aLibHandle, aSymbol);
+ }
+ 
+-#ifndef MOZ_LINKER
+ static void
+ CloseLibHandle(LibHandleType aLibHandle)
+ {
+   dlclose(aLibHandle);
+ }
+ #endif
+-#endif
+ 
+ struct DependentLib
+ {
+   LibHandleType libHandle;
+   DependentLib* next;
+ };
+ 
+ static DependentLib* sTop;
+@@ -145,20 +131,18 @@ AppendDependentLib(LibHandleType aLibHan
+   d->libHandle = aLibHandle;
+ 
+   sTop = d;
+ }
+ 
+ static bool
+ ReadDependentCB(pathstr_t aDependentLib)
+ {
+-#ifndef MOZ_LINKER
+   // We do this unconditionally because of data in bug 771745
+   ReadAheadLib(aDependentLib);
+-#endif
+   LibHandleType libHandle = GetLibHandle(aDependentLib);
+   if (libHandle) {
+     AppendDependentLib(libHandle);
+   }
+ 
+   return libHandle;
+ }
+ 
+@@ -195,30 +179,28 @@ struct ScopedCloseFileTraits
+   {
+     if (aFile) {
+       fclose(aFile);
+     }
+   }
+ };
+ typedef Scoped<ScopedCloseFileTraits> ScopedCloseFile;
+ 
+-#ifndef MOZ_LINKER
+ static void
+ XPCOMGlueUnload()
+ {
+   while (sTop) {
+     CloseLibHandle(sTop->libHandle);
+ 
+     DependentLib* temp = sTop;
+     sTop = sTop->next;
+ 
+     delete temp;
+   }
+ }
+-#endif
+ 
+ #if defined(XP_WIN)
+ // like strpbrk but finds the *last* char, not the first
+ static const char*
+ ns_strrpbrk(const char* string, const char* strCharSet)
+ {
+   const char* found = nullptr;
+   for (; *string; ++string) {
+@@ -233,21 +215,16 @@ ns_strrpbrk(const char* string, const ch
+ 
+   return found;
+ }
+ #endif
+ 
+ static nsresult
+ XPCOMGlueLoad(const char* aXPCOMFile)
+ {
+-#ifdef MOZ_LINKER
+-  if (!ReadDependentCB(aXPCOMFile)) {
+-    return NS_ERROR_FAILURE;
+-  }
+-#else
+   char xpcomDir[MAXPATHLEN];
+ #ifdef XP_WIN
+   const char* lastSlash = ns_strrpbrk(aXPCOMFile, "/\\");
+ #elif XP_MACOSX
+   // On OSX, the dependentlibs.list file lives under Contents/Resources.
+   // However, the actual libraries listed in dependentlibs.list live under
+   // Contents/MacOS. We want to read the list from Contents/Resources, then
+   // load the libraries from Contents/MacOS.
+@@ -330,17 +307,16 @@ XPCOMGlueLoad(const char* aXPCOMFile)
+     }
+ 
+     strcpy(cursor, buffer);
+     if (!ReadDependentCB(xpcomDir)) {
+       XPCOMGlueUnload();
+       return NS_ERROR_FAILURE;
+     }
+   }
+-#endif
+   return NS_OK;
+ }
+ 
+ #if defined(MOZ_WIDGET_GTK) && (defined(MOZ_MEMORY) || defined(__FreeBSD__) || defined(__NetBSD__))
+ #define MOZ_GSLICE_INIT
+ #endif
+ 
+ #ifdef MOZ_GSLICE_INIT

+ 35 - 0
mozilla-release/patches/NOBUG-removessdks-25319.patch

@@ -0,0 +1,35 @@
+# HG changeset patch
+# User Frank-Rainer Grahl <frgrahl@gmx.net>
+# Date 1705406924 -3600
+# Parent  8dc104d0262ddbe0b48cff08d3132592240f50c9
+No Bug - Remove unsued sdks from build files. r=me a=me
+
+Leanplum and friends produce variables in config.status and are useless for us.
+We keep the underlying python functions generationg the variables for now.
+
+diff --git a/toolkit/moz.configure b/toolkit/moz.configure
+--- a/toolkit/moz.configure
++++ b/toolkit/moz.configure
+@@ -625,22 +625,16 @@ check_prog('GN', ('gn',), allow_missing=
+ include('../build/moz.configure/keyfiles.configure')
+ 
+ simple_keyfile('Mozilla API')
+ 
+ simple_keyfile('Google Location Service API')
+ 
+ simple_keyfile('Google Safebrowsing API')
+ 
+-id_and_secret_keyfile('Bing API')
+-
+-simple_keyfile('Adjust SDK')
+-
+-id_and_secret_keyfile('Leanplum SDK')
+-
+ # Servo integration
+ # ==============================================================
+ option('--enable-stylo', nargs='?', choices=('build', 'only'),
+        help='Include Stylo in the build.  "build" means to disable Stylo at ' +
+             'runtime, and "only" means to exclude the old style system from ' +
+             'the build.')
+ 
+ @depends('--enable-stylo', '--help')

+ 1 - 1
mozilla-release/patches/TOP-NOBUG-PLASTER-fix-strip-25319.patch

@@ -2,7 +2,7 @@
 # User Bill Gianopoulos <wgianopoulos@gmail.com>
 # Date 1702217928 0
 # Parent  c08a036551aeadedccd73f67ec02c70d0d01b742
-No Bug - Avoid package faiures on Windows with some strip otion combinations.
+No Bug - Avoid package faiures on Windows with some strip option combinations. r=me a=me
 
 diff --git a/js/src/old-configure.in b/js/src/old-configure.in
 --- a/js/src/old-configure.in

+ 6 - 6
mozilla-release/patches/TOP-NOBUG-REGEXP-28-1640592-78a1-25318.patch

@@ -1,7 +1,7 @@
 # HG changeset patch
 # User Dmitry Butskoy <buc@buc.me>
 # Date 1690630870 -7200
-# Parent  a2561eccfadd55fbbf7a1d759b0ceeba284910cd
+# Parent  6602be0e32a5b8e8ed8dac4322a30f6e7a337259
 No Bug - Import new regexp V8 engine. r=frg a=frg
 
 hawkeye116477 <hawkeye116477@gmail.com>
@@ -11,7 +11,8 @@ Bug 1640592: Add RegExpShared to update list
 diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp
 --- a/js/src/jsgc.cpp
 +++ b/js/src/jsgc.cpp
-@@ -2812,17 +2812,18 @@ static const AllocKinds UpdatePhaseMisc 
+@@ -2811,17 +2811,18 @@ GCRuntime::updateCellPointers(MovingTrac
+ static const AllocKinds UpdatePhaseMisc {
      AllocKind::SCRIPT,
      AllocKind::LAZY_SCRIPT,
      AllocKind::BASE_SHAPE,
@@ -19,18 +20,17 @@ diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp
      AllocKind::ACCESSOR_SHAPE,
      AllocKind::OBJECT_GROUP,
      AllocKind::STRING,
-     AllocKind::JITCODE,
--    AllocKind::SCOPE
-+    AllocKind::SCOPE,
+-    AllocKind::JITCODE
++    AllocKind::JITCODE,
 +    AllocKind::REGEXP_SHARED
  };
  
  static const AllocKinds UpdatePhaseObjects {
+     AllocKind::SCOPE,
      AllocKind::FUNCTION,
      AllocKind::FUNCTION_EXTENDED,
      AllocKind::OBJECT0,
      AllocKind::OBJECT0_BACKGROUND,
-     AllocKind::OBJECT2,
 diff --git a/js/src/vm/RegExpObject.cpp b/js/src/vm/RegExpObject.cpp
 --- a/js/src/vm/RegExpObject.cpp
 +++ b/js/src/vm/RegExpObject.cpp

+ 15 - 15
mozilla-release/patches/TOP-NOBUG-REGEXP-37-1642493-79a1-25318.patch

@@ -1,7 +1,7 @@
 # HG changeset patch
 # User Dmitry Butskoy <buc@buc.me>
 # Date 1690631112 -7200
-# Parent  3bf4903dd80a38b55137ddaf56b3b04c3d631e94
+# Parent  3608afa1789f2fbe9264ecb4d48af895485e8b56
 No Bug - Import new regexp V8 engine. r=frg a=frg
 
 diff --git a/.clang-format-ignore b/.clang-format-ignore
@@ -46,14 +46,14 @@ diff --git a/js/moz.configure b/js/moz.configure
 -set_define('ENABLE_NEW_REGEXP', enable_new_regexp)
 -
 -
- # ECMAScript Internationalization API Support (uses ICU)
- # ======================================================
- js_option('--with-system-icu', help='Use system ICU')
+ # Options for generating the shell as a script
+ # ============================================
+ js_option('--with-qemu-exe', nargs=1, help='Use path as an arm emulator on host platforms')
+ set_config('QEMU_EXE', depends_if('--with-qemu-exe')(lambda x: x))
  
- system_icu = pkg_check_modules('MOZ_ICU', 'icu-i18n >= 67.1', when='--with-system-icu')
- 
- set_config('MOZ_SYSTEM_ICU', True, when=system_icu)
- set_define('MOZ_SYSTEM_ICU', True, when=system_icu)
+ js_option('--with-cross-lib', nargs=1, default=depends(target.alias)(lambda x: '/usr/%s' % x),
+           help='Use dir as the location for arm libraries')
+ set_config('CROSS_LIB', depends_if('--with-cross-lib')(lambda x: x))
 diff --git a/js/src/.clang-format b/js/src/.clang-format
 --- a/js/src/.clang-format
 +++ b/js/src/.clang-format
@@ -228,7 +228,7 @@ diff --git a/js/src/builtin/TestingFunctions.cpp b/js/src/builtin/TestingFunctio
  #include "js/RegExpFlags.h"
  #include "js/StructuredClone.h"
  #include "js/UbiNode.h"
-@@ -4389,370 +4384,16 @@ GetModuleEnvironmentValue(JSContext* cx,
+@@ -4390,370 +4385,16 @@ GetModuleEnvironmentValue(JSContext* cx,
      if (args.rval().isMagic(JS_UNINITIALIZED_LEXICAL)) {
          ReportRuntimeLexicalError(cx, JSMSG_UNINITIALIZED_LEXICAL, id);
          return false;
@@ -599,7 +599,7 @@ diff --git a/js/src/builtin/TestingFunctions.cpp b/js/src/builtin/TestingFunctio
  
      if (args.length() != 0) {
          ReportUsageErrorASCII(cx, callee, "Wrong number of arguments");
-@@ -5785,26 +5426,16 @@ gc::ZealModeHelpText),
+@@ -5786,26 +5427,16 @@ gc::ZealModeHelpText),
  "    baselineCompile();  for (var i=0; i<1; i++) {} ...\n"
  "  The interpreter will enter the new jitcode at the loop header unless\n"
  "  baselineCompile returned a string or threw an error.\n"),
@@ -654,7 +654,7 @@ diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp
  #include "wasm/AsmJS.h"
  
  #include "frontend/ParseContext-inl.h"
-@@ -9325,24 +9320,19 @@ Parser<SyntaxParseHandler, CharT>::newRe
+@@ -9321,24 +9316,19 @@ Parser<SyntaxParseHandler, CharT>::newRe
                    "code below will need changing for UTF-8 handling");
  
      // Only check the regexp's syntax, but don't create a regexp object.
@@ -23846,7 +23846,7 @@ diff --git a/js/src/jit/CodeGenerator.cpp b/js/src/jit/CodeGenerator.cpp
  #include "vm/TraceLogging.h"
  #include "vm/TypedArrayObject.h"
  #include "vm/Unicode.h"
-@@ -1317,18 +1312,16 @@ UpdateRegExpStatics(MacroAssembler& masm
+@@ -1343,18 +1338,16 @@ UpdateRegExpStatics(MacroAssembler& masm
      masm.loadPtr(Address(regexp, NativeObject::getFixedSlotOffset(RegExpObject::PRIVATE_SLOT)),
                   temp1);
      masm.loadPtr(Address(temp1, RegExpShared::offsetOfSource()), temp2);
@@ -23865,7 +23865,7 @@ diff --git a/js/src/jit/CodeGenerator.cpp b/js/src/jit/CodeGenerator.cpp
  PrepareAndExecuteRegExp(JSContext* cx,
                          MacroAssembler& masm,
                          Register regexp,
-@@ -1495,181 +1488,16 @@ PrepareAndExecuteRegExp(JSContext* cx,
+@@ -1521,181 +1514,16 @@ PrepareAndExecuteRegExp(JSContext* cx,
                          temp2,
                          temp3,
                          // stringsCanBeInNursery,
@@ -24047,7 +24047,7 @@ diff --git a/js/src/jit/CodeGenerator.cpp b/js/src/jit/CodeGenerator.cpp
  {
      Register string_;
      Register temp_;
-@@ -1956,41 +1784,37 @@ JitCompartment::generateRegExpMatcherStu
+@@ -1981,41 +1809,37 @@ JitCompartment::generateRegExpMatcherStu
      Label notFound, oolEntry;
      if (!PrepareAndExecuteRegExp(cx, masm, regexp, input, lastIndex,
                                   temp1, temp2, temp5, inputOutputDataStartOffset,
@@ -43106,7 +43106,7 @@ diff --git a/js/src/vm/RegExpShared.h b/js/src/vm/RegExpShared.h
 diff --git a/js/src/vm/Runtime.h b/js/src/vm/Runtime.h
 --- a/js/src/vm/Runtime.h
 +++ b/js/src/vm/Runtime.h
-@@ -22,19 +22,16 @@
+@@ -23,19 +23,16 @@
  
  #include "builtin/AtomicsObject.h"
  #include "builtin/intl/SharedIntlData.h"

+ 161 - 159
mozilla-release/patches/series

@@ -5631,156 +5631,27 @@ NOBUG-removemobilethemes-25318.patch
 1837261-2-version-beta-mr-25318.patch
 1861842-version-release-mr-25318.patch
 1861843-1-version-prebeta-mr-25319.patch
-PPPPPPP-check_stdcxx-warn.patch
-PPPPPPP-NOBUG-PLASTER-getrandom.patch
-PPPPPPP-NSSgetentropy.patch
-TOP-1294490-7-PLASTER-webp-2535.patch
-TOP-1493400-6-PLASTER-dav1d-avoid-mColorDepth-2535.patch
-TOP-1445683-14-PLASTER-aom-fix-win32-bustage-2535.patch
-TOP-1683545-PLASTER-webrender-2536.patch
-TOP-1667581-3-PLASTER-2537.patch
-TOP-1469021-PLASTER-2538.patch
-TOP-1699835-PARTIAL-7810.patch
-TOP-1758291-fixgithubpolyfill-253111.patch
-TOP-1398895-2a-57a1.patch
-TOP-NOBUG-skiptests-25312.patch
-TOP-NOBUG-dav1d-V1-support-25312.patch
-TOP-NOBUG-unfiedloadicon-25312.patch
-TOP-NOBUG-nometadata-25312.patch
-TOP-1641640-BACKOUT-25313.patch
-TOP-NOBUG-fixup-VS2022-25313.patch
-TOP-1779027-freebsd-25314.patch
-TOP-1722226-aarch64-webrtc-25315.patch
-TOP-NOBUG-nsslink-25315.patch
-TOP-NOBUG-fixtests-25315.patch
-TOP-NOBUG-nonodedefault-25315.patch
-TOP-1797696-macos11sdk-25315.patch
-TOP-1804537-macostransparent-25315.patch
-TOP-1804537-macosfullscreen-25315.patch
-TOP-1804539-fixlangpack-25316.patch
-TOP-1750671-1only-PARTIAL-98a1.patch
-TOP-1788837-PARTIAL-108a1.patch
-TOP-1807802-shared-tree-styling-25316.patch
-TOP-1584803-rust133.patch
-TOP-1584803-rust135.patch
-TOP-NOBUG-cubeb-25317.patch
-TOP-NOBUG-PLASTER-IOSurface-fix-25317.patch
-TOP-1512450-60.patch
-TOP-NOBUG-texth-25317.patch
-TOP-NOBUG-PLASTER-wayland-25317.patch
-TOP-NOBUG-PLASTER-Stylo-25314.patch
-TOP-1834230-HTMLTableEditor-tb-td-25317.patch
-TOP-1794292-1-10210.patch
-TOP-1794292-2-10210.patch
-TOP-NOBUG-PLASTER-PY3-Codegen-25317.patch
-TOP-NOBUG-PLASTER-PY3-GenerateCSSPropsGenerated-25317.patch
-TOP-NOBUG-PLASTER-PY3-idl-parser-25317.patch
-TOP-NOBUG-PLASTER-PY3-typelib-25317.patch
-TOP-NOBUG-PLASTER-PY3-check_binary-25317.patch
-TOP-1620143-PARTIAL-PY3-dependentlibs-75a1.patch
-TOP-NOBUG-PLASTER-PY3-25317.patch
-TOP-NOBUG-PLASTER-PY310_support-25314.patch
-TOP-NOBUG-PLASTER-PY311_support-25317.patch
-TOP-NOBUG-enableCE-25318.patch
-TOP-1539694-allsettled-68a1-25313.patch
-TOP-1378808-optchain-63a1-25313.patch
-TOP-1466000-1-optchain-64a1-25313.patch
-TOP-1566143-1to2-optchain-74a1-25313.patch
-TOP-1566143-3-optchain-74a1-25313.patch
-TOP-1610447-optchain-74a1-25313.patch
-TOP-1611777-12-74a1-25313.patch
-TOP-1378808-2-optchain-63a1-25313.patch
-TOP-NOBUG-optchain-baselinejit-25313.patch
-TOP-1629106-1-logicassign-25317.patch
-TOP-1629106-2-logicassign-25317.patch
-TOP-NOBUG-REGEXP-01-Import-25318.patch
-TOP-NOBUG-REGEXP-02-1361856-1-dotall-76a1-25318.patch
-TOP-NOBUG-REGEXP-03-1537978-68a1-25318.patch
-TOP-NOBUG-REGEXP-04-1539690-68a1-25318.patch
-TOP-NOBUG-REGEXP-05-1546300-68a1-25318.patch
-TOP-NOBUG-REGEXP-06-1504947-10-68a1-25318.patch
-TOP-NOBUG-REGEXP-07-1626713-76a1-25318.patch
-TOP-NOBUG-REGEXP-09-1627356-77a1-25318.patch
-TOP-NOBUG-REGEXP-10-1627838-77a1-25318.patch
-TOP-NOBUG-REGEXP-11-deunify-25318.patch
-TOP-NOBUG-REGEXP-12-1628835-77a1-25318.patch
-TOP-NOBUG-REGEXP-13-1361856-2-76a1-25318.patch
-TOP-NOBUG-REGEXP-14-1629670-77a1-25318.patch
-TOP-NOBUG-REGEXP-15-1630090-1-77a1-25318.patch
-TOP-NOBUG-REGEXP-16-1630090-2-77a1-25318.patch
-TOP-1630383-02-77a1.patch
-TOP-1630383-07-77a1.patch
-TOP-NOBUG-REGEXP-17-1630383-77a1-25318.patch
-TOP-1607405-77a1.patch
-TOP-1636495-1-78a1.patch
-TOP-1636495-2no3-78a1.patch
-TOP-1637199-78a1.patch
-TOP-NOBUG-REGEXP-21-1634135-78a1-25318.patch
-TOP-NOBUG-REGEXP-22-1637977-78a1-25318.patch
-TOP-NOBUG-REGEXP-23-1637913-78a1-25318.patch
-TOP-NOBUG-REGEXP-24-1631504-77a1-25318.patch
-TOP-NOBUG-REGEXP-25-1362154-1to4-78a1-25318.patch
-TOP-NOBUG-REGEXP-26-1362154-5to9-78a1-25318.patch
-TOP-NOBUG-REGEXP-27-1640487-78a1-25318.patch
-TOP-NOBUG-REGEXP-28-1640592-78a1-25318.patch
-TOP-NOBUG-REGEXP-29-1640475-78a1-25318.patch
-TOP-NOBUG-REGEXP-30-1640479-78a1-25318.patch
-TOP-NOBUG-REGEXP-31-1640473-78a1-25318.patch
-TOP-NOBUG-REGEXP-32-1638154-78a1-25318.patch
-TOP-NOBUG-REGEXP-33-1641352-79a1-25318.patch
-TOP-NOBUG-REGEXP-34-1361856-1-fix-76a1-25318.patch
-TOP-NOBUG-REGEXP-35-1435829-66a1-25318.patch
-TOP-NOBUG-REGEXP-36-1590543-73a1-25318.patch
-TOP-NOBUG-REGEXP-37-1642493-79a1-25318.patch
-TOP-NOBUG-REGEXP-38-1662073-82a1-25318.patch
-TOP-NOBUG-REGEXP-39-1681084-1-85a1-25318.patch
-TOP-NOBUG-REGEXP-40-1644590-79a1-25318.patch
-TOP-NOBUG-REGEXP-41-1667094-83a1-25318.patch
-TOP-NOBUG-REGEXP-42-1643171-79a1-25318.patch
-TOP-NOBUG-REGEXP-43-1691184-88a1-25318.patch
-TOP-NOBUG-REGEXP-44-irregexp-25318.patch
-TOP-NOBUG-REGEXP-45-final-25318.patch
-TOP-NOBUG-REGEXP-46-fixes-25318.patch
-TOP-NOBUG-revendor-25318.patch
-TOP-NOBUG-backout1440761-25318.patch
-TOP-NOBUG-test-fixes-25318.patch
-TOP-1846703-binutilsfix-11504.patch
-TOP-1859635-NSS3901-11506.patch
-1333140-2no1-59a1.patch
-1477010-63a1.patch
-1426827-63a1.patch
-1554306-69a1.patch
-1560439-69a1.patch
-1639815-1-78a1.patch
-1639815-2-78a1.patch
-1639815-3-78a1.patch
-1639815-4-78a1.patch
-1639815-5-78a1.patch
-1639815-6-78a1.patch
-1639815-7-78a1.patch
-1639815-8-78a1.patch
-1654470-81a1.patch
-1667896-83a1.patch
-1670130-83a1.patch
-1480005-3-86a1.patch
-1714632-92a1.patch
-1716613-92a1.patch
-1747754-PARTIAL-97a1.patch
-1761303-108a1.patch
-TOP-NOBUG-PLASTER-fix-strip-25319.patch
-TOP-1707096-91a1.patch
 1388954-57a1.patch
+1372927-57a1.patch
 1380512-57a1.patch
+1387088-57a1.patch
 1393900-57a1.patch
 1391704-57a1.patch
 1395990-1no2-57a1.patch
 1395990-3-57a1.patch
+1388331-57a1.patch
+1396888-57a1.patch
+1401242-57a1.patch
 1394804-1-57a1.patch
 1394804-2-57a1.patch
 1394804-3-57a1.patch
+1400846-58a1.patch
 1401187-1-58a1.patch
 1401187-2-58a1.patch
 1398576-58a1.patch
+1403494-58a1.patch
+1403486-58a1.patch
+1392533-58a1.patch
 1305777-1-58a1.patch
 1305777-2-58a1.patch
 1305777-3-58a1.patch
@@ -5790,6 +5661,7 @@ TOP-1707096-91a1.patch
 1305777-7-58a1.patch
 1398722-58a1.patch
 1403389-58a1.patch
+1404578-58a1.patch
 1348960-58a1.patch
 1404197-58a1.patch
 1405983-1-58a1.patch
@@ -5904,6 +5776,7 @@ TOP-1707096-91a1.patch
 1420233-59a1.patch
 1420303-59a1.patch
 1417039-59a1.patch
+1333140-2no1-59a1.patch
 1422258-59a1.patch
 1422265-59a1.patch
 1422282-59a1.patch
@@ -5986,6 +5859,7 @@ TOP-1707096-91a1.patch
 1406841-59a1.patch
 1429271-59a1.patch
 1430001-59a1.patch
+1420811-59a1.patch
 1429121-1-59a1.patch
 1429121-2-59a1.patch
 1425273-2-59a1.patch
@@ -6010,6 +5884,7 @@ TOP-1707096-91a1.patch
 1430408-2-59a1.patch
 1430383-59a1.patch
 1431457-60a1.patch
+1432112-60a1.patch
 1335316-60a1.patch
 1431127-60a1.patch
 1404883-60a1.patch
@@ -6018,6 +5893,7 @@ TOP-1707096-91a1.patch
 1429763-60a1.patch
 1421225-60a1.patch
 1404888-60a1.patch
+1432520-60a1.patch
 1433123-60a1.patch
 1432842-1-60a1.patch
 1432842-2-60a1.patch
@@ -6274,6 +6150,7 @@ TOP-1707096-91a1.patch
 1444106-61a1.patch
 1444414-61a1.patch
 1443831-61a1.patch
+1431050-61a1.patch
 1443081-01-client-aboutdebugging-61a1.patch
 1443081-02-client-animationinspector-61a1.patch
 1443081-03-client-root-61a1.patch
@@ -6327,30 +6204,155 @@ NOBUG-20180313-inspector-61a1.patch
 1444594-61a1.patch
 1442153-61a1.patch
 1403188-61a1.patch
+1448194-61a1.patch
+1425866-61a1.patch
 1451683-62a1.patch
-1434848-68a1.patch
-TOP-NOBUG-killtelemetry-debugger-25319.patch
-1372927-57a1.patch
-1387088-57a1.patch
-1388331-57a1.patch
-1396888-57a1.patch
-1401242-57a1.patch
-1400846-58a1.patch
-1403494-58a1.patch
-1403486-58a1.patch
-1392533-58a1.patch
-1404578-58a1.patch
-1420811-59a1.patch
-1432112-60a1.patch
-1432520-60a1.patch
-1431050-61a1.patch
+1477010-63a1.patch
+1426827-63a1.patch
 1506798-65a1.patch
+1434848-68a1.patch
+1554306-69a1.patch
+1560439-69a1.patch
+1639815-1-78a1.patch
+1639815-2-78a1.patch
+1639815-3-78a1.patch
+1639815-4-78a1.patch
+1639815-5-78a1.patch
+1639815-6-78a1.patch
+1639815-7-78a1.patch
+1639815-8-78a1.patch
+1654470-81a1.patch
+1667896-83a1.patch
+1670130-83a1.patch
+1480005-3-86a1.patch
+1711872-91a1.patch
+1714632-92a1.patch
+1721149-92a1.patch
+1716613-92a1.patch
+1747754-PARTIAL-97a1.patch
+1761303-108a1.patch
 1854076-11505.patch
 1826791-121a1.patch
-WIP-1729459-comment25.patch
 1660223-11507.patch
-1425866-61a1.patch
+NOBUG-removessdks-25319.patch
+NOBUG-nukemozlinker-25319.patch
+PPPPPPP-check_stdcxx-warn.patch
+PPPPPPP-NOBUG-PLASTER-getrandom.patch
+PPPPPPP-NSSgetentropy.patch
+WIP-1729459-comment25.patch
+TOP-1294490-7-PLASTER-webp-2535.patch
+TOP-1493400-6-PLASTER-dav1d-avoid-mColorDepth-2535.patch
+TOP-1445683-14-PLASTER-aom-fix-win32-bustage-2535.patch
+TOP-1683545-PLASTER-webrender-2536.patch
+TOP-1667581-3-PLASTER-2537.patch
+TOP-1469021-PLASTER-2538.patch
+TOP-1699835-PARTIAL-7810.patch
+TOP-1758291-fixgithubpolyfill-253111.patch
+TOP-1398895-2a-57a1.patch
+TOP-NOBUG-skiptests-25312.patch
+TOP-NOBUG-dav1d-V1-support-25312.patch
+TOP-NOBUG-unfiedloadicon-25312.patch
+TOP-NOBUG-nometadata-25312.patch
+TOP-1641640-BACKOUT-25313.patch
+TOP-NOBUG-fixup-VS2022-25313.patch
+TOP-1779027-freebsd-25314.patch
+TOP-1722226-aarch64-webrtc-25315.patch
+TOP-NOBUG-nsslink-25315.patch
+TOP-NOBUG-fixtests-25315.patch
+TOP-NOBUG-nonodedefault-25315.patch
+TOP-1797696-macos11sdk-25315.patch
+TOP-1804537-macostransparent-25315.patch
+TOP-1804537-macosfullscreen-25315.patch
+TOP-1804539-fixlangpack-25316.patch
+TOP-1750671-1only-PARTIAL-98a1.patch
+TOP-1788837-PARTIAL-108a1.patch
+TOP-1807802-shared-tree-styling-25316.patch
+TOP-1584803-rust133.patch
+TOP-1584803-rust135.patch
+TOP-NOBUG-cubeb-25317.patch
+TOP-NOBUG-PLASTER-IOSurface-fix-25317.patch
+TOP-1512450-60.patch
+TOP-NOBUG-texth-25317.patch
+TOP-NOBUG-PLASTER-wayland-25317.patch
+TOP-NOBUG-PLASTER-Stylo-25314.patch
+TOP-1834230-HTMLTableEditor-tb-td-25317.patch
+TOP-1794292-1-10210.patch
+TOP-1794292-2-10210.patch
+TOP-NOBUG-PLASTER-PY3-Codegen-25317.patch
+TOP-NOBUG-PLASTER-PY3-GenerateCSSPropsGenerated-25317.patch
+TOP-NOBUG-PLASTER-PY3-idl-parser-25317.patch
+TOP-NOBUG-PLASTER-PY3-typelib-25317.patch
+TOP-NOBUG-PLASTER-PY3-check_binary-25317.patch
+TOP-1620143-PARTIAL-PY3-dependentlibs-75a1.patch
+TOP-NOBUG-PLASTER-PY3-25317.patch
+TOP-NOBUG-PLASTER-PY310_support-25314.patch
+TOP-NOBUG-PLASTER-PY311_support-25317.patch
+TOP-NOBUG-enableCE-25318.patch
+TOP-1539694-allsettled-68a1-25313.patch
+TOP-1378808-optchain-63a1-25313.patch
+TOP-1466000-1-optchain-64a1-25313.patch
+TOP-1566143-1to2-optchain-74a1-25313.patch
+TOP-1566143-3-optchain-74a1-25313.patch
+TOP-1610447-optchain-74a1-25313.patch
+TOP-1611777-12-74a1-25313.patch
+TOP-1378808-2-optchain-63a1-25313.patch
+TOP-NOBUG-optchain-baselinejit-25313.patch
+TOP-1629106-1-logicassign-25317.patch
+TOP-1629106-2-logicassign-25317.patch
+TOP-NOBUG-REGEXP-01-Import-25318.patch
+TOP-NOBUG-REGEXP-02-1361856-1-dotall-76a1-25318.patch
+TOP-NOBUG-REGEXP-03-1537978-68a1-25318.patch
+TOP-NOBUG-REGEXP-04-1539690-68a1-25318.patch
+TOP-NOBUG-REGEXP-05-1546300-68a1-25318.patch
+TOP-NOBUG-REGEXP-06-1504947-10-68a1-25318.patch
+TOP-NOBUG-REGEXP-07-1626713-76a1-25318.patch
+TOP-NOBUG-REGEXP-09-1627356-77a1-25318.patch
+TOP-NOBUG-REGEXP-10-1627838-77a1-25318.patch
+TOP-NOBUG-REGEXP-11-deunify-25318.patch
+TOP-NOBUG-REGEXP-12-1628835-77a1-25318.patch
+TOP-NOBUG-REGEXP-13-1361856-2-76a1-25318.patch
+TOP-NOBUG-REGEXP-14-1629670-77a1-25318.patch
+TOP-NOBUG-REGEXP-15-1630090-1-77a1-25318.patch
+TOP-NOBUG-REGEXP-16-1630090-2-77a1-25318.patch
+TOP-1630383-02-77a1.patch
+TOP-1630383-07-77a1.patch
+TOP-NOBUG-REGEXP-17-1630383-77a1-25318.patch
+TOP-1607405-77a1.patch
+TOP-1636495-1-78a1.patch
+TOP-1636495-2no3-78a1.patch
+TOP-1637199-78a1.patch
+TOP-NOBUG-REGEXP-21-1634135-78a1-25318.patch
+TOP-NOBUG-REGEXP-22-1637977-78a1-25318.patch
+TOP-NOBUG-REGEXP-23-1637913-78a1-25318.patch
+TOP-NOBUG-REGEXP-24-1631504-77a1-25318.patch
+TOP-NOBUG-REGEXP-25-1362154-1to4-78a1-25318.patch
+TOP-NOBUG-REGEXP-26-1362154-5to9-78a1-25318.patch
+TOP-NOBUG-REGEXP-27-1640487-78a1-25318.patch
+TOP-NOBUG-REGEXP-28-1640592-78a1-25318.patch
+TOP-NOBUG-REGEXP-29-1640475-78a1-25318.patch
+TOP-NOBUG-REGEXP-30-1640479-78a1-25318.patch
+TOP-NOBUG-REGEXP-31-1640473-78a1-25318.patch
+TOP-NOBUG-REGEXP-32-1638154-78a1-25318.patch
+TOP-NOBUG-REGEXP-33-1641352-79a1-25318.patch
+TOP-NOBUG-REGEXP-34-1361856-1-fix-76a1-25318.patch
+TOP-NOBUG-REGEXP-35-1435829-66a1-25318.patch
+TOP-NOBUG-REGEXP-36-1590543-73a1-25318.patch
+TOP-NOBUG-REGEXP-37-1642493-79a1-25318.patch
+TOP-NOBUG-REGEXP-38-1662073-82a1-25318.patch
+TOP-NOBUG-REGEXP-39-1681084-1-85a1-25318.patch
+TOP-NOBUG-REGEXP-40-1644590-79a1-25318.patch
+TOP-NOBUG-REGEXP-41-1667094-83a1-25318.patch
+TOP-NOBUG-REGEXP-42-1643171-79a1-25318.patch
+TOP-NOBUG-REGEXP-43-1691184-88a1-25318.patch
+TOP-NOBUG-REGEXP-44-irregexp-25318.patch
+TOP-NOBUG-REGEXP-45-final-25318.patch
+TOP-NOBUG-REGEXP-46-fixes-25318.patch
+TOP-NOBUG-revendor-25318.patch
+TOP-NOBUG-backout1440761-25318.patch
+TOP-NOBUG-test-fixes-25318.patch
+TOP-NOBUG-PLASTER-fix-strip-25319.patch
+TOP-1707096-91a1.patch
+TOP-1846703-binutilsfix-11504.patch
+TOP-1859635-NSS3901-11506.patch
+TOP-NOBUG-killtelemetry-debugger-25319.patch
 TOP-1472170-PARTIAL-NOTESTS-63a1.patch
-1448194-61a1.patch
-1711872-91a1.patch
-1721149-92a1.patch