DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Implementation

Mercurial (50bba836b642)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
/* 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 */