1// Copyright 2014 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
18namespace crazy {
19
20class LibraryList;
21class 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
31class SharedLibrary {
32 public:
33  SharedLibrary();
34  ~SharedLibrary();
35
36  size_t load_address() const { return view_.load_address(); }
37  size_t load_size() const { return view_.load_size(); }
38  size_t load_bias() const { return view_.load_bias(); }
39  const ELF::Phdr* phdr() const { return view_.phdr(); }
40  size_t phdr_count() const { return view_.phdr_count(); }
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
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.
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.
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:
148    DependencyIterator(SharedLibrary* lib)
149        : iter_(&lib->view_), symbols_(&lib->symbols_), dep_name_(NULL) {}
150
151    bool GetNext();
152
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#if defined(__arm__) || defined(__aarch64__)
197  // Packed relocations data, NULL if absent.
198  uint8_t* packed_relocations_;
199#endif
200
201  link_map_t link_map_;
202
203  bool has_DT_SYMBOLIC_;
204
205  void* java_vm_;
206
207  const char* base_name_;
208  char full_path_[512];
209};
210
211}  // namespace crazy
212
213#endif  // CRAZY_LINKER_SHARED_LIBRARY_H
214