Bug 1077384 - Make libmozglue a pseudo-LD_PRELOAD on android. r=nfroyd
authorMike Hommey <mh+mozilla@glandium.org>
Tue, 07 Oct 2014 07:42:18 +0900
changeset 232300 7c160422459608e12142f82b50822b27d2ffdedb
parent 232299 4e8f29e386bda1cb17ffb0e02e62cf6ece3cc000
child 232301 46b5882f52f8170882671e2c2e5c15b74d7e2690
push id4187
push userbhearsum@mozilla.com
push dateFri, 28 Nov 2014 15:29:12 +0000
treeherdermozilla-beta@f23cc6a30c11 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnfroyd
bugs1077384
milestone35.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1077384 - Make libmozglue a pseudo-LD_PRELOAD on android. r=nfroyd In order to avoid adding more dlsym overhead than there already is, resolve symbols directly in the library containing the linker. (GetSymbolPtr is essentially free ; dlsym makes the system linker compule a ElfHash itself, and that's quite expensive to do on all symbols) This also paves the way for direct symbol resolution in all system libraries.
mozglue/linker/BaseElf.cpp
mozglue/linker/BaseElf.h
mozglue/linker/CustomElf.cpp
mozglue/linker/CustomElf.h
mozglue/linker/ElfLoader.cpp
mozglue/linker/ElfLoader.h
mozglue/linker/Utils.h
mozglue/linker/moz.build
new file mode 100644
--- /dev/null
+++ b/mozglue/linker/BaseElf.cpp
@@ -0,0 +1,55 @@
+/* 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"
+
+using namespace Elf;
+
+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, 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;
+}
new file mode 100644
--- /dev/null
+++ b/mozglue/linker/BaseElf.h
@@ -0,0 +1,93 @@
+/* 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)
+  : LibHandle(path) { }
+
+protected:
+   /**
+    * Inherited from LibHandle. Those are temporary and are not supposed to
+    * be used.
+    */
+   virtual void *GetSymbolPtr(const char *symbol) const { return NULL; };
+   virtual bool Contains(void *addr) const { return false; };
+   virtual void *GetBase() const { return GetPtr(0); }
+
+#ifdef __ARM_EABI__
+  virtual const void *FindExidx(int *pcount) const { return NULL; };
+#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);
+  }
+
+  /* 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;
+};
+
+#endif /* BaseElf_h */
--- a/mozglue/linker/CustomElf.cpp
+++ b/mozglue/linker/CustomElf.cpp
@@ -2,17 +2,19 @@
  * 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"
 
 using namespace Elf;
 using namespace mozilla;
 
 /* TODO: Fill ElfLoader::Singleton.lastError on errors. */
 
@@ -274,53 +276,20 @@ CustomElf::~CustomElf()
   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);
 }
 
-namespace {
-
-/**
- * Hash function for symbol lookup, as defined in ELF standard for System V
- */
-unsigned long
-ElfHash(const char *symbol)
-{
-  const unsigned char *sym = reinterpret_cast<const unsigned char *>(symbol);
-  unsigned long h = 0, g;
-  while (*sym) {
-    h = (h << 4) + *sym++;
-    if ((g = h & 0xf0000000))
-      h ^= g >> 24;
-    h &= ~g;
-  }
-  return h;
-}
-
-} /* anonymous namespace */
-
 void *
 CustomElf::GetSymbolPtr(const char *symbol) const
 {
-  return GetSymbolPtr(symbol, ElfHash(symbol));
-}
-
-void *
-CustomElf::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("CustomElf::GetSymbolPtr(%p [\"%s\"], \"%s\") = %p",
-            reinterpret_cast<const void *>(this), GetPath(), symbol, ptr);
-  return ptr;
+  return BaseElf::GetSymbolPtr(symbol, Hash(symbol));
 }
 
 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)
@@ -367,69 +336,48 @@ CustomElf::GetSymbolPtrInDeps(const char
   // so stub those out here
   if (strncmp(symbol,
               MISSING_FLASH_SYMNAME_START,
               sizeof(MISSING_FLASH_SYMNAME_START) - 1) == 0) {
     return FunctionPtr(__void_stub);
   }
 
   void *sym;
-  /* Search the symbol in the main program. Note this also tries all libraries
-   * the system linker will have loaded RTLD_GLOBAL. Unfortunately, that doesn't
-   * work with bionic, but its linker doesn't normally search the main binary
-   * anyways. Moreover, on android, the main binary is dalvik. */
-#ifdef __GLIBC__
-  sym = dlsym(RTLD_DEFAULT, symbol);
-  DEBUG_LOG("dlsym(RTLD_DEFAULT, \"%s\") = %p", symbol, sym);
-  if (sym)
-    return sym;
-#endif
+
+  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 = ElfLoader::Singleton.self_elf->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. */
-  unsigned long hash = ElfHash(symbol);
   for (std::vector<RefPtr<LibHandle> >::const_iterator it = dependencies.begin();
        it < dependencies.end(); ++it) {
     if (!(*it)->IsSystemElf()) {
-      sym = reinterpret_cast<CustomElf *>((*it).get())->GetSymbolPtr(symbol, hash);
-#ifndef __GLIBC__
+      sym = static_cast<BaseElf *>(
+        static_cast<CustomElf *>((*it).get()))->GetSymbolPtr(symbol, hash);
     } else {
       sym = (*it)->GetSymbolPtr(symbol);
-#endif
     }
     if (sym)
       return sym;
   }
   return nullptr;
 }
 
-const Sym *
-CustomElf::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
 CustomElf::Contains(void *addr) const
 {
   return base.Contains(addr);
 }
 
 #ifdef __ARM_EABI__
 const void *
--- a/mozglue/linker/CustomElf.h
+++ b/mozglue/linker/CustomElf.h
@@ -1,24 +1,25 @@
 /* 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 LibHandle, private ElfLoader::link_map
+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
@@ -26,17 +27,17 @@ public:
    * 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 mozilla::TemporaryRef<LibHandle> Load(Mappable *mappable,
                                                const char *path, int flags);
 
   /**
-   * Inherited from LibHandle
+   * Inherited from LibHandle/BaseElf
    */
   virtual ~CustomElf();
   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;
@@ -50,65 +51,35 @@ public:
    * Shows some stats about the Mappable instance. The when argument is to be
    * used by the caller to give an identifier of the when the stats call is
    * made.
    */
   void stats(const char *when) const;
 
 private:
   /**
-   * 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;
-
-  /**
-   * Returns the address corresponding to the given symbol name (with a
-   * pre-computed hash).
-   */
-  void *GetSymbolPtr(const char *symbol, unsigned long hash) const;
-
-  /**
    * 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)
-  : LibHandle(path)
+  : BaseElf(path)
   , mappable(mappable)
   , init(0)
   , fini(0)
   , initialized(false)
   , has_text_relocs(false)
   { }
 
   /**
-   * Returns a pointer relative to the base address where the library is
-   * loaded.
-   */
-  void *GetPtr(const Elf::Addr offset) const
-  {
-    return base + offset;
-  }
-
-  /**
-   * Like the above, but returns a typed (const) pointer
-   */
-  template <typename T>
-  const T *GetPtr(const Elf::Addr offset) const
-  {
-    return reinterpret_cast<const T *>(base + offset);
-  }
-
-  /**
    * 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.
@@ -162,29 +133,16 @@ private:
   void CallFunction(Elf::Addr addr) const
   {
     return CallFunction(GetPtr(addr));
   }
 
   /* Appropriated Mappable */
   mozilla::RefPtr<Mappable> mappable;
 
-  /* Base address where the library is loaded */
-  MappedPtr base;
-
-  /* String table */
-  Elf::Strtab strtab;
-
-  /* Symbol table */
-  UnsizedArray<Elf::Sym> symtab;
-
-  /* Buckets and chains for the System V symbol hash table */
-  Array<Elf::Word> buckets;
-  UnsizedArray<Elf::Word> chains;
-
   /* List of dependent libraries */
   std::vector<mozilla::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;
--- a/mozglue/linker/ElfLoader.cpp
+++ b/mozglue/linker/ElfLoader.cpp
@@ -6,16 +6,17 @@
 #include <cstring>
 #include <cstdlib>
 #include <cstdio>
 #include <dlfcn.h>
 #include <unistd.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>
 
@@ -33,16 +34,20 @@ inline int sigaltstack(const stack_t *ss
 #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)
@@ -326,16 +331,20 @@ SystemElf::FindExidx(int *pcount) const
 ElfLoader ElfLoader::Singleton;
 
 TemporaryRef<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;
   }
 
@@ -461,16 +470,64 @@ ElfLoader::Forget(LibHandle *handle)
       dbg.Remove(static_cast<CustomElf *>(handle));
     handles.erase(it);
   } else {
     DEBUG_LOG("ElfLoader::Forget(%p [\"%s\"]): Handle not found",
               reinterpret_cast<void *>(handle), handle->GetPath());
   }
 }
 
+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) {
+    /* Ideally, we wouldn't be initializing self_elf this way, but until
+     * SystemElf actually inherits from BaseElf, we'll just do it this
+     * (gross) way. */
+    UniquePtr<BaseElf> elf = mozilla::MakeUnique<BaseElf>(info.dli_fname);
+    elf->base.Assign(info.dli_fbase, -1);
+    size_t symnum = 0;
+    for (const Elf::Dyn *dyn = _DYNAMIC; dyn->d_tag; dyn++) {
+      switch (dyn->d_tag) {
+        case DT_HASH:
+          {
+            DEBUG_LOG("%s 0x%08" PRIxAddr, "DT_HASH", dyn->d_un.d_val);
+            const Elf::Word *hash_table_header = \
+              elf->GetPtr<Elf::Word>(dyn->d_un.d_ptr);
+            symnum = hash_table_header[1];
+            elf->buckets.Init(&hash_table_header[2], hash_table_header[0]);
+            elf->chains.Init(&*elf->buckets.end());
+          }
+          break;
+        case DT_STRTAB:
+          DEBUG_LOG("%s 0x%08" PRIxAddr, "DT_STRTAB", dyn->d_un.d_val);
+          elf->strtab.Init(elf->GetPtr(dyn->d_un.d_ptr));
+          break;
+        case DT_SYMTAB:
+          DEBUG_LOG("%s 0x%08" PRIxAddr, "DT_SYMTAB", dyn->d_un.d_val);
+          elf->symtab.Init(elf->GetPtr(dyn->d_un.d_ptr));
+          break;
+      }
+    }
+    if (!elf->buckets || !symnum) {
+      ERROR("%s: Missing or broken DT_HASH", info.dli_fname);
+    } else if (!elf->strtab) {
+      ERROR("%s: Missing DT_STRTAB", info.dli_fname);
+    } else if (!elf->symtab) {
+      ERROR("%s: Missing DT_SYMTAB", info.dli_fname);
+    } else {
+      self_elf = Move(elf);
+    }
+  }
+}
+
 ElfLoader::~ElfLoader()
 {
   LibHandleList list;
   /* 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. */
@@ -502,16 +559,20 @@ ElfLoader::~ElfLoader()
                   "[%d direct refs, %d 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 */
       }
     }
   }
+  /* Avoid self_elf->base destructor unmapping something that doesn't actually
+   * belong to it. */
+  if (self_elf)
+    self_elf->base.release();
 }
 
 void
 ElfLoader::stats(const char *when)
 {
   for (LibHandleList::iterator it = Singleton.handles.begin();
        it < Singleton.handles.end(); ++it)
     if (!(*it)->IsSystemElf())
--- a/mozglue/linker/ElfLoader.h
+++ b/mozglue/linker/ElfLoader.h
@@ -4,16 +4,17 @@
 
 #ifndef ElfLoader_h
 #define ElfLoader_h
 
 #include <vector>
 #include <dlfcn.h>
 #include <signal.h>
 #include "mozilla/RefPtr.h"
+#include "mozilla/UniquePtr.h"
 #include "Zip.h"
 #include "Elfxx.h"
 #include "Mappable.h"
 
 /**
  * dlfcn.h replacement functions
  */
 extern "C" {
@@ -58,16 +59,19 @@ MFBT_API void *
 MFBT_API void
 __dl_munmap(void *handle, void *addr, size_t length);
 
 MFBT_API bool
 IsSignalHandlingBroken();
 
 }
 
+/* Forward declaration because BaseElf.h includes ElfLoader.h */
+class BaseElf;
+
 /**
  * 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;
 
@@ -434,16 +438,23 @@ protected:
   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();
 
+  /* 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. */
+  mozilla::UniquePtr<BaseElf> self_elf;
+
   /* Bookkeeping */
   typedef std::vector<LibHandle *> LibHandleList;
   LibHandleList handles;
 
 protected:
   friend class CustomElf;
   /**
    * Show some stats about Mappables in CustomElfs. The when argument is to
@@ -552,23 +563,31 @@ private:
      * 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);
 
--- a/mozglue/linker/Utils.h
+++ b/mozglue/linker/Utils.h
@@ -285,16 +285,20 @@ public:
   }
 
   ~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) { }
--- a/mozglue/linker/moz.build
+++ b/mozglue/linker/moz.build
@@ -1,15 +1,16 @@
 # -*- Mode: python; c-basic-offset: 4; 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',
     'SeekableZStream.cpp',
     'Zip.cpp',
 ]
 
 Library('linker')