• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef CRAZY_LINKER_SHARED_LIBRARY_H
6 #define CRAZY_LINKER_SHARED_LIBRARY_H
7 
8 #include <link.h>
9 
10 #include "crazy_linker_elf_relro.h"
11 #include "crazy_linker_elf_symbols.h"
12 #include "crazy_linker_elf_view.h"
13 #include "crazy_linker_error.h"
14 #include "crazy_linker_rdebug.h"
15 #include "crazy_linker_util.h"
16 #include "elf_traits.h"
17 
18 namespace crazy {
19 
20 class LibraryList;
21 class LibraryView;
22 
23 // A class that models a shared library loaded by the crazy linker.
24 
25 // Libraries have dependencies (which are listed in their dynamic section
26 // as DT_NEEDED entries). Circular dependencies are forbidden, so they
27 // form an ADG, where the root is the crazy linker itself, since all
28 // libraries that it loads will depend on it (to ensure their
29 // dlopen/dlsym/dlclose calls are properly wrapped).
30 
31 class SharedLibrary {
32  public:
33   SharedLibrary();
34   ~SharedLibrary();
35 
load_address()36   size_t load_address() const { return view_.load_address(); }
load_size()37   size_t load_size() const { return view_.load_size(); }
load_bias()38   size_t load_bias() const { return view_.load_bias(); }
phdr()39   const ELF::Phdr* phdr() const { return view_.phdr(); }
phdr_count()40   size_t phdr_count() const { return view_.phdr_count(); }
base_name()41   const char* base_name() const { return base_name_; }
42 
43   // Load a library (without its dependents) from an ELF file.
44   // Note: This does not apply relocations, nor runs constructors.
45   // |full_path| if the file full path.
46   // |load_address| is the page-aligned load address in memory, or 0.
47   // |file_offset| is the page-aligned file offset.
48   // On failure, return false and set |error| message.
49   //
50   // After this, the caller should load all library dependencies,
51   // Then call Relocate() and CallConstructors() to complete the
52   // operation.
53   bool Load(const char* full_path,
54             size_t load_address,
55             size_t file_offset,
56             Error* error);
57 
58   // Relocate this library, assuming all its dependencies are already
59   // loaded in |lib_list|. On failure, return false and set |error|
60   // message.
61   bool Relocate(LibraryList* lib_list,
62                 Vector<LibraryView*>* dependencies,
63                 Error* error);
64 
GetInfo(size_t * load_address,size_t * load_size,size_t * relro_start,size_t * relro_size)65   void GetInfo(size_t* load_address,
66                size_t* load_size,
67                size_t* relro_start,
68                size_t* relro_size) {
69     *load_address = view_.load_address();
70     *load_size = view_.load_size();
71     *relro_start = relro_start_;
72     *relro_size = relro_size_;
73   }
74 
75   // Returns true iff a given library is mapped to a virtual address range
76   // that contains a given address.
ContainsAddress(void * address)77   bool ContainsAddress(void* address) const {
78     size_t addr = reinterpret_cast<size_t>(address);
79     return load_address() <= addr && addr <= load_address() + load_size();
80   }
81 
82   // Call all constructors in the library.
83   void CallConstructors();
84 
85   // Call all destructors in the library.
86   void CallDestructors();
87 
88   // Return the ELF symbol entry for a given symbol, if defined by
89   // this library, or NULL otherwise.
90   const ELF::Sym* LookupSymbolEntry(const char* symbol_name);
91 
92   // Find the nearest symbol near a given |address|. On success, return
93   // true and set |*sym_name| to the symbol name, |*sym_addr| to its address
94   // in memory, and |*sym_size| to its size in bytes, if any.
FindNearestSymbolForAddress(void * address,const char ** sym_name,void ** sym_addr,size_t * sym_size)95   bool FindNearestSymbolForAddress(void* address,
96                                    const char** sym_name,
97                                    void** sym_addr,
98                                    size_t* sym_size) {
99     return symbols_.LookupNearestByAddress(
100         address, load_bias(), sym_name, sym_addr, sym_size);
101   }
102 
103   // Return the address of a given |symbol_name| if it is exported
104   // by the library, NULL otherwise.
105   void* FindAddressForSymbol(const char* symbol_name);
106 
107   // Create a new Ashmem region holding a copy of the library's RELRO section,
108   // potentially relocated for a new |load_address|. On success, return true
109   // and sets |*relro_start|, |*relro_size| and |*relro_fd|. Note that the
110   // RELRO start address is adjusted for |load_address|, and that the caller
111   // becomes the owner of |*relro_fd|. On failure, return false and set
112   // |error| message.
113   bool CreateSharedRelro(size_t load_address,
114                          size_t* relro_start,
115                          size_t* relro_size,
116                          int* relro_fd,
117                          Error* error);
118 
119   // Try to use a shared relro section from another process.
120   // On success, return true. On failure return false and
121   // sets |error| message.
122   bool UseSharedRelro(size_t relro_start,
123                       size_t relro_size,
124                       int relro_fd,
125                       Error* error);
126 
127   // Look for a symbol named 'JNI_OnLoad' in this library, and if it
128   // exists, call it with |java_vm| as the first parameter. If the
129   // function result is less than |minimum_jni_version|, fail with
130   // a message in |error|. On success, return true, and record
131   // |java_vm| to call 'JNI_OnUnload' at unload time, if present.
132   bool SetJavaVM(void* java_vm, int minimum_jni_version, Error* error);
133 
134   // Call 'JNI_OnUnload()' is necessary, i.e. if there was a succesful call
135   // to SetJavaVM() before. This will pass the same |java_vm| value to the
136   // callback, if it is present in the library.
137   void CallJniOnUnload();
138 
139   // Helper class to iterate over dependencies in a given SharedLibrary.
140   // Usage:
141   //    SharedLibary::DependencyIterator iter(lib);
142   //    while (iter.GetNext() {
143   //      dependency_name = iter.GetName();
144   //      ...
145   //    }
146   class DependencyIterator {
147    public:
DependencyIterator(SharedLibrary * lib)148     DependencyIterator(SharedLibrary* lib)
149         : iter_(&lib->view_), symbols_(&lib->symbols_), dep_name_(NULL) {}
150 
151     bool GetNext();
152 
GetName()153     const char* GetName() const { return dep_name_; }
154 
155    private:
156     DependencyIterator();
157     DependencyIterator(const DependencyIterator&);
158     DependencyIterator& operator=(const DependencyIterator&);
159 
160     ElfView::DynamicIterator iter_;
161     const ElfSymbols* symbols_;
162     const char* dep_name_;
163   };
164 
165   typedef void (*linker_function_t)();
166 
167  private:
168   friend class LibraryList;
169 
170   ElfView view_;
171   ElfSymbols symbols_;
172 
173   ELF::Addr relro_start_;
174   ELF::Addr relro_size_;
175   bool relro_used_;
176 
177   SharedLibrary* list_next_;
178   SharedLibrary* list_prev_;
179   unsigned flags_;
180 
181   linker_function_t* preinit_array_;
182   size_t preinit_array_count_;
183   linker_function_t* init_array_;
184   size_t init_array_count_;
185   linker_function_t* fini_array_;
186   size_t fini_array_count_;
187   linker_function_t init_func_;
188   linker_function_t fini_func_;
189 
190 #ifdef __arm__
191   // ARM EABI section used for stack unwinding.
192   unsigned* arm_exidx_;
193   size_t arm_exidx_count_;
194 #endif
195 
196   link_map_t link_map_;
197 
198   bool has_DT_SYMBOLIC_;
199 
200   void* java_vm_;
201 
202   const char* base_name_;
203   char full_path_[512];
204 };
205 
206 }  // namespace crazy
207 
208 #endif  // CRAZY_LINKER_SHARED_LIBRARY_H
209