1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/mozglue/linker/ElfLoader.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,609 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this file, 1.6 + * You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +#ifndef ElfLoader_h 1.9 +#define ElfLoader_h 1.10 + 1.11 +#include <vector> 1.12 +#include <dlfcn.h> 1.13 +#include <signal.h> 1.14 +#include "mozilla/RefPtr.h" 1.15 +#include "Zip.h" 1.16 +#include "Elfxx.h" 1.17 +#include "Mappable.h" 1.18 + 1.19 +/** 1.20 + * dlfcn.h replacement functions 1.21 + */ 1.22 +extern "C" { 1.23 + void *__wrap_dlopen(const char *path, int flags); 1.24 + const char *__wrap_dlerror(void); 1.25 + void *__wrap_dlsym(void *handle, const char *symbol); 1.26 + int __wrap_dlclose(void *handle); 1.27 + 1.28 +#ifndef HAVE_DLADDR 1.29 + typedef struct { 1.30 + const char *dli_fname; 1.31 + void *dli_fbase; 1.32 + const char *dli_sname; 1.33 + void *dli_saddr; 1.34 + } Dl_info; 1.35 +#endif 1.36 + int __wrap_dladdr(void *addr, Dl_info *info); 1.37 + 1.38 + struct dl_phdr_info { 1.39 + Elf::Addr dlpi_addr; 1.40 + const char *dlpi_name; 1.41 + const Elf::Phdr *dlpi_phdr; 1.42 + Elf::Half dlpi_phnum; 1.43 + }; 1.44 + 1.45 + typedef int (*dl_phdr_cb)(struct dl_phdr_info *, size_t, void *); 1.46 + int __wrap_dl_iterate_phdr(dl_phdr_cb callback, void *data); 1.47 + 1.48 +#ifdef __ARM_EABI__ 1.49 + const void *__wrap___gnu_Unwind_Find_exidx(void *pc, int *pcount); 1.50 +#endif 1.51 + 1.52 +/** 1.53 + * faulty.lib public API 1.54 + */ 1.55 +MFBT_API size_t 1.56 +__dl_get_mappable_length(void *handle); 1.57 + 1.58 +MFBT_API void * 1.59 +__dl_mmap(void *handle, void *addr, size_t length, off_t offset); 1.60 + 1.61 +MFBT_API void 1.62 +__dl_munmap(void *handle, void *addr, size_t length); 1.63 + 1.64 +MFBT_API bool 1.65 +IsSignalHandlingBroken(); 1.66 + 1.67 +} 1.68 + 1.69 +/** 1.70 + * Specialize RefCounted template for LibHandle. We may get references to 1.71 + * LibHandles during the execution of their destructor, so we need 1.72 + * RefCounted<LibHandle>::Release to support some reentrancy. See further 1.73 + * below. 1.74 + */ 1.75 +class LibHandle; 1.76 + 1.77 +namespace mozilla { 1.78 +namespace detail { 1.79 + 1.80 +template <> inline void RefCounted<LibHandle, AtomicRefCount>::Release() const; 1.81 + 1.82 +template <> inline RefCounted<LibHandle, AtomicRefCount>::~RefCounted() 1.83 +{ 1.84 + MOZ_ASSERT(refCnt == 0x7fffdead); 1.85 +} 1.86 + 1.87 +} /* namespace detail */ 1.88 +} /* namespace mozilla */ 1.89 + 1.90 +/** 1.91 + * Abstract class for loaded libraries. Libraries may be loaded through the 1.92 + * system linker or this linker, both cases will be derived from this class. 1.93 + */ 1.94 +class LibHandle: public mozilla::AtomicRefCounted<LibHandle> 1.95 +{ 1.96 +public: 1.97 + MOZ_DECLARE_REFCOUNTED_TYPENAME(LibHandle) 1.98 + /** 1.99 + * Constructor. Takes the path of the loaded library and will store a copy 1.100 + * of the leaf name. 1.101 + */ 1.102 + LibHandle(const char *path) 1.103 + : directRefCnt(0), path(path ? strdup(path) : nullptr), mappable(nullptr) { } 1.104 + 1.105 + /** 1.106 + * Destructor. 1.107 + */ 1.108 + virtual ~LibHandle(); 1.109 + 1.110 + /** 1.111 + * Returns the pointer to the address to which the given symbol resolves 1.112 + * inside the library. It is not supposed to resolve the symbol in other 1.113 + * libraries, although in practice, it will for system libraries. 1.114 + */ 1.115 + virtual void *GetSymbolPtr(const char *symbol) const = 0; 1.116 + 1.117 + /** 1.118 + * Returns whether the given address is part of the virtual address space 1.119 + * covered by the loaded library. 1.120 + */ 1.121 + virtual bool Contains(void *addr) const = 0; 1.122 + 1.123 + /** 1.124 + * Returns the file name of the library without the containing directory. 1.125 + */ 1.126 + const char *GetName() const; 1.127 + 1.128 + /** 1.129 + * Returns the full path of the library, when available. Otherwise, returns 1.130 + * the file name. 1.131 + */ 1.132 + const char *GetPath() const 1.133 + { 1.134 + return path; 1.135 + } 1.136 + 1.137 + /** 1.138 + * Library handles can be referenced from other library handles or 1.139 + * externally (when dlopen()ing using this linker). We need to be 1.140 + * able to distinguish between the two kind of referencing for better 1.141 + * bookkeeping. 1.142 + */ 1.143 + void AddDirectRef() 1.144 + { 1.145 + ++directRefCnt; 1.146 + mozilla::AtomicRefCounted<LibHandle>::AddRef(); 1.147 + } 1.148 + 1.149 + /** 1.150 + * Releases a direct reference, and returns whether there are any direct 1.151 + * references left. 1.152 + */ 1.153 + bool ReleaseDirectRef() 1.154 + { 1.155 + bool ret = false; 1.156 + if (directRefCnt) { 1.157 + MOZ_ASSERT(directRefCnt <= 1.158 + mozilla::AtomicRefCounted<LibHandle>::refCount()); 1.159 + if (--directRefCnt) 1.160 + ret = true; 1.161 + mozilla::AtomicRefCounted<LibHandle>::Release(); 1.162 + } 1.163 + return ret; 1.164 + } 1.165 + 1.166 + /** 1.167 + * Returns the number of direct references 1.168 + */ 1.169 + MozRefCountType DirectRefCount() 1.170 + { 1.171 + return directRefCnt; 1.172 + } 1.173 + 1.174 + /** 1.175 + * Returns the complete size of the file or stream behind the library 1.176 + * handle. 1.177 + */ 1.178 + size_t GetMappableLength() const; 1.179 + 1.180 + /** 1.181 + * Returns a memory mapping of the file or stream behind the library 1.182 + * handle. 1.183 + */ 1.184 + void *MappableMMap(void *addr, size_t length, off_t offset) const; 1.185 + 1.186 + /** 1.187 + * Unmaps a memory mapping of the file or stream behind the library 1.188 + * handle. 1.189 + */ 1.190 + void MappableMUnmap(void *addr, size_t length) const; 1.191 + 1.192 +#ifdef __ARM_EABI__ 1.193 + /** 1.194 + * Find the address and entry count of the ARM.exidx section 1.195 + * associated with the library 1.196 + */ 1.197 + virtual const void *FindExidx(int *pcount) const = 0; 1.198 +#endif 1.199 + 1.200 +protected: 1.201 + /** 1.202 + * Returns a mappable object for use by MappableMMap and related functions. 1.203 + */ 1.204 + virtual Mappable *GetMappable() const = 0; 1.205 + 1.206 + /** 1.207 + * Returns whether the handle is a SystemElf or not. (short of a better way 1.208 + * to do this without RTTI) 1.209 + */ 1.210 + friend class ElfLoader; 1.211 + friend class CustomElf; 1.212 + friend class SEGVHandler; 1.213 + virtual bool IsSystemElf() const { return false; } 1.214 + 1.215 +private: 1.216 + MozRefCountType directRefCnt; 1.217 + char *path; 1.218 + 1.219 + /* Mappable object keeping the result of GetMappable() */ 1.220 + mutable mozilla::RefPtr<Mappable> mappable; 1.221 +}; 1.222 + 1.223 +/** 1.224 + * Specialized RefCounted<LibHandle>::Release. Under normal operation, when 1.225 + * refCnt reaches 0, the LibHandle is deleted. Its refCnt is however increased 1.226 + * to 1 on normal builds, and 0x7fffdead on debug builds so that the LibHandle 1.227 + * can still be referenced while the destructor is executing. The refCnt is 1.228 + * allowed to grow > 0x7fffdead, but not to decrease under that value, which 1.229 + * would mean too many Releases from within the destructor. 1.230 + */ 1.231 +namespace mozilla { 1.232 +namespace detail { 1.233 + 1.234 +template <> inline void RefCounted<LibHandle, AtomicRefCount>::Release() const { 1.235 +#ifdef DEBUG 1.236 + if (refCnt > 0x7fff0000) 1.237 + MOZ_ASSERT(refCnt > 0x7fffdead); 1.238 +#endif 1.239 + MOZ_ASSERT(refCnt > 0); 1.240 + if (refCnt > 0) { 1.241 + if (0 == --refCnt) { 1.242 +#ifdef DEBUG 1.243 + refCnt = 0x7fffdead; 1.244 +#else 1.245 + refCnt = 1; 1.246 +#endif 1.247 + delete static_cast<const LibHandle*>(this); 1.248 + } 1.249 + } 1.250 +} 1.251 + 1.252 +} /* namespace detail */ 1.253 +} /* namespace mozilla */ 1.254 + 1.255 +/** 1.256 + * Class handling libraries loaded by the system linker 1.257 + */ 1.258 +class SystemElf: public LibHandle 1.259 +{ 1.260 +public: 1.261 + /** 1.262 + * Returns a new SystemElf for the given path. The given flags are passed 1.263 + * to dlopen(). 1.264 + */ 1.265 + static mozilla::TemporaryRef<LibHandle> Load(const char *path, int flags); 1.266 + 1.267 + /** 1.268 + * Inherited from LibHandle 1.269 + */ 1.270 + virtual ~SystemElf(); 1.271 + virtual void *GetSymbolPtr(const char *symbol) const; 1.272 + virtual bool Contains(void *addr) const { return false; /* UNIMPLEMENTED */ } 1.273 + 1.274 +#ifdef __ARM_EABI__ 1.275 + virtual const void *FindExidx(int *pcount) const; 1.276 +#endif 1.277 + 1.278 +protected: 1.279 + virtual Mappable *GetMappable() const; 1.280 + 1.281 + /** 1.282 + * Returns whether the handle is a SystemElf or not. (short of a better way 1.283 + * to do this without RTTI) 1.284 + */ 1.285 + friend class ElfLoader; 1.286 + virtual bool IsSystemElf() const { return true; } 1.287 + 1.288 + /** 1.289 + * Remove the reference to the system linker handle. This avoids dlclose() 1.290 + * being called when the instance is destroyed. 1.291 + */ 1.292 + void Forget() 1.293 + { 1.294 + dlhandle = nullptr; 1.295 + } 1.296 + 1.297 +private: 1.298 + /** 1.299 + * Private constructor 1.300 + */ 1.301 + SystemElf(const char *path, void *handle) 1.302 + : LibHandle(path), dlhandle(handle) { } 1.303 + 1.304 + /* Handle as returned by system dlopen() */ 1.305 + void *dlhandle; 1.306 +}; 1.307 + 1.308 +/** 1.309 + * The ElfLoader registers its own SIGSEGV handler to handle segmentation 1.310 + * faults within the address space of the loaded libraries. It however 1.311 + * allows a handler to be set for faults in other places, and redispatches 1.312 + * to the handler set through signal() or sigaction(). 1.313 + */ 1.314 +class SEGVHandler 1.315 +{ 1.316 +public: 1.317 + bool hasRegisteredHandler() { 1.318 + return registeredHandler; 1.319 + } 1.320 + 1.321 + bool isSignalHandlingBroken() { 1.322 + return signalHandlingBroken; 1.323 + } 1.324 + 1.325 +protected: 1.326 + SEGVHandler(); 1.327 + ~SEGVHandler(); 1.328 + 1.329 +private: 1.330 + static int __wrap_sigaction(int signum, const struct sigaction *act, 1.331 + struct sigaction *oldact); 1.332 + 1.333 + /** 1.334 + * SIGSEGV handler registered with __wrap_signal or __wrap_sigaction. 1.335 + */ 1.336 + struct sigaction action; 1.337 + 1.338 + /** 1.339 + * ElfLoader SIGSEGV handler. 1.340 + */ 1.341 + static void handler(int signum, siginfo_t *info, void *context); 1.342 + 1.343 + /** 1.344 + * Temporary test handler. 1.345 + */ 1.346 + static void test_handler(int signum, siginfo_t *info, void *context); 1.347 + 1.348 + /** 1.349 + * Size of the alternative stack. The printf family requires more than 8KB 1.350 + * of stack, and our signal handler may print a few things. 1.351 + */ 1.352 + static const size_t stackSize = 12 * 1024; 1.353 + 1.354 + /** 1.355 + * Alternative stack information used before initialization. 1.356 + */ 1.357 + stack_t oldStack; 1.358 + 1.359 + /** 1.360 + * Pointer to an alternative stack for signals. Only set if oldStack is 1.361 + * not set or not big enough. 1.362 + */ 1.363 + MappedPtr stackPtr; 1.364 + 1.365 + bool registeredHandler; 1.366 + bool signalHandlingBroken; 1.367 + bool signalHandlingSlow; 1.368 +}; 1.369 + 1.370 +/** 1.371 + * Elf Loader class in charge of loading and bookkeeping libraries. 1.372 + */ 1.373 +class ElfLoader: public SEGVHandler 1.374 +{ 1.375 +public: 1.376 + /** 1.377 + * The Elf Loader instance 1.378 + */ 1.379 + static ElfLoader Singleton; 1.380 + 1.381 + /** 1.382 + * Loads the given library with the given flags. Equivalent to dlopen() 1.383 + * The extra "parent" argument optionally gives the handle of the library 1.384 + * requesting the given library to be loaded. The loader may look in the 1.385 + * directory containing that parent library for the library to load. 1.386 + */ 1.387 + mozilla::TemporaryRef<LibHandle> Load(const char *path, int flags, 1.388 + LibHandle *parent = nullptr); 1.389 + 1.390 + /** 1.391 + * Returns the handle of the library containing the given address in 1.392 + * its virtual address space, i.e. the library handle for which 1.393 + * LibHandle::Contains returns true. Its purpose is to allow to 1.394 + * implement dladdr(). 1.395 + */ 1.396 + mozilla::TemporaryRef<LibHandle> GetHandleByPtr(void *addr); 1.397 + 1.398 + /** 1.399 + * Returns a Mappable object for the path. Paths in the form 1.400 + * /foo/bar/baz/archive!/directory/lib.so 1.401 + * try to load the directory/lib.so in /foo/bar/baz/archive, provided 1.402 + * that file is a Zip archive. 1.403 + */ 1.404 + static Mappable *GetMappableFromPath(const char *path); 1.405 + 1.406 +protected: 1.407 + /** 1.408 + * Registers the given handle. This method is meant to be called by 1.409 + * LibHandle subclass creators. 1.410 + */ 1.411 + void Register(LibHandle *handle); 1.412 + 1.413 + /** 1.414 + * Forget about the given handle. This method is meant to be called by 1.415 + * LibHandle subclass destructors. 1.416 + */ 1.417 + void Forget(LibHandle *handle); 1.418 + 1.419 + /* Last error. Used for dlerror() */ 1.420 + friend class SystemElf; 1.421 + friend const char *__wrap_dlerror(void); 1.422 + friend void *__wrap_dlsym(void *handle, const char *symbol); 1.423 + friend int __wrap_dlclose(void *handle); 1.424 + const char *lastError; 1.425 + 1.426 +private: 1.427 + ~ElfLoader(); 1.428 + 1.429 + /* Bookkeeping */ 1.430 + typedef std::vector<LibHandle *> LibHandleList; 1.431 + LibHandleList handles; 1.432 + 1.433 +protected: 1.434 + friend class CustomElf; 1.435 + /** 1.436 + * Show some stats about Mappables in CustomElfs. The when argument is to 1.437 + * be used by the caller to give an identifier of the when the stats call 1.438 + * is made. 1.439 + */ 1.440 + static void stats(const char *when); 1.441 + 1.442 + /* Definition of static destructors as to be used for C++ ABI compatibility */ 1.443 + typedef void (*Destructor)(void *object); 1.444 + 1.445 + /** 1.446 + * C++ ABI makes static initializers register destructors through a specific 1.447 + * atexit interface. On glibc/linux systems, the dso_handle is a pointer 1.448 + * within a given library. On bionic/android systems, it is an undefined 1.449 + * symbol. Making sense of the value is not really important, and all that 1.450 + * is really important is that it is different for each loaded library, so 1.451 + * that they can be discriminated when shutting down. For convenience, on 1.452 + * systems where the dso handle is a symbol, that symbol is resolved to 1.453 + * point at corresponding CustomElf. 1.454 + * 1.455 + * Destructors are registered with __*_atexit with an associated object to 1.456 + * be passed as argument when it is called. 1.457 + * 1.458 + * When __cxa_finalize is called, destructors registered for the given 1.459 + * DSO handle are called in the reverse order they were registered. 1.460 + */ 1.461 +#ifdef __ARM_EABI__ 1.462 + static int __wrap_aeabi_atexit(void *that, Destructor destructor, 1.463 + void *dso_handle); 1.464 +#else 1.465 + static int __wrap_cxa_atexit(Destructor destructor, void *that, 1.466 + void *dso_handle); 1.467 +#endif 1.468 + 1.469 + static void __wrap_cxa_finalize(void *dso_handle); 1.470 + 1.471 + /** 1.472 + * Registered destructor. Keeps track of the destructor function pointer, 1.473 + * associated object to call it with, and DSO handle. 1.474 + */ 1.475 + class DestructorCaller { 1.476 + public: 1.477 + DestructorCaller(Destructor destructor, void *object, void *dso_handle) 1.478 + : destructor(destructor), object(object), dso_handle(dso_handle) { } 1.479 + 1.480 + /** 1.481 + * Call the destructor function with the associated object. 1.482 + * Call only once, see CustomElf::~CustomElf. 1.483 + */ 1.484 + void Call(); 1.485 + 1.486 + /** 1.487 + * Returns whether the destructor is associated to the given DSO handle 1.488 + */ 1.489 + bool IsForHandle(void *handle) const 1.490 + { 1.491 + return handle == dso_handle; 1.492 + } 1.493 + 1.494 + private: 1.495 + Destructor destructor; 1.496 + void *object; 1.497 + void *dso_handle; 1.498 + }; 1.499 + 1.500 +private: 1.501 + /* Keep track of all registered destructors */ 1.502 + std::vector<DestructorCaller> destructors; 1.503 + 1.504 + /* Forward declaration, see further below */ 1.505 + class DebuggerHelper; 1.506 +public: 1.507 + /* Loaded object descriptor for the debugger interface below*/ 1.508 + struct link_map { 1.509 + /* Base address of the loaded object. */ 1.510 + const void *l_addr; 1.511 + /* File name */ 1.512 + const char *l_name; 1.513 + /* Address of the PT_DYNAMIC segment. */ 1.514 + const void *l_ld; 1.515 + 1.516 + private: 1.517 + friend class ElfLoader::DebuggerHelper; 1.518 + /* Double linked list of loaded objects. */ 1.519 + link_map *l_next, *l_prev; 1.520 + }; 1.521 + 1.522 +private: 1.523 + /* Data structure used by the linker to give details about shared objects it 1.524 + * loaded to debuggers. This is normally defined in link.h, but Android 1.525 + * headers lack this file. */ 1.526 + struct r_debug { 1.527 + /* Version number of the protocol. */ 1.528 + int r_version; 1.529 + 1.530 + /* Head of the linked list of loaded objects. */ 1.531 + link_map *r_map; 1.532 + 1.533 + /* Function to be called when updates to the linked list of loaded objects 1.534 + * are going to occur. The function is to be called before and after 1.535 + * changes. */ 1.536 + void (*r_brk)(void); 1.537 + 1.538 + /* Indicates to the debugger what state the linked list of loaded objects 1.539 + * is in when the function above is called. */ 1.540 + enum { 1.541 + RT_CONSISTENT, /* Changes are complete */ 1.542 + RT_ADD, /* Beginning to add a new object */ 1.543 + RT_DELETE /* Beginning to remove an object */ 1.544 + } r_state; 1.545 + }; 1.546 + 1.547 + /* Helper class used to integrate libraries loaded by this linker in 1.548 + * r_debug */ 1.549 + class DebuggerHelper 1.550 + { 1.551 + public: 1.552 + DebuggerHelper(); 1.553 + 1.554 + operator bool() 1.555 + { 1.556 + return dbg; 1.557 + } 1.558 + 1.559 + /* Make the debugger aware of a new loaded object */ 1.560 + void Add(link_map *map); 1.561 + 1.562 + /* Make the debugger aware of the unloading of an object */ 1.563 + void Remove(link_map *map); 1.564 + 1.565 + /* Iterates over all link_maps */ 1.566 + class iterator 1.567 + { 1.568 + public: 1.569 + const link_map *operator ->() const 1.570 + { 1.571 + return item; 1.572 + } 1.573 + 1.574 + const link_map &operator ++() 1.575 + { 1.576 + item = item->l_next; 1.577 + return *item; 1.578 + } 1.579 + 1.580 + bool operator<(const iterator &other) const 1.581 + { 1.582 + if (other.item == nullptr) 1.583 + return item ? true : false; 1.584 + MOZ_CRASH("DebuggerHelper::iterator::operator< called with something else than DebuggerHelper::end()"); 1.585 + } 1.586 + protected: 1.587 + friend class DebuggerHelper; 1.588 + iterator(const link_map *item): item(item) { } 1.589 + 1.590 + private: 1.591 + const link_map *item; 1.592 + }; 1.593 + 1.594 + iterator begin() const 1.595 + { 1.596 + return iterator(dbg ? dbg->r_map : nullptr); 1.597 + } 1.598 + 1.599 + iterator end() const 1.600 + { 1.601 + return iterator(nullptr); 1.602 + } 1.603 + 1.604 + private: 1.605 + r_debug *dbg; 1.606 + link_map *firstAdded; 1.607 + }; 1.608 + friend int __wrap_dl_iterate_phdr(dl_phdr_cb callback, void *data); 1.609 + DebuggerHelper dbg; 1.610 +}; 1.611 + 1.612 +#endif /* ElfLoader_h */