michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this file, michael@0: * You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef CustomElf_h michael@0: #define CustomElf_h michael@0: michael@0: #include "ElfLoader.h" michael@0: #include "Logging.h" michael@0: #include "Elfxx.h" michael@0: michael@0: /** michael@0: * Library Handle class for ELF libraries we don't let the system linker michael@0: * handle. michael@0: */ michael@0: class CustomElf: public LibHandle, private ElfLoader::link_map michael@0: { michael@0: friend class ElfLoader; michael@0: friend class SEGVHandler; michael@0: public: michael@0: /** michael@0: * Returns a new CustomElf using the given file descriptor to map ELF michael@0: * content. The file descriptor ownership is stolen, and it will be closed michael@0: * in CustomElf's destructor if an instance is created, or by the Load michael@0: * method otherwise. The path corresponds to the file descriptor, and flags michael@0: * are the same kind of flags that would be given to dlopen(), though michael@0: * currently, none are supported and the behaviour is more or less that of michael@0: * RTLD_GLOBAL | RTLD_BIND_NOW. michael@0: */ michael@0: static mozilla::TemporaryRef Load(Mappable *mappable, michael@0: const char *path, int flags); michael@0: michael@0: /** michael@0: * Inherited from LibHandle michael@0: */ michael@0: virtual ~CustomElf(); michael@0: virtual void *GetSymbolPtr(const char *symbol) const; michael@0: virtual bool Contains(void *addr) const; michael@0: michael@0: #ifdef __ARM_EABI__ michael@0: virtual const void *FindExidx(int *pcount) const; michael@0: #endif michael@0: michael@0: protected: michael@0: virtual Mappable *GetMappable() const; michael@0: michael@0: public: michael@0: /** michael@0: * Shows some stats about the Mappable instance. The when argument is to be michael@0: * used by the caller to give an identifier of the when the stats call is michael@0: * made. michael@0: */ michael@0: void stats(const char *when) const; michael@0: michael@0: private: michael@0: /** michael@0: * Returns a pointer to the Elf Symbol in the Dynamic Symbol table michael@0: * corresponding to the given symbol name (with a pre-computed hash). michael@0: */ michael@0: const Elf::Sym *GetSymbol(const char *symbol, unsigned long hash) const; michael@0: michael@0: /** michael@0: * Returns the address corresponding to the given symbol name (with a michael@0: * pre-computed hash). michael@0: */ michael@0: void *GetSymbolPtr(const char *symbol, unsigned long hash) const; michael@0: michael@0: /** michael@0: * Scan dependent libraries to find the address corresponding to the michael@0: * given symbol name. This is used to find symbols that are undefined michael@0: * in the Elf object. michael@0: */ michael@0: void *GetSymbolPtrInDeps(const char *symbol) const; michael@0: michael@0: /** michael@0: * Private constructor michael@0: */ michael@0: CustomElf(Mappable *mappable, const char *path) michael@0: : LibHandle(path) michael@0: , mappable(mappable) michael@0: , init(0) michael@0: , fini(0) michael@0: , initialized(false) michael@0: , has_text_relocs(false) michael@0: { } michael@0: michael@0: /** michael@0: * Returns a pointer relative to the base address where the library is michael@0: * loaded. michael@0: */ michael@0: void *GetPtr(const Elf::Addr offset) const michael@0: { michael@0: return base + offset; michael@0: } michael@0: michael@0: /** michael@0: * Like the above, but returns a typed (const) pointer michael@0: */ michael@0: template michael@0: const T *GetPtr(const Elf::Addr offset) const michael@0: { michael@0: return reinterpret_cast(base + offset); michael@0: } michael@0: michael@0: /** michael@0: * Loads an Elf segment defined by the given PT_LOAD header. michael@0: * Returns whether this succeeded or failed. michael@0: */ michael@0: bool LoadSegment(const Elf::Phdr *pt_load) const; michael@0: michael@0: /** michael@0: * Initializes the library according to information found in the given michael@0: * PT_DYNAMIC header. michael@0: * Returns whether this succeeded or failed. michael@0: */ michael@0: bool InitDyn(const Elf::Phdr *pt_dyn); michael@0: michael@0: /** michael@0: * Apply .rel.dyn/.rela.dyn relocations. michael@0: * Returns whether this succeeded or failed. michael@0: */ michael@0: bool Relocate(); michael@0: michael@0: /** michael@0: * Apply .rel.plt/.rela.plt relocations. michael@0: * Returns whether this succeeded or failed. michael@0: */ michael@0: bool RelocateJumps(); michael@0: michael@0: /** michael@0: * Call initialization functions (.init/.init_array) michael@0: * Returns true; michael@0: */ michael@0: bool CallInit(); michael@0: michael@0: /** michael@0: * Call destructor functions (.fini_array/.fini) michael@0: * Returns whether this succeeded or failed. michael@0: */ michael@0: void CallFini(); michael@0: michael@0: /** michael@0: * Call a function given a pointer to its location. michael@0: */ michael@0: void CallFunction(void *ptr) const michael@0: { michael@0: /* C++ doesn't allow direct conversion between pointer-to-object michael@0: * and pointer-to-function. */ michael@0: union { michael@0: void *ptr; michael@0: void (*func)(void); michael@0: } f; michael@0: f.ptr = ptr; michael@0: DEBUG_LOG("%s: Calling function @%p", GetPath(), ptr); michael@0: f.func(); michael@0: } michael@0: michael@0: /** michael@0: * Call a function given a an address relative to the library base michael@0: */ michael@0: void CallFunction(Elf::Addr addr) const michael@0: { michael@0: return CallFunction(GetPtr(addr)); michael@0: } michael@0: michael@0: /* Appropriated Mappable */ michael@0: mozilla::RefPtr mappable; michael@0: michael@0: /* Base address where the library is loaded */ michael@0: MappedPtr base; michael@0: michael@0: /* String table */ michael@0: Elf::Strtab strtab; michael@0: michael@0: /* Symbol table */ michael@0: UnsizedArray symtab; michael@0: michael@0: /* Buckets and chains for the System V symbol hash table */ michael@0: Array buckets; michael@0: UnsizedArray chains; michael@0: michael@0: /* List of dependent libraries */ michael@0: std::vector > dependencies; michael@0: michael@0: /* List of .rel.dyn/.rela.dyn relocations */ michael@0: Array relocations; michael@0: michael@0: /* List of .rel.plt/.rela.plt relocation */ michael@0: Array jumprels; michael@0: michael@0: /* Relative address of the initialization and destruction functions michael@0: * (.init/.fini) */ michael@0: Elf::Addr init, fini; michael@0: michael@0: /* List of initialization and destruction functions michael@0: * (.init_array/.fini_array) */ michael@0: Array init_array, fini_array; michael@0: michael@0: bool initialized; michael@0: michael@0: bool has_text_relocs; michael@0: michael@0: #ifdef __ARM_EABI__ michael@0: /* ARM.exidx information used by FindExidx */ michael@0: Array arm_exidx; michael@0: #endif michael@0: }; michael@0: michael@0: #endif /* CustomElf_h */