mozglue/linker/CustomElf.h
author Jim Blandy <jimb@mozilla.com>
Tue, 24 Jun 2014 22:12:07 -0700
changeset 199513 69d61e42d5dfbf4588b72449249ff3e7f2125304
parent 168012 dec061c862ff904c41465821d77ea7d15c23d3d9
child 218274 4aafc40bcd62ad4e289fa28ed0269ef33e52b399
permissions -rw-r--r--
Bug 914753: Make Emacs file variable header lines correct, or at least consistent. DONTBUILD r=ehsan The -*- file variable lines -*- establish per-file settings that Emacs will pick up. This patch makes the following changes to those lines (and touches nothing else): - Never set the buffer's mode. Years ago, Emacs did not have a good JavaScript mode, so it made sense to use Java or C++ mode in .js files. However, Emacs has had js-mode for years now; it's perfectly serviceable, and is available and enabled by default in all major Emacs packagings. Selecting a mode in the -*- file variable line -*- is almost always the wrong thing to do anyway. It overrides Emacs's default choice, which is (now) reasonable; and even worse, it overrides settings the user might have made in their '.emacs' file for that file extension. It's only useful when there's something specific about that particular file that makes a particular mode appropriate. - Correctly propagate settings that establish the correct indentation level for this file: c-basic-offset and js2-basic-offset should be js-indent-level. Whatever value they're given should be preserved; different parts of our tree use different indentation styles. - We don't use tabs in Mozilla JS code. Always set indent-tabs-mode: nil. Remove tab-width: settings, at least in files that don't contain tab characters. - Remove js2-mode settings that belong in the user's .emacs file, like js2-skip-preprocessor-directives.

/* 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 "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
{
  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 mozilla::TemporaryRef<LibHandle> Load(Mappable *mappable,
                                               const char *path, int flags);

  /**
   * Inherited from LibHandle
   */
  virtual ~CustomElf();
  virtual void *GetSymbolPtr(const char *symbol) const;
  virtual bool Contains(void *addr) const;

#ifdef __ARM_EABI__
  virtual const void *FindExidx(int *pcount) const;
#endif

protected:
  virtual Mappable *GetMappable() const;

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)
  , 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.
   * 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));
  }

  /* 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;

  /* 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;

#ifdef __ARM_EABI__
  /* ARM.exidx information used by FindExidx */
  Array<uint32_t[2]> arm_exidx;
#endif
};

#endif /* CustomElf_h */