ElfLoader.h (16342B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this file, 3 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 #ifndef ElfLoader_h 6 #define ElfLoader_h 7 8 #include <vector> 9 #include <dlfcn.h> 10 #include <signal.h> 11 #include "mozilla/Atomics.h" 12 #include "mozilla/RefCounted.h" 13 #include "mozilla/RefPtr.h" 14 #include "Elfxx.h" 15 #include "Mappable.h" 16 17 /** 18 * dlfcn.h replacement functions 19 */ 20 extern "C" { 21 void* __wrap_dlopen(const char* path, int flags); 22 const char* __wrap_dlerror(void); 23 void* __wrap_dlsym(void* handle, const char* symbol); 24 int __wrap_dlclose(void* handle); 25 26 #ifndef HAVE_DLADDR 27 typedef struct { 28 const char* dli_fname; 29 void* dli_fbase; 30 const char* dli_sname; 31 void* dli_saddr; 32 } Dl_info; 33 #endif 34 int __wrap_dladdr(const void* addr, Dl_info* info); 35 36 typedef int (*dl_phdr_cb)(struct dl_phdr_info*, size_t, void*); 37 int __wrap_dl_iterate_phdr(dl_phdr_cb callback, void* data); 38 39 #ifdef __ARM_EABI__ 40 const void* __wrap___gnu_Unwind_Find_exidx(void* pc, int* pcount); 41 #endif 42 } 43 44 /* Forward declarations for use in LibHandle */ 45 class BaseElf; 46 class CustomElf; 47 class SystemElf; 48 49 /** 50 * Specialize RefCounted template for LibHandle. We may get references to 51 * LibHandles during the execution of their destructor, so we need 52 * RefCounted<LibHandle>::Release to support some reentrancy. See further 53 * below. 54 */ 55 class LibHandle; 56 57 namespace mozilla { 58 namespace detail { 59 60 template <> 61 inline void RefCounted<LibHandle, AtomicRefCount>::Release() const; 62 63 #ifdef DEBUG 64 template <> 65 inline RefCounted<LibHandle, AtomicRefCount>::~RefCounted() { 66 MOZ_ASSERT(mRefCnt == 0x7fffdead); 67 } 68 #endif 69 70 } /* namespace detail */ 71 } /* namespace mozilla */ 72 73 /** 74 * Abstract class for loaded libraries. Libraries may be loaded through the 75 * system linker or this linker, both cases will be derived from this class. 76 */ 77 class LibHandle : public mozilla::external::AtomicRefCounted<LibHandle> { 78 public: 79 MOZ_DECLARE_REFCOUNTED_TYPENAME(LibHandle) 80 /** 81 * Constructor. Takes the path of the loaded library and will store a copy 82 * of the leaf name. 83 */ 84 LibHandle(const char* path) 85 : directRefCnt(0), 86 path(path ? strdup(path) : nullptr), 87 mappable(nullptr) {} 88 89 /** 90 * Destructor. 91 */ 92 virtual ~LibHandle(); 93 94 /** 95 * Returns the pointer to the address to which the given symbol resolves 96 * inside the library. It is not supposed to resolve the symbol in other 97 * libraries, although in practice, it will for system libraries. 98 */ 99 virtual void* GetSymbolPtr(const char* symbol) const = 0; 100 101 /** 102 * Returns whether the given address is part of the virtual address space 103 * covered by the loaded library. 104 */ 105 virtual bool Contains(void* addr) const = 0; 106 107 /** 108 * Returns the base address of the loaded library. 109 */ 110 virtual void* GetBase() const = 0; 111 112 /** 113 * Returns the file name of the library without the containing directory. 114 */ 115 const char* GetName() const; 116 117 /** 118 * Returns the full path of the library, when available. Otherwise, returns 119 * the file name. 120 */ 121 const char* GetPath() const { return path; } 122 123 /** 124 * Library handles can be referenced from other library handles or 125 * externally (when dlopen()ing using this linker). We need to be 126 * able to distinguish between the two kind of referencing for better 127 * bookkeeping. 128 */ 129 void AddDirectRef() { 130 mozilla::external::AtomicRefCounted<LibHandle>::AddRef(); 131 ++directRefCnt; 132 } 133 134 /** 135 * Releases a direct reference, and returns whether there are any direct 136 * references left. 137 */ 138 bool ReleaseDirectRef() { 139 const MozRefCountType count = --directRefCnt; 140 MOZ_ASSERT(count + 1 > 0); 141 MOZ_ASSERT(count + 1 <= 142 mozilla::external::AtomicRefCounted<LibHandle>::refCount()); 143 mozilla::external::AtomicRefCounted<LibHandle>::Release(); 144 return !!count; 145 } 146 147 /** 148 * Returns the number of direct references 149 */ 150 MozRefCountType DirectRefCount() { return directRefCnt; } 151 152 #ifdef __ARM_EABI__ 153 /** 154 * Find the address and entry count of the ARM.exidx section 155 * associated with the library 156 */ 157 virtual const void* FindExidx(int* pcount) const = 0; 158 #endif 159 160 protected: 161 /** 162 * Returns the instance, casted as the wanted type. Returns nullptr if 163 * that's not the actual type. (short of a better way to do this without 164 * RTTI) 165 */ 166 friend class ElfLoader; 167 friend class CustomElf; 168 friend class SEGVHandler; 169 friend int __wrap_dl_iterate_phdr(dl_phdr_cb callback, void* data); 170 virtual BaseElf* AsBaseElf() { return nullptr; } 171 virtual SystemElf* AsSystemElf() { return nullptr; } 172 173 private: 174 mozilla::Atomic<MozRefCountType> directRefCnt; 175 char* path; 176 177 /* Mappable object keeping the result of GetMappable() */ 178 mutable RefPtr<Mappable> mappable; 179 }; 180 181 /** 182 * Specialized RefCounted<LibHandle>::Release. Under normal operation, when 183 * mRefCnt reaches 0, the LibHandle is deleted. Its mRefCnt is however 184 * increased to 1 on normal builds, and 0x7fffdead on debug builds so that the 185 * LibHandle can still be referenced while the destructor is executing. The 186 * mRefCnt is allowed to grow > 0x7fffdead, but not to decrease under that 187 * value, which would mean too many Releases from within the destructor. 188 */ 189 namespace mozilla { 190 namespace detail { 191 192 template <> 193 inline void RefCounted<LibHandle, AtomicRefCount>::Release() const { 194 #ifdef DEBUG 195 if (mRefCnt > 0x7fff0000) MOZ_ASSERT(mRefCnt > 0x7fffdead); 196 #endif 197 MOZ_ASSERT(mRefCnt > 0); 198 if (mRefCnt > 0) { 199 if (0 == --mRefCnt) { 200 #ifdef DEBUG 201 mRefCnt = 0x7fffdead; 202 #else 203 ++mRefCnt; 204 #endif 205 delete static_cast<const LibHandle*>(this); 206 } 207 } 208 } 209 210 } /* namespace detail */ 211 } /* namespace mozilla */ 212 213 /** 214 * Class handling libraries loaded by the system linker 215 */ 216 class SystemElf : public LibHandle { 217 public: 218 /** 219 * Returns a new SystemElf for the given path. The given flags are passed 220 * to dlopen(). 221 */ 222 static already_AddRefed<LibHandle> Load(const char* path, int flags); 223 224 /** 225 * Inherited from LibHandle 226 */ 227 virtual ~SystemElf(); 228 virtual void* GetSymbolPtr(const char* symbol) const; 229 virtual bool Contains(void* addr) const { return false; /* UNIMPLEMENTED */ } 230 virtual void* GetBase() const { return nullptr; /* UNIMPLEMENTED */ } 231 232 #ifdef __ARM_EABI__ 233 virtual const void* FindExidx(int* pcount) const; 234 #endif 235 236 protected: 237 /** 238 * Returns the instance, casted as SystemElf. (short of a better way to do 239 * this without RTTI) 240 */ 241 friend class ElfLoader; 242 virtual SystemElf* AsSystemElf() { return this; } 243 244 /** 245 * Remove the reference to the system linker handle. This avoids dlclose() 246 * being called when the instance is destroyed. 247 */ 248 void Forget() { dlhandle = nullptr; } 249 250 private: 251 /** 252 * Private constructor 253 */ 254 SystemElf(const char* path, void* handle) 255 : LibHandle(path), dlhandle(handle) {} 256 257 /* Handle as returned by system dlopen() */ 258 void* dlhandle; 259 }; 260 261 /** 262 * The ElfLoader registers its own SIGSEGV handler to handle segmentation 263 * faults within the address space of the loaded libraries. It however 264 * allows a handler to be set for faults in other places, and redispatches 265 * to the handler set through signal() or sigaction(). 266 */ 267 class SEGVHandler { 268 public: 269 bool hasRegisteredHandler() { 270 if (!initialized) FinishInitialization(); 271 return registeredHandler; 272 } 273 274 static int __wrap_sigaction(int signum, const struct sigaction* act, 275 struct sigaction* oldact); 276 277 protected: 278 SEGVHandler(); 279 ~SEGVHandler(); 280 281 private: 282 /** 283 * The constructor doesn't do all initialization, and the tail is done 284 * at a later time. 285 */ 286 void FinishInitialization(); 287 288 /** 289 * SIGSEGV handler registered with __wrap_signal or __wrap_sigaction. 290 */ 291 struct sigaction action; 292 293 /** 294 * ElfLoader SIGSEGV handler. 295 */ 296 static void handler(int signum, siginfo_t* info, void* context); 297 298 /** 299 * Temporary test handler. 300 */ 301 static void test_handler(int signum, siginfo_t* info, void* context); 302 303 /** 304 * Size of the alternative stack. The printf family requires more than 8KB 305 * of stack, and our signal handler may print a few things. 306 */ 307 static const size_t stackSize = 12 * 1024; 308 309 /** 310 * Alternative stack information used before initialization. 311 */ 312 stack_t oldStack; 313 314 /** 315 * Pointer to an alternative stack for signals. Only set if oldStack is 316 * not set or not big enough. 317 */ 318 MappedPtr stackPtr; 319 320 bool initialized; 321 bool registeredHandler; 322 bool signalHandlingSlow; 323 }; 324 325 /** 326 * Elf Loader class in charge of loading and bookkeeping libraries. 327 */ 328 class ElfLoader : public SEGVHandler { 329 public: 330 /** 331 * The Elf Loader instance 332 */ 333 static ElfLoader Singleton; 334 335 /** 336 * Loads the given library with the given flags. Equivalent to dlopen() 337 * The extra "parent" argument optionally gives the handle of the library 338 * requesting the given library to be loaded. The loader may look in the 339 * directory containing that parent library for the library to load. 340 */ 341 already_AddRefed<LibHandle> Load(const char* path, int flags, 342 LibHandle* parent = nullptr); 343 344 /** 345 * Returns the handle of the library containing the given address in 346 * its virtual address space, i.e. the library handle for which 347 * LibHandle::Contains returns true. Its purpose is to allow to 348 * implement dladdr(). 349 */ 350 already_AddRefed<LibHandle> GetHandleByPtr(void* addr); 351 352 /** 353 * Returns a Mappable object for the path. Paths in the form 354 * /foo/bar/baz/archive!/directory/lib.so 355 * try to load the directory/lib.so in /foo/bar/baz/archive, provided 356 * that file is a Zip archive. 357 */ 358 static Mappable* GetMappableFromPath(const char* path); 359 360 void ExpectShutdown(bool val) { expect_shutdown = val; } 361 bool IsShutdownExpected() { return expect_shutdown; } 362 363 private: 364 bool expect_shutdown; 365 366 protected: 367 /** 368 * Registers the given handle. This method is meant to be called by 369 * LibHandle subclass creators. 370 */ 371 void Register(LibHandle* handle); 372 void Register(CustomElf* handle); 373 374 /** 375 * Forget about the given handle. This method is meant to be called by 376 * LibHandle subclass destructors. 377 */ 378 void Forget(LibHandle* handle); 379 void Forget(CustomElf* handle); 380 381 friend class SystemElf; 382 friend const char* __wrap_dlerror(void); 383 friend void* __wrap_dlsym(void* handle, const char* symbol); 384 friend int __wrap_dlclose(void* handle); 385 /* __wrap_dlerror() returns this custom last error if non-null or the system 386 * dlerror() value if this is null. Must refer to a string constant. */ 387 mozilla::Atomic<const char*, mozilla::Relaxed> lastError; 388 389 private: 390 ElfLoader() : expect_shutdown(true), lastError(nullptr) { 391 pthread_mutex_init(&handlesMutex, nullptr); 392 } 393 394 ~ElfLoader(); 395 396 /* Initialization code that can't run during static initialization. */ 397 void Init(); 398 399 /* System loader handle for the library/program containing our code. This 400 * is used to resolve wrapped functions. */ 401 RefPtr<LibHandle> self_elf; 402 403 /* Bookkeeping */ 404 typedef std::vector<LibHandle*> LibHandleList; 405 LibHandleList handles; 406 407 pthread_mutex_t handlesMutex; 408 409 protected: 410 friend class CustomElf; 411 friend class LoadedElf; 412 413 /* Definition of static destructors as to be used for C++ ABI compatibility */ 414 typedef void (*Destructor)(void* object); 415 416 /** 417 * C++ ABI makes static initializers register destructors through a specific 418 * atexit interface. On glibc/linux systems, the dso_handle is a pointer 419 * within a given library. On bionic/android systems, it is an undefined 420 * symbol. Making sense of the value is not really important, and all that 421 * is really important is that it is different for each loaded library, so 422 * that they can be discriminated when shutting down. For convenience, on 423 * systems where the dso handle is a symbol, that symbol is resolved to 424 * point at corresponding CustomElf. 425 * 426 * Destructors are registered with __*_atexit with an associated object to 427 * be passed as argument when it is called. 428 * 429 * When __cxa_finalize is called, destructors registered for the given 430 * DSO handle are called in the reverse order they were registered. 431 */ 432 #ifdef __ARM_EABI__ 433 static int __wrap_aeabi_atexit(void* that, Destructor destructor, 434 void* dso_handle); 435 #else 436 static int __wrap_cxa_atexit(Destructor destructor, void* that, 437 void* dso_handle); 438 #endif 439 440 static void __wrap_cxa_finalize(void* dso_handle); 441 442 /** 443 * Registered destructor. Keeps track of the destructor function pointer, 444 * associated object to call it with, and DSO handle. 445 */ 446 class DestructorCaller { 447 public: 448 DestructorCaller(Destructor destructor, void* object, void* dso_handle) 449 : destructor(destructor), object(object), dso_handle(dso_handle) {} 450 451 /** 452 * Call the destructor function with the associated object. 453 * Call only once, see CustomElf::~CustomElf. 454 */ 455 void Call(); 456 457 /** 458 * Returns whether the destructor is associated to the given DSO handle 459 */ 460 bool IsForHandle(void* handle) const { return handle == dso_handle; } 461 462 private: 463 Destructor destructor; 464 void* object; 465 void* dso_handle; 466 }; 467 468 private: 469 /* Keep track of all registered destructors */ 470 std::vector<DestructorCaller> destructors; 471 472 /* Forward declaration, see further below */ 473 class DebuggerHelper; 474 475 public: 476 /* Loaded object descriptor for the debugger interface below*/ 477 struct link_map { 478 /* Base address of the loaded object. */ 479 const void* l_addr; 480 /* File name */ 481 const char* l_name; 482 /* Address of the PT_DYNAMIC segment. */ 483 const void* l_ld; 484 485 private: 486 friend class ElfLoader::DebuggerHelper; 487 /* Double linked list of loaded objects. */ 488 link_map *l_next, *l_prev; 489 }; 490 491 private: 492 /* Data structure used by the linker to give details about shared objects it 493 * loaded to debuggers. This is normally defined in link.h, but Android 494 * headers lack this file. */ 495 struct r_debug { 496 /* Version number of the protocol. */ 497 int r_version; 498 499 /* Head of the linked list of loaded objects. */ 500 link_map* r_map; 501 502 /* Function to be called when updates to the linked list of loaded objects 503 * are going to occur. The function is to be called before and after 504 * changes. */ 505 void (*r_brk)(void); 506 507 /* Indicates to the debugger what state the linked list of loaded objects 508 * is in when the function above is called. */ 509 enum { 510 RT_CONSISTENT, /* Changes are complete */ 511 RT_ADD, /* Beginning to add a new object */ 512 RT_DELETE /* Beginning to remove an object */ 513 } r_state; 514 }; 515 516 /* Memory representation of ELF Auxiliary Vectors */ 517 struct AuxVector { 518 Elf::Addr type; 519 Elf::Addr value; 520 }; 521 522 /* Helper class used to integrate libraries loaded by this linker in 523 * r_debug */ 524 class DebuggerHelper { 525 public: 526 DebuggerHelper(); 527 528 void Init(AuxVector* auvx); 529 530 explicit operator bool() { return dbg; } 531 532 /* Make the debugger aware of a new loaded object */ 533 void Add(link_map* map); 534 535 /* Make the debugger aware of the unloading of an object */ 536 void Remove(link_map* map); 537 538 /* Iterates over all link_maps */ 539 class iterator { 540 public: 541 const link_map* operator->() const { return item; } 542 543 const link_map& operator++() { 544 item = item->l_next; 545 return *item; 546 } 547 548 bool operator<(const iterator& other) const { 549 if (other.item == nullptr) return item ? true : false; 550 MOZ_CRASH( 551 "DebuggerHelper::iterator::operator< called with something else " 552 "than DebuggerHelper::end()"); 553 } 554 555 protected: 556 friend class DebuggerHelper; 557 explicit iterator(const link_map* item) : item(item) {} 558 559 private: 560 const link_map* item; 561 }; 562 563 iterator begin() const { return iterator(dbg ? dbg->r_map : nullptr); } 564 565 iterator end() const { return iterator(nullptr); } 566 567 private: 568 r_debug* dbg; 569 link_map* firstAdded; 570 }; 571 friend int __wrap_dl_iterate_phdr(dl_phdr_cb callback, void* data); 572 DebuggerHelper dbg; 573 }; 574 575 #endif /* ElfLoader_h */