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/. */
11 #include "mozilla/Atomics.h"
12 #include "mozilla/RefCounted.h"
13 #include "mozilla/RefPtr.h"
14 #include "mozilla/UniquePtr.h"
20 * dlfcn.h replacement functions
23 void* __wrap_dlopen(const char* path
, int flags
);
24 const char* __wrap_dlerror(void);
25 void* __wrap_dlsym(void* handle
, const char* symbol
);
26 int __wrap_dlclose(void* handle
);
30 const char* dli_fname
;
32 const char* dli_sname
;
36 int __wrap_dladdr(const void* addr
, Dl_info
* info
);
40 const char* dlpi_name
;
41 const Elf::Phdr
* dlpi_phdr
;
45 typedef int (*dl_phdr_cb
)(struct dl_phdr_info
*, size_t, void*);
46 int __wrap_dl_iterate_phdr(dl_phdr_cb callback
, void* data
);
49 const void* __wrap___gnu_Unwind_Find_exidx(void* pc
, int* pcount
);
53 * faulty.lib public API
55 MFBT_API
size_t __dl_get_mappable_length(void* handle
);
57 MFBT_API
void* __dl_mmap(void* handle
, void* addr
, size_t length
, off_t offset
);
59 MFBT_API
void __dl_munmap(void* handle
, void* addr
, size_t length
);
61 MFBT_API
bool IsSignalHandlingBroken();
64 /* Forward declarations for use in LibHandle */
70 * Specialize RefCounted template for LibHandle. We may get references to
71 * LibHandles during the execution of their destructor, so we need
72 * RefCounted<LibHandle>::Release to support some reentrancy. See further
81 inline void RefCounted
<LibHandle
, AtomicRefCount
>::Release() const;
85 inline RefCounted
<LibHandle
, AtomicRefCount
>::~RefCounted() {
86 MOZ_ASSERT(mRefCnt
== 0x7fffdead);
90 } /* namespace detail */
91 } /* namespace mozilla */
94 * Abstract class for loaded libraries. Libraries may be loaded through the
95 * system linker or this linker, both cases will be derived from this class.
97 class LibHandle
: public mozilla::external::AtomicRefCounted
<LibHandle
> {
99 MOZ_DECLARE_REFCOUNTED_TYPENAME(LibHandle
)
101 * Constructor. Takes the path of the loaded library and will store a copy
104 LibHandle(const char* path
)
106 path(path
? strdup(path
) : nullptr),
112 virtual ~LibHandle();
115 * Returns the pointer to the address to which the given symbol resolves
116 * inside the library. It is not supposed to resolve the symbol in other
117 * libraries, although in practice, it will for system libraries.
119 virtual void* GetSymbolPtr(const char* symbol
) const = 0;
122 * Returns whether the given address is part of the virtual address space
123 * covered by the loaded library.
125 virtual bool Contains(void* addr
) const = 0;
128 * Returns the base address of the loaded library.
130 virtual void* GetBase() const = 0;
133 * Returns the file name of the library without the containing directory.
135 const char* GetName() const;
138 * Returns the full path of the library, when available. Otherwise, returns
141 const char* GetPath() const { return path
; }
144 * Library handles can be referenced from other library handles or
145 * externally (when dlopen()ing using this linker). We need to be
146 * able to distinguish between the two kind of referencing for better
149 void AddDirectRef() {
150 mozilla::external::AtomicRefCounted
<LibHandle
>::AddRef();
155 * Releases a direct reference, and returns whether there are any direct
158 bool ReleaseDirectRef() {
159 const MozRefCountType count
= --directRefCnt
;
160 MOZ_ASSERT(count
+ 1 > 0);
161 MOZ_ASSERT(count
+ 1 <=
162 mozilla::external::AtomicRefCounted
<LibHandle
>::refCount());
163 mozilla::external::AtomicRefCounted
<LibHandle
>::Release();
168 * Returns the number of direct references
170 MozRefCountType
DirectRefCount() { return directRefCnt
; }
173 * Returns the complete size of the file or stream behind the library
176 size_t GetMappableLength() const;
179 * Returns a memory mapping of the file or stream behind the library
182 void* MappableMMap(void* addr
, size_t length
, off_t offset
) const;
185 * Unmaps a memory mapping of the file or stream behind the library
188 void MappableMUnmap(void* addr
, size_t length
) const;
192 * Find the address and entry count of the ARM.exidx section
193 * associated with the library
195 virtual const void* FindExidx(int* pcount
) const = 0;
200 * Returns a mappable object for use by MappableMMap and related functions.
202 virtual Mappable
* GetMappable() const = 0;
205 * Returns the instance, casted as the wanted type. Returns nullptr if
206 * that's not the actual type. (short of a better way to do this without
209 friend class ElfLoader
;
210 friend class CustomElf
;
211 friend class SEGVHandler
;
212 friend int __wrap_dl_iterate_phdr(dl_phdr_cb callback
, void* data
);
213 virtual BaseElf
* AsBaseElf() { return nullptr; }
214 virtual SystemElf
* AsSystemElf() { return nullptr; }
217 mozilla::Atomic
<MozRefCountType
> directRefCnt
;
220 /* Mappable object keeping the result of GetMappable() */
221 mutable RefPtr
<Mappable
> mappable
;
225 * Specialized RefCounted<LibHandle>::Release. Under normal operation, when
226 * mRefCnt reaches 0, the LibHandle is deleted. Its mRefCnt is however
227 * increased to 1 on normal builds, and 0x7fffdead on debug builds so that the
228 * LibHandle can still be referenced while the destructor is executing. The
229 * mRefCnt is allowed to grow > 0x7fffdead, but not to decrease under that
230 * value, which would mean too many Releases from within the destructor.
236 inline void RefCounted
<LibHandle
, AtomicRefCount
>::Release() const {
238 if (mRefCnt
> 0x7fff0000) MOZ_ASSERT(mRefCnt
> 0x7fffdead);
240 MOZ_ASSERT(mRefCnt
> 0);
242 if (0 == --mRefCnt
) {
244 mRefCnt
= 0x7fffdead;
248 delete static_cast<const LibHandle
*>(this);
253 } /* namespace detail */
254 } /* namespace mozilla */
257 * Class handling libraries loaded by the system linker
259 class SystemElf
: public LibHandle
{
262 * Returns a new SystemElf for the given path. The given flags are passed
265 static already_AddRefed
<LibHandle
> Load(const char* path
, int flags
);
268 * Inherited from LibHandle
270 virtual ~SystemElf();
271 virtual void* GetSymbolPtr(const char* symbol
) const;
272 virtual bool Contains(void* addr
) const { return false; /* UNIMPLEMENTED */ }
273 virtual void* GetBase() const { return nullptr; /* UNIMPLEMENTED */ }
276 virtual const void* FindExidx(int* pcount
) const;
280 virtual Mappable
* GetMappable() const;
283 * Returns the instance, casted as SystemElf. (short of a better way to do
286 friend class ElfLoader
;
287 virtual SystemElf
* AsSystemElf() { return this; }
290 * Remove the reference to the system linker handle. This avoids dlclose()
291 * being called when the instance is destroyed.
293 void Forget() { dlhandle
= nullptr; }
297 * Private constructor
299 SystemElf(const char* path
, void* handle
)
300 : LibHandle(path
), dlhandle(handle
) {}
302 /* Handle as returned by system dlopen() */
307 * The ElfLoader registers its own SIGSEGV handler to handle segmentation
308 * faults within the address space of the loaded libraries. It however
309 * allows a handler to be set for faults in other places, and redispatches
310 * to the handler set through signal() or sigaction().
314 bool hasRegisteredHandler() {
315 if (!initialized
) FinishInitialization();
316 return registeredHandler
;
319 bool isSignalHandlingBroken() { return signalHandlingBroken
; }
321 static int __wrap_sigaction(int signum
, const struct sigaction
* act
,
322 struct sigaction
* oldact
);
330 * The constructor doesn't do all initialization, and the tail is done
333 void FinishInitialization();
336 * SIGSEGV handler registered with __wrap_signal or __wrap_sigaction.
338 struct sigaction action
;
341 * ElfLoader SIGSEGV handler.
343 static void handler(int signum
, siginfo_t
* info
, void* context
);
346 * Temporary test handler.
348 static void test_handler(int signum
, siginfo_t
* info
, void* context
);
351 * Size of the alternative stack. The printf family requires more than 8KB
352 * of stack, and our signal handler may print a few things.
354 static const size_t stackSize
= 12 * 1024;
357 * Alternative stack information used before initialization.
362 * Pointer to an alternative stack for signals. Only set if oldStack is
363 * not set or not big enough.
368 bool registeredHandler
;
369 bool signalHandlingBroken
;
370 bool signalHandlingSlow
;
374 * Elf Loader class in charge of loading and bookkeeping libraries.
376 class ElfLoader
: public SEGVHandler
{
379 * The Elf Loader instance
381 static ElfLoader Singleton
;
384 * Loads the given library with the given flags. Equivalent to dlopen()
385 * The extra "parent" argument optionally gives the handle of the library
386 * requesting the given library to be loaded. The loader may look in the
387 * directory containing that parent library for the library to load.
389 already_AddRefed
<LibHandle
> Load(const char* path
, int flags
,
390 LibHandle
* parent
= nullptr);
393 * Returns the handle of the library containing the given address in
394 * its virtual address space, i.e. the library handle for which
395 * LibHandle::Contains returns true. Its purpose is to allow to
396 * implement dladdr().
398 already_AddRefed
<LibHandle
> GetHandleByPtr(void* addr
);
401 * Returns a Mappable object for the path. Paths in the form
402 * /foo/bar/baz/archive!/directory/lib.so
403 * try to load the directory/lib.so in /foo/bar/baz/archive, provided
404 * that file is a Zip archive.
406 static Mappable
* GetMappableFromPath(const char* path
);
408 void ExpectShutdown(bool val
) { expect_shutdown
= val
; }
409 bool IsShutdownExpected() { return expect_shutdown
; }
412 bool expect_shutdown
;
416 * Registers the given handle. This method is meant to be called by
417 * LibHandle subclass creators.
419 void Register(LibHandle
* handle
);
420 void Register(CustomElf
* handle
);
423 * Forget about the given handle. This method is meant to be called by
424 * LibHandle subclass destructors.
426 void Forget(LibHandle
* handle
);
427 void Forget(CustomElf
* handle
);
429 friend class SystemElf
;
430 friend const char* __wrap_dlerror(void);
431 friend void* __wrap_dlsym(void* handle
, const char* symbol
);
432 friend int __wrap_dlclose(void* handle
);
433 /* __wrap_dlerror() returns this custom last error if non-null or the system
434 * dlerror() value if this is null. Must refer to a string constant. */
435 mozilla::Atomic
<const char*, mozilla::Relaxed
> lastError
;
438 ElfLoader() : expect_shutdown(true), lastError(nullptr) {
439 pthread_mutex_init(&handlesMutex
, nullptr);
444 /* Initialization code that can't run during static initialization. */
447 /* System loader handle for the library/program containing our code. This
448 * is used to resolve wrapped functions. */
449 RefPtr
<LibHandle
> self_elf
;
452 /* System loader handle for the libc. This is used to resolve weak symbols
453 * that some libcs contain that the Android linker won't dlsym(). Normally,
454 * we wouldn't treat non-Android differently, but glibc uses versioned
455 * symbols which this linker doesn't support. */
456 RefPtr
<LibHandle
> libc
;
459 RefPtr
<LibHandle
> libm
;
463 typedef std::vector
<LibHandle
*> LibHandleList
;
464 LibHandleList handles
;
466 pthread_mutex_t handlesMutex
;
469 friend class CustomElf
;
470 friend class LoadedElf
;
472 /* Definition of static destructors as to be used for C++ ABI compatibility */
473 typedef void (*Destructor
)(void* object
);
476 * C++ ABI makes static initializers register destructors through a specific
477 * atexit interface. On glibc/linux systems, the dso_handle is a pointer
478 * within a given library. On bionic/android systems, it is an undefined
479 * symbol. Making sense of the value is not really important, and all that
480 * is really important is that it is different for each loaded library, so
481 * that they can be discriminated when shutting down. For convenience, on
482 * systems where the dso handle is a symbol, that symbol is resolved to
483 * point at corresponding CustomElf.
485 * Destructors are registered with __*_atexit with an associated object to
486 * be passed as argument when it is called.
488 * When __cxa_finalize is called, destructors registered for the given
489 * DSO handle are called in the reverse order they were registered.
492 static int __wrap_aeabi_atexit(void* that
, Destructor destructor
,
495 static int __wrap_cxa_atexit(Destructor destructor
, void* that
,
499 static void __wrap_cxa_finalize(void* dso_handle
);
502 * Registered destructor. Keeps track of the destructor function pointer,
503 * associated object to call it with, and DSO handle.
505 class DestructorCaller
{
507 DestructorCaller(Destructor destructor
, void* object
, void* dso_handle
)
508 : destructor(destructor
), object(object
), dso_handle(dso_handle
) {}
511 * Call the destructor function with the associated object.
512 * Call only once, see CustomElf::~CustomElf.
517 * Returns whether the destructor is associated to the given DSO handle
519 bool IsForHandle(void* handle
) const { return handle
== dso_handle
; }
522 Destructor destructor
;
528 /* Keep track of all registered destructors */
529 std::vector
<DestructorCaller
> destructors
;
531 /* Forward declaration, see further below */
532 class DebuggerHelper
;
535 /* Loaded object descriptor for the debugger interface below*/
537 /* Base address of the loaded object. */
541 /* Address of the PT_DYNAMIC segment. */
545 friend class ElfLoader::DebuggerHelper
;
546 /* Double linked list of loaded objects. */
547 link_map
*l_next
, *l_prev
;
551 /* Data structure used by the linker to give details about shared objects it
552 * loaded to debuggers. This is normally defined in link.h, but Android
553 * headers lack this file. */
555 /* Version number of the protocol. */
558 /* Head of the linked list of loaded objects. */
561 /* Function to be called when updates to the linked list of loaded objects
562 * are going to occur. The function is to be called before and after
566 /* Indicates to the debugger what state the linked list of loaded objects
567 * is in when the function above is called. */
569 RT_CONSISTENT
, /* Changes are complete */
570 RT_ADD
, /* Beginning to add a new object */
571 RT_DELETE
/* Beginning to remove an object */
575 /* Memory representation of ELF Auxiliary Vectors */
581 /* Helper class used to integrate libraries loaded by this linker in
583 class DebuggerHelper
{
587 void Init(AuxVector
* auvx
);
589 explicit operator bool() { return dbg
; }
591 /* Make the debugger aware of a new loaded object */
592 void Add(link_map
* map
);
594 /* Make the debugger aware of the unloading of an object */
595 void Remove(link_map
* map
);
597 /* Iterates over all link_maps */
600 const link_map
* operator->() const { return item
; }
602 const link_map
& operator++() {
607 bool operator<(const iterator
& other
) const {
608 if (other
.item
== nullptr) return item
? true : false;
610 "DebuggerHelper::iterator::operator< called with something else "
611 "than DebuggerHelper::end()");
615 friend class DebuggerHelper
;
616 explicit iterator(const link_map
* item
) : item(item
) {}
619 const link_map
* item
;
622 iterator
begin() const { return iterator(dbg
? dbg
->r_map
: nullptr); }
624 iterator
end() const { return iterator(nullptr); }
628 link_map
* firstAdded
;
630 friend int __wrap_dl_iterate_phdr(dl_phdr_cb callback
, void* data
);
634 #endif /* ElfLoader_h */