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 "mozilla/UniquePtr.h"
15 #include "Zip.h"
16 #include "Elfxx.h"
17 #include "Mappable.h"
18 
19 /**
20  * dlfcn.h replacement functions
21  */
22 extern "C" {
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);
27 
28 #ifndef HAVE_DLADDR
29 typedef struct {
30   const char* dli_fname;
31   void* dli_fbase;
32   const char* dli_sname;
33   void* dli_saddr;
34 } Dl_info;
35 #endif
36 int __wrap_dladdr(const void* addr, Dl_info* info);
37 
38 struct dl_phdr_info {
39   Elf::Addr dlpi_addr;
40   const char* dlpi_name;
41   const Elf::Phdr* dlpi_phdr;
42   Elf::Half dlpi_phnum;
43 };
44 
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);
47 
48 #ifdef __ARM_EABI__
49 const void* __wrap___gnu_Unwind_Find_exidx(void* pc, int* pcount);
50 #endif
51 
52 /**
53  * faulty.lib public API
54  */
55 MFBT_API size_t __dl_get_mappable_length(void* handle);
56 
57 MFBT_API void* __dl_mmap(void* handle, void* addr, size_t length, off_t offset);
58 
59 MFBT_API void __dl_munmap(void* handle, void* addr, size_t length);
60 
61 MFBT_API bool IsSignalHandlingBroken();
62 }
63 
64 /* Forward declarations for use in LibHandle */
65 class BaseElf;
66 class CustomElf;
67 class SystemElf;
68 
69 /**
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
73  * below.
74  */
75 class LibHandle;
76 
77 namespace mozilla {
78 namespace detail {
79 
80 template <>
81 inline void RefCounted<LibHandle, AtomicRefCount>::Release() const;
82 
83 #ifdef DEBUG
84 template <>
~RefCounted()85 inline RefCounted<LibHandle, AtomicRefCount>::~RefCounted() {
86   MOZ_ASSERT(mRefCnt == 0x7fffdead);
87 }
88 #endif
89 
90 } /* namespace detail */
91 } /* namespace mozilla */
92 
93 /**
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.
96  */
97 class LibHandle : public mozilla::external::AtomicRefCounted<LibHandle> {
98  public:
MOZ_DECLARE_REFCOUNTED_TYPENAME(LibHandle)99   MOZ_DECLARE_REFCOUNTED_TYPENAME(LibHandle)
100   /**
101    * Constructor. Takes the path of the loaded library and will store a copy
102    * of the leaf name.
103    */
104   LibHandle(const char* path)
105       : directRefCnt(0),
106         path(path ? strdup(path) : nullptr),
107         mappable(nullptr) {}
108 
109   /**
110    * Destructor.
111    */
112   virtual ~LibHandle();
113 
114   /**
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.
118    */
119   virtual void* GetSymbolPtr(const char* symbol) const = 0;
120 
121   /**
122    * Returns whether the given address is part of the virtual address space
123    * covered by the loaded library.
124    */
125   virtual bool Contains(void* addr) const = 0;
126 
127   /**
128    * Returns the base address of the loaded library.
129    */
130   virtual void* GetBase() const = 0;
131 
132   /**
133    * Returns the file name of the library without the containing directory.
134    */
135   const char* GetName() const;
136 
137   /**
138    * Returns the full path of the library, when available. Otherwise, returns
139    * the file name.
140    */
GetPath()141   const char* GetPath() const { return path; }
142 
143   /**
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
147    * bookkeeping.
148    */
AddDirectRef()149   void AddDirectRef() {
150     mozilla::external::AtomicRefCounted<LibHandle>::AddRef();
151     ++directRefCnt;
152   }
153 
154   /**
155    * Releases a direct reference, and returns whether there are any direct
156    * references left.
157    */
ReleaseDirectRef()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();
164     return !!count;
165   }
166 
167   /**
168    * Returns the number of direct references
169    */
DirectRefCount()170   MozRefCountType DirectRefCount() { return directRefCnt; }
171 
172   /**
173    * Returns the complete size of the file or stream behind the library
174    * handle.
175    */
176   size_t GetMappableLength() const;
177 
178   /**
179    * Returns a memory mapping of the file or stream behind the library
180    * handle.
181    */
182   void* MappableMMap(void* addr, size_t length, off_t offset) const;
183 
184   /**
185    * Unmaps a memory mapping of the file or stream behind the library
186    * handle.
187    */
188   void MappableMUnmap(void* addr, size_t length) const;
189 
190 #ifdef __ARM_EABI__
191   /**
192    * Find the address and entry count of the ARM.exidx section
193    * associated with the library
194    */
195   virtual const void* FindExidx(int* pcount) const = 0;
196 #endif
197 
198  protected:
199   /**
200    * Returns a mappable object for use by MappableMMap and related functions.
201    */
202   virtual Mappable* GetMappable() const = 0;
203 
204   /**
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
207    * RTTI)
208    */
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);
AsBaseElf()213   virtual BaseElf* AsBaseElf() { return nullptr; }
AsSystemElf()214   virtual SystemElf* AsSystemElf() { return nullptr; }
215 
216  private:
217   mozilla::Atomic<MozRefCountType> directRefCnt;
218   char* path;
219 
220   /* Mappable object keeping the result of GetMappable() */
221   mutable RefPtr<Mappable> mappable;
222 };
223 
224 /**
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.
231  */
232 namespace mozilla {
233 namespace detail {
234 
235 template <>
Release()236 inline void RefCounted<LibHandle, AtomicRefCount>::Release() const {
237 #ifdef DEBUG
238   if (mRefCnt > 0x7fff0000) MOZ_ASSERT(mRefCnt > 0x7fffdead);
239 #endif
240   MOZ_ASSERT(mRefCnt > 0);
241   if (mRefCnt > 0) {
242     if (0 == --mRefCnt) {
243 #ifdef DEBUG
244       mRefCnt = 0x7fffdead;
245 #else
246       ++mRefCnt;
247 #endif
248       delete static_cast<const LibHandle*>(this);
249     }
250   }
251 }
252 
253 } /* namespace detail */
254 } /* namespace mozilla */
255 
256 /**
257  * Class handling libraries loaded by the system linker
258  */
259 class SystemElf : public LibHandle {
260  public:
261   /**
262    * Returns a new SystemElf for the given path. The given flags are passed
263    * to dlopen().
264    */
265   static already_AddRefed<LibHandle> Load(const char* path, int flags);
266 
267   /**
268    * Inherited from LibHandle
269    */
270   virtual ~SystemElf();
271   virtual void* GetSymbolPtr(const char* symbol) const;
Contains(void * addr)272   virtual bool Contains(void* addr) const { return false; /* UNIMPLEMENTED */ }
GetBase()273   virtual void* GetBase() const { return nullptr; /* UNIMPLEMENTED */ }
274 
275 #ifdef __ARM_EABI__
276   virtual const void* FindExidx(int* pcount) const;
277 #endif
278 
279  protected:
280   virtual Mappable* GetMappable() const;
281 
282   /**
283    * Returns the instance, casted as SystemElf. (short of a better way to do
284    * this without RTTI)
285    */
286   friend class ElfLoader;
AsSystemElf()287   virtual SystemElf* AsSystemElf() { return this; }
288 
289   /**
290    * Remove the reference to the system linker handle. This avoids dlclose()
291    * being called when the instance is destroyed.
292    */
Forget()293   void Forget() { dlhandle = nullptr; }
294 
295  private:
296   /**
297    * Private constructor
298    */
SystemElf(const char * path,void * handle)299   SystemElf(const char* path, void* handle)
300       : LibHandle(path), dlhandle(handle) {}
301 
302   /* Handle as returned by system dlopen() */
303   void* dlhandle;
304 };
305 
306 /**
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().
311  */
312 class SEGVHandler {
313  public:
hasRegisteredHandler()314   bool hasRegisteredHandler() {
315     if (!initialized) FinishInitialization();
316     return registeredHandler;
317   }
318 
isSignalHandlingBroken()319   bool isSignalHandlingBroken() { return signalHandlingBroken; }
320 
321   static int __wrap_sigaction(int signum, const struct sigaction* act,
322                               struct sigaction* oldact);
323 
324  protected:
325   SEGVHandler();
326   ~SEGVHandler();
327 
328  private:
329   /**
330    * The constructor doesn't do all initialization, and the tail is done
331    * at a later time.
332    */
333   void FinishInitialization();
334 
335   /**
336    * SIGSEGV handler registered with __wrap_signal or __wrap_sigaction.
337    */
338   struct sigaction action;
339 
340   /**
341    * ElfLoader SIGSEGV handler.
342    */
343   static void handler(int signum, siginfo_t* info, void* context);
344 
345   /**
346    * Temporary test handler.
347    */
348   static void test_handler(int signum, siginfo_t* info, void* context);
349 
350   /**
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.
353    */
354   static const size_t stackSize = 12 * 1024;
355 
356   /**
357    * Alternative stack information used before initialization.
358    */
359   stack_t oldStack;
360 
361   /**
362    * Pointer to an alternative stack for signals. Only set if oldStack is
363    * not set or not big enough.
364    */
365   MappedPtr stackPtr;
366 
367   bool initialized;
368   bool registeredHandler;
369   bool signalHandlingBroken;
370   bool signalHandlingSlow;
371 };
372 
373 /**
374  * Elf Loader class in charge of loading and bookkeeping libraries.
375  */
376 class ElfLoader : public SEGVHandler {
377  public:
378   /**
379    * The Elf Loader instance
380    */
381   static ElfLoader Singleton;
382 
383   /**
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.
388    */
389   already_AddRefed<LibHandle> Load(const char* path, int flags,
390                                    LibHandle* parent = nullptr);
391 
392   /**
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().
397    */
398   already_AddRefed<LibHandle> GetHandleByPtr(void* addr);
399 
400   /**
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.
405    */
406   static Mappable* GetMappableFromPath(const char* path);
407 
ExpectShutdown(bool val)408   void ExpectShutdown(bool val) { expect_shutdown = val; }
IsShutdownExpected()409   bool IsShutdownExpected() { return expect_shutdown; }
410 
411  private:
412   bool expect_shutdown;
413 
414  protected:
415   /**
416    * Registers the given handle. This method is meant to be called by
417    * LibHandle subclass creators.
418    */
419   void Register(LibHandle* handle);
420   void Register(CustomElf* handle);
421 
422   /**
423    * Forget about the given handle. This method is meant to be called by
424    * LibHandle subclass destructors.
425    */
426   void Forget(LibHandle* handle);
427   void Forget(CustomElf* handle);
428 
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;
436 
437  private:
ElfLoader()438   ElfLoader() : expect_shutdown(true), lastError(nullptr) {
439     pthread_mutex_init(&handlesMutex, nullptr);
440   }
441 
442   ~ElfLoader();
443 
444   /* Initialization code that can't run during static initialization. */
445   void Init();
446 
447   /* System loader handle for the library/program containing our code. This
448    * is used to resolve wrapped functions. */
449   RefPtr<LibHandle> self_elf;
450 
451 #if defined(ANDROID)
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;
457 
458   /* And for libm. */
459   RefPtr<LibHandle> libm;
460 #endif
461 
462   /* Bookkeeping */
463   typedef std::vector<LibHandle*> LibHandleList;
464   LibHandleList handles;
465 
466   pthread_mutex_t handlesMutex;
467 
468  protected:
469   friend class CustomElf;
470   friend class LoadedElf;
471 
472   /* Definition of static destructors as to be used for C++ ABI compatibility */
473   typedef void (*Destructor)(void* object);
474 
475   /**
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.
484    *
485    * Destructors are registered with __*_atexit with an associated object to
486    * be passed as argument when it is called.
487    *
488    * When __cxa_finalize is called, destructors registered for the given
489    * DSO handle are called in the reverse order they were registered.
490    */
491 #ifdef __ARM_EABI__
492   static int __wrap_aeabi_atexit(void* that, Destructor destructor,
493                                  void* dso_handle);
494 #else
495   static int __wrap_cxa_atexit(Destructor destructor, void* that,
496                                void* dso_handle);
497 #endif
498 
499   static void __wrap_cxa_finalize(void* dso_handle);
500 
501   /**
502    * Registered destructor. Keeps track of the destructor function pointer,
503    * associated object to call it with, and DSO handle.
504    */
505   class DestructorCaller {
506    public:
DestructorCaller(Destructor destructor,void * object,void * dso_handle)507     DestructorCaller(Destructor destructor, void* object, void* dso_handle)
508         : destructor(destructor), object(object), dso_handle(dso_handle) {}
509 
510     /**
511      * Call the destructor function with the associated object.
512      * Call only once, see CustomElf::~CustomElf.
513      */
514     void Call();
515 
516     /**
517      * Returns whether the destructor is associated to the given DSO handle
518      */
IsForHandle(void * handle)519     bool IsForHandle(void* handle) const { return handle == dso_handle; }
520 
521    private:
522     Destructor destructor;
523     void* object;
524     void* dso_handle;
525   };
526 
527  private:
528   /* Keep track of all registered destructors */
529   std::vector<DestructorCaller> destructors;
530 
531   /* Forward declaration, see further below */
532   class DebuggerHelper;
533 
534  public:
535   /* Loaded object descriptor for the debugger interface below*/
536   struct link_map {
537     /* Base address of the loaded object. */
538     const void* l_addr;
539     /* File name */
540     const char* l_name;
541     /* Address of the PT_DYNAMIC segment. */
542     const void* l_ld;
543 
544    private:
545     friend class ElfLoader::DebuggerHelper;
546     /* Double linked list of loaded objects. */
547     link_map *l_next, *l_prev;
548   };
549 
550  private:
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. */
554   struct r_debug {
555     /* Version number of the protocol. */
556     int r_version;
557 
558     /* Head of the linked list of loaded objects. */
559     link_map* r_map;
560 
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
563      * changes. */
564     void (*r_brk)(void);
565 
566     /* Indicates to the debugger what state the linked list of loaded objects
567      * is in when the function above is called. */
568     enum {
569       RT_CONSISTENT, /* Changes are complete */
570       RT_ADD,        /* Beginning to add a new object */
571       RT_DELETE      /* Beginning to remove an object */
572     } r_state;
573   };
574 
575   /* Memory representation of ELF Auxiliary Vectors */
576   struct AuxVector {
577     Elf::Addr type;
578     Elf::Addr value;
579   };
580 
581   /* Helper class used to integrate libraries loaded by this linker in
582    * r_debug */
583   class DebuggerHelper {
584    public:
585     DebuggerHelper();
586 
587     void Init(AuxVector* auvx);
588 
589     explicit operator bool() { return dbg; }
590 
591     /* Make the debugger aware of a new loaded object */
592     void Add(link_map* map);
593 
594     /* Make the debugger aware of the unloading of an object */
595     void Remove(link_map* map);
596 
597     /* Iterates over all link_maps */
598     class iterator {
599      public:
600       const link_map* operator->() const { return item; }
601 
602       const link_map& operator++() {
603         item = item->l_next;
604         return *item;
605       }
606 
607       bool operator<(const iterator& other) const {
608         if (other.item == nullptr) return item ? true : false;
609         MOZ_CRASH(
610             "DebuggerHelper::iterator::operator< called with something else "
611             "than DebuggerHelper::end()");
612       }
613 
614      protected:
615       friend class DebuggerHelper;
iterator(const link_map * item)616       explicit iterator(const link_map* item) : item(item) {}
617 
618      private:
619       const link_map* item;
620     };
621 
begin()622     iterator begin() const { return iterator(dbg ? dbg->r_map : nullptr); }
623 
end()624     iterator end() const { return iterator(nullptr); }
625 
626    private:
627     r_debug* dbg;
628     link_map* firstAdded;
629   };
630   friend int __wrap_dl_iterate_phdr(dl_phdr_cb callback, void* data);
631   DebuggerHelper dbg;
632 };
633 
634 #endif /* ElfLoader_h */
635